History
From Note G to WebAssembly
Two centuries of turning text into running programs: the first interpreters and compilers, the theory of grammars and automata, optimisers, virtual machines and JITs, and the browser as a compilation target. Filter by chapter to follow one thread.
1843 – 1951
Before compilers
Programs are written as numbers, or wired by hand. Then they start living in memory, and the first interpreters appear.
-
1843
Note G
Ada Lovelace
In her notes on Babbage's Analytical Engine, Lovelace writes out step by step how the machine would compute Bernoulli numbers, often called the first published program.
Read chapter 00 · Execution models → -
1945
The stored-program computer
John von Neumann
The First Draft of a Report on the EDVAC describes a machine whose program lives in memory alongside its data. Programs become data that other programs can write.
Read chapter 06 · The runtime → -
1949
Short Code
John Mauchly, William Schmitt
Programmers write arithmetic expressions in a code that an interpreter carries out, at about fifty times the cost of machine code.
Read chapter 00 · Execution models → -
1951
Regular events and finite automata
Stephen Kleene
Studying nerve nets, Kleene shows that regular expressions describe exactly what finite automata recognise: the theory behind every lexer.
Read chapter 01 · Lexical analysis →
1952 – 1959
The first compilers
Translating formulas into machine code automatically, and convincing programmers that the result can be fast.
-
1952
Autocode
Alick Glennie
For the Manchester Mark 1, often considered the first compiled programming language.
Read chapter 00 · Execution models → -
1952
The A-0 system
Grace Hopper
Hopper's team at Remington Rand builds a system that assembles programs from a library of routines, and starts calling such tools “compilers”.
Read chapter 00 · Execution models → -
1956
Three models for the description of language
Noam Chomsky
Chomsky classifies grammars by their power. Context-free grammars, one level above regular ones, become the standard way of describing programming languages.
Read chapter 02 · Syntax analysis → -
1957
FORTRAN
John Backus and his team at IBM
The first FORTRAN compiler produces code nearly as fast as an expert's, and proves that high-level languages can be practical.
Read chapter 05 · Optimisation → -
1958
Lisp and the first eval
John McCarthy, Steve Russell
McCarthy defines Lisp through a function that evaluates Lisp; Russell implements it on the IBM 704, creating the first Lisp interpreter.
Read chapter 00 · Execution models →
1960 – 1979
Theory meets practice
Grammars, automata and types give compilers a mathematical foundation; Lex and Yacc make them easier to build.
-
1960
The ALGOL 60 report and BNF
John Backus, Peter Naur et al.
The syntax of a programming language is defined precisely, for the first time, with a grammar notation: Backus–Naur form.
Read chapter 02 · Syntax analysis → -
1962
A compiler that compiles itself
Timothy Hart, Michael Levin
The Lisp 1.5 compiler is written in Lisp: the first self-hosting compiler.
Read chapter 00 · Execution models → -
1965
LR parsing
Donald Knuth
Knuth defines the grammars that can be parsed bottom-up, deterministically, reading left to right: the LR(k) family.
Read chapter 02 · Syntax analysis → -
1968
From regular expressions to automata
Ken Thompson
Thompson's construction turns a regular expression into an automaton mechanically; it powers grep, editors and lexer generators.
Read chapter 01 · Lexical analysis → -
1969
Principal types
Roger Hindley
Every expression of combinatory logic has a most general type that can be computed: the seed of type inference.
Read chapter 03 · Semantic analysis → -
1970
Control flow analysis
Frances Allen
Basic blocks and control-flow graphs: the framework every optimiser still uses. With John Cocke she publishes the catalogue of optimising transformations a year later.
Read chapter 05 · Optimisation → -
1972
C
Dennis Ritchie
A language close enough to the machine to write an operating system in. Unix is rewritten in C in 1973, and C becomes the portable assembler of the industry.
Read chapter 00 · Execution models → -
1973
Top-down operator precedence
Vaughan Pratt
Binding powers instead of grammar levels: the expression-parsing method that Wahoo uses.
Read chapter 02 · Syntax analysis → -
1973
A unified approach to optimisation
Gary Kildall
Data-flow analyses become instances of one iterative framework over the control-flow graph.
Read chapter 05 · Optimisation → -
1975
Lex and Yacc
Mike Lesk, Eric Schmidt, Stephen Johnson
At Bell Labs, generators that write a lexer from regular expressions and an LALR parser from a grammar. Their descendants Flex and Bison are still used.
Read chapter 01 · Lexical analysis → -
1977
UCSD Pascal and p-code
Kenneth Bowles and students
Pascal compiled to bytecode for a virtual machine runs on many microcomputers: “write once, run anywhere” twenty years before Java.
Read chapter 06 · The runtime → -
1978
A theory of type polymorphism
Robin Milner
Algorithm W infers the most general types of a whole ML program without annotations. Haskell, OCaml and F# inherit it.
Read chapter 03 · Semantic analysis →
1980 – 1994
Optimising and portable
Register allocation, SSA and free compilers; dynamic languages learn to compile themselves on the fly.
-
1981
Register allocation by graph colouring
Gregory Chaitin et al.
Values that are alive at the same time cannot share a register: allocating registers becomes colouring a graph.
Read chapter 04 · Code generation → -
1984
Reflections on Trusting Trust
Ken Thompson
A compiler can hide a back door in every program it compiles, including itself, leaving no trace in any source code.
Read chapter 00 · Execution models → -
1984
Dynamic translation of Smalltalk
Peter Deutsch, Allan Schiffman
Bytecode is translated to machine code when a method is first called, and cached: an ancestor of just-in-time compilation.
Read chapter 06 · The runtime → -
1987
GCC 1.0
Richard Stallman
A free, retargetable optimising C compiler. It grows into the GNU Compiler Collection.
Read chapter 04 · Code generation → -
1988
Static single assignment
Barry Rosen, Mark Wegman, Kenneth Zadeck
Every variable assigned exactly once: the intermediate form that nearly every optimising compiler uses today.
Read chapter 05 · Optimisation → -
1991
Polymorphic inline caches
Urs Hölzle, Craig Chambers, David Ungar
The Self project learns to optimise dynamic code from the types it actually sees: the techniques behind HotSpot and V8.
Read chapter 06 · The runtime → -
1991
Python 0.9
Guido van Rossum
A dynamic language compiled to bytecode for a virtual machine, which becomes one of the most used languages in the world.
Read chapter 00 · Execution models →
1995 – 2009
Virtual machines and JITs
Bytecode becomes mainstream with Java, and just-in-time compilers make dynamic languages fast.
-
1995
Java and JavaScript
James Gosling; Brendan Eich
Java ships portable bytecode for the JVM; JavaScript, written in ten days, is interpreted inside Netscape Navigator.
Read chapter 00 · Execution models → -
1999
HotSpot
Sun Microsystems (from the Self and Strongtalk team)
A JVM that interprets first and compiles only the hot methods, with optimisations based on what the program actually does.
Read chapter 06 · The runtime → -
2003
LLVM 1.0
Chris Lattner, Vikram Adve
A reusable optimiser and back end around a well-defined SSA IR. Clang, Rust, Swift and Zig are built on it.
Read chapter 04 · Code generation → -
2004
GCC drops its generated C++ parser
GCC developers
GCC 3.4 replaces its Bison grammar for C++ with a hand-written recursive-descent parser; the C front end follows in 2006.
Read chapter 02 · Syntax analysis → -
2008
V8
Lars Bak and the Chrome team
JavaScript compiled straight to machine code makes web applications fast enough to replace desktop software.
Read chapter 06 · The runtime →
2010 – today
The browser as a target
Compilers that compile themselves, languages that compile to JavaScript, and a portable bytecode for the web.
-
2011
Rust compiles itself
Graydon Hoare and the Rust team
The Rust compiler, first written in OCaml, is rewritten in Rust and bootstraps itself. Rust 1.0 follows in 2015.
Read chapter 00 · Execution models → -
2012
TypeScript
Anders Hejlsberg (Microsoft)
A typed language that compiles to JavaScript: the type checker catches errors, then the types are erased.
Read chapter 00 · Execution models → -
2013
asm.js
Luke Wagner, Alon Zakai, David Herman (Mozilla)
A strict subset of JavaScript that engines can compile ahead of time shows that C and C++ can run in the browser at near-native speed.
Read chapter 06 · The runtime → -
2015
Compiler errors for humans
Evan Czaplicki
Elm redesigns its error messages as plain explanations with suggestions; Rust and others follow, and Wahoo's messages copy the recipe.
Read chapter 03 · Semantic analysis → -
2015
Go compiles itself
The Go team
Go 1.5 removes the last C from its compiler and runtime, translated to Go mostly by a program.
Read chapter 00 · Execution models → -
2017
WebAssembly ships
Mozilla, Google, Microsoft, Apple
A portable, validated bytecode, designed together by all four browser makers, runs in Firefox, Chrome, Edge and Safari.
Read chapter 06 · The runtime → -
2018
Tree-sitter
Max Brunsfeld (GitHub)
An incremental parser generator that re-parses code as you type and gives editors accurate syntax trees.
Read chapter 02 · Syntax analysis → -
2019
WebAssembly becomes a W3C Recommendation
W3C WebAssembly Working Group
The fourth language of the web, after HTML, CSS and JavaScript.
Read chapter 06 · The runtime → -
2024
A JIT for CPython
Brandt Bucher and the CPython team
Python 3.13 includes an experimental copy-and-patch JIT compiler, disabled by default: the reference Python starts compiling to machine code.
Read chapter 00 · Execution models → -
2026
Wahoo
This site
A compiler from the Mushroom Kingdom to WebAssembly, written in Rust, running in your browser. Try it in the playground.