The compiler was treating letrec as let — binding values sequentially. This meant mutually recursive functions (like sx-parse's read-list calling read-expr and vice versa) couldn't reference each other. compile-letrec uses two phases: 1. Define all local slots initialized to nil 2. Compile and assign values — all names already in scope This fixes sx-parse producing wrong ASTs (nested instead of sibling lists) when JIT-compiled, which caused the stepper's step count to be 2 instead of 16. Also: skip JIT for lambdas with closure bindings (inner functions like read-list-loop) — the closure merging into vm_env_ref produces incorrect variable resolution. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
389 KiB
389 KiB