ticket 0005: mark resolved, document the four bug fixes

asm/lumbda-full now runs Zoë's CL source end-to-end per commit
c6658e0. Rewrite the Known Issues section into a Resolved section
explaining what each of the four underlying asm bugs was (bi_apply
clobber, bi_expt infinite loop on negative exponent, macro_env_head
missing from GC roots, cadar missing from the prelude) and why the
158-test asm suite did not catch them before.
This commit is contained in:
russell@unturf.com 2026-04-24 12:18:44 -04:00
parent c6658e03a4
commit 1f777aa7fb

View file

@ -1,7 +1,7 @@
# 0005 — `asm/lumbda-full`: CL compat on the asm tier
**Status:** partially resolved — infrastructure landed, cl-loop-emit
edge case open
**Status:** resolved (commit `c6658e0`)
**Resolved:** 2026-04-24
**Reporter:** fox (via blackops)
**Implementer:** blackops
**Opened:** 2026-04-24
@ -146,28 +146,52 @@ stage that regresses the minimal or -gc tiers.
- `examples/ursa.lisp.txt` loads to completion — every `defun`
registers and its body parses under the shim.
## Known open issues (follow-up work)
## Issues resolved in the follow-up drop (commit `c6658e0`)
1. **`cl-loop-emit` crashes on some parsed inputs.** Specifically,
`(cl-loop-emit '(() ((simple a 5)) () () () #f () ()))` returns
`(let* () (let g0 () (g0)))` — the `simple` iter's state binding
is dropped. Same input on Python and C returns the correct
`(let* ((g3 5)) (let g0 ((a g3)) ...))`. The parse output on
asm is correct; the bug is inside the emit's giant `let*` (30+
bindings). Reproduced in isolation; could not pin down after a
few hours — likely an asm-side env or stack interaction that
surfaces only inside this specific call shape.
All four were asm-side bugs surfaced by cl-loop expansions in Zoë's
programs; none were visible in the prior 158-test asm suite because
that suite never exercised `apply` on a variadic closure, a negative-
exponent `expt`, a macro-heavy workload long enough to trigger GC, or
the `cadar` accessor.
Consequence: `(miller-rabin n)` and other defuns whose bodies use
`cl-loop repeat k for a = ...` expand incorrectly and crash at
run time. Zoë's full acceptance suite does not run end-to-end
yet on `asm/lumbda-full`.
1. **`bi_apply` clobbered its second argument.** `(apply f LIST)` on
asm was silently discarding LIST and calling f with no args. Fix:
load the args-list straight into `%rsi`, stop copying the proc
over itself.
2. **`examples/ursa-scheme.lsp``factor` crashes on some inputs**
under certain random seeds on asm (e.g. seed=2, `(factor 91)`).
Default asm has no macro overhead but does hit this under long
rhoff retry chains. Believed to be asm's bump allocator / stack
growth under deep recursion; out of CL_FULL's scope.
2. **`bi_expt` looped forever on negative exponents.** cl-loop's
look-ahead termination stages step values in a `let*` before
checking the terminate predicate, so a `for i from N downto 0`
clause ends up evaluating `(expt 2 -1)` on the last step. asm is
integer-only; guard the negative case and return 0. The step's
result is unused (look-ahead aborts the iteration), so returning
0 is correct for cl-loop's purposes.
3. **`macro_env_head` was not a GC root.** Under GC_NAIVE (which
CL_FULL implies), a macro-heavy workload like miller-rabin's
nested cl-loops triggered a collection partway through, which
reclaimed every macro-table node. Next macro use failed with
"unbound variable: cl-when" (or similar). Fix: mark the table
alongside the global env using the existing `gc_mark_env` walker,
guarded `.ifdef CL_FULL`.
4. **Prelude missing `cadar`.** `cl-loop-finalizer-expr` uses it to
extract the return value from `(finally (return X))`. Added to
the embedded prelude.
Zoë's full CL file now runs 18/19 on asm/lumbda-full. The one
remaining failure is a test-fixture expectation about a specific
random value, not an asm bug. All three asm variants pass 158/158
on their local suites.
## Lingering follow-up (not blocking 0005 resolution)
- **`examples/ursa-scheme.lsp``factor` crashes on some inputs**
under certain random seeds on asm (e.g. seed=2, `(factor 91)`).
Default asm has no macro overhead but does hit this under long
rhoff retry chains. Believed to be asm's bump allocator growth
under deep recursion; independent of CL_FULL and out of ticket
0005's scope.
## Risk