The moment I wrote my first program, I knew I wanted to build a programming language. But how are languages made? How did these carefully arranged magic spells become instructions a machine could execute?
For a long time, compiler construction was my main technical obsession — and it still is. I devoured anything I could find about compilers, intermediate representations, parsers, and LLVM. I worked through the Kaleidoscope tutorials and spent hours refining the syntax of my soon-to-be language. At the start of my third year of college, that obsession led me to an internship with Intel's Compilers and Languages team. I was suddenly being paid to work on real programming languages used by real developers.
Eight years later, I know much more about compilers, CPUs, GPUs, and the systems around them. I also have more questions.
Why are production compilers so complicated? Which parts of that complexity are inherent to the problem, and which are consequences of accumulated design decisions? Is the architecture we use today the only reasonable one? Do I really understand how compilers work well enough to derive one from the machine upward?
Puzzled by those questions, and deeply inspired by John Regehr's Future Directions for Optimizing Compilers, I decided to build a compiler from scratch. Not by pretending that the last fifty years of compiler research never happened, and not by reproducing an existing compiler feature for feature. Instead, I want to treat familiar design choices as hypotheses rather than axioms. I want to begin with the semantics of the machine, derive the requirements of each layer, and justify every abstraction as it appears.






