From 3d465f21dca224e8b35b72c2b074c4b02cc49ab7 Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Mon, 24 Mar 2014 13:24:37 +0900 Subject: [PATCH] now you can 'throw' exceptions from catch clause --- include/picrin.h | 1 + include/picrin/error.h | 27 ++++++++++++++++++--------- src/error.c | 28 ++++++++++++++++++++++++++++ src/state.c | 1 + 4 files changed, 48 insertions(+), 9 deletions(-) diff --git a/include/picrin.h b/include/picrin.h index 0767b008..34953544 100644 --- a/include/picrin.h +++ b/include/picrin.h @@ -104,6 +104,7 @@ typedef struct { jmp_buf *jmp; struct pic_error *err; + struct pic_jmpbuf *try_jmps; struct pic_heap *heap; struct pic_object *arena[PIC_ARENA_SIZE]; diff --git a/include/picrin/error.h b/include/picrin/error.h index 69db71c9..a4caf63a 100644 --- a/include/picrin/error.h +++ b/include/picrin/error.h @@ -9,6 +9,24 @@ extern "C" { #endif +struct pic_jmpbuf { + jmp_buf here; + jmp_buf *prev_jmp; + struct pic_jmpbuf *prev; +}; + +#define pic_try \ + pic_push_try(pic); \ + if (setjmp(*pic->jmp) == 0) \ + do +#define pic_catch \ + while (pic_pop_try(pic), 0); \ + else \ + if (pic_pop_try(pic), 1) + +void pic_push_try(pic_state *); +void pic_pop_try(pic_state *); + struct pic_error { PIC_OBJECT_HEADER enum pic_error_kind { @@ -24,15 +42,6 @@ struct pic_error { #define pic_error_p(v) (pic_type(v) == PIC_TT_ERROR) #define pic_error_ptr(v) ((struct pic_error *)pic_ptr(v)) -#define pic_try \ - pic_try_helper__(GENSYM(i), GENSYM(here), GENSYM(prev_jmp)) -#define pic_try_helper__(i, here, prev_jmp) \ - for (int i = 0; ! i; ) \ - for (jmp_buf here, *prev_jmp = pic->jmp; ! i; ) \ - for (pic->jmp = &here; ! i++; pic->jmp = prev_jmp) \ - if (setjmp(here) == 0) -#define pic_catch else - pic_value pic_raise_continuable(pic_state *, pic_value); #if defined(__cplusplus) diff --git a/src/error.c b/src/error.c index 42dedae1..d3798f21 100644 --- a/src/error.c +++ b/src/error.c @@ -11,6 +11,34 @@ #include "picrin/string.h" #include "picrin/error.h" +void +pic_push_try(pic_state *pic) +{ + struct pic_jmpbuf *try_jmp; + + try_jmp = pic_alloc(pic, sizeof(struct pic_jmpbuf)); + + try_jmp->prev_jmp = pic->jmp; + pic->jmp = &try_jmp->here; + + try_jmp->prev = pic->try_jmps; + pic->try_jmps = try_jmp; +} + +void +pic_pop_try(pic_state *pic) +{ + struct pic_jmpbuf *prev; + + assert(pic->jmp == &pic->try_jmps->here); + + pic->jmp = pic->try_jmps->prev_jmp; + + prev = pic->try_jmps->prev; + pic_free(pic, pic->try_jmps); + pic->try_jmps = prev; +} + const char * pic_errmsg(pic_state *pic) { diff --git a/src/state.c b/src/state.c index e171ac53..c0a511eb 100644 --- a/src/state.c +++ b/src/state.c @@ -72,6 +72,7 @@ pic_open(int argc, char *argv[], char **envp) /* error handling */ pic->jmp = NULL; pic->err = NULL; + pic->try_jmps = NULL; /* GC arena */ pic->arena_idx = 0;