From d4cb9e58d97ee8ee47ac83431179e1bb86cf4ab1 Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Sat, 15 Apr 2017 18:22:26 +0900 Subject: [PATCH] restart of continuation should restore dynamic environment --- lib/cont.c | 15 ++++++++++----- lib/error.c | 2 +- lib/object.h | 2 +- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/lib/cont.c b/lib/cont.c index 68a72440..91fb04dc 100644 --- a/lib/cont.c +++ b/lib/cont.c @@ -12,7 +12,7 @@ static pic_value cont_call(pic_state *pic) { int argc; - pic_value *argv; + pic_value *argv, k, dyn_env; struct context *cxt, *c; int i; @@ -30,26 +30,31 @@ cont_call(pic_state *pic) pic_error(pic, "calling dead escape continuation", 0); } + k = pic_closure_ref(pic, 1); + dyn_env = pic_closure_ref(pic, 2); + #define MKCALLK(argc) \ (cxt->tmpcode[0] = OP_CALL, cxt->tmpcode[1] = (argc), cxt->tmpcode) cxt->pc = MKCALLK(argc); cxt->sp = pic_make_frame_unsafe(pic, argc + 2); - cxt->sp->regs[0] = pic_closure_ref(pic, 1); /* cont. */ + cxt->sp->regs[0] = k; for (i = 0; i < argc; ++i) { cxt->sp->regs[i + 1] = argv[i]; } pic->cxt = cxt; + pic->dyn_env = dyn_env; + longjmp(cxt->jmp, 1); PIC_UNREACHABLE(); } pic_value -pic_make_cont(pic_state *pic, struct context *cxt, pic_value k) +pic_make_cont(pic_state *pic, struct context *cxt, pic_value k, pic_value dyn_env) { static const pic_data_type cxt_type = { "cxt", NULL }; - return pic_lambda(pic, cont_call, 2, pic_data_value(pic, cxt, &cxt_type), k); + return pic_lambda(pic, cont_call, 3, pic_data_value(pic, cxt, &cxt_type), k, dyn_env); } static pic_value @@ -59,7 +64,7 @@ pic_cont_callcc(pic_state *pic) pic_get_args(pic, "l", &f); - args[0] = pic_make_cont(pic, pic->cxt, pic->cxt->fp->regs[1]); + args[0] = pic_make_cont(pic, pic->cxt, pic->cxt->fp->regs[1], pic->dyn_env); return pic_applyk(pic, f, 1, args); } diff --git a/lib/error.c b/lib/error.c index 72f672b3..d922dcad 100644 --- a/lib/error.c +++ b/lib/error.c @@ -69,7 +69,7 @@ pic_enter_try(pic_state *pic) pic_value var, env; /* call/cc */ - cont = pic_make_cont(pic, pic->cxt, pic_invalid_value(pic)); + cont = pic_make_cont(pic, pic->cxt, pic_invalid_value(pic), pic->dyn_env); handler = pic_lambda(pic, native_exception_handler, 1, cont); /* with-exception-handler */ var = pic_exc(pic); diff --git a/lib/object.h b/lib/object.h index 8a26c991..2bb32471 100644 --- a/lib/object.h +++ b/lib/object.h @@ -272,7 +272,7 @@ pic_value pic_make_record(pic_state *, pic_value type, pic_value datum); pic_value pic_record_type(pic_state *pic, pic_value record); pic_value pic_record_datum(pic_state *pic, pic_value record); struct context; -pic_value pic_make_cont(pic_state *pic, struct context *cxt, pic_value k); +pic_value pic_make_cont(pic_state *pic, struct context *cxt, pic_value k, pic_value dyn_env); struct rope *pic_rope_incref(struct rope *); void pic_rope_decref(pic_state *, struct rope *);