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.
Compiler front end 2026-11-05
A compiler front end reads a source language and checks or translates its meaning into a representation used by later compilation stages. lexical analysis groups characters into tokens; parsing builds structured syntax; name resolution and type checking establish which declarations and operations the program denotes. These responsibilities need not be implemented as completely separate passes.
For example, x + 2 * y must be grouped as x + (2 * y) under the usual precedence rules. The parser establishes that grouping, while semantic analysis determines whether x and y exist and support the requested operations. An abstract syntax tree can retain source locations for precise diagnostics. The LLVM Kaleidoscope tutorial shows this transition from parsed syntax to LLVM intermediate code.[ref] The front end's language-facing checks complement the machine-facing decisions of a compiler back end.