Part IV · Overview — from language design to a running program
A programming language is two things at once: a design (what you can express and what the compiler guarantees) and an implementation (the machinery that turns source into behavior). Memory management sits at the seam between them — it is a semantic choice with runtime consequences.
The pipeline
source ──▶ lexer ──▶ parser ──▶ AST ──▶ semantic analysis / types ──▶ IR ──▶ codegen ──▶ machine code
│
▼
runtime (execution + MEMORY)The front-end (lexerparserAST — Koda's kparse) establishes what the program means. The back-end lowers it to machine code. The runtime carries what can't be resolved statically — dynamic dispatch, exceptions, concurrency, and memory reclamation.
Where memory management sits
Two questions decide a language's whole performance and safety character:
- Who frees memory? — the programmer (manual), the compiler (static: ownership, regions),
or the runtime (dynamic: garbage collection, reference counting)?
- When? — deterministically (at a known program point) or eventually (whenever the
collector runs)?
These are not implementation footnotes; they shape the language itself (Rust's borrow checker exists to answer them at compile time; Koka's effect system enables Perceus reuse). For a language that must be fast (compete with zero-GC systems languages) and ergonomic, this is the central runtime decision — which is why the next chapter, Memory Management, is the seed of this compendium.