Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
193 commits
Select commit Hold shift + click to select a range
e692dc3
✨ Add ndc_vm crate skeleton for bytecode VM
timfennis Mar 2, 2026
9927b52
📚 Chapter 14 + 15
timfennis Mar 2, 2026
5d5377d
🚧 WIP bytecode VM compiler and chunk
timfennis Mar 3, 2026
4abee12
New Value type for the VM, and constant compilation
timfennis Mar 3, 2026
4df1fa1
WIP
timfennis Mar 3, 2026
9165783
Fix warnings
timfennis Mar 3, 2026
ef9dcf1
Basic conditions implemented
timfennis Mar 3, 2026
044efc3
Make function definition expression contain a signature instead of ex…
timfennis Mar 4, 2026
e162ea3
Add tests for the compiler output
timfennis Mar 4, 2026
77fc8c4
Add disassembling functionality
timfennis Mar 4, 2026
2760d43
🌍 Add GetGlobal opcode and wire up Call instruction in the VM
timfennis Mar 4, 2026
6f878d9
🔧 Bridge stdlib globals into VM and fix locals to use the stack
timfennis Mar 4, 2026
ed4c9df
🔀 Add runtime dynamic dispatch for overloaded functions in the VM
timfennis Mar 4, 2026
beb98c3
Fix compilation of return opcodes
timfennis Mar 5, 2026
b11186e
✅ Fix Statement/Block compilation and add compiler tests
timfennis Mar 5, 2026
4fc75bd
♻️ Add Value::unit() constructor and use it in the compiler
timfennis Mar 5, 2026
87b3178
♻️ Extract dispatch_call to remove duplicated Call logic
timfennis Mar 5, 2026
2968da1
✅ Run tests against both tree-walk and VM interpreter
timfennis Mar 5, 2026
e6c1571
🔌 Wire VM print output to the interpreter's captured buffer
timfennis Mar 5, 2026
1648d06
🏗️ Make declarations pure statements and fix VM local variable stack …
timfennis Mar 5, 2026
95219b6
🔍 Add vm-trace feature for source-annotated instruction tracing
timfennis Mar 5, 2026
5624eeb
💥 Add todo!() panics for unimplemented compiler branches
timfennis Mar 5, 2026
b5c90b0
🧹 Move vm-trace ip capture inside cfg block, suppress unused param wa…
timfennis Mar 5, 2026
3b046b8
Benchmark tool + tuple and list support
timfennis Mar 5, 2026
8513531
⚡ Pre-allocate stack and avoid to_vec() on native calls
timfennis Mar 5, 2026
1338322
Upvalue WIP + cargo fmt
timfennis Mar 6, 2026
ab5d717
🔒 Implement closure capture and upvalue resolution in the VM
timfennis Mar 6, 2026
bbb0e6d
📦 Make VM lists reference-counted and sync mutations through the bridge
timfennis Mar 6, 2026
1f83e69
🏗️ Pre-allocate locals at function entry to fix stack corruption
timfennis Mar 6, 2026
6bf53a9
Make [] indexing a function call (#94)
timfennis Mar 8, 2026
6f87860
Cargo fmt
timfennis Mar 8, 2026
5c84d6b
🔄 Add FunctionBody::Opaque to round-trip VM functions through the int…
timfennis Mar 8, 2026
7dd5765
WIP
timfennis Mar 9, 2026
875ae19
WIP on upvalue hoisting in the analyzer
timfennis Mar 9, 2026
43e361c
🚧 Analyser-side upvalue hoisting (steps 1-4 of PLAN_upvalue_mutation.md)
timfennis Mar 10, 2026
e8c03af
✅ Fix upvalue mutation and iteration scope transparency
timfennis Mar 11, 2026
009bd0c
♻️ Split compiler tests into separate crate
timfennis Mar 11, 2026
699f576
✅ Implement analyser-side upvalue hoisting in the VM (steps 5 & 6)
timfennis Mar 11, 2026
b96cbb1
Remove completed plan
timfennis Mar 11, 2026
5b0ea12
🔍 Replace unreachable todo in FunctionDeclaration compiler
timfennis Mar 11, 2026
5dfd055
Add nested break/continue test cases
timfennis Mar 13, 2026
402d4f9
Refactor VM compiler for readability
timfennis Mar 13, 2026
01d4331
Implement break/continue in VM compiler and add vm-ready markers
timfennis Mar 13, 2026
ca7b55e
Simplify compile_while by returning loop_start from new_loop_context
timfennis Mar 13, 2026
ca47d6f
Implement op-assignment for identifier lvalues
timfennis Mar 13, 2026
695a4d1
✅ Fix VM return-outside-function error and function equality
timfennis Mar 13, 2026
3ef705d
✅ Implement index assignment via stdlib []= function call
timfennis Mar 14, 2026
f9beaa5
✅ Mark string index assignment tests as vm-ready
timfennis Mar 14, 2026
eb1203f
✅ Mark 3 more passing VM tests as vm-ready
timfennis Mar 14, 2026
157d2e9
✅ Implement for-loops, ranges, and iterators in the bytecode VM
timfennis Mar 14, 2026
1fc6ddd
✅ Fix compiler test + mark 14 more tests as vm-ready
timfennis Mar 14, 2026
d342380
♻️ Refactor iteration_local_slot helper in analyser
timfennis Mar 14, 2026
124191b
✅ Implement op-assign index (x[i] += v) in the bytecode VM
timfennis Mar 14, 2026
b0d0e22
✅ Implement tuple destructuring (Unpack opcode) in the bytecode VM
timfennis Mar 15, 2026
0b76322
✅ Enable VM closure callbacks from stdlib HOFs (map, filter, fold, al…
timfennis Mar 15, 2026
6aa932e
✅ Mark 6 more tests as vm-ready
timfennis Mar 15, 2026
07d4741
🐛 Fix two regressions introduced by HOF callback commit
timfennis Mar 15, 2026
888c683
🐛 Fix sequence op-assignment error handling
timfennis Mar 15, 2026
5c82612
✅ Implement index assignment in destructuring (compile_lvalue)
timfennis Mar 15, 2026
354c36b
✅ Implement map literals in VM compiler
timfennis Mar 15, 2026
9769e55
✅ Add proper error handling for non-iterable values in VM
timfennis Mar 15, 2026
32db5aa
🔄 Narrow VM error spans for for-loop sequences
timfennis Mar 15, 2026
10dccc0
⬜ Narrow spans on synthetic VM opcodes
timfennis Mar 15, 2026
db62928
✅ Propagate stdlib errors from VM native functions
timfennis Mar 15, 2026
df0de85
✅ Implement destructuring and map iteration in VM for-loops
timfennis Mar 15, 2026
760f66c
🔧 Fix compiler warnings and mark 11 more tests vm-ready
timfennis Mar 15, 2026
f205c7e
✅ Support string destructuring in VM and improve unpack error messages
timfennis Mar 15, 2026
435e12b
✅ Add test for invalid string destructuring and unify unpack error me…
timfennis Mar 15, 2026
ec777c1
🔧 Refactor vm.rs for readability
timfennis Mar 15, 2026
7bd9609
✅ Type-check bool conditions in VM JumpIfFalse/JumpIfTrue
timfennis Mar 15, 2026
e001e37
✅ Mark 038_invalid_if_gaurd_in_comprehension as vm-ready
timfennis Mar 15, 2026
ba5112c
✅ Fix closure-over-loop-variable and mark 041/014 as vm-ready
timfennis Mar 15, 2026
386fafc
✅ Fix tuple range slicing in VM (042_unit_is_tuple)
timfennis Mar 15, 2026
b620387
✅ Fix Hash/PartialEq mismatch for VM-bridged function values (007/005)
timfennis Mar 15, 2026
2eca0c1
✅ Mark 009_slicing 003/004/006 as vm-ready
timfennis Mar 15, 2026
a209cc1
✅ Fix op-assign on map values; mark 007/018 as vm-ready
timfennis Mar 15, 2026
1460943
✅ Implement map/set comprehensions in VM; fix accumulator slot with d…
timfennis Mar 15, 2026
e9236d5
✅ Implement MinHeap, MaxHeap, Deque in VM; fix None identifier in com…
timfennis Mar 15, 2026
4a1424c
Fix int/float comparison tiebreaker in VM; add ordering edge-case tests
timfennis Mar 15, 2026
39fa055
✅ Cover cross-type numeric ordering gaps in VM OrdValue
timfennis Mar 16, 2026
c7f76d3
Expand CLAUDE.md with commands and architecture overview
timfennis Mar 16, 2026
3a301ef
Implement unbounded range (start..) in bytecode VM
timfennis Mar 16, 2026
59af23f
Mark slicing and deque indexing tests as vm-ready
timfennis Mar 16, 2026
8edfd15
Fix upvalue access in transparent iteration scopes
timfennis Mar 16, 2026
7fe03b4
✅ VM op-assign: use in-place path when resolved_assign_operation matc…
timfennis Mar 16, 2026
7b25f91
Implement memoization for pure fn in the bytecode VM
timfennis Mar 16, 2026
0f9e1fb
Implement vectorized tuple math in the bytecode VM
timfennis Mar 16, 2026
3508fcd
Fix unbalanced if as expression: always yields a value (unit when false)
timfennis Mar 16, 2026
cff502e
fix indentation in test
timfennis Mar 16, 2026
d74b10a
VM: return error instead of panicking when calling a non-function value
timfennis Mar 16, 2026
bbcbd17
Fix big_int_ranges: return error instead of panicking, improve message
timfennis Mar 16, 2026
d4021c4
Fix weird_iterator_cloning VM test; remove borrow_mut test
timfennis Mar 16, 2026
ba56695
Remove // vm-ready markers; all VM tests run by default
timfennis Mar 16, 2026
b86c3d7
Fix two VM bugs: open upvalues and destructive list unpack (#104)
timfennis Mar 16, 2026
234caec
Phase 0: update CLAUDE.md and remove stale // vm-ready comments
timfennis Mar 16, 2026
5b48049
Phase 1: add vm_native field to Function for bridge-free dispatch
timfennis Mar 16, 2026
8a26296
Migrate arithmetic operators to VM-native dispatch
timfennis Mar 16, 2026
5a10def
Migrate comparison and boolean operators to VM-native dispatch
timfennis Mar 16, 2026
db4796e
Add VM-native dispatch for trig/math functions; add trig test coverage
timfennis Mar 16, 2026
e53e0f8
export_module: auto-generate vm_native for simple-typed functions
timfennis Mar 16, 2026
1cb477d
Extend export_module macro: auto vm_native for &str, String, i64 types
timfennis Mar 16, 2026
3040f68
Inverted bridge: VmNative body for stdlib; migrate list/index/value/s…
timfennis Mar 17, 2026
84dd045
Refactor: Rc<Object> replaces Box<Object>; flatten inner Rc from muta…
timfennis Mar 17, 2026
110542f
Migrate deque/heap/map stdlib to VmNative; add VecDeque/BinaryHeap/Ha…
timfennis Mar 17, 2026
1929835
Migrate list ++/++=, is_some/is_none, max/min to VmNative
timfennis Mar 17, 2026
1225855
Fix VM slot collision in nested list/map comprehensions
timfennis Mar 17, 2026
ad22172
Change NativeFunction error type from String to VmError
timfennis Mar 17, 2026
d27455d
Fix sort() being a no-op in the tree-walk interpreter
timfennis Mar 17, 2026
3ab56f8
Migrate stdlib Sequence params to VM-native SeqValue; fix VM Int/Floa…
timfennis Mar 17, 2026
c930502
Optimize VM HOF dispatch with two-tier NativeFunc enum
timfennis Mar 17, 2026
9785365
Migrate cmp/math/regex stdlib to VM-native types; fix cross-type nume…
timfennis Mar 18, 2026
b927b56
Migrate rand/sequence/value stdlib to VM-native types; add VM RepeatI…
timfennis Mar 18, 2026
4f218b7
Migrate serde stdlib to VM-native types
timfennis Mar 18, 2026
27695c4
Fix -= operator display for sets and add test
timfennis Mar 18, 2026
2ce1193
Fix op-assign dynamic dispatch for maps, strings, and lists
timfennis Mar 18, 2026
1c868cb
Migrate string ++= to VM-native return type; add Value::from_string_rc
timfennis Mar 18, 2026
819bf49
Migrate hash_map stdlib to VM-native types; add MapValue type alias
timfennis Mar 18, 2026
b3b9f7e
add git info to CLAUDE.md
timfennis Mar 18, 2026
2d8c332
Migrate string.rs: replace ndc_interpreter::sequence::StringRepr import
timfennis Mar 18, 2026
91705b7
Add VM output support and wire print/dbg to VM-native path
timfennis Mar 18, 2026
ba0c2c7
Migrate list stdlib inner module to VM-native types
timfennis Mar 19, 2026
a7bebea
Replace ndc_interpreter::num/int with ndc_core in math stdlib
timfennis Mar 19, 2026
628fd54
Replace ndc_interpreter::num/compare with ndc_core in rand and sequence
timfennis Mar 19, 2026
15e2003
Remove tree-walk interpreter; make VM the only execution path
timfennis Mar 19, 2026
c382a56
Update bench.sh to reflect VM-only execution
timfennis Mar 19, 2026
c7cd03c
Add error type prefix to diagnostic messages
timfennis Mar 19, 2026
7e17604
Add persistent REPL VM with resume-from-halt support
timfennis Mar 19, 2026
a04ed14
Print REPL expression results; silence statements and unit
timfennis Mar 19, 2026
73fc805
Delete GenericFunction interpreter paths from stdlib
timfennis Mar 19, 2026
92f836e
Move StaticType from ndc_parser to ndc_core
timfennis Mar 19, 2026
4a7e526
Fix build after moving StaticType to ndc_core
timfennis Mar 19, 2026
4bf498e
Fix missing Value import in ndc_vm/src/value/function.rs
timfennis Mar 19, 2026
9579242
Move ndc_vm/src/value.rs to ndc_vm/src/value/mod.rs
timfennis Mar 19, 2026
9f41526
Apply formatting from cargo fmt
timfennis Mar 19, 2026
431084f
🔧 Adjust imports and add FunctionRegistry skeleton
timfennis Mar 19, 2026
5e5b059
Replace Environment-based function registry with FunctionRegistry<Rc<…
timfennis Mar 19, 2026
130f1aa
Fix docs command and improve function return type annotations
timfennis Mar 19, 2026
c885439
Add 10k recursion depth test
timfennis Mar 19, 2026
9a5c1a7
Fix pi_approx benchmark: move float conversion inside function
timfennis Mar 19, 2026
21b55f5
Rewrite docs with pretty output and --no-color flag, migrate to yansi
timfennis Mar 19, 2026
ce41492
Remove duplicate tree-walk test variants; update CLAUDE.md
timfennis Mar 19, 2026
faf9a19
Perf: add int/float fast paths in PartialOrd, use with_context in rand
timfennis Mar 19, 2026
38afbfc
Perf: cache StaticType on CompiledFunction, inline vectorized calls, …
timfennis Mar 19, 2026
55dd0c4
Perf: zero-alloc overload matching, skip upvalue materialization for …
timfennis Mar 19, 2026
0a1952b
Bench: increase fibonacci to fib(26), sieve to 200k
timfennis Mar 20, 2026
1e6d589
Refactor: remove tree-walk evaluator, Environment, and dead macro inf…
timfennis Mar 20, 2026
30eecfe
Refactor: remove vm_bridge, interpreter Value type, and all bridge mo…
timfennis Mar 20, 2026
2a75813
Cleanup: remove as_any from VmIterator, Vm::stub, stale bridge comments
timfennis Mar 20, 2026
7ce193e
Refactor: extract ndc_analyser crate, remove WithStdlib trait
timfennis Mar 20, 2026
b195dfb
Bump version to 0.3.0
timfennis Mar 20, 2026
bc1bd13
Refactor: simplify output, decouple ndc_lsp from ndc_stdlib
timfennis Mar 20, 2026
4347534
Add benchmarks, fix quicksort/sieve, update bench.sh for version comp…
timfennis Mar 20, 2026
55fb2d0
Fix: upvalue dispatch in overload sets, precise container static types
timfennis Mar 20, 2026
c3f0b9a
Perf: add Value::is_number, avoid O(n) static_type in hot path
timfennis Mar 20, 2026
3f8a9a2
Perf: borrow opcode by ref in dispatch loop, ~4-8% speedup
timfennis Mar 20, 2026
351ad5c
Fix: map default function called when key is missing
timfennis Mar 20, 2026
b739b4f
Perf: skip static_type() for Any params in overload dispatch (~6-8%)
timfennis Mar 20, 2026
8695538
Docs: document memoization key cost and upvalue pattern
timfennis Mar 20, 2026
f9f82a8
Fix: B1/B2/B3 — convert panics and overflows to VmErrors
timfennis Mar 20, 2026
05cffb7
Fix: B5 — delete materialize_upvalues_in_args
timfennis Mar 20, 2026
1d38459
Perf: P3/P4/P5 — close_upvalues single pass, vectorization deferred a…
timfennis Mar 20, 2026
39f213b
Fix: O(N) dynamic dispatch for container params in overload resolution
timfennis Mar 20, 2026
06def8b
Docs: fix manual spelling, grammar, and factual errors
timfennis Mar 20, 2026
6f5c018
Perf: P7 — MapIter clones keys only, borrows values on demand
timfennis Mar 20, 2026
e7d6c31
Feat: lazy combinations and take iterators
timfennis Mar 21, 2026
667b2ba
Refactor: eval() returns Value, re-export NativeFunction
timfennis Mar 21, 2026
8674302
Fix: B4 — UnboundedRangeIter overflow at i64::MAX
timfennis Mar 21, 2026
b76bea1
Fix: B6 — resolve_callee returns VmError instead of panicking
timfennis Mar 21, 2026
5017a9c
Fix: analyser rejects calling non-function types
timfennis Mar 21, 2026
26f0f33
Refactor: R5 — remove RefCell from VmCallable
timfennis Mar 21, 2026
05bac65
Refactor: M1, M2, RD1–RD4 from code review
timfennis Mar 21, 2026
f90dc38
Add documentation to all manually registered stdlib functions
timfennis Mar 21, 2026
d16a50f
Add docs to all undocumented stdlib functions, fix spelling, add docs…
timfennis Mar 21, 2026
e7586c0
Remove obsolete design documents
timfennis Mar 21, 2026
c289f3e
Refactor ndc_macros: rename match→types, add NdcType enum, remove ful…
timfennis Mar 21, 2026
3fadf31
Collect TODOs into TODO.md, remove from source, add CLAUDE.md rule
timfennis Mar 21, 2026
9838b67
Clean up ndc_vm: deduplicate code, cache unit value, use references i…
timfennis Mar 21, 2026
70b35ab
Add ndc_analyser code review notes
timfennis Mar 21, 2026
7478585
Deduplicate ndc_analyser: scope-walk helpers, fold_lub, merge lvalue …
timfennis Mar 21, 2026
ccdc179
Small cleanups in ndc_analyser: unreachable!, stale comments, docs
timfennis Mar 21, 2026
be2d57d
Merge triple scope walk into single-pass resolve_function_binding
timfennis Mar 21, 2026
0fa13f2
Fix function overload resolution across closure boundaries, add redef…
timfennis Mar 21, 2026
ed1344d
Pass actual types when resolving index operators [] and []=
timfennis Mar 21, 2026
a18aefc
Function calls skip non-callable bindings, fix return type inference
timfennis Mar 21, 2026
17005c4
Add StaticType::Never for diverging expressions, fix lub(Int, unit) =…
timfennis Mar 21, 2026
dea95fc
⚡ Skip close_upvalues when no open upvalues; use Vec::new() for empty…
timfennis Mar 21, 2026
349f326
📝 Improve README examples
timfennis Mar 21, 2026
faaace5
Convert accumulator_slot .expect() panics to CompileErrors
timfennis Mar 21, 2026
db792e4
Convert ListPush and MapInsert panics to VmErrors
timfennis Mar 21, 2026
adac20d
Embed git commit hash in --version output
timfennis Mar 21, 2026
a641c66
Add memory management page to manual
timfennis Mar 21, 2026
5361ec6
📎 clippy fixes
timfennis Mar 21, 2026
5b1cd6d
📎 Fix all clippy warnings, add &mut [T] macro support
timfennis Mar 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ rustflags = [
"-Wclippy::dbg_macro",
"-Wclippy::debug_assert_with_mut_call",
"-Wclippy::doc_markdown",
"-Wclippy::empty_enum",
"-Wclippy::empty_enums",
"-Wclippy::enum_glob_use",
"-Wclippy::exit",
"-Wclippy::expl_impl_clone_on_copy",
Expand Down Expand Up @@ -76,7 +76,7 @@ rustflags = [
"-Wtrivial-numeric-casts",
"-Wunused-crate-dependencies",
"-Wunused-qualifications",
"-Wclippy::as_conversions",
"-Aclippy::as_conversions",
"-Wclippy::as_pointer_underscore",
"-Wclippy::doc_include_without_cfg",
"-Wclippy::get_unwrap",
Expand Down
108 changes: 108 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Before commit
- Run `cargo fmt`
- Run `cargo clippy` and fix all warnings
- Ensure all tests pass (`cargo test`)
- Do not leave `TODO` comments in code — either fix the issue immediately or open a GitHub issue and record it in `TODO.md`

## Common Commands

```bash
# Build
cargo build

# Run all tests
cargo test

# Run a single test by name (substring match on the filename)
cargo test test_001_math_001_addition

# Run benchmarks
cargo bench -p benches

# Start REPL
cargo run --bin ndc

# Run a .ndc script
cargo run --bin ndc -- script.ndc

# Disassemble bytecode
cargo run --bin ndc -- disassemble script.ndc

# Show documentation (optionally filtered by query)
cargo run --bin ndc -- docs [query] [--no-color]

# Profile with perf (requires release-with-debug profile in Cargo.toml)
cargo build --profile release-with-debug
hyperfine --warmup 3 './target/release-with-debug/ndc script.ndc'
perf stat ./target/release-with-debug/ndc script.ndc
perf record -g --call-graph=dwarf -o /tmp/out.perf ./target/release-with-debug/ndc script.ndc
perf report -i /tmp/out.perf --stdio --no-children --percent-limit=1
```

## Manual

User-facing language documentation lives in `manual/src/`. It is an mdBook project. The entry point is `manual/src/SUMMARY.md`.

When making changes that affect language behaviour or runtime semantics, update the relevant manual page.

## Architecture

This is a custom language interpreter ("Andy C++") with a bytecode VM backend:

```
Source → [Lexer] → Tokens → [Parser] → AST → [Analyser] → Annotated AST
[Compiler]
[Bytecode VM] → Value
```

### Git Workflow
- Prefer short commit messages, only use multiple lines in case of unrelated changes
- Pull request titles must start with an emoji

### Crate Layout

| Crate | Role |
|---|---|
| `ndc_lexer` | Tokenisation, `Span` (offset+length) |
| `ndc_parser` | AST (`Expression`, `ExpressionLocation`), parser |
| `ndc_core` | `Number` (BigInt/Rational/Complex), `StaticType`, `FunctionRegistry`, ordering, hashing |
| `ndc_interpreter` | Semantic analyser, `Interpreter` facade (compile + run via VM) |
| `ndc_vm` | Bytecode `Compiler` and stack-based `Vm` |
| `ndc_stdlib` | Built-in functions registered via `FunctionRegistry` |
| `ndc_lsp` | LSP backend (hover, inlay hints) |
| `ndc_bin` | CLI entry point, REPL, syntax highlighting |

### Key Concepts

**Single execution path** — The bytecode VM in `ndc_vm` is the only execution path. `ndc_interpreter` acts as a facade: it runs the semantic analyser, compiles to bytecode via `ndc_vm::Compiler`, and executes via `ndc_vm::Vm`. `vm_bridge.rs` handles value conversion between `ndc_interpreter::Value` and `ndc_vm::Value`.

**Value types** — `ndc_interpreter/src/value.rs` and `ndc_vm/src/value.rs` are separate enums. The VM `Value` is constrained to 16 bytes (`Int(i64)`, `Float(f64)`, `Bool`, `None`, `Object(Box<Object>)`).

**Function overloading** — Functions are matched by name and arity. The semantic analyser produces `Binding::Resolved` (exact compile-time match) or `Binding::Dynamic(Vec<ResolvedVar>)` (runtime dispatch among candidates). Binary operators like `+` are parsed as `Expression::Call`.

**Semantic analyser** — `ndc_interpreter/src/semantic/analyser.rs` infers `StaticType` and resolves function bindings. `StaticType::Any` is the fallback when inference fails.

**`FunctionRegistry`** — Lives in `ndc_core`. Holds all registered built-in functions as `Rc<NativeFunction>`. Replaces the old `Environment`-based function registry. At runtime, natives are passed to the VM as global slots.

**Persistent REPL** — The `Interpreter` keeps `repl_state: Option<(Vm, Compiler)>` so variables declared on one REPL line are visible on subsequent lines (resume-from-halt pattern).

### Test Infrastructure

The `tests` crate auto-generates one test function per `.ndc` file at build time via `tests/build.rs`. For every `.ndc` file under `tests/programs/`, a single Rust test function is generated:
- `test_<path>` — runs via `Interpreter::run_str` (VM)

Test directives are comments inside `.ndc` files:
```ndc
// expect-output: 42 ← assert stdout equals this
// expect-error: divide ← assert error message contains this substring
```

### Compiler Tests

`compiler_tests/` validates the bytecode compiler by asserting exact `OpCode` sequences. Use these when adding new VM instructions.
Loading
Loading