Fix letrec thunk resolution + compiler letrec support + closure JIT check
Root cause: sf-letrec returns a thunk (for TCO) but the CEK dispatch wrapped it as a value without evaluating. The thunk leaked as the return value of letrec expressions, breaking sx-parse and any function using letrec. Fix: step-sf-letrec unwraps the thunk into a CEK state, so the last letrec body expression is properly evaluated by the CEK machine. Also: - compile-letrec: two-phase (nil-init then assign) for mutual recursion - Skip JIT for inner functions (closure.bindings != globals) in both vm_call and JIT hook - vm-reset-fn for sx-parse removed (no longer needed) - Parser regression test: letrec with mutable pos + recursive sublists Test results: JS 943/17, OCaml 955/0, Python 747/0 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -913,9 +913,8 @@ let register_jit_hook env =
|
||||
| Some _ -> None (* compile failed — CEK handles *)
|
||||
| None ->
|
||||
if !_jit_compiling then None
|
||||
else if Hashtbl.length l.l_closure.bindings > 0
|
||||
|| l.l_closure.parent <> None then
|
||||
(* Skip JIT for lambdas with closure bindings *)
|
||||
else if l.l_closure.bindings != env.bindings then
|
||||
(* Skip JIT for inner functions — closure != globals *)
|
||||
None
|
||||
else begin
|
||||
let fn_name = match l.l_name with Some n -> n | None -> "?" in
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -328,11 +328,10 @@ and vm_call vm f args =
|
||||
push vm (Sx_ref.cek_call f (List args))
|
||||
| None ->
|
||||
if l.l_name <> None
|
||||
(* Skip JIT for lambdas with closure bindings — the closure
|
||||
merging into vm_env_ref produces incorrect variable resolution
|
||||
for inner functions (e.g. parser's read-list-loop). *)
|
||||
&& Hashtbl.length l.l_closure.bindings = 0
|
||||
&& l.l_closure.parent = None
|
||||
(* Skip JIT for inner functions (closure != globals).
|
||||
The closure merging produces incorrect variable resolution
|
||||
for functions that capture letrec/let-local bindings. *)
|
||||
&& l.l_closure.bindings == vm.globals
|
||||
then begin
|
||||
(* Pre-mark before compile attempt to prevent re-entrancy *)
|
||||
l.l_compiled <- Some jit_failed_sentinel;
|
||||
|
||||
Reference in New Issue
Block a user