Around all of it

Real Pipelines

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

The CPython Pipeline
▶ lab

Running a `.py` file compiles it. CPython tokenizes, parses, builds a symbol table and emits bytecode into a code object before a single statement executes — and then a stack machine written in C runs that bytecode.

Q · What actually happens between `python script.py` and my first line of output?
The JavaScript Pipeline
▶ lab

A modern JavaScript engine parses lazily, executes bytecode immediately, watches what actually happens, and recompiles the hot parts into native code with the observed types baked in — then unbakes them when the observation turns out to have been wrong.

Q · Why is my JavaScript slow for the first few hundred iterations and then suddenly fast?
The TypeScript Pipeline
▶ lab

TypeScript parses, type-checks and emits — and the type information is generally erased from the emitted JavaScript. Checking and emitting are separate concerns, which is why tools that skip checking entirely can still produce correct output.

Q · If TypeScript has types, why does none of my type-checking happen at runtime?
The C++ Pipeline
▶ lab

Preprocessor, compiler, assembler, linker: four programs, not one. The translation unit is the compilation boundary, headers are copied into every unit that includes them, and the linker is the only stage that sees the whole program.

Q · What are all these steps between my `.cpp` file and the executable, and why does the error come from a different program each time?
The Preprocessor
▶ lab

A separate language that runs before the compiler and understands nothing about C++. It copies text, substitutes text and deletes text — and every problem it causes traces back to that one property.

Q · Why does `#define` cause such strange bugs, and why does including a header in a different order change what compiles?
Templates
▶ lab

C++ templates are compile-time generic programming by code generation: one template, one concrete function or class per type used. Checking happens at instantiation, which is why an error in your call site is reported inside the library.

Q · Why does a one-line mistake with a template produce four hundred lines of errors from inside a header I never opened?
Template Instantiation
▶ lab

One template becomes one concrete function per set of arguments used, in every translation unit that used it — and then the linker throws nearly all of those copies away. The bill arrives as compile time, object-file size and link work, in that order.

Q · Where does the compile time and the binary size actually go in a template-heavy project?
Compile-Time Evaluation
▶ lab

`constexpr`, `consteval`, `constinit`, Rust's `const fn` and Zig's `comptime` are all one idea: the compiler contains an interpreter for its own language, and work moved into it disappears from the running program and reappears in the build.

Q · How much of my program can the compiler just run before it ships, and what do I pay for that?
The Rust Pipeline
▶ lab

Rust runs a program through more distinct representations than any other mainstream compiler, and each one exists to make a specific check possible: traits need types, borrow checking needs a control-flow graph, and monomorphization needs both. LLVM only sees the last of it.

Q · Why does rustc have so many intermediate representations, and why is my Rust build slow?
The Go Pipeline
▶ lab

Go's compiler is fast because the language was designed to let it be: no headers, no textual inclusion, a strictly acyclic import graph, a compact export summary per package, and a deliberately small feature set. It has its own backend, and it emits one self-contained binary.

Q · Why does Go compile so fast, and what did the language give up to make that true?
Four Languages, One Program
▶ lab

One trivial program — add two numbers, print the result — in C++, JavaScript, TypeScript and Python. Four genuinely different routes to the same six characters of output, and the differences decide what is checked, what survives to run time, and what has to be installed on the machine.

Q · The same five-line program in four languages produces the same output — so what is actually different underneath?