Abstract syntax tree 2026-10-13
An abstract syntax tree is a rooted tree recording the meaningful syntactic pieces of a program and how they fit together. A program identifier such as
x, a literal value such as 2, and a node representing addition have different roles. Their arrangement answers structural questions: which program expression supplies an operand, which name is a variable assignment target, and which construct encloses another. This makes an abstract syntax tree useful to a compiler, an interpreter, and the type system that checks a program.The word "abstract" describes what is omitted. Lexical analysis first recognizes lexical tokens, such as
x, =, 2, +, 3, *, 4. A concrete parse tree can retain grammar derivation structure, including punctuation and intermediate context-free grammar categories such as expression, term and factor. An abstract syntax tree usually keeps the operation and its operands without all those grammar scaffolds. Parentheses can determine its shape without surviving as separate nodes. A parser may construct the abstract syntax tree directly; it need not first allocate a concrete parse tree.An abstract syntax tree records programming language syntax, but does not by itself supply all programming language semantics. In
a+b, the names do not reveal their current values, and + might perform addition of integers or concatenate strings. The programming language rules, name bindings, and operand types determine the meaning. In Python, successfully calling ast.parse also does not guarantee that later compilation will accept the result: parsing return 42 succeeds, but compiling that statement outside a function fails. [ref]ast — Abstract syntax trees, Python 3.14 documentation. ast.parse: parsing performs no scoping checks; the return 42 example
An abstract syntax tree is not machine code. Its nodes describe language constructs. A compiler can check and transform this structure before translating it into executable instructions; an interpreter can evaluate an appropriate tree directly. The little evaluator below demonstrates this distinction without pretending to implement an entire programming language.
Algorithm Created 2026-09-24 Updated 2026-10-13
Here "finite" refers to the description: a short algorithm can perform arbitrarily many steps on increasingly large inputs. Solving a computational problem additionally requires termination and the specified output on every permitted input. State assumptions explicitly: binary search requires a sorted array.
An algorithm is an idea that can have implementations in different programming languages. Its explanation should make three things visible: the permitted inputs, the rule for each step, and the meaning of the returned output. Algorithm correctness then separates finding the right answer from eventually finishing; time complexity asks how much work finishing requires.
A particularly useful design question is: what knowledge survives each step? In binary search, it is the location of every possible match inside the remaining candidate range. Writing that fact as a loop invariant turns an intuitive shortcut into a procedure whose discarded candidates can be justified. This often helps discover the algorithm, rather than merely check it afterward.
Assembly language 2026-10-24
A programming language expressing machine instructions through symbolic operation names, processor registers, labels and data directives. A concrete program must respect its instruction set's operand restrictions and the platform's calling convention.
Boolean operation Created 2026-09-24 Updated 2026-10-14
A Boolean operation is a Boolean function taking truth values encoded as bits: means false and means true. These operations supply the concrete two-valued interpretation of a Boolean algebra. A Boolean valuation fixes the inputs; a truth table lists every possible input. With two input bits there are four rows.
The basic logical connectives are logical conjunction (AND, , both true), logical disjunction (OR, , at least one true), exclusive or (XOR, , exactly one true), and logical negation (NOT, , the opposite value). OR is inclusive: it accepts the case where both inputs are true.[ref]
3.1 Propositional Logic. Discrete Mathematics: An Open Introduction (3rd edition) by Oscar Levin; Discrete Mathematics: An Open Introduction, 3rd edition by Oscar Levin, §3.1, Truth Tables: conjunction, disjunction and negation tables
Four input pairs distinguish logical conjunction, inclusive logical disjunction, exclusive or, and logical negation
. Details. For an original program-condition example, let mean “the backup is recent” and mean “the backup is verified”. A rule requiring a recent, verified backup uses logical conjunction; one accepting either qualification uses logical disjunction. A rule flagging a mismatch between the two qualifications uses exclusive or. A recent, verified backup gives : AND and OR accept it, while XOR does not flag it. The last row of the truth table makes this difference explicit.
The same small Boolean operations build larger tests and Boolean circuits. In a programming language, the value of a condition and the procedure for evaluating it both matter. For Boolean operands, Python's
and, or, and not implement these logical connectives. Evaluation proceeds from the left; and skips its right operand if the left is false, and or skips it if the left is true. More generally, and and or return an operand, whereas not returns a Boolean.[ref]Expressions, Python 3.14 language reference. Python 3.14 documentation; Python Language Reference, version 3.14, §6.11 Boolean operations: evaluation order and returned operands
For example, the Python condition
denominator != 0 and numerator / denominator > 2 avoids division by zero because the logical conjunction's second test is evaluated only when the first succeeds. Reversing the tests preserves the abstract truth table for defined operands but can raise a division-by-zero error handled through exception handling. A rewrite involving a side effect must also preserve the needed evaluation behavior. Compilation arithmetic example 2026-10-14
Consider the program expression
x*(2+3)-4 in a deliberately small programming language. Its only program identifier is x, supplied as an integer input. Its literal values are nonnegative decimal numerals, interpreted as integers. Whitespace is ignored between lexical tokens. Its context-free grammar is:expression ::= term (("+" | "-") term)*
term ::= factor ("*" factor)*
factor ::= numeral | "x" | "(" expression ")"
numeral ::= digit digit*
digit ::= "0" | "1" | "2" | "3" | "4"
| "5" | "6" | "7" | "8" | "9"Here
* outside quotation marks means zero or more repetitions. Repeated operators are grouped to the left, specifying operator associativity; term gives multiplication higher operator precedence than addition and subtraction. Parentheses override that grouping. There is no unary minus, variable assignment, function call, or side effect in this language. Evaluation obtains each left operand before its right operand and uses exact integer arithmetic, with no fixed-width overflow.Lexical analysis recognizes
x, *, (, 2, +, 3, ), -, 4. Parsing constructs the concrete abstract syntax tree Sub(Mul(Name(x), Add(Int(2), Int(3))), Int(4)). Parentheses have done their work by making Add a child of Mul; they need not survive as nodes. Constant folding changes this to Sub(Mul(Name(x), Int(5)), Int(4)). It cannot replace Name(x) by a literal value because the input is supplied at execution. The resulting function of the input is .A compiler for our stack machine emits
LOAD x; PUSH 5; MUL; PUSH 4; SUB. LOAD x pushes the current input; PUSH n pushes the integer literal value n. Each binary instruction removes the top item as its right operand, then the next item as its left operand, and pushes the result. The instruction sequence is an intermediate representation that an interpreter can execute; no machine code has been emitted. A compact binary encoding could make it bytecode, but these printed instruction names are only a readable notation.Why does this compilation preserve the result? A structural induction supplies a short proof outline. Translating a literal value or
x appends its value to any initial stack. For a binary abstract syntax tree node, first translating the left child and then the right child appends the two operand values; the matching instruction replaces them by exactly the original operation's result. Previously present stack items remain intact. Constant folding also preserves the result because in the specified integer arithmetic. Together these facts explain agreement for every integer input, rather than merely agreement for one trial. Compiler Created 2026-10-13 Updated 2026-10-14
A compiler translates a program from one representation to another while aiming to preserve its programming language semantics. Its input might be source code or an intermediate representation; its output might be another programming language, bytecode, an intermediate representation, or machine code. Producing machine code is therefore one possible destination, rather than the definition of compilation. For example, the LLVM 20.1.0 tutorial translates an abstract syntax tree into an intermediate representation before introducing execution.[ref]
Compilation can use an abstract syntax tree for checking and transformations such as constant folding before producing machine code. These are useful possibilities, not a compulsory sequence of separate stages for every compiler. The central distinction is between translating a program and executing its operations: a compiler can translate
x*(2+3)-4 without knowing the input value of x, whereas an interpreter needs that value to produce this program expression's result.Different representations expose different questions. Source code preserves what a programmer wrote; an abstract syntax tree exposes grouping; a type system checks permitted combinations; a stack machine makes operand movement explicit. Retaining abstract syntax tree source locations across compilation helps an error message identify the original construct even after constant folding has changed its shape. A malformed
x*(2+)-4 is a programming language syntax error; an unavailable x in the valid example is instead a missing input. Locating the failing rule is more helpful than treating both as an unexplained execution failure. C programming language 2026-10-24
A systems programming language supporting explicit memory access, arrays, and implementation-dependent integer widths. Signed integer overflow is not generally specified as modular arithmetic; correctness arguments must state the relevant range assumptions.
Equational reasoning 2026-10-31
Prove equality of expressions through a chain of substitutions justified by definitions, previously established equalities, or algebraic laws. Each step preserves the expression's value. In a programming language with lazy evaluation, an asserted program law must also preserve termination and the demanded amount of a partial value, not just agree on finite defined inputs.
Formal verification Created 2026-10-13 Updated 2026-10-18
Establishing specified properties of a system using formal proofs about a precise model. Formal verification connects an implementation to a formal specification; correctness of the model and its assumptions still matters when applying the result to a physical system.
For a small example, the summation loop verification below starts with executable steps and asks two separate questions: does any returned value satisfy the postcondition, and does execution reach that return? A loop invariant answers the first; a loop variant answers the second. This turns an unbounded family of permitted inputs into a few reusable proof obligations.
The model must specify programming language semantics, including the meaning of variable assignments, comparisons and integer arithmetic. A proof about exact mathematical integers need not describe a machine that wraps on integer overflow. Similarly, a correct formal proof of a weak or mistaken formal specification does not establish the intended behavior. Choosing the right formal specification and relating the model to the implemented system remain substantive tasks.
Software testing examines chosen executions and can expose a counterexample. A formal proof instead justifies a statement throughout its stated model; it does not require executing every permitted input. This makes formal verification valuable when rare boundary cases matter, while software testing can still reveal an incorrect model or misunderstood requirement.
In 1969, Tony Hoare presented rules for variable assignment, composition and iteration in a small programming language. His paper explicitly says those rules do not prove successful termination, and discusses the dependence of arithmetic reasoning on the chosen overflow behavior. These reservations already make the model's scope part of the argument.[ref]
An Axiomatic Basis for Computer Programming by Tony Hoare. Hoare, An Axiomatic Basis for Computer Programming, §2 Computer Arithmetic, pp. 576–577; §§3.1–3.4, pp. 577–578; §4 General Reservations, pp. 578–579
Function type 2026-10-13
A function type classifies functions that accept arguments of type and produce results of type if they return. For example, has function type in our teaching programming language, while has function type . A function type specifies how a function may be used; it does not guarantee that a call returns.
The two central typing judgment rules areThe lambda abstraction rule checks the body under an extended typing context; the lambda application rule checks that the argument has exactly the required type. These rules describe our simple type examples. [ref]
https://softwarefoundations.cis.upenn.edu/plf-current/Stlc.html. Software Foundations, Programming Language Foundations, The Simply Typed Lambda-Calculus: typing rules
For , assume ; both and have type
int, so has type int. The abstraction therefore has function type . Since has type int, the call has type int and evaluates to . Replacing by true fails the argument requirement. This local derivation explains each step without running the program.Arrows associate to the right: means , a function returning another function. For instance, has function type . Supplying one integer yields a function awaiting the second. Functions can also be arguments: accepts an integer-to-integer function and has an integer result type.
// Target: computer-science.bigb
Integer overflow 2026-10-18
An integer arithmetic result outside the range of its chosen representation. A programming language may specify wrapping, trapping or another behavior; a proof over mathematical integers must account for that difference.
Interpreter (computing) Created 2026-10-13 Updated 2026-10-14
An interpreter executes a program's operations according to its programming language semantics. It can recursively evaluate an abstract syntax tree, or follow an instruction sequence using an execution state such as a stack and an instruction pointer. It need not repeatedly read source code characters, and it need not use an abstract syntax tree at all.
Compilation and interpretation can coexist. In CPython, Python source code is compiled into bytecode for execution by an interpreter; its bytecode is not promised to remain stable between releases.[ref]
Glossary, Python 3.14 documentation. Python 3.14 documentation; Python 3.14 glossary: bytecode and virtual machine entries; compilation, execution and release-specific bytecodes
The Python 3.14 compile function accepts text or an abstract syntax tree and can produce a code object, which eval or exec can execute.[ref]Built-in Functions, Python 3.14 documentation. Python 3.14 documentation; Python 3.14 Built-in Functions: compile, accepted source forms, code objects and execution by eval or exec
These operations make translation and execution separately accessible without requiring them to live in different applications.Just-in-time compilation gives another combination: an interactive implementation can translate a submitted program expression into machine code and then execute it immediately. The LLVM 20.1.0 tutorial demonstrates this by adding an intermediate representation module to its just-in-time compilation facility, looking up the generated function, and calling it.[ref]
4. Kaleidoscope: Adding JIT and Optimizer Support. LLVM 20.1.0 documentation; Implementing a language with LLVM, chapter 4, section 4.4: HandleTopLevelExpression, addModule, lookup and calling the generated native function
Thus calling a programming language permanently "compiled" or "interpreted" hides an implementation choice: ask which representation is translated, which is executed, and when. Machine code 2026-10-13
Encoded instructions executed by a central processing unit. An abstract syntax tree instead describes programming language constructs and their nesting.
Memoization 2026-10-13
Memoization retains a completed function result under a memoization key and returns that result when an equivalent request recurs. For a terminating pure function, repeated evaluation can therefore become lookup rather than repeated work. The benefit is especially striking with recursion and overlapping subproblems: a large tree of calls can refer to a small Directed acyclic graph of distinct answers. The memoization cache contract determines whether reuse is correct; the memoization cache lifetime determines whether an answer is still present when wanted.
Memoization records computed answers, whereas a memory cache retains data from computer memory. A CPU cache hit does not by itself prevent a program from evaluating the same function again. Spreadsheet dependency evaluation adds an explicit mechanism for invalidating affected cached cell values after inputs change; a general memoization table does not discover such changes automatically.
A documented early motivation was to let programs improve their efficiency during execution through rote learning: the abstract of a 1968 paper explicitly proposes such a programming language facility.[ref]
“Memo” Functions and Machine Learning by Donald Michie. Donald Michie, “Memo” Functions and Machine Learning, Nature 218, pp. 19–22 (1968), abstract: programming-language rote learning motivated by efficiency during execution
Expand the two type synonyms to see what survives an exception:In the first order, a failed computation can still produce
(Nothing,s'). The exception handler therefore runs with , including writes made before failure. In the second order, failure produces Nothing, with no returned computer memory. A handler defined by applying the underlying orelse pointwise runs its alternative from the original input computer memory . This gives rollback of this explicit program state for the failed branch.For example, start with a memory location holding , write , fail, and handle the failure by reading that memory location. The first order returns ; the second returns . This rollback concerns the explicit computer memory only: arbitrary effects in the base computational monad are not thereby reversed.A conventional programming language normally retains writes made before an exception is caught. Its mutable computer memory and exception handling therefore correspond more closely to .
Pointer (computer programming) 2026-10-24
A pointer is a value designating a location in a program's memory model, or a special value such as a null pointer that designates no object. A node in a pointer-linked binary tree stores pointers to its two children. Representation, size, alignment and the validity of dereferencing depend on the programming language and target; 32-bit AAPCS32 data pointers occupy four bytes.
Programming language Created 2026-10-13 Updated 2026-10-14
A programming language specifies how programs are written and what their execution means. Its type system describes which operations may be combined; an abstract syntax tree records the structure on which these rules act. The examples under type system use a small teaching language with integers, Boolean values and function types.
// Target: computer-science.bigb
Programming language semantics 2026-10-13
The meaning of constructs in a programming language, including their permitted values and execution behavior. Programming language syntax organizes constructs; a type system and execution rules give further constraints and meaning.
Programming language syntax 2026-10-13
The rules for forming programs in a programming language. A parser checks and structures text according to these rules; an abstract syntax tree records the resulting constructs.
Python (programming language) 2026-10-13
A programming language whose standard-library
ast module provides access to its abstract syntax trees. The examples here use its version 3.14 schema and literal integer arithmetic.
