This repository hosts a minimal interpreter and CLI for the proposed Lx language core described in SPEC.md. It includes:
- A Peggy-based parser (
grammar/lx.pegjs) that recognises modules, types, functions, and tests. - A TypeScript AST, type checker, and interpreter covering the v0.1 core.
- A CLI (
lx) withrun,test, andcheckcommands. - A worked example under
examples/median.lx.
npm install
npm run build
node dist/cli.js test examples/median.lxAfter npm install, the prepare script builds the project automatically and generates the parser. To try the CLI without reinstalling, run npm run build.
lx run [--format=json|text] [--input=source|ast] <file> <module.fn> [args...]
lx test [--format=json|text] [--input=source|ast] <file>
lx check [--format=json|text] [--input=source|ast] <file>
lx format <file.lx>
lx explain [--format=json|text] [--input=source|ast] <file> <module.fn> [args...]
lx patch-body <file.lx> <module.fn> <bodySnippet.lx>
lx apply-refactor <file.lx> <refactorName>
Arguments to lx run and lx explain are parsed as JSON and converted to interpreter values (numbers, strings, booleans, and arrays).
Structured output: Use --format=json to get machine-readable JSON output (errors, logs, results) suitable for LLM consumption. Default is --format=text for human-readable output.
AST input: Use --input=ast to treat the file as JSON that already matches the Lx AST schema. This lets LLMs emit structured modules that can be executed directly without going through the parser. See examples/ast_demo.json for a complete sample.
Deterministic actor scheduling: Pass --scheduler=deterministic to keep actor messages queued instead of processed immediately. Use the new Concurrent.step() (process one message, returns Bool) and Concurrent.flush() (drain the queue, returns Int) builtins—callers must declare the [Concurrent] effect. This makes mailbox delivery reproducible and testable; see examples/actor_scheduler.lx.
Holes: Use hole("label") inside an expression to mark unfinished code. The typechecker reports any remaining holes (with their labels and locations) so you can commit partial work safely.
Patch-based edits: Use lx patch-body to replace a function body by referencing the module + symbol name. Only the targeted function changes, which keeps diffs small for LLM workflows.
LLM-friendly tools:
lx format- Produces deterministic, canonical formatting from ASTlx explain- Shows step-by-step execution trace with function calls, returns, and variable bindingslx patch-body- Replaces a single function body without touching surrounding codelx apply-refactor- Applies structured refactor declarations (rename type,rename fn) across all affected modules
Examples:
# Run with JSON output
lx run --format=json examples/structured_output.lx examples.structured_output.compute 5
# Check for type errors with structured output
lx check --format=json examples/error_example.lx
# Format code canonically
lx format examples/median.lx
# Explain execution with trace
lx explain examples/median.lx median '[2,4,6,8]'
# Get execution trace as JSON
lx explain --format=json examples/median.lx median '[2,4,6,8]'
# Run a JSON AST module
lx test --input=ast examples/ast_demo.json
lx run --input=ast examples/ast_demo.json app.ast_demo.add 2 3
# Patch a function body in-place
lx patch-body examples/median.lx app.stats.median examples/patches/median_body.lxsnip
lx check examples/median.lx
# Deterministic actor scheduling
lx test --scheduler=deterministic examples/actor_scheduler.lxThe interpreter now exposes parallel_map, parallel_fold, and parallel_for_each builtins. They require pure (effect-free) callback functions, and the current implementation executes them deterministically (sequentially) so tests stay reproducible. See examples/parallel.lx for end-to-end usage.
- SPEC.md - Full language specification
- WHY.md - Why you (or your AI) should care about Lx
- THOUGHTS.md - Design philosophy and LLM-first principles
- STATUS.md - Source of Truth for implementation status and roadmap
- Update
grammar/lx.pegjsand regen the parser withnpm run gen:parser. - The generated parser (
src/parser.generated.js) is ignored by git; rebuild to regenerate it. - The TypeScript sources live in
src/and compile todist/vianpm run build.
Unit tests are currently expressed in Lx itself via test blocks. Running npm test rebuilds the compiler and executes the sample tests.