Skip to main content
2023 C (C99)

clox

Single-pass bytecode compiler and stack-based VM in pure C with Pratt parsing

clox screenshot

Overview

clox is a bytecode compiler and stack-based virtual machine for the Lox programming language, implemented in pure C. The system compiles source text in a single pass directly to a compact bytecode representation using a Pratt parser for operator precedence, then executes the bytecode on a register-free stack machine with a tagged-union value representation. The implementation covers trie-based keyword scanning, run-length encoded line information, constant pool with automatic promotion from 8-bit to 24-bit operands, and ~900 lines across 10 modules.

Architecture

clox architecture

The compiler emits bytecode directly during parsing with no AST intermediate, enabled by the Pratt parser which handles operator precedence through a table lookup rather than grammar encoding. A static VM instance avoids pointer indirection on every stack operation. A single Chunk struct owns the instruction stream, constant pool, and source position data, keeping related data co-located.

Code Highlights

Pratt Parser Core -- Entire Expression Engine in 12 Lines
static void parsePrecedence(Precedence precedence) {
    advance();
    ParseFn prefixRule = getRule(parser.previous.type)->prefix;
    if (prefixRule == NULL) {
        error("Expected expression.");
        return;
    }
    prefixRule();
    while (precedence <= getRule(parser.current.type)->precedence) {
        advance();
        ParseFn infixRule = getRule(parser.previous.type)->infix;
        infixRule();
    }
}

Highlights

  • Complete single-pass bytecode compiler in C -- from source text to executing VM -- with no AST intermediate representation
  • Pratt parser: the entire expression language parsed by a 12-line function plus a data table
  • In-place stack mutation, RLE-compressed debug info, automatic constant-operand size promotion, and unified allocation choke-point for future GC
  • Low-level C craftsmanship: manual tagged unions, macro-based generic containers, geometric growth allocators