@@ -1584,6 +1584,7 @@ static SgContFrame * splice_cont(SgVM *vm, SgContFrame *saved,
15841584static SgObject throw_continuation_cc (SgObject , void * * );
15851585static SgObject merge_winders (SgObject , SgObject );
15861586static SgObject take_prompt_winders (SgPrompt * , SgObject );
1587+ static SgObject capture_prompt_winders (SgPrompt * , SgObject );
15871588
15881589static 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. */
17241751static 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 ;
0 commit comments