Step 10c: fix bind subscriber re-evaluation — track names not frames

Root cause: context called inside lambdas (e.g. swap!) went through
nested cek_run with empty kont, so provide frames weren't found and
never tracked to *bind-tracking*.

Three changes in evaluator.sx:
- step-sf-context: track context names (not frames) to *bind-tracking*
  — names work across cek_run boundaries via scope-peek fallback
- bind continue: resolve tracked names to frames via kont-find-provide
  on rest-k before registering subscribers
- subscriber: use empty kont instead of kont-extract-provides — old
  approach created provide frames whose continue handlers called
  scope-pop!, corrupting the scope stack

2752/2768 OCaml tests pass (all 7 bind subscriber tests fixed).
32/32 WASM native tests pass.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-05 11:05:17 +00:00
parent a965731a33
commit 44b520a9e9
6 changed files with 5366 additions and 8054 deletions

View File

@@ -2745,10 +2745,10 @@
nil))
(frame (kont-find-provide kont name)))
(when
(and frame *bind-tracking*)
*bind-tracking*
(when
(not (contains? *bind-tracking* frame))
(append! *bind-tracking* frame)))
(not (contains? *bind-tracking* name))
(append! *bind-tracking* name)))
(make-cek-value
(if
frame
@@ -3597,14 +3597,18 @@
(prev (get frame "prev-tracking")))
(set! *bind-tracking* prev)
(let
((subscriber (fn (fire-kont) (let ((provide-kont (kont-extract-provides fire-kont))) (cek-run (make-cek-state body fenv provide-kont))))))
((subscriber (fn (fire-kont) (cek-run (make-cek-state body fenv (list))))))
(for-each
(fn
(pf)
(dict-set!
pf
"subscribers"
(append (get pf "subscribers") (list subscriber))))
(name)
(let
((pf (kont-find-provide rest-k name)))
(when
pf
(dict-set!
pf
"subscribers"
(append (get pf "subscribers") (list subscriber))))))
tracked))
(make-cek-value value fenv rest-k)))
("provide-set"