;; Letrec + perform/resume regression tests — Step 2
;; Verifies sibling bindings survive across an IO suspension when the
;; suspended call goes through call_closure_reuse (JIT path).
;; The browser/WASM kernel reuses the host VM via call_closure_reuse;
;; if restore_reuse drops the caller's saved sp, sibling letrec bindings
;; come back as nil after resume.
(defsuite
  "letrec-resume"
  (deftest
    "single binding survives perform/resume"
    (let
      ((state (cek-step-loop (make-cek-state (quote (letrec ((f (fn () (perform {:op "io"})))) (f))) (make-env) (list)))))
      (assert (cek-suspended? state))
      (let
        ((final (cek-resume state 7)))
        (assert (cek-terminal? final))
        (assert= (cek-value final) 7))))
  (deftest
    "sibling bindings survive perform/resume"
    (let
      ((state (cek-step-loop (make-cek-state (quote (letrec ((g (fn () 100)) (f (fn () (perform {:op "io"})))) (+ (f) (g)))) (make-env) (list)))))
      (assert (cek-suspended? state))
      (let
        ((final (cek-resume state 5)))
        (assert (cek-terminal? final))
        (assert= (cek-value final) 105))))
  (deftest
    "mutual recursion sibling preserved across resume"
    (let
      ((state (cek-step-loop (make-cek-state (quote (letrec ((even? (fn (n) (if (= n 0) true (odd? (- n 1))))) (odd? (fn (n) (if (= n 0) false (even? (- n 1))))) (fetch (fn () (perform {:op "io"})))) (let ((x (fetch))) (even? x)))) (make-env) (list)))))
      (assert (cek-suspended? state))
      (let
        ((final (cek-resume state 4)))
        (assert (cek-terminal? final))
        (assert= (cek-value final) true))))
  (deftest
    "nested letrec — outer sibling survives inner perform"
    (let
      ((state (cek-step-loop (make-cek-state (quote (letrec ((outer-val (fn () 99)) (inner-call (fn () (letrec ((suspend-fn (fn () (perform {:op "io"})))) (suspend-fn))))) (+ (inner-call) (outer-val)))) (make-env) (list)))))
      (assert (cek-suspended? state))
      (let
        ((final (cek-resume state 1)))
        (assert (cek-terminal? final))
        (assert= (cek-value final) 100)))))
