Vibe Coding a Lox Compiler, Part 0: Background
I have been working with Claude Code for maybe a year, in various ways. Often, I would use it to understand compiler error messages, since I’ve been teaching myself Rust for that time and more, and as you might know, the Rust borrow checker can give one fits. I would also purposefully limit my use of Claude when programming Rust because I want to learn Rust, and you learn by doing; reading code doesn’t have the same impact. In some cases I worked on projects where I would write the backend (whether Java or Rust) and have Claude build me the frontend, since I am barely literate with frontend stuff and whatever literacy I did have with JavaScript, Typescript, React, Angular or whatever I have been quickly dumping from core memory. ...
Vibe Coding a Lox Compiler, Part 1: Introduction & Compilers 101
Written with AI This post — and all the code behind it — was built with Claude Code. Read Part 0 for the full story of how this AI-assisted project came together. If you have ever been curious about how programming languages actually work — how text you type into an editor ends up running as a program — this series is for you. We are going to build a complete compiler for a language called Lox, from scratch, in Rust. By the end you will have seen every layer of a real language implementation: the tokenizer, the parser, a tree-walk interpreter, a bytecode virtual machine, and an LLVM-powered native code compiler. ...
Vibe Coding a Lox Compiler, Part 2: Tokenization
Written with AI This post — and all the code behind it — was built with Claude Code. Read Part 0 for the full story of how this AI-assisted project came together. In Part 1 we introduced the Lox language and took a high-level tour of the full compiler pipeline — from raw source text all the way to native code. Now it’s time to go deep on the first phase of that pipeline: tokenization. This is where a plain string of characters becomes something a parser can actually reason about. ...
Vibe Coding a Lox Compiler, Part 3: Parsing & the Abstract Syntax Tree
Written with AI This post — and all the code behind it — was built with Claude Code. Read Part 0 for the full story of how this AI-assisted project came together. Previously in this series, Part 1 introduced the overall pipeline — scanner, parser, AST, and the multiple backends (tree-walk interpreter, bytecode VM, and LLVM codegen) — and Part 2 covered tokenization: how winnow turns raw source text into a flat stream of typed tokens. Now we have that token stream in hand. The parser’s job is to take that flat sequence and build a tree that captures the actual structure and meaning of the program. ...
Vibe Coding a Lox Compiler, Part 4: The Tree-Walk Interpreter
Written with AI This post — and all the code behind it — was built with Claude Code. Read Part 0 for the full story of how this AI-assisted project came together. Previously in this series we built the tokenizer (Part 2) and the recursive descent parser (Part 3), turning raw source text into a typed AST. Part 1 gave the bird’s-eye view of the whole pipeline. At this point, vibe-lox can take a .lox file, scan it into tokens, and parse those tokens into a tree of strongly-typed Rust structs — every node stamped with a unique ExprId for later use. Now we need to actually run the thing. This post covers the first execution backend: the tree-walk interpreter. ...
Vibe Coding a Lox Compiler, Part 5: The Bytecode VM
Written with AI This post — and all the code behind it — was built with Claude Code. Read Part 0 for the full story of how this AI-assisted project came together. This is part 5 of a series on building a Lox compiler in Rust. Parts 1 through 4 covered the language and compiler pipeline (Part 1), the tokenizer (Part 2), the parser and AST (Part 3), and the tree-walk interpreter (Part 4). ...
Vibe Coding a Lox Compiler, Part 6: LLVM IR & Native Compilation
Written with AI This post — and all the code behind it — was built with Claude Code. Read Part 0 for the full story of how this AI-assisted project came together. Previously in this series, Part 1 introduced the project and the Lox language. Part 2 built the tokenizer using winnow, Part 3 wrote the recursive descent parser, Part 4 covered the tree-walk interpreter, and Part 5 added a bytecode virtual machine as a second execution backend. At this point, vibe-lox has two ways to run a Lox program: walk the AST directly, or compile to bytecode and run it in a stack VM. This post covers the most ambitious backend yet: compiling Lox all the way to native machine code via LLVM. ...
Vibe Coding a Lox Compiler, Part 7: The REPL
Written with AI This post — and all the code behind it — was built with Claude Code. Read Part 0 for the full story of how this AI-assisted project came together. Previously in this series: Part 1 — Introduction, Part 2 — Tokenization, Part 3 — Parsing, Part 4 — The Tree-Walk Interpreter, Part 5 — The Bytecode VM, and Part 6 — LLVM Compilation. This is the final post in the series. Over six posts we have built the complete compiler pipeline: a winnow-based scanner, a recursive-descent parser, an AST, a tree-walk interpreter, a bytecode VM with its own compiler, and an LLVM IR code generator. What we have not talked about yet is the part that most users will touch first — typing something at a prompt and seeing what happens. This post is about the REPL. ...
Level Up Your Rust Testing With testcontainers and rstest
Writing software tests is hard. Whether you’re writing unit tests or integration tests or system tests, each presents unique challenges that generally only get harder as you go from unit to integration to system testing. To see how I differentiate these types of tests, see my post here. Writing unit tests in Rust is relatively straightforward, with built in support via #[test] annotations and test configuration support. The cargo new command even generates an initial test module and test for you: ...
Using CodeSnap or nvim-silicon For Screenshots in Neovim
In a previous blog I discussed using nvim-silicon to capture a screenshot of my Neovim buffer. At the time it felt like a good solution, and it is still a viable and usable tool. Recently I have come across another solution for creating a screenshot within Neovim. It is called CodeSnap. In this blog I will briefly show how to use CodeSnap and discuss how it compares to Silicon. CodeSnap I cover only `CodeSnap` v1.0 here. Install CodeSnap uses a Rust libary. As of v1.0 CodeSnap has a pre-built library for some architectures. For others, you need to build from source so you will need a Rust environment. The pre-built libary is available for ...