spec: dynamic-wind — after-thunk fires on normal return, raise, and call/cc escape

- Add make-wind-after-frame / make-wind-return-frame CEK frame types
- Add *winders* global stack tracking active after-thunks
- Add kont-unwind-to-handler (replaces kont-find-handler in raise-eval) — calls
  after-thunks for wind frames encountered while unwinding to handler
- Add wind-escape-to — pops and calls after-thunks down to captured winders-len
- Replace sf-dynamic-wind with step-sf-dynamic-wind (full CEK dispatch)
- Fix "callcc" frame: store winders-len in continuation object
- Fix callcc-continuation? case: call wind-escape-to before escape
- JS platform: extend SxCallccContinuation to store windersLen; add
  callcc-continuation-winders-len accessor
- 8 tests: normal return, raise escape, call/cc escape, nested LIFO, guard ordering
- 1948/2500 (was 1940); zero regressions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-26 14:19:17 +00:00
parent 0577f245e2
commit a9d5a1082f
4 changed files with 270 additions and 28 deletions

View File

@@ -929,11 +929,12 @@ PREAMBLE = '''\
function parameterUid(p) { return p._uid; }
function parameterDefault(p) { return p._default; }
function SxCallccContinuation(capturedKont) { this._captured = capturedKont; }
function SxCallccContinuation(capturedKont, windersLen) { this._captured = capturedKont; this._winders_len = windersLen !== undefined ? windersLen : 0; }
SxCallccContinuation.prototype._callcc = true;
function makeCallccContinuation(kont) { return new SxCallccContinuation(kont); }
function makeCallccContinuation(kont, windersLen) { return new SxCallccContinuation(kont, windersLen !== undefined ? windersLen : 0); }
function callccContinuation_p(x) { return x != null && x._callcc === true; }
function callccContinuationData(x) { return x._captured; }
function callccContinuationWindersLen(x) { return x._winders_len !== undefined ? x._winders_len : 0; }
function evalError_p(v) {
return v != null && typeof v === "object" && v["__eval_error__"] === true;