Skip to content
Select theme

Write an interpreter

What you end up with: a small scripting language that runs real programs — variables, functions, closures, control flow, arrays — with error messages that point at the line that broke.

A birch session: arithmetic, a function, a multi-line input, and runtime and parse errors that keep their line and column

Writing an interpreter gives you a vocabulary that transfers everywhere: parsing is how you read config files and query languages, ASTs are how you transform code, and the evaluator is where Rust’s enums and pattern matching are at their most beautiful.

  • A scanner and a recursive-descent parser with proper error recovery
  • An AST as Rust enums, with a printer for debugging
  • A tree-walking evaluator with environments and scoping
  • Functions, closures, recursion and a call stack with a depth limit
  • Arrays, strings and a small standard library
  • Error reporting with line numbers and a caret pointing at the offending token
  • A REPL, plus an ahead-of-time resolver pass for variable lookup

Structs, enums, and pattern matching is required reading — this track is essentially an extended exercise in match. Add Smart pointers and memory before the closures article, where Rc becomes unavoidable.