Compiler (source code)

= Compiler
{wiki}

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.<LLVM 20.1.0 documentation/3. Kaleidoscope: Code generation to LLVM IR>[LLVM 20.1.0 documentation; Implementing a language with LLVM, chapter 3, sections 3.1 and 3.5: AST to LLVM IR and the initial driver that prints IR]{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.