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:
@@ -535,3 +535,36 @@
|
||||
(deftest "parse nil is not a symbol"
|
||||
(let ((result (first (sx-parse "nil"))))
|
||||
(assert-nil result))))
|
||||
|
||||
|
||||
;; --------------------------------------------------------------------------
|
||||
;; JIT regression: mutable pos shared via upvalues across recursive calls
|
||||
;; --------------------------------------------------------------------------
|
||||
|
||||
(defsuite "parser-jit-regression"
|
||||
(deftest "letrec parser with mutable pos — recursive sublists"
|
||||
;; Minimal reproducer for the sx-parse JIT bug.
|
||||
;; Uses define inside fn (like sx-parse's read-list-loop pattern).
|
||||
(let ((parse-fn (fn (src)
|
||||
(let ((pos 0))
|
||||
(letrec
|
||||
((read-list (fn ()
|
||||
(let ((result (list))
|
||||
(done false))
|
||||
(define go (fn ()
|
||||
(when (and (not done) (< pos (len src)))
|
||||
(let ((ch (nth src pos)))
|
||||
(set! pos (inc pos))
|
||||
(cond
|
||||
(= ch ")") (set! done true)
|
||||
(= ch "(") (do (append! result (read-list)) (go))
|
||||
:else (do (append! result ch) (go)))))))
|
||||
(go)
|
||||
result))))
|
||||
(set! pos 1)
|
||||
(read-list))))))
|
||||
(let ((r (parse-fn "(a(b)(c))")))
|
||||
(assert (list? r) (str "result should be list, got type=" (type-of r)))
|
||||
(assert-equal 3 (len r))
|
||||
(assert-equal (list "a" (list "b") (list "c")) r))))
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user