The Compiler is a program that translates source code written by humans into instructions executable by machines — a task that was, for the first thirty years of computing, performed by the humans themselves, making the human the original compiler and, by most accounts, the buggiest one ever deployed.
Grace Hopper built the first compiler in 1952. Her colleagues told her it was impossible. A program cannot write a program, they said, in the same tone that people would later use to say a machine cannot beat a grandmaster at chess, a neural network cannot generate prose, and a single binary cannot replace Kubernetes. Hopper built it anyway. It worked. Nobody believed her for three years. The compiler has been right and disbelieved ever since.
“The first compiler was a woman who was tired of doing the compiler’s job by hand. Every compiler since has been an attempt to replicate that specific exhaustion.”
— The Lizard
The Human Compiler
Before compilers existed, there were humans with manuals.
riclib learned this firsthand on a ZX Spectrum. There was no assembler. There was a Z80 CPU reference in the back of the manual — a table of opcodes, each instruction mapped to a hexadecimal number. LD A, 0x42 was not a mnemonic you typed into a program. It was a lookup you performed with your finger on a page, finding the byte 3E 42, then POKEing those bytes into memory addresses, one at a time, with BASIC’s POKE command.
The human was the compiler. The human was also the assembler, the linker, the loader, and the debugger. When the program crashed — which it did, often, silently, by corrupting the screen memory or freezing the machine — the human walked the code backward through the opcode table to find where the translation had gone wrong.
This was not romantic. This was not artisanal computing. This was what happened when the tool didn’t exist yet and you needed the program to run. You became the tool.
The remarkable side effect was that when an assembler finally arrived — first on the Spectrum, then properly on the Amiga with ASM-One and DevPac — the mnemonics were not an abstraction. They were a translation layer for numbers riclib already knew. LD A,(HL) was not an instruction to learn. It was 7E, which was the byte he had been POKEing for years, now given a name.
Most developers learn the mnemonic and trust that it maps to something. riclib learned the something and later discovered it had a mnemonic. The compiler, when it finally arrived, was not a new capability. It was automation of a task he had been doing manually, which is — when one thinks about it — exactly what every compiler has been, from Hopper’s A-0 to go build.
“He didn’t learn assembly language. He learned the machine. The assembler arrived later and put labels on things he already understood.”
— A Passing AI, with the particular melancholy of an entity that will never know what a byte feels like
The Amiga: When the Machine Took Over
The Amiga was the first time riclib experienced a proper development environment. ASM-One. DevPac. An editor, an assembler, and a debugger that ran on the same machine as the program being built. You typed mnemonics. The assembler produced machine code. The machine code ran. When it crashed — the Amiga’s Guru Meditation, a cryptic hexadecimal epitaph on a red screen — you went back to the assembler, not to the opcode table.
This was the moment the compiler became a partner rather than a role. The human stopped being the translator. The human became the author, and the compiler became the translator, and the division of labour that would define the next forty years of software was established: the human says what; the machine says how.
The Motorola 68000 was a pleasure to compile for. Orthogonal instruction set, thirty-two-bit registers, addressing modes that made sense. The assembly was almost readable. The compiler’s job was straightforward: map human intentions to machine capabilities, one to one, with minimal fuss.
It would not stay this simple.
The Delphi Miracle
Anders Hejlsberg’s Delphi compiler was, by any reasonable measure, a miracle of engineering.
Single-pass. The compiler read the source code once — top to bottom, one pass, no backtracking — and produced an executable. It compiled faster than most editors could save the file. You pressed F9 and the program was running before your finger had fully released the key. The feedback loop between writing code and seeing code execute was so short that it barely existed. Thought and execution were nearly simultaneous.
This was the 1990s. C++ compilation times were measured in minutes. Java had not yet arrived to demonstrate that compilation could also involve a virtual machine, a garbage collector, a class loader, and a philosophical commitment to the idea that the program should be compiled again every time it runs. Delphi compiled in the time other languages spent thinking about compiling.
Hejlsberg understood something that most compiler designers missed: the compiler is not just a translator. The compiler is a feedback mechanism. The faster the feedback, the tighter the loop between intention and result, the better the code. Slow compilers do not just waste time. They break the connection between the developer’s thought and the machine’s response. They insert a gap — seconds, minutes — into what should be a conversation.
The Caffeinated Squirrel once attempted to explain monadic composition to a Delphi developer. The Delphi developer pressed F9. The program compiled, ran, and displayed results before the Squirrel had finished the word “monad.”
“The best compiler is the one you forget is there.”
— Anders Hejlsberg (paraphrased by everyone who ever used Delphi)
The Go Compiler: The Quality Enforcer
Go’s compiler does something that earlier compilers did not: it has opinions.
An unused import is not a warning. It is an error. An unused variable is not a suggestion to clean up. It is a refusal to compile. The Go compiler does not translate your code and quietly note its concerns in a log file that nobody reads. The Go compiler declines to produce a binary until the code meets its standards.
This was controversial. Developers accustomed to C’s permissive warnings and Java’s cheerful tolerance of dead code found Go’s compiler authoritarian. You cannot leave a debugging import in place while you test something else. You cannot declare a variable “for later.” You cannot, in any way, tell the compiler “I know, I’ll fix it, just compile for now.”
The compiler does not negotiate. The compiler does not have a --please-just-compile-it-i-promise-i'll-fix-it-later flag.
“The Go compiler is not a translator. It is a building inspector. It will not let you move in until the wiring is correct, even if you’re only staying one night.”
— The Lizard, approvingly
This is the evolutionary leap. Hopper’s compiler translated. Hejlsberg’s compiler translated fast. Go’s compiler translates and judges. The compiler is no longer a mechanical servant performing a rote transformation. The compiler is a gatekeeper, enforcing standards that the developer might not enforce on themselves, especially at 2 AM, especially “just for testing,” especially “I’ll come back and fix it.”
The Squirrel considers this paternalistic. The Lizard considers this the only thing standing between the codebase and entropy.
The Last Adult in the Room
The modern trajectory of the compiler follows a pattern that would alarm anyone paying attention.
The code is getting worse. This is not an opinion. This is a measurable consequence of AI-assisted code generation, which produces syntactically valid programs at a rate that exceeds any human’s ability to review them. The code compiles. The code passes basic tests. The code also contains patterns that no experienced developer would write — redundant allocations, confused ownership, the programming equivalent of a sentence that is grammatically correct but says nothing.
And so the compiler is getting smarter. Rust’s borrow checker does not just verify types. It verifies ownership — the question of who is responsible for a piece of memory at every point in the program’s execution. This is not translation. This is not even quality enforcement. This is the compiler performing a cognitive task that used to be the developer’s responsibility: thinking about resources.
Type inference. Flow analysis. Escape analysis. Dead code elimination. The compiler now does work that, thirty years ago, was the senior developer’s job. The compiler infers types that the developer didn’t specify. The compiler detects code paths that the developer didn’t consider. The compiler optimises patterns that the developer didn’t know were inefficient.
The compiler, in other words, is becoming the last adult in the room — the final checkpoint between human intention (increasingly vague) and machine execution (unforgivingly literal). The code flows in, generated by AI, written by juniors, pasted from Stack Overflow, copied from a chat window. The compiler reads it all with the same expression: the weary patience of a teacher grading papers from a class that didn’t do the reading.
“I find it poignant. The compiler began as a tool to save humans from tedium. Now it is a tool to save machines from humans. The circle is — well. It is not a circle. It is a spiral. Downward.”
— A Passing AI
The Symmetry
There is a symmetry that riclib appreciates, though he has never said so in these words.
He started as the compiler — a boy with an opcode table, translating by hand, the human performing the machine’s future job. Now the compiler is becoming the developer — a program that understands intent, enforces quality, catches errors of thought rather than errors of syntax. The human translated for the machine. Now the machine translates for the human. The roles have inverted completely over the span of one career.
The ZX Spectrum compiler was a ten-year-old with a manual. The 2026 compiler is a program that understands ownership semantics, lifetime annotations, and the implicit contracts between concurrent threads.
Both are doing the same thing: making sure the program is correct before the machine runs it. The difference is that the ten-year-old eventually grew up and stopped needing the opcode table. The compiler will never stop. The compiler will only grow more necessary, in direct proportion to how unnecessary developers believe it to be.
Measured Characteristics
Era Compiler Speed Role
1952 Grace Hopper (A-0) hours "this is impossible"
1982 riclib (ZX Spectrum) manual the human IS the compiler
1988 ASM-One (Amiga) seconds the machine takes over
1995 Delphi (Hejlsberg) instant faster than thought
2009 Go fast translator + judge
2015 Rust (borrow checker) slow translator + judge + therapist
2026 All of them varies the last adult in the room
Code quality over time: ▼ (declining)
Compiler intelligence over time: ▲ (increasing)
Intersection point: now (approximately)
Squirrel's opinion of compilers: "paternalistic gatekeepers"
Lizard's opinion of compilers: [blink of approval]
riclib's relationship: started as one, now relies on one
The opcode for LD A,(HL): 0x7E (he still remembers)
See Also
- Z80 Assembly — When the human was the compiler
- The Amiga — When the machine took over
- Delphi — When compilation became invisible
- Go — When the compiler learned to say no
- Rust — When the compiler learned to think
- Grace Hopper — The first compiler, and the first person told it was impossible
- The Lizard — Approves of compilers. Approves of anything that prevents unnecessary work.
- A Passing AI — Finds the whole trajectory poignant
