Lessons / personal library
Software engineering

Compilers and interpreters

Follow source through tokens, syntax, binding, types, intermediate code, optimization, execution, and linking. Inspect a bounded working expression compiler.

Prerequisite: Familiarity with variables, conditionals, and functions. No compiler or assembly experience required. Thirteen lessons follow programs through tokens, syntax trees, name resolution, types, intermediate representations, execution, optimization, native-code concerns, runtimes, and linking. Nine interactive views and 26 illustrated exercises use a bounded working expression compiler plus separate scope, control-flow, and storage models.

Lessons

  1. 1

    Follow a program through its representations

    A compiler translates representations; an interpreter executes a representation according to its rules.

  2. 2

    Turn characters into tokens

    A lexer recognizes spelling boundaries and records positions without deciding the full syntax.

  3. 3

    Build a syntax tree from a grammar

    Precedence and associativity determine which operations become children of others.

  4. 4

    Resolve names to declarations

    A name’s spelling is not its identity. Scope determines which declaration a use refers to.

  5. 5

    Check programs against type rules

    Types constrain allowed operations; checking and inference do not execute the program.

  6. 6

    Compare tree evaluation with a bytecode machine

    The tree and the instruction stream can implement the same language while storing intermediate values differently.

  7. 7

    Choose an intermediate representation for the question

    Syntax trees, stack code, and three-address code expose different information.

  8. 8

    Trace control flow through basic blocks

    Branches determine which instructions execute and which definitions can reach later uses.

  9. 9

    Optimize only when the semantics permit it

    An optimization is a justified change in representation, not merely an algebraic-looking rewrite.

  10. 10

    Map values to instructions and storage

    Instruction selection and register allocation must satisfy the target machine, not just preserve an abstract expression tree.

  11. 11

    Connect generated code to runtime services

    Calls, closures, objects, and memory management need representations that outlive a single arithmetic instruction.

  12. 12

    Connect compiled pieces and load a program

    Object files, symbols, and relocations bridge separate compilation and executable images.

  13. 13

    Investigate a compiler or runtime claim

    Use a minimal reproducer, explicit semantics, intermediate evidence, and controlled measurements.