c: retire TODO-named-let-bytecode.md

Resolved by 45a90b8 (vm restores cur_code across CALL/RETURN).
The reproducer at lines 5-11 of the TODO file runs cleanly now
under both `lumbda --fast` and `lumbda -j --fast`, and the
proof/eml_proof_in_lumbda.lsp `normalize` function no longer
needs the `(define (iter ...))` workaround that the TODO
documented. Future regressions are caught by
tests/regression-named-let-leak.{lsp,sh}.
This commit is contained in:
russell@unturf.com 2026-06-04 01:11:26 -04:00
parent 45a90b84e9
commit 03a3534f0e
No known key found for this signature in database

View file

@ -1,60 +0,0 @@
# C --fast bytecode compiler: named-let + inner `let`+`if` bug
## Reproduction (minimal)
```scheme
(define (maybe x) (if (> x 3) #f (+ x 1)))
(define (g start)
(let loop ((t start))
(let ((next (maybe t)))
(if next (loop next) t))))
(display (g 0)) (newline)
```
Expected output: `4`
Actual with `c/lumbda --fast`: hangs or segfaults.
Tree-walker (`c/lumbda` default) works correctly.
Python `--fast` and asm tree-walker both work correctly.
## What's special
The bug fires when:
- Outer named-let: `(let loop ((t ...)) BODY)`
- Inside BODY: `(let ((next (fn t))) ...)` — another let
- Inside inner let: `(if next (loop next) t)` — recursive call
through an if branch that was reached via an inner let-body
The recursive tail call to `loop` through the nested let + if doesn't
reach the loop closure. Bytecode emission likely walks the wrong env
chain or targets the wrong stack slot.
## Workaround
Replace named-let with an internal recursive `define`:
```scheme
(define (g start)
(define (iter t)
(let ((next (maybe t)))
(if next (iter next) t)))
(iter start))
```
Compiles correctly under `--fast`. Applied to `proof/eml_proof_in_lumbda.lsp`
for the `normalize` function.
## Where to look
`c/vm.c:344` `SYM_LET` named-let branch emits:
`PUSH_ENV, MAKE_CLOSURE, DUP, BIND name, <args...>, CALL/TAIL_CALL`.
Suspected: the lambda body's closure-env capture plus the inner `let`
PUSH_ENV interact badly when the tail call is behind an `if` whose
compilation path doesn't POP_ENV back to the closure's expected level.
## Priority
Low for now — workaround lands in every affected .lsp and the other
three tiers are unaffected. File for cleanup when the C --fast
refactor happens.