diff --git a/include/picrin.h b/include/picrin.h index 0af29e40..ac22bea5 100644 --- a/include/picrin.h +++ b/include/picrin.h @@ -3,6 +3,7 @@ #include #include +#include #include "picconf.h" #include "picrin/value.h" @@ -34,6 +35,9 @@ typedef struct { struct pic_irep **irep; size_t ilen, icapa; + jmp_buf *jmp; + const char *errmsg; + struct heap_page *heap; struct pic_object *arena[PIC_ARENA_SIZE]; int arena_idx; @@ -68,7 +72,7 @@ struct pic_proc *pic_codegen(pic_state *, pic_value, struct pic_env *); void pic_abort(pic_state *, const char *); void pic_raise(pic_state *, pic_value); -void pic_error(pic_state *, const char *, ...); +void pic_error(pic_state *, const char *); void pic_debug(pic_state *, pic_value); diff --git a/src/codegen.c b/src/codegen.c index 5ec0c652..808b66e7 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -204,7 +204,7 @@ pic_gen(pic_state *pic, struct pic_irep *irep, pic_value obj, struct pic_env *en b = env_lookup(pic, obj, env, &depth, &idx); if (! b) { - pic_abort(pic, "unbound variable"); + pic_error(pic, "unbound variable"); } if (depth == -1) { /* global */ @@ -218,7 +218,7 @@ pic_gen(pic_state *pic, struct pic_irep *irep, pic_value obj, struct pic_env *en irep->clen++; } else { /* nonlocal */ - pic_abort(pic, "reference to closed variable not supported"); + pic_error(pic, "reference to closed variable not supported"); } break; } @@ -362,7 +362,7 @@ pic_gen(pic_state *pic, struct pic_irep *irep, pic_value obj, struct pic_env *en case PIC_TT_PROC: case PIC_TT_UNDEF: case PIC_TT_PORT: { - pic_abort(pic, "invalid expression given"); + pic_error(pic, "invalid expression given"); } } } @@ -438,6 +438,17 @@ pic_codegen(pic_state *pic, pic_value obj, struct pic_env *env) proc->cfunc_p = false; proc->u.irep = irep = new_irep(pic); + if (! pic->jmp) { + jmp_buf jmp; + + pic->jmp = &jmp; + if (setjmp(*pic->jmp) != 0) { + /* error occured */ + + pic->jmp = NULL; + return NULL; + } + } pic_gen(pic, irep, obj, env); irep->code[irep->clen].insn = OP_STOP; irep->clen++; diff --git a/src/error.c b/src/error.c index 5ac13860..b963b3a9 100644 --- a/src/error.c +++ b/src/error.c @@ -3,6 +3,17 @@ #include "picrin.h" +void +pic_error(pic_state *pic, const char *msg) +{ + pic->errmsg = msg; + if (! pic->jmp) { + puts(msg); + abort(); + } + longjmp(*pic->jmp, 1); +} + void pic_abort(pic_state *pic, const char *msg) { diff --git a/src/main.c b/src/main.c index 82fd2174..d6011621 100644 --- a/src/main.c +++ b/src/main.c @@ -66,13 +66,11 @@ main() /* read */ r = pic_parse(pic, code, &v); if (! r) { /* wait for more input */ - pic_gc_arena_restore(pic, ai); - continue; + goto next; } code[0] = '\0'; if (pic_undef_p(v)) { /* parse error */ - pic_gc_arena_restore(pic, ai); - continue; + goto next; } #if DEBUG @@ -83,6 +81,11 @@ main() /* eval */ proc = pic_codegen(pic, v, pic->global_env); + if (proc == NULL) { + printf("compilation error: %s\n", pic->errmsg); + pic->errmsg = NULL; + goto next; + } v = pic_run(pic, proc, pic_nil_value()); /* print */ @@ -90,6 +93,7 @@ main() pic_debug(pic, v); printf("\n"); + next: pic_gc_arena_restore(pic, ai); } diff --git a/src/state.c b/src/state.c index e954a528..3f9fd836 100644 --- a/src/state.c +++ b/src/state.c @@ -51,6 +51,10 @@ pic_open() pic->glen = 0; pic->gcapa = PIC_GLOBALS_SIZE; + /* error handling */ + pic->jmp = NULL; + pic->errmsg = NULL; + /* GC arena */ pic->arena_idx = 0;