Compilers & Programming Languages

How does source code become executable behavior, and how do language and compiler design choices affect correctness, performance, safety, tooling and developer experience?

The question this domain answers

What actually happens to my code between the editor and the CPU — and which of it was a choice?

A compiler is not a translation step. It is a sequence of representations, each one built because the previous form could not answer the next question — and every transformation between them is legal only under a precondition someone had to establish. This domain is about those representations, those preconditions, and the design decisions that put them there.

The pipeline every lesson sits on
SourceLexingTokensParsingASTSemanticsTypedIROptimizeCodegenMachine codeLinkExecute

Read it as a list of questions rather than a list of steps. Tokens exist because characters cannot say which of them belong together. An AST exists because a token list cannot say what applies to what. IR exists because a tree cannot say in what order things happen. Every arrow is a question the previous box could not answer — and something the new box has thrown away.

Three sentences the whole domain hangs on

If a lesson here ever seems to contradict one of these, the lesson is wrong.

1

A compiler is a sequence of representations, not a translation step. Every phase exists because the previous representation could not answer the next question.

2

An optimization is legal only if it preserves the language's defined observable behavior — so what a compiler may do is decided by language semantics, not by cleverness.

3

"Compiled" and "interpreted" are not properties of languages. They are implementation strategies, and real systems combine them.

This domain is not Runtime Internals, and not Computer Architecture

Both neighbours are close enough to be worth stating the line.

Runtime Internals owns

Object representation, garbage collection, virtual-machine execution, runtime dispatch. What happens while the program runs.

We own

Everything up to the handover, plus the compiler-side half of every runtime mechanism — the metadata emitted, the guard inserted, the state map that makes deoptimization possible.

Computer Architecture owns

The ISA and the microarchitecture. We own the compiler's model of that machine, and the places where the model is deliberately wrong.

Almost nothing here is true of every compiler. Every lesson labels its claims — spec when the standard requires it, implementation when it is one compiler at one version, typical when it is a habit rather than a guarantee, target when it is really about the machine, and simplified when our own model has left something out. A reader who memorises an unlabelled fact will carry it to a language where it is false.

Flagship experiences

The parts of this domain that are not reading.

Learning modules

36 modules, grouped by where they sit on the pipeline.

284 lessons →

Frontend

Source to a checked, structured program.

Grammar & Syntax8

Writing down what a valid program looks like: productions, derivations, EBNF, and the ambiguity that precedence and associativity exist to resolve.

Lexical Analysis8

Characters to tokens, why regular languages are enough for this job, and the hazards — maximal munch, keywords that are also identifiers, numbers that run into letters.

Parsing9

Tokens to structure. Recursive descent and Pratt parsing by hand, LL and LR as families, and what a parser generator buys and costs.

Diagnostics & Error Recovery6

A compiler that stops at the first error is a bad tool. Spans, recovery, synchronization, and diagnostics that name what was expected instead of saying "syntax error".

The Abstract Syntax Tree6

The representation every later phase is written against: node design, traversal, the visitor as the standard shape of a pass, and why the AST outlives the parser.

Semantic Analysis8

Names, scopes and everything the grammar could not express. Symbol tables, shadowing, resolution, and the annotated tree the type checker needs.

Type Systems12

What the language can prove before it runs. Checking, typing rules, environments, inference, unification, polymorphism, subtyping and variance.

Type System Design7

Composing types and representing absence: unions, intersections, algebraic data types, exhaustive pattern matching, nullability and gradual typing.

Types at the Implementation Boundary7

What survives to runtime and what proves memory safety: erasure versus reification, monomorphization, ownership, lifetimes and effects.

Middle-end

A representation you can analyse, and the transformations that are legal on it.

Around all of it

Real pipelines, correctness, tooling, builds — and building your own.

Real Pipelines11

Python, JavaScript, TypeScript, C++, Rust and Go: four genuinely different routes from source to behavior, compared without pretending they are the same.

Compiler Infrastructure9

LLVM as reusable middle-end and code generator rather than "a compiler", GCC as the other one, and WebAssembly as a portable sandboxed target.

Compiler Correctness & Security8

The one program whose bugs are everyone else’s bugs: miscompilation, differential testing, fuzzing, translation validation and formal verification.

Static Analysis & Language Tooling10

The frontend is the IDE. Abstract interpretation, interprocedural analysis, linters, formatters, concrete syntax trees and the language server that serves them all.

Debug Information6

Mapping optimized machine code back to what you wrote — line tables, variable locations, source maps, and why a variable reads as "optimized out".

Compilation at Scale9

Compilation units, modules, interface files and the dependency analysis that keeps a rebuild proportional to the change rather than to the codebase.

Whole-Program & Feedback-Directed Optimization6

Seeing across module boundaries with LTO, and measuring before optimizing with PGO — including what an unrepresentative profile does to the result.

Compilers for Agent Systems5

A model-generated plan is a program in an untrusted language. Parse it, type it, validate it and check its permissions before any of it executes.

AtlasLang9

Build the whole thing, one stage at a time, from `print(1 + 2)` to a typed language with a bytecode VM, an SSA optimizer and a language server.

Reference

For when you already know roughly what you are looking for.