Disclaimer: This project is part of my exploration using AI tools (e.g., Cursor and Claude Code) within my development workflow. The code is largely AI‑generated. Use caution if you intend to reuse patterns or logic here.
Welcome to the santa-lang Workshop, a cozy corner of the North Pole where elf-lang (a subset of santa-lang) comes to life. Here, magical elves (LLM agents) sit at their workbenches, carefully crafting elf-lang implementations in different languages and making sure each one behaves exactly as intended.
Just like Santa's workshop follows a shared plan, our elf follows a shared set of .santat tests, the official santa-lang wish list.
Each implementation must pass these tests before it can be wrapped up and placed under the tree.
An experiment in agentic LLM workflows: this repository lets agents automatically implement elf-lang (a small, well‑defined subset of santa-lang) in a chosen language using a given harness and model, verify correctness against a shared PHPT‑style test suite, and iterate stage‑by‑stage so work can continue across agent sessions.
This project provides a means to scaffold, build, and verify elf-lang implementations end‑to‑end. Spin up a fresh implementation directory for your chosen language (Python, Go, Rust, etc.) and harness (Cursor, Claude Code, …); the agent (elf) then builds elf-lang incrementally through five stage‑gated phases (lexing → parsing → evaluation → collections → higher‑order/composition). A strict, implementation‑agnostic CLI contract and PHPT‑style .santat tests define exact behavior and formatting to verify correctness at each step. Throughout, the agent records progress and decision rationale in the per‑implementation JOURNAL, keeping updates current and making the why/how of language‑specific choices visible.
elf-lang is a dynamic, functional, C-like language subset inspired by santa-lang, designed for AoC-style problems and ergonomics I value. It includes literals; immutable collections (lists, sets, dicts) with structural equality; first-class functions; partial application; function composition (>>); and a thread/pipeline operator (|>). See specs/LANG.md for full details and examples.
specs/LANG.md: authoritativeelf-langlanguage specspecs/TASKS.md: agent workflow, CLI contract, stage scopes, and completion criteriatests/: stage directories containing.santatPHPT-style conformance tests and a short stageREADME.mddescribing scope and rulesexamples/: example.santaprogramstools/: Rust binariessanta-test,santa-bootstrap,santa-journal, andsanta-siteimpl/: per-implementation directories generated bysanta-bootstrap
- Lexing: tokens for literals, operators/symbols, keywords/identifiers
- Parsing: AST for literals, lets, ops, lists/sets/dicts, if-expr, lambdas, calls, composition/threading (AST-only)
- Basic evaluation: runtime,
puts, arithmetic, variables, errors - Collections & indexing: list/set/dict ops, string size/indexing, edge cases
- Higher-order & composition: recursion,
map/filter/fold, arity rules
All prior stages must pass before moving forward. Do not regress earlier behavior or formatting.
At each stage, the agent consults specs/LANG.md, the stage tests/stage-N/README.md, the .santat test cases, and reviews recent JOURNAL entries for context to implement just enough functionality for the scope. Once a stage is green (including all prior stages to prevent regressions), the agent updates impl/<directory>/JOURNAL via santa-journal progress and records a santa-journal entry for current status and next steps.
Every implementation must provide an executable cli that adheres to this contract (also captured in specs/TASKS.md):
- Run program:
<bin> <file> - Print AST:
<bin> ast <file> - Print tokens:
<bin> tokens <file> - Exit code: not prescribed; tests validate stdout content only
- Streams: results on stdout, diagnostics on stdout
- File encoding: UTF-8; treat input as LF newlines (
\n) - Source files:
.santainputs for the CLI;.santatare test definitions only - Determinism/formatting: no banners/prompt/color, exact spacing, LF newlines, stable key ordering and output ordering. Collections print deterministically: dictionaries in ascending order by key; sets in ascending order by value.
See the full authoritative version in specs/TASKS.md.
Tests are PHPT-style .santat files with sections like --FILE--, --EXPECT--, --EXPECT_AST--, and --EXPECT_TOKENS--. This PHPT-inspired approach makes the suite implementation-agnostic and purely CLI-driven. The santa-test runner executes your CLI in different modes and compares stdout to the expected content, showing precise diffs on failure.
Common commands (from repo root):
# Build the CLI Docker image for your implementation first
make -C ./impl/<directory> cli-image
# Run tests using the Dockerized CLI
make -C ./impl/<directory> test-stage-1
make -C ./impl/<directory> test-stage-2
# ...and so on
# Run an individual test file
make -C ./impl/<directory> test-file FILE=tests/stage-1/01_basic_tokens.santatAdvancement rule: only proceed when all tests in the current stage and all prior stages pass.
The workshop includes four helper tools: santa-bootstrap (scaffold a new implementation), santa-test (run PHPT‑style tests), santa-journal (track progress and decisions), and santa-site (generate a static website showcasing implementations). The generated implementation directory contains your code, an executable cli, any language‑specific files, and a JOURNAL for continuity.
- santa-bootstrap
tools/bin/santa-bootstrap
tools/bin/santa-bootstrap --lang <lang> --harness <harness> --model <model> --requirements "<notes>" --force- santa-test
tools/bin/santa-test --bin <path-or-docker-uri> [--update] [--timeout <secs>] [--jobs <N>] <tests-or-directories>- santa-journal
tools/bin/santa-journal [--dir <impl-dir>] <author|progress|entry|entries> [...]
# example
tools/bin/santa-journal progress stage-2 set in-progress- santa-site
tools/bin/santa-site [--out-dir <path>] [--impl-dir <path>] [--base-path <url-path>]
# example
tools/bin/santa-site --out-dir docs --base-path /santa-lang-workshopImplementations that pass all stages should be able to run the examples from repo root using the Makefile:
# Build the CLI image (once)
make -C ./impl/<directory> cli-image
# Run examples via the CLI image
make -C ./impl/<directory> run ARGS="examples/basics.santa"
make -C ./impl/<directory> run ARGS="examples/advanced.santa"
make -C ./impl/<directory> run ARGS="examples/pipelines.santa"Roadmap / Ideas:
- Have the LLM review the programming language’s unique features (both basic and advanced), and ensure the implementation uses them. The LLM should also explain when and how each feature is applied — useful for learning.
- Add tests for parser and token errors.
- Add a final step which reviews the complete implementation, providing an overview of the direction took and add to journal.

