diff --git a/src/h.h b/src/h.h index 32ab6a74..76bfc7ac 100644 --- a/src/h.h +++ b/src/h.h @@ -337,6 +337,7 @@ B bqn_fmt(B x); // consumes B bqn_repr(B x); // consumes NOINLINE NORETURN void thr(B b); +NOINLINE NORETURN void rethrow(); NOINLINE NORETURN void thrM(char* s); NOINLINE NORETURN void thrF(char* s, ...); NOINLINE NORETURN void thrOOM(void); diff --git a/src/load.c b/src/load.c index e8d69389..00b309f1 100644 --- a/src/load.c +++ b/src/load.c @@ -96,6 +96,7 @@ B rtWrap_wrap(B x, bool nnbi); // consumes void rtWrap_print(void); +// comp_currEnvPos/comp_currPath/comp_currArgs/comp_currSrc are only valid while evaluating through bqn_comp*; comp_currRe is valid at all times i64 comp_currEnvPos; B comp_currPath; B comp_currArgs; @@ -275,7 +276,10 @@ B getPrimitives() { } B rebqn_exec(B str, B path, B args, B o) { - B prevRe = comp_currRe; comp_currRe = inc(o); + B prevRe = comp_currRe; + if (CATCH) { comp_currRe = prevRe; rethrow(); } + comp_currRe = inc(o); + B* op = harr_ptr(o); i32 replMode = o2iu(op[0]); Scope* sc = c(Scope, op[1]); @@ -296,6 +300,8 @@ B rebqn_exec(B str, B path, B args, B o) { ptr_dec(block); } dec(o); + + popCatch(); return res; } diff --git a/src/vm.c b/src/vm.c index 2b177e5c..d543a622 100644 --- a/src/vm.c +++ b/src/vm.c @@ -1221,18 +1221,17 @@ NOINLINE void printErrMsg(B msg) { } -NOINLINE NORETURN void thr(B msg) { +NOINLINE NORETURN void throwImpl(bool rethrow) { // printf("gStack %p-%p:\n", gStackStart, gStack); B* c = gStack; // while (c>gStackStart) { print(*--c); putchar('\n'); } printf("gStack printed\n"); if (cf>cfStart) { // something wants to catch errors - thrownMsg = msg; cf--; B* gStackNew = gStackStart + cf->gsDepth; assert(gStackNew<=gStack); while (gStack!=gStackNew) dec(*--gStack); - envPrevHeight = envCurr-envStart + 1; + if (!rethrow) envPrevHeight = envCurr-envStart + 1; unwindEnv(envStart + cf->envDepth - 1); @@ -1241,7 +1240,7 @@ NOINLINE NORETURN void thr(B msg) { longjmp(cf->jmp, 1); } else { // uncaught error assert(cf==cfStart); - printf("Error: "); printErrMsg(msg); putchar('\n'); fflush(stdout); + printf("Error: "); printErrMsg(thrownMsg); putchar('\n'); fflush(stdout); Env* envEnd = envCurr+1; unwindEnv(envStart-1); vm_pst(envCurr+1, envEnd); @@ -1253,6 +1252,14 @@ NOINLINE NORETURN void thr(B msg) { } } +NOINLINE NORETURN void thr(B msg) { + thrownMsg = msg; + throwImpl(false); +} +NOINLINE NORETURN void rethrow() { + throwImpl(true); +} + NOINLINE void freeThrown() { dec(thrownMsg); thrownMsg = bi_N;