Part IV · Overview — from language design to a running program

draft

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:

  1. Who frees memory? — the programmer (manual), the compiler (static: ownership, regions),

    or the runtime (dynamic: garbage collection, reference counting)?

  2. 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.