@@ -957,6 +957,7 @@ SgObject Sg_VMEnvironment(SgObject lib, SgObject spec)
957957}
958958
959959static void print_frames (SgVM * vm , SgContFrame * cont );
960+ static void print_prompts (SgVM * vm , SgPromptNode * node );
960961static void expand_stack (SgVM * vm );
961962
962963/* it does not improve performance */
@@ -1580,8 +1581,9 @@ static SgObject capture_prompt_winders(SgPrompt *, SgObject);
15801581
15811582/* Forward declarations for delimited call/cc support */
15821583static SgPrompt * make_prompt (SgObject tag , SgObject handler , SgVM * vm );
1583- static void install_prompt (SgVM * vm , SgPrompt * prompt );
1584- static void remove_prompt (SgVM * vm , SgPrompt * prompt );
1584+ static void install_prompt (SgVM * , SgPrompt * );
1585+ static void remove_prompt (SgVM * , SgPrompt * );
1586+ static SgPromptNode * remove_prompts (SgVM * , SgObject );
15851587static SgObject abort_body (SgPromptNode * node , SgObject winders , SgObject args );
15861588
15871589static SgObject throw_delimited_continuation_body (SgObject ,
@@ -1807,6 +1809,7 @@ static SgObject throw_cont_compute_handlers(SgContinuation *c,
18071809 SG_APPEND1 (h , t , Sg_Cons (SG_CDAR (p ), SG_CDR (p )));
18081810 }
18091811 }
1812+
18101813 SG_FOR_EACH (p , target ) {
18111814 SgObject chain = Sg_Memq (SG_CAR (p ), escapes );
18121815 SgObject next_winders = SG_CDR (chain );
@@ -1846,17 +1849,18 @@ static SgObject throw_continuation(SgObject *argv, int argc, void *data)
18461849 save_cont (vm );
18471850 }
18481851 if (c -> type == SG_DELIMIETED_CONTINUATION ) {
1852+ /* here we emulate abort/cc */
18491853 SgContinuation abort_c ;
18501854 SgPromptNode * node = search_prompt_node_by_tag (vm , prompt -> tag );
18511855 abort_c .winders = node -> prompt -> winders ;
1852- abort_c .cstack = node -> prompt -> cstack ; /* Non-null to enable post-thunks */
1853- abort_c .cont = NULL ;
1854- abort_c .prev = NULL ;
1855- abort_c .ehandler = SG_FALSE ;
1856+ abort_c .cstack = node -> prompt -> cstack ;
18561857 handlers = throw_cont_compute_handlers (& abort_c , node -> prompt , vm );
18571858 return throw_delimited_continuation_body (handlers , c , argv [0 ], prompt );
18581859 } else {
18591860 handlers = throw_cont_compute_handlers (c , prompt , vm );
1861+ /* Sg_Printf(Sg_StandardErrorPort(), UC("comp: vm->dw: %A\n"), vm->dynamicWinders); */
1862+ /* Sg_Printf(Sg_StandardErrorPort(), UC("comp: c->dw: %A\n"), c->winders); */
1863+ /* Sg_Printf(Sg_StandardErrorPort(), UC("comp: hndlrs: %A\n"), handlers); */
18601864 return throw_continuation_body (handlers , c , argv [0 ], prompt );
18611865 }
18621866}
@@ -1959,8 +1963,7 @@ static SgObject throw_delimited_continuation_body(SgObject handlers,
19591963 SgObject args ,
19601964 SgPrompt * prompt )
19611965{
1962- SgVM * vm = Sg_VM ();
1963-
1966+ SgVM * vm = theVM ;
19641967 /* Process abort handlers (post-thunks for unwinding) */
19651968 if (SG_PAIRP (handlers )) {
19661969 SgObject handler , chain ;
@@ -1982,52 +1985,67 @@ static SgObject throw_delimited_continuation_body(SgObject handlers,
19821985 2. Compute wind-in handlers (pre-thunks) to restore the continuation's
19831986 dynamic extent
19841987 3. Run those handlers, then apply the continuation */
1985-
1986- SgPrompt * new_prompt ;
1987- SgPromptNode * node = search_prompt_node_by_tag (vm , prompt -> tag );
1988-
1988+ SgPromptNode * node = remove_prompts (vm , prompt -> tag );
19891989 if (!node ) {
19901990 Sg_Error (UC ("Stale prompt in delimited continuation: %S" ), prompt -> tag );
19911991 }
19921992
1993- /* Pop continuation frames up to and including the prompt frame */
1994- SgContFrame * cont_frame = vm -> cont ;
1995- while (!cont_prompt_match_p (cont_frame , node -> prompt )) {
1996- if (PROMPT_FRAME_MARK_P (cont_frame )) {
1997- remove_prompt (vm , (SgPrompt * )cont_frame -> pc );
1998- }
1999- cont_frame = cont_frame -> prev ;
2000- }
2001-
20021993 /* Remove the original prompt and set continuation to just before
20031994 the prompt */
20041995 remove_prompt (vm , node -> prompt );
20051996 vm -> cont = node -> frame -> prev ;
2006-
1997+
20071998 /* Create a new prompt for the continuation */
2008- new_prompt = make_prompt (prompt -> tag , SG_FALSE , vm );
1999+ SgPrompt * new_prompt = make_prompt (prompt -> tag , SG_FALSE , vm );
20092000
20102001 CHECK_STACK (CONT_FRAME_SIZE , vm );
20112002 PUSH_PROMPT_CONT (vm , new_prompt );
20122003 install_prompt (vm , new_prompt );
2013-
2004+
20142005 /* Now compute and run wind-in handlers using the composable
20152006 continuation path. We've already aborted to the prompt, so
20162007 current vm->dynamicWinders is at the prompt's level. We need to
20172008 wind into c's winders. */
20182009 SgObject wind_handlers = throw_cont_compute_handlers (c , prompt , vm );
2010+
2011+ /* Sg_Printf(Sg_StandardErrorPort(), UC("delim: vm->dw: %A\n"), vm->dynamicWinders); */
2012+ /* Sg_Printf(Sg_StandardErrorPort(), UC("delim: c->dw: %A\n"), c->winders); */
2013+ /* Sg_Printf(Sg_StandardErrorPort(), UC("delim: hndlrs: %A\n"), wind_handlers); */
2014+
20192015 /* Use the regular composable continuation body to process these handlers */
20202016 return throw_continuation_body (wind_handlers , c , args , prompt );
20212017 }
20222018}
20232019
2020+ /* Strip the delimited cc handlers.
2021+ If the cont frame is captured, then the captured frame may contain
2022+ outside of the prompt chain.
2023+ The VM dynamicWinders should contain only the prompt winders,
2024+ so the handler is not in the winders, we should strip it.
2025+ */
2026+ static SgObject strip_delimied_cc_handlers (SgObject handlers )
2027+ {
2028+ SgVM * vm = theVM ;
2029+ while (!SG_NULLP (handlers )) {
2030+ SgObject handler = SG_CAAR (handlers );
2031+ SgObject cp ;
2032+ SG_FOR_EACH (cp , vm -> dynamicWinders ) {
2033+ if (SG_EQ (SG_CAAR (cp ), handler ) || SG_EQ (SG_CDAR (cp ), handler )) goto end ;
2034+ }
2035+ handlers = SG_CDR (handlers );
2036+ }
2037+ end :
2038+ return handlers ;
2039+ }
2040+
20242041static SgObject throw_delimited_continuation_cc (SgObject result , void * * data )
20252042{
20262043 SgObject handlers = SG_OBJ (data [0 ]);
20272044 SgContinuation * c = (SgContinuation * )data [1 ];
20282045 SgObject args = SG_OBJ (data [2 ]);
20292046 SgPrompt * prompt = (SgPrompt * )data [3 ];
2030- return throw_delimited_continuation_body (handlers , c , args , prompt );
2047+ return throw_delimited_continuation_body (strip_delimied_cc_handlers (handlers ),
2048+ c , args , prompt );
20312049}
20322050
20332051/* call-with-current-continuation with prompt delimiting (Racket-like call/cc) */
@@ -2043,10 +2061,10 @@ SgObject Sg_VMCallDelimitedCC(SgObject proc, SgObject tag)
20432061 save_cont (vm );
20442062
20452063 cont = SG_NEW (SgContinuation );
2046- /* Use capture_prompt_winders to only include winders installed AFTER the prompt.
2047- Unlike take_prompt_winders which returns a tail, this returns a NEW list
2048- containing only the winders not in prompt->winders, stopping at the first
2049- common winder. */
2064+ /* Use capture_prompt_winders to only include winders installed
2065+ AFTER the prompt. Unlike take_prompt_winders which returns a
2066+ tail, this returns a NEW list containing only the winders not in
2067+ prompt->winders, stopping at the first common winder. */
20502068 cont -> winders = capture_prompt_winders (node -> prompt , vm -> dynamicWinders );
20512069 cont -> cont = vm -> cont ;
20522070 cont -> prev = NULL ;
@@ -2104,6 +2122,22 @@ static void remove_prompt(SgVM *vm, SgPrompt *prompt)
21042122 }
21052123}
21062124
2125+ /* remove prompts up to the tag */
2126+ static SgPromptNode * remove_prompts (SgVM * vm , SgObject tag )
2127+ {
2128+ SgPromptNode * cur_node = search_prompt_node_by_tag (vm , tag );
2129+ if (!cur_node ) return NULL ;
2130+ SgPrompt * prompt = cur_node -> prompt ;
2131+ SgContFrame * cont = vm -> cont ;
2132+
2133+ /* remove the prompt in the aborting cont frame from the chain */
2134+ while (!cont_prompt_match_p (cont , prompt )) {
2135+ if (PROMPT_FRAME_MARK_P (cont )) remove_prompt (vm , (SgPrompt * )cont -> pc );
2136+ cont = cont -> prev ;
2137+ }
2138+ return cur_node ;
2139+ }
2140+
21072141SgObject Sg_VMCallCP (SgObject proc , SgObject tag ,
21082142 SgObject handler , SgObject args )
21092143{
@@ -2623,16 +2657,10 @@ static SgObject abort_body(SgPromptNode *node, SgObject winders, SgObject args)
26232657 NOTE: when this abort_cc frame is captured in a continuation,
26242658 the captured node is not loger valid.
26252659 */
2626- SgPromptNode * cur_node = search_prompt_node_by_tag (vm , node -> prompt -> tag );
2660+ SgPromptNode * cur_node = remove_prompts (vm , node -> prompt -> tag );
26272661 if (!cur_node ) Sg_Error (UC ("Stale prompt: %S" ), node -> prompt -> tag );
26282662 SgPrompt * prompt = cur_node -> prompt ;
2629- SgContFrame * cont = vm -> cont ;
26302663
2631- /* remove the prompt in the aborting cont frame from the chain */
2632- while (!cont_prompt_match_p (cont , prompt )) {
2633- if (PROMPT_FRAME_MARK_P (cont )) remove_prompt (vm , (SgPrompt * )cont -> pc );
2634- cont = cont -> prev ;
2635- }
26362664 if (prompt -> cstack != vm -> cstack ) {
26372665 vm -> escapeReason = SG_VM_ESCAPE_ABORT ;
26382666 vm -> escapeData [0 ] = cur_node ;
@@ -3150,6 +3178,22 @@ static SgContFrame * print_cont1(SgContFrame *cont, SgVM *vm)
31503178 return cont -> prev ;
31513179}
31523180
3181+ static void print_prompts (SgVM * vm , SgPromptNode * node )
3182+ {
3183+ if (node ) {
3184+ Sg_Printf (vm -> logPort , UC (";; Prompt chain\n" ));
3185+ Sg_Printf (vm -> logPort , UC (";; [%S:%S %p]" ),
3186+ node -> prompt -> tag , node -> prompt -> handler , node -> prompt );
3187+ node = node -> next ;
3188+ while (node ) {
3189+ Sg_Printf (vm -> logPort , UC (" => [%S:%S %p]" ),
3190+ node -> prompt -> tag , node -> prompt -> handler , node -> prompt );
3191+ node = node -> next ;
3192+ }
3193+ Sg_Printf (vm -> logPort , UC ("\n" ));
3194+ }
3195+ }
3196+
31533197static void print_frames (SgVM * vm , SgContFrame * cont )
31543198{
31553199 SgObject * stack = vm -> stack , * sp = SP (vm );
@@ -3172,18 +3216,7 @@ static void print_frames(SgVM *vm, SgContFrame *cont)
31723216 UC (";; %p +---------------------------------------------+ < bottom\n" ),
31733217 stack );
31743218
3175- if (node ) {
3176- Sg_Printf (vm -> logPort , UC (";; Prompt chain\n" ));
3177- Sg_Printf (vm -> logPort , UC (";; [%S:%S %p]" ),
3178- node -> prompt -> tag , node -> prompt -> handler , node -> prompt );
3179- node = node -> next ;
3180- while (node ) {
3181- Sg_Printf (vm -> logPort , UC (" => [%S:%S %p]" ),
3182- node -> prompt -> tag , node -> prompt -> handler , node -> prompt );
3183- node = node -> next ;
3184- }
3185- Sg_Printf (vm -> logPort , UC ("\n" ));
3186- }
3219+ print_prompts (vm , node );
31873220
31883221}
31893222
0 commit comments