Skip to content

cd ..

R-Lox

A tree-walking interpreter for Lox, written in Rust — my first Rust project, and how I learned the language.

status
through closures & resolution · classes next
stack
Rust
source
github.com/RazerBlade6/rlox-lang (opens in a new tab)
[asciinema recording — coming soon]
rlox REPL — recursion, closures, native functions

The problem

I wanted to understand how programming languages actually work, end to end, and I wanted to learn Rust properly. Robert Nystrom’s Crafting Interpreters (opens in a new tab) builds its first interpreter in Java. Porting it to Rust, without any coding assistance, forced me to understand every design choice instead of copying it — because half of them don’t translate.

Architecture

 source ──► scanner ──► tokens ──► parser ──► AST ──► resolver ──► interpreter
                                   (recursive        (static        (tree-walk,
                                    descent)          scopes)        environments)

About 2,700 lines across a scanner, a recursive-descent parser, a resolver pass for static scope, and a tree-walking interpreter with a REPL. It supports variables, control flow, functions, recursion, closures, and native functions (clock, input, parse, clear) — everything in Part II of the book up to classes.

Key decisions

A resolver pass, not dynamic lookup. Closures that capture variables need to bind to the right scope even when a later declaration shadows the name. Resolving every variable’s depth statically, before interpretation, fixes that class of bug and makes lookups cheaper.

Fight the borrow checker honestly. The Java original shares mutable environments freely. In Rust, environments that closures can capture and mutate need shared ownership with interior mutability, and choosing where to pay that cost shaped the whole interpreter.

Rewrite the scanner once I knew better. The first scanner allocated constantly. A later refactor rebuilt it around lifetimes and borrowed slices of the source, which is the version that’s in the repo now.

What I’d do differently

NORMAL