clay is a small open-source programming language playground written in C. It is designed as a self-paced learning apprenticeship for developers studying the fundamentals of language implementation through two complementary tracks:
- a tree-walk interpreter, inspired by the metalinguistic abstraction approach in Structure and Interpretation of Computer Programs JavaScript Edition and Part II of Crafting Interpreters
- a bytecode virtual machine, inspired by the machine-model perspective in SICP JS and Part III of Crafting Interpreters
All the fundamental atoms of a minimal programming language are now in place.
The repository now contains:
- the project contract, a minimal build, and bootstrap tests
- a tree-walk interpreter consisting of a handwritten scanner, a recursive descent parser, an explicit AST, a working tree-walk evaluator, user-defined functions with closures, and classes with inheritance
- a bytecode virtual machine supporting chunks, recursive disassembly, an execution loop, arithmetic and comparisons, printing, global variables, block-scoped locals, jump-based control flow, short-circuit logical operators, function calls with explicit call frames, nested closures with VM upvalues, and classes with fields, methods, inheritance,
this, andsuper.
- teach core programming language implementation ideas in small understandable steps
- keep the codebase simple, testable, and contributor-friendly
- prefer handwritten components over generators in the early stages
- document design decisions, trade-offs, and acceptance criteria as the project grows
- make each milestone understandable enough that a new contributor or AI agent can continue it
- building a production-ready optimizing compiler first
- merging every Lox and Scheme feature into the earliest milestones
- clever abstractions that hide the basic interpreter machinery
- adding a package manager, module system, or JIT in the foundation phase
- doing performance work before behavior is correct and well-tested
clay starts with a Lox/JS-like surface syntax and a simple C implementation. Its early focus is a readable tree-walk interpreter with lexical scope, dynamic values, first-class functions, and a small object model.
As the project matures, it will grow toward:
- the full educational core of Lox
- a bytecode execution engine
- carefully selected Scheme and SICP ideas when they clarify evaluator or VM design
When the reference books diverge, the project chooses the simpler design that best teaches the current concept and records the reason in docs/architecture.md.
- The GNU C Reference Manual
- GNU Coding Standards
- Crafting Interpreters
- Structure and Interpretation of Computer Programs JavaScript Edition
Prerequisites:
- a C17-capable compiler
makeclangfor analysisclang-tidyfor lintingclang-formatfor formatting- LLDB for debugging is optional
Common development commands:
make formatmake checkmake testmake lintmake format-check
make run
Run a script with ./build/clay examples/functions.clay or ./build/clay examples/classes.clay.
The repository also includes compile_flags.txt so clangd-based editors can resolve project headers correctly, and .clang-tidy to define the baseline lint checks.
.github/workflows/continuous integration workflow definitionsdocs/project contract and technical directionsrc/implementation codetests/unit and integration testsexamples/runnable sample programs once the interpreter exists
- update the relevant docs when the language changes
- add or update tests with every feature
- keep modules small and explicit
- prefer readable diagnostics over clever internals
- keep the public build entry points small:
make format,make check, andmake run
- Post-Milestone 7 planning, including small cleanup passes that keep ownership-sensitive helpers shared and explicit before broader VM memory-management and language-growth priorities
See docs/spec.md, docs/architecture.md, and docs/roadmap.md for the current working contract.
This project uses the MIT License. See LICENSE for details.