Skip to content

Commit b11fe78

Browse files
committed
Fixing winder computation for composable continuation
1 parent 2fd4da6 commit b11fe78

File tree

2 files changed

+48
-6
lines changed

2 files changed

+48
-6
lines changed

src/vm.c

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1584,6 +1584,7 @@ static SgContFrame * splice_cont(SgVM *vm, SgContFrame *saved,
15841584
static SgObject throw_continuation_cc(SgObject, void **);
15851585
static SgObject merge_winders(SgObject, SgObject);
15861586
static SgObject take_prompt_winders(SgPrompt *, SgObject);
1587+
static SgObject capture_prompt_winders(SgPrompt *, SgObject);
15871588

15881589
static SgObject throw_continuation_body(SgObject handlers,
15891590
SgContinuation *c,
@@ -1627,9 +1628,11 @@ static SgObject throw_continuation_body(SgObject handlers,
16271628
vm->cont = splice_cont(vm, c->cont, prompt);
16281629
if (c->winders != vm->dynamicWinders) {
16291630
/* continuation is invoked outside of the winder's dynamic extent.
1630-
Merge it and take only the prompt ones.
1631+
Merge only winders that are inside the continuation's scope
1632+
(not the ones that were in place at prompt creation time).
16311633
*/
1632-
vm->dynamicWinders = merge_winders(c->winders, vm->dynamicWinders);
1634+
SgObject to_merge = capture_prompt_winders(prompt, c->winders);
1635+
vm->dynamicWinders = merge_winders(to_merge, vm->dynamicWinders);
16331636
}
16341637
} else {
16351638
vm->cont = c->cont;
@@ -1667,8 +1670,8 @@ static SgObject throw_continuation_cc(SgObject result, void **data)
16671670
SgObject handlers = SG_OBJ(data[0]);
16681671
SgContinuation *c = (SgContinuation*)data[1];
16691672
SgObject args = SG_OBJ(data[2]);
1670-
SgObject tag = SG_OBJ(data[3]);
1671-
return throw_continuation_body(handlers, c, args, tag);
1673+
SgPrompt *prompt = (SgPrompt*)data[3];
1674+
return throw_continuation_body(handlers, c, args, prompt);
16721675
}
16731676

16741677
/* remove and re-order continuation's handlers */
@@ -1721,6 +1724,30 @@ static SgObject merge_winders(SgObject current, SgObject escapes)
17211724
is also provided.
17221725
17231726
*/
1727+
1728+
/* Returns only winders from the input list that are NOT in prompt->winders.
1729+
Stops when we reach a winder that IS in prompt->winders.
1730+
This is used when capturing a composable continuation to only include
1731+
winders installed after the prompt. Returns a new list (copies winders). */
1732+
static SgObject capture_prompt_winders(SgPrompt *prompt, SgObject winders)
1733+
{
1734+
SgObject p, h = SG_NIL, t = SG_NIL;
1735+
if (SG_NULLP(winders)) return winders;
1736+
1737+
SG_FOR_EACH(p, winders) {
1738+
if (SG_FALSEP(Sg_Memq(SG_CAR(p), prompt->winders))) {
1739+
SG_APPEND1(h, t, SG_CAR(p));
1740+
} else {
1741+
/* Found a winder that's in the prompt's winders - stop here */
1742+
break;
1743+
}
1744+
}
1745+
return h;
1746+
}
1747+
1748+
/* Returns the tail of the winders list starting from the first winder
1749+
that is NOT in prompt->winders. This preserves list structure for
1750+
chain computation in handler invocation. */
17241751
static SgObject take_prompt_winders(SgPrompt *prompt, SgObject winders)
17251752
{
17261753
/* now we only need the uncommon winders, e.g.
@@ -1759,6 +1786,11 @@ static SgObject throw_cont_compute_handlers(SgContinuation *c,
17591786
SgObject target = remove_common_winders(current, escapes);
17601787
SgObject h = SG_NIL, t = SG_NIL, p;
17611788

1789+
/* Sg_Printf(Sg_StandardErrorPort(), UC("targt: %S\n"), target);
1790+
Sg_Printf(Sg_StandardErrorPort(), UC("p->dw: %S\n"), prompt ? prompt->winders : SG_FALSE);
1791+
Sg_Printf(Sg_StandardErrorPort(), UC("c->dw: %S\n"), c->winders);
1792+
Sg_Printf(Sg_StandardErrorPort(), UC("v->dw: %S\n\n"), vm->dynamicWinders); */
1793+
17621794
if (prompt) target = take_prompt_winders(prompt, target);
17631795

17641796
/* When the continuation is partial continuation,
@@ -1774,7 +1806,17 @@ static SgObject throw_cont_compute_handlers(SgContinuation *c,
17741806
}
17751807
SG_FOR_EACH(p, target) {
17761808
SgObject chain = Sg_Memq(SG_CAR(p), escapes);
1777-
SG_APPEND1(h, t, Sg_Cons(SG_CAAR(p), SG_CDR(chain)));
1809+
SgObject next_winders = SG_CDR(chain);
1810+
/* For composable continuations, don't include winders that were
1811+
in place when the prompt was created - they're outside the
1812+
continuation's scope and shouldn't be added to vm->dynamicWinders */
1813+
if (prompt && SG_PAIRP(next_winders)) {
1814+
SgObject w = SG_CAR(next_winders);
1815+
if (!SG_FALSEP(Sg_Memq(w, prompt->winders))) {
1816+
next_winders = SG_NIL;
1817+
}
1818+
}
1819+
SG_APPEND1(h, t, Sg_Cons(SG_CAAR(p), next_winders));
17781820
}
17791821

17801822
return h;

test/includes/partcont.scm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -486,7 +486,7 @@
486486
;; srfi226: [d01][d02][d01][d02][d11][d12][d01][d02][d01][d02][d11][d12][d11][d12]
487487
;; racket : [d01][d02][d01][d11][d12][d02][d11][d12][d11][d12]
488488
(test* "dynamic-wind + reset/shift 5"
489-
"[d01][d02][d01][d11][d12][d02][d11][d12][d02][d01][d11][d12]"
489+
"[d01][d02][d01][d11][d12][d02][d11][d12][d11][d12]"
490490
(with-output-to-string
491491
(lambda ()
492492
(define k1 #f)

0 commit comments

Comments
 (0)