A year ago I built a programming language. This year it crossed the line that separates a toy from a real compiler: it started compiling itself.
(That GIF is the real thing — machin compiling its own compiler, then that binary reproducing its own source byte-for-byte.)
That sentence sounds like a party trick. It isn't. It's one of the oldest and hardest proofs in systems engineering — and reaching it, with AI as my pair, is the clearest evidence I can offer of how I actually build software.
First, the backstory
machin is a language I designed for a specific user: the AI agent writing the code, not the human reading it. Zero type annotations, one canonical declaration per line, every design choice measured in tokens — then compiled straight through C to a single native binary. Script-like to write, C-class to run. (I wrote about why in an earlier post.)
For a year it grew the way real tools grow — by being used. Web servers, database drivers, a WebSocket client, crypto, even games. But a language is only as trustworthy as its compiler, and machin's compiler was written in Go. So I asked the question every language eventually has to answer:
Could machin compile itself?
What "compiles itself" actually means
Every serious compiler faces a rite of passage called the bootstrap. You rewrite the compiler in its own language, and then you use the original to compile the new one. If the language is real — expressive enough, correct enough, fast enough — the new compiler works. If it isn't, you find out fast.
The gold standard is the fixpoint:
- The original compiler builds the self-hosted one.
- That self-hosted compiler compiles its own source into a fresh native binary.
- That fresh binary compiles the same source again — and the output is byte-for-byte identical.
When those bytes match, you have proof that isn't a matter of opinion. The compiler has reproduced itself exactly. It stands on its own.
Machin now does this. The whole pipeline — lexer, parser, type checker, and C code generator, about 4,000 lines — is written in machin, and it emits the same machine code as the original compiler down to the byte.
How it was actually built (this is the part that matters)
I don't ship "it works on my machine." I ship proof. So every single stage was built against a byte-diff oracle: the original compiler and the new one were run on the same input and their output compared, character for character, across the entire ecosystem of real programs I'd already written. A stage wasn't "done" until that diff was empty — not on a test case, but on every program in the corpus.
That discipline paid for itself immediately. Building the compiler in its own language stress-tested the language harder than a year of app-building had, and it flushed out three genuine bugs in the original compiler that had been hiding in plain sight — a string-comparison that compared memory addresses instead of contents, a quadratic slowdown in string handling, an escaping edge case in code generation. Each was found because the self-hosted compiler and the reference disagreed by a byte, and I refused to wave it away.
Then the honest numbers. The self-hosted compiler doesn't just work — on the full parse-typecheck-codegen of its own source, it runs at about 0.9× the original's speed. Slightly faster than the compiler that built it. (It didn't start there — the first version was 7× slower, and closing that gap meant finding the real bottleneck instead of the obvious-looking one. It was string building, not the "slow lookups" everyone assumes.)
Why I'm telling you this
Because this is what I mean when I say I build with AI.
Not "I prompted a chatbot and shipped whatever came out." The opposite. AI was the engine, but the engineering — the oracles, the byte-level verification, the refusal to accept a passing test over a passing proof, the honesty about what's fast and what isn't — that's the part that makes the output trustworthy. AI without that rigor produces plausible code. AI with it produces a compiler that compiles itself, byte-for-byte, and you can go check the bytes.
That combination — senior engineering judgment as the guardrail, AI as the multiplier — is exactly what I bring to the systems I build for clients at Intrane. Most teams get one or the other: rigor without speed, or speed without rigor. The interesting work lives where they meet.
A language that compiles itself is a hard, verifiable, slightly obsessive proof that they can meet. If that's the kind of engineer you want on your hardest problem, let's talk.
machin is open source (MIT) — the self-hosting compiler lives in selfhost/, and you can reproduce the fixpoint yourself.

Top comments (0)