refactor pic_try/catch

This commit is contained in:
Yuichi Nishiwaki 2016-02-20 23:55:40 +09:00
parent 4751131b4f
commit 10aae770c9
4 changed files with 67 additions and 52 deletions

View File

@ -5,9 +5,32 @@
#include "picrin.h" #include "picrin.h"
#include "picrin/object.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 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 */ /* save runtime context */
cont->cp = pic->cp; cont->cp = pic->cp;
cont->sp_offset = pic->sp - pic->stbase; 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; return val;
} }
#define CV_ID 0
#define CV_ESCAPE 1
static pic_value static pic_value
cont_call(pic_state *pic) cont_call(pic_state *pic)
{ {
@ -99,7 +119,9 @@ cont_call(pic_state *pic)
pic_get_args(pic, "*", &argc, &argv); 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 */ /* check if continuation is alive */
for (cc = pic->cc; cc != NULL; cc = cc->prev) { 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"); pic_errorf(pic, "calling dead escape continuation");
} }
cont = pic_data(pic, pic_closure_ref(pic, CV_ESCAPE));
cont->retc = argc; cont->retc = argc;
cont->retv = argv; cont->retv = argv;
pic_load_point(pic, cont); pic_load_point(pic, cont);
PIC_LONGJMP(pic, cont->jmp, 1); PIC_LONGJMP(pic, *cont->jmp, 1);
PIC_UNREACHABLE(); PIC_UNREACHABLE();
} }
@ -125,26 +146,30 @@ cont_call(pic_state *pic)
pic_value pic_value
pic_make_cont(pic_state *pic, struct pic_cont *cont) 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 */ struct pic_cont *
return pic_lambda(pic, cont_call, 2, pic_int_value(pic, cont->id), pic_data_value(pic, cont, &cont_type)); pic_alloca_cont(pic_state *pic)
{
return pic_alloca(pic, sizeof(struct pic_cont));
} }
static pic_value static pic_value
pic_callcc(pic_state *pic, pic_value proc) 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, jmp)) {
return pic_valuesk(pic, cont->retc, cont->retv);
if (PIC_SETJMP(pic, cont.jmp)) {
return pic_valuesk(pic, cont.retc, cont.retv);
} }
else { else {
pic_value val; 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); pic_exit_point(pic);

View File

@ -47,8 +47,8 @@ pic_errorf(pic_state *pic, const char *fmt, ...)
pic_error(pic, "", msg, pic_nil_value(pic)); pic_error(pic, "", msg, pic_nil_value(pic));
} }
pic_value static pic_value
pic_native_exception_handler(pic_state *pic) native_exception_handler(pic_state *pic)
{ {
pic_value err; pic_value err;
@ -61,6 +61,16 @@ pic_native_exception_handler(pic_state *pic)
PIC_UNREACHABLE(); 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 void
pic_push_handler(pic_state *pic, pic_value handler) pic_push_handler(pic_state *pic, pic_value handler)
{ {

View File

@ -345,6 +345,14 @@ void pic_load_cstr(pic_state *, const char *);
pic_in_library(pic, lib); \ pic_in_library(pic, lib); \
} while (0) } 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! */ /* do not return from try block! */
#define pic_try \ #define pic_try \
@ -353,22 +361,13 @@ void pic_load_cstr(pic_state *, const char *);
pic_catch_(PIC_GENSYM(label)) pic_catch_(PIC_GENSYM(label))
#define pic_try_(cont, handler) \ #define pic_try_(cont, handler) \
do { \ do { \
extern pic_value pic_make_cont(pic_state *, struct pic_cont *); \ PIC_JMPBUF jmp; \
extern void pic_push_handler(pic_state *, pic_value proc); \ struct pic_cont *cont = pic_alloca_cont(pic); \
extern pic_value pic_pop_handler(pic_state *); \ if (PIC_SETJMP(pic, jmp) == 0) { \
extern pic_value pic_native_exception_handler(pic_state *); \ pic_save_point(pic, cont, &jmp); \
extern void pic_save_point(pic_state *, struct pic_cont *); \ pic_push_native_handler(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);
#define pic_catch_(label) \ #define pic_catch_(label) \
pic_pop_handler(pic); \ pic_pop_handler(pic); \
} while (0); \
pic_exit_point(pic); \ pic_exit_point(pic); \
} else { \ } else { \
goto label; \ goto label; \

View File

@ -22,25 +22,6 @@ struct pic_lib {
struct pic_dict *exports; 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 { typedef struct {
int argc, retc; int argc, retc;
pic_code *ip; pic_code *ip;