After building my first set of compilers for the excellent Nand to Tetris course, I wanted to learn more. Looking around the internet for books about compilers led me to another excellent resource: Robert Nystrom's Crafting Interpreters. What an excellent book!
Building a Tree Walk Interpreter
Crafting Interpreters is broken up into two parts. Part One is about programming languages in general, learning about what a grammar is in the context of programming languages, Abstract Syntax Trees, and more. Part one uses Java to build the classic tree-walk interpreter. Tree walk meaning it scans the source code, tokenizes each word into the grammar (statements, expressions, numbers, strings, etc.), and builds a tree from the source. The tree is then walked and executed.
At the time I was looking for ways to ramp up my experience with Rust, so I decided to translate each section of the book from Java into Rust.
From Java to Rust
Java is an easy language to understand. It's totally straightforward to read and very flexible for the dev. Rust is not an OOP language and has a completely different shape to it. This was a surprisingly demanding exercise especially without the aid of an LLM. As I worked my way through the project, LLMs became more advanced and I started using them to check my work and give me translation pointers. Many object-oriented patterns just do not translate well to Rust at all. So identifying what to do and what is good idiomatic Rust can be challenging. In some instances patterns from OOP can be forced into Rust to resemble the original pattern, but the results are fairly non-idiomatic and sometimes wasteful (low-performing) translations.
One example of this is the Visitor Pattern. It's a pattern that Crafting Interpreters uses in Java to create an exhaustive pattern to execute the various different operations like evaluate, resolve, print tree, etc. that are identified during scan and parse. The visitor pattern is a somewhat boilerplate-heavy pattern that makes sense in Java, but in Rust it's better to use what's built into the language: powerful pattern matching statements.
Try it
Use the runner below to execute Lox code through the backend endpoint.
Run Rust Lox on the server:
Highlights
Tokenization and parsing for a custom language grammar.
AST evaluation with scoped environments.
REPL support, including multiline mode for larger snippets.
Test programs for control flow, classes, assignment, and function behavior.
Why this belongs in the portfolio
This is strong systems-level work: parser design, runtime semantics, and careful ownership across interpreter components. It showcases language implementation skills, not just app UI development.