What is a Compiler?
Start here. One program translated ahead of time, one interpreted line by line, and why Java does both.
Skip to the animationA compiler is a program that reads a program in one language and produces an equivalent program in another, reporting any errors it can prove exist — and the defining choice is that it does all of this before the program runs.
Translator, and error reporter
Source code is written to be read by people: it has names, structure and types. A CPU decodes fixed-width binary instructions and has no concept of a variable or a loop. Something has to close that gap, and the only question is when.
A compiler closes it ahead of time. Two obligations come with the word *equivalent*: the output must mean the same thing as the input, and any error the compiler can prove exists must be reported rather than emitted. Diagnosis is as much the job as translation.
Compiler versus interpreter
An interpreter takes the source and the input together and produces the output directly, executing each construct as it reaches it. There is no target program at all.
| Compiler | Interpreter | |
|---|---|---|
| When translation happens | once, before running | every time, while running |
| Produces | a target program | the result directly |
| A loop body is analysed | once | once per iteration |
| Execution speed | fast | typically 10–100× slower |
| Error reporting | all at once, before running | one at a time, at the point of failure |
| Errors point at | sometimes an address | the source line |
| Portability | rebuild per target | run anywhere the interpreter runs |
| Edit–run cycle | build step first | immediate |
Everything the compiler gains, it gains by leaving. The translator is not present at run time, which is why the code is fast and also why a crash gives you less to work with.
Real systems do both
- 1
javaccompiles Java ahead of time into bytecode — machine code for a CPU that does not exist. The expensive analysis happens once, and the result is portable. - 2The JVM interprets that bytecode, so the same
.classfile runs on any machine with a JVM. - 3A JIT compiler watches which methods are hot and compiles those to real machine code while the program runs, using profile information a static compiler never has.
Python, C# and JavaScript all sit somewhere on this spectrum. "Compiled language" and "interpreted language" are, strictly, category errors — compilation and interpretation are properties of an *implementation*, not of a language.
The rest of the toolchain is not the compiler
- Assembler
- Translates assembly mnemonics to machine code, roughly one-to-one. A compiler's output is often assembly *text*, which this turns into binary.
- Linker
- Combines object files and libraries, resolving names like
printfto real addresses.undefined referencecomes from here and is never a syntax error. - Loader
- Part of the OS. Brings the executable into memory and starts it — the only one of these that runs every time you launch the program.
The definition is wider than machine code
Nothing in the definition mentions hardware. Any faithful, error-reporting translation from one language to another is a compiler: C to assembly, TypeScript to JavaScript, SQL to a query plan, a shader to GPU code, LaTeX to PDF.
This is why the subject is worth learning once. The same phases — lexing, parsing, checking, intermediate code, optimisation, generation — appear in all of them.
Advantages and disadvantages
Advantages
- Translation cost is paid once, so run-time speed is as good as the target allows.
- The optimiser can spend seconds on code that will run for years.
- Errors across the whole program are found before it is ever executed.
- The shipped binary needs no translator present.
Disadvantages
- A build step sits between editing and seeing the result.
- Runtime errors report addresses rather than source, without extra debug information.
- A binary is built for one target, so portability means rebuilding.
- Dynamic features like
evalcannot be resolved ahead of time at all.
Watch it work
Check yourself
question 1 / 4
One question at a time. Pick an answer to see why it is right or wrong, then move on — there is no score to keep and nothing is saved.