Skip to main content
2024 Mojo

Mojo Crafting Interpreters

Bytecode VM with mark-and-sweep GC in Mojo using compile-time parametric structs

Mojo Crafting Interpreters screenshot

Overview

A bytecode virtual machine interpreter for the Lox programming language implemented entirely in Mojo -- Modular's systems programming language combining Python's ergonomics with C-level performance. The implementation follows the clox path: single-pass Pratt-parser compiler emitting bytecode for a stack-based VM with mark-and-sweep garbage collection, string interning, function calls via call frames, and native function FFI. Demonstrates how Mojo's ownership model, compile-time parametric types, InlineArray stack allocation, and UnsafePointer primitives replace C's raw pointer arithmetic while preserving performance.

Architecture

Mojo Crafting Interpreters architecture

The VM is parameterized at compile time with a Config value struct containing stack size, frames max, and debug flags -- monomorphized so debug code is dead-code-eliminated in production builds. Both the value stack and call frames use InlineArray (stack-allocated, no heap indirection). Object hierarchy uses pointer casting with a common Obj header (type tag, GC next pointer, marked flag), mirroring C's struct-prefix inheritance with Mojo's typed bitcast.

Code Highlights

Compile-Time Parametric VM Instantiation
struct VM[config: Config]:
  var frames: InlineArray[CallFrame, config.framesMax]
  var framesCount: Int
  var stack: InlineArray[Value, config.stackMax]
  var stackTop: UnsafePointer[Value]
  var globals: Hashmap[StrObjHashmapKey, Value]
  var strings: InternedStringsMap
  # GC
  var bytesAllocated: UInt
  var nextGC: UInt
  var objects: UnsafePointer[Obj]
  var grayStack: DynamicArray[UnsafePointer[Obj]]

Highlights

  • Complete bytecode VM with mark-and-sweep GC in Mojo -- one of very few public garbage-collected language runtimes in Modular's systems language
  • Compile-time parametric VM architecture: InlineArray stack allocation, monomorphized dispatch loops, zero-cost debug instrumentation via Config struct
  • Tri-color mark-and-sweep GC with weak-reference awareness for interned strings and GC-safe allocation sequences
  • Custom data structures from scratch: generic DynamicArray with move semantics, open-addressing Hashmap with tombstone deletion, RLE line info