From 10aae770c9d97a298b7f2e6864a525ed3012dc4d Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Sat, 20 Feb 2016 23:55:40 +0900 Subject: [PATCH] refactor pic_try/catch --- extlib/benz/cont.c | 57 +++++++++++++++++++++--------- extlib/benz/error.c | 14 ++++++-- extlib/benz/include/picrin.h | 29 ++++++++------- extlib/benz/include/picrin/state.h | 19 ---------- 4 files changed, 67 insertions(+), 52 deletions(-) diff --git a/extlib/benz/cont.c b/extlib/benz/cont.c index e4c6aa62..0df3d685 100644 --- a/extlib/benz/cont.c +++ b/extlib/benz/cont.c @@ -5,9 +5,32 @@ #include "picrin.h" #include "picrin/object.h" +struct pic_cont { + PIC_JMPBUF *jmp; + + int id; + + struct pic_checkpoint *cp; + ptrdiff_t sp_offset; + ptrdiff_t ci_offset; + ptrdiff_t xp_offset; + size_t arena_idx; + pic_value ptable; + pic_code *ip; + + int retc; + pic_value *retv; + + struct pic_cont *prev; +}; + +static const pic_data_type cont_type = { "pic_cont", NULL, NULL }; + void -pic_save_point(pic_state *pic, struct pic_cont *cont) +pic_save_point(pic_state *pic, struct pic_cont *cont, PIC_JMPBUF *jmp) { + cont->jmp = jmp; + /* save runtime context */ cont->cp = pic->cp; cont->sp_offset = pic->sp - pic->stbase; @@ -86,9 +109,6 @@ pic_dynamic_wind(pic_state *pic, pic_value in, pic_value thunk, pic_value out) return val; } -#define CV_ID 0 -#define CV_ESCAPE 1 - static pic_value cont_call(pic_state *pic) { @@ -99,7 +119,9 @@ cont_call(pic_state *pic) pic_get_args(pic, "*", &argc, &argv); - id = pic_int(pic, pic_closure_ref(pic, CV_ID)); + cont = pic_data(pic, pic_closure_ref(pic, 0)); + + id = cont->id; /* check if continuation is alive */ for (cc = pic->cc; cc != NULL; cc = cc->prev) { @@ -111,13 +133,12 @@ cont_call(pic_state *pic) pic_errorf(pic, "calling dead escape continuation"); } - cont = pic_data(pic, pic_closure_ref(pic, CV_ESCAPE)); cont->retc = argc; cont->retv = argv; pic_load_point(pic, cont); - PIC_LONGJMP(pic, cont->jmp, 1); + PIC_LONGJMP(pic, *cont->jmp, 1); PIC_UNREACHABLE(); } @@ -125,26 +146,30 @@ cont_call(pic_state *pic) pic_value pic_make_cont(pic_state *pic, struct pic_cont *cont) { - static const pic_data_type cont_type = { "cont", NULL, NULL }; + return pic_lambda(pic, cont_call, 1, pic_data_value(pic, cont, &cont_type)); +} - /* save the escape continuation in proc */ - return pic_lambda(pic, cont_call, 2, pic_int_value(pic, cont->id), pic_data_value(pic, cont, &cont_type)); +struct pic_cont * +pic_alloca_cont(pic_state *pic) +{ + return pic_alloca(pic, sizeof(struct pic_cont)); } static pic_value pic_callcc(pic_state *pic, pic_value proc) { - struct pic_cont cont; + PIC_JMPBUF jmp; + struct pic_cont *cont = pic_alloca_cont(pic); - pic_save_point(pic, &cont); - - if (PIC_SETJMP(pic, cont.jmp)) { - return pic_valuesk(pic, cont.retc, cont.retv); + if (PIC_SETJMP(pic, jmp)) { + return pic_valuesk(pic, cont->retc, cont->retv); } else { pic_value val; - val = pic_call(pic, proc, 1, pic_make_cont(pic, &cont)); + pic_save_point(pic, cont, &jmp); + + val = pic_call(pic, proc, 1, pic_make_cont(pic, cont)); pic_exit_point(pic); diff --git a/extlib/benz/error.c b/extlib/benz/error.c index b854508f..08b1808e 100644 --- a/extlib/benz/error.c +++ b/extlib/benz/error.c @@ -47,8 +47,8 @@ pic_errorf(pic_state *pic, const char *fmt, ...) pic_error(pic, "", msg, pic_nil_value(pic)); } -pic_value -pic_native_exception_handler(pic_state *pic) +static pic_value +native_exception_handler(pic_state *pic) { pic_value err; @@ -61,6 +61,16 @@ pic_native_exception_handler(pic_state *pic) PIC_UNREACHABLE(); } +void +pic_push_native_handler(pic_state *pic, struct pic_cont *cont) +{ + pic_value handler; + + handler = pic_lambda(pic, native_exception_handler, 1, pic_make_cont(pic, cont)); + + pic_push_handler(pic, handler); +} + void pic_push_handler(pic_state *pic, pic_value handler) { diff --git a/extlib/benz/include/picrin.h b/extlib/benz/include/picrin.h index df9e8bce..72c82833 100644 --- a/extlib/benz/include/picrin.h +++ b/extlib/benz/include/picrin.h @@ -345,6 +345,14 @@ void pic_load_cstr(pic_state *, const char *); pic_in_library(pic, lib); \ } while (0) +struct pic_cont *pic_alloca_cont(pic_state *); +pic_value pic_make_cont(pic_state *, struct pic_cont *); +void pic_push_native_handler(pic_state *, struct pic_cont *); +void pic_push_handler(pic_state *, pic_value); +pic_value pic_pop_handler(pic_state *); +void pic_save_point(pic_state *, struct pic_cont *, PIC_JMPBUF *); +void pic_exit_point(pic_state *); + /* do not return from try block! */ #define pic_try \ @@ -353,22 +361,13 @@ void pic_load_cstr(pic_state *, const char *); pic_catch_(PIC_GENSYM(label)) #define pic_try_(cont, handler) \ do { \ - extern pic_value pic_make_cont(pic_state *, struct pic_cont *); \ - extern void pic_push_handler(pic_state *, pic_value proc); \ - extern pic_value pic_pop_handler(pic_state *); \ - extern pic_value pic_native_exception_handler(pic_state *); \ - extern void pic_save_point(pic_state *, struct pic_cont *); \ - extern void pic_exit_point(pic_state *); \ - struct pic_cont cont; \ - pic_save_point(pic, &cont); \ - if (PIC_SETJMP(pic, cont.jmp) == 0) { \ - pic_value handler; \ - handler = pic_lambda(pic, pic_native_exception_handler, 1, pic_make_cont(pic, &cont)); \ - do { \ - pic_push_handler(pic, handler); + PIC_JMPBUF jmp; \ + struct pic_cont *cont = pic_alloca_cont(pic); \ + if (PIC_SETJMP(pic, jmp) == 0) { \ + pic_save_point(pic, cont, &jmp); \ + pic_push_native_handler(pic, cont); #define pic_catch_(label) \ - pic_pop_handler(pic); \ - } while (0); \ + pic_pop_handler(pic); \ pic_exit_point(pic); \ } else { \ goto label; \ diff --git a/extlib/benz/include/picrin/state.h b/extlib/benz/include/picrin/state.h index 2d1566da..eb224086 100644 --- a/extlib/benz/include/picrin/state.h +++ b/extlib/benz/include/picrin/state.h @@ -22,25 +22,6 @@ struct pic_lib { struct pic_dict *exports; }; -struct pic_cont { - PIC_JMPBUF jmp; - - int id; - - struct pic_checkpoint *cp; - ptrdiff_t sp_offset; - ptrdiff_t ci_offset; - ptrdiff_t xp_offset; - size_t arena_idx; - pic_value ptable; - pic_code *ip; - - int retc; - pic_value *retv; - - struct pic_cont *prev; -}; - typedef struct { int argc, retc; pic_code *ip;