From 889f633bd3d3c9e2eb5cbda4d021eb24de68795f Mon Sep 17 00:00:00 2001 From: dzaima Date: Thu, 15 Apr 2021 01:20:50 +0300 Subject: [PATCH] catch errors --- src/arith.c | 14 +++++------ src/h.h | 10 +++++++- src/main.c | 6 +++++ src/md1.c | 18 ++++++------- src/mm_2buddy.c | 2 +- src/mm_buddy.c | 2 +- src/mm_buddyTemplate.c | 20 +++++++-------- src/sysfn.c | 6 ++--- src/vm.c | 57 +++++++++++++++++++++++++++++++++++++++++- 9 files changed, 99 insertions(+), 36 deletions(-) diff --git a/src/arith.c b/src/arith.c index 5912051c..07d0ee32 100644 --- a/src/arith.c +++ b/src/arith.c @@ -4,7 +4,7 @@ #define ffnx(name, expr, extra) B name(B t, B w, B x) { \ if (isF64(w) & isF64(x)) return m_f64(expr); \ extra \ - return err(#name ": invalid arithmetic"); \ + thrM(#name ": invalid arithmetic"); \ } #define ffn(name, op, extra) ffnx(name, w.f op x.f, extra) @@ -51,12 +51,12 @@ B eq_c2(B t, B w, B x) { B add_c1(B t, B x) { return x; } -B sub_c1(B t, B x) { if (isF64(x)) return m_f64( -x.f ); return err("negating non-number"); } -B mul_c1(B t, B x) { if (isF64(x)) return m_f64(x.f?x.f>0?1:-1:0); return err("getting sign of non-number"); } -B div_c1(B t, B x) { if (isF64(x)) return m_f64( 1/x.f ); return err("getting reciprocal of non-number"); } -B pow_c1(B t, B x) { if (isF64(x)) return m_f64( exp(x.f)); return err("getting exp of non-number"); } -B floor_c1(B t, B x) { if (isF64(x)) return m_f64(floor(x.f)); return err("getting floor of non-number"); } -B log_c1(B t, B x) { if (isF64(x)) return m_f64( log(x.f)); return err("getting log of non-number"); } +B sub_c1(B t, B x) { if (isF64(x)) return m_f64( -x.f ); thrM("negating non-number"); } +B mul_c1(B t, B x) { if (isF64(x)) return m_f64(x.f?x.f>0?1:-1:0); thrM("getting sign of non-number"); } +B div_c1(B t, B x) { if (isF64(x)) return m_f64( 1/x.f ); thrM("getting reciprocal of non-number"); } +B pow_c1(B t, B x) { if (isF64(x)) return m_f64( exp(x.f)); thrM("getting exp of non-number"); } +B floor_c1(B t, B x) { if (isF64(x)) return m_f64(floor(x.f)); thrM("getting floor of non-number"); } +B log_c1(B t, B x) { if (isF64(x)) return m_f64( log(x.f)); thrM("getting log of non-number"); } B eq_c1(B t, B x) { B r = m_i32(isArr(x)? rnk(x) : 0); decR(x); return r; } diff --git a/src/h.h b/src/h.h index 0921dbd4..3dc65dec 100644 --- a/src/h.h +++ b/src/h.h @@ -6,6 +6,7 @@ #include #include #include +#include #define i8 int8_t #define u8 uint8_t @@ -20,6 +21,7 @@ #define U16_MAX ((u16)-1) #define UD __builtin_unreachable(); #define NOINLINE __attribute__ ((noinline)) +#define NORETURN __attribute__ ((noreturn)) #define usz u32 #define ur u8 @@ -180,7 +182,6 @@ u64 mm_size(Value* x); u64 mm_heapAllocated(); u64 mm_heapUsed(); - void mm_forHeap(V2v f); B mm_alloc(usz sz, u8 type, u64 tag) { assert(tag>1LL<<16 || tag==0); // make sure it's `ftag`ged :| @@ -198,6 +199,13 @@ B m_v1(B a ); B m_v2(B a, B b ); B m_v3(B a, B b, B c ); B m_v4(B a, B b, B c, B d); +B m_str32(u32* s); +NORETURN void thr(B b); +NORETURN void thrM(char* s); +jmp_buf* prepareCatch(); // use with `if (setjmp(prepareCatch())) { /*catch*/ } /*regular execution*/` +void popCatch(); +B catchMessage; + #define c(T,x) ((T*)((x).u&0xFFFFFFFFFFFFull)) #define v(x) c(Value, x) diff --git a/src/main.c b/src/main.c index 5ffff577..a2343541 100644 --- a/src/main.c +++ b/src/main.c @@ -167,6 +167,12 @@ int main() { // comp = m_funBlock(cbc_b, 0); // free(c_src); // } + while (setjmp(*prepareCatch())) { + printf("caught: "); + print(catchMessage); + puts(""); + dec(catchMessage); + } while (true) { // exit by evaluating an empty expression char* ln = NULL; size_t gl = 0; diff --git a/src/md1.c b/src/md1.c index 6716bd6f..4dc72549 100644 --- a/src/md1.c +++ b/src/md1.c @@ -1,7 +1,7 @@ #include "h.h" B tbl_c1(B d, B x) { B f = c(Md1D,d)->f; - if (!isArr(x)) return err("⌜: argument was atom"); + if (!isArr(x)) thrM("⌜: argument cannot be an atom"); usz ia = a(x)->ia; if (ia==0) return x; BS2B xget = TI(x).get; @@ -70,7 +70,7 @@ B tbl_c2(B d, B w, B x) { B f = c(Md1D,d)->f; usz wia = a(w)->ia; ur wr = rnk(w); usz xia = a(x)->ia; ur xr = rnk(x); usz ria = wia*xia; ur rr = wr+xr; - if (rrf; } dec(w); dec(x); return r.b; - } else return err("⌜: one argument was an atom"); + } else thrM("⌜: 𝕨 and 𝕩 must be arrays"); } B scan_c1(B d, B x) { B f = c(Md1D,d)->f; - if (!isArr(x)) return err("`: argument cannot be a scalar"); + if (!isArr(x) || rnk(x)==0) thrM("`: argument cannot have rank 0"); ur xr = rnk(x); usz ia = a(x)->ia; - if (xr==0) return err("`: argument cannot be a scalar"); if (ia==0) return x; bool reuse = v(x)->type==t_harr && reusable(x); HArr_p r = reuse? harr_parts(inc(x)) : m_harrc(x); @@ -115,23 +114,22 @@ B scan_c1(B d, B x) { B f = c(Md1D,d)->f; return r.b; } B scan_c2(B d, B w, B x) { B f = c(Md1D,d)->f; - if (!isArr(x)) return err("`: 𝕩 cannot be a scalar"); + if (!isArr(x) || rnk(x)==0) thrM("`: 𝕩 cannot have rank 0"); ur xr = rnk(x); usz* xsh = a(x)->sh; usz ia = a(x)->ia; bool reuse = v(x)->type==t_harr && reusable(x); HArr_p r = reuse? harr_parts(inc(x)) : m_harrc(x); BS2B xget = reuse? TI(x).getU : TI(x).get; if (isArr(w)) { ur wr = rnk(w); usz* wsh = a(w)->sh; BS2B wget = TI(w).get; - if (xr==0) return err("`: 𝕩 cannot be a scalar"); - if (wr+1 != xr) return err("`: shape of 𝕨 must match the cell of 𝕩"); - if (memcmp(wsh, xsh+1, wr)) return err("`: shape of 𝕨 must match the cell of 𝕩"); + if (wr+1 != xr) thrM("`: shape of 𝕨 must match the cell of 𝕩"); + if (memcmp(wsh, xsh+1, wr)) thrM("`: shape of 𝕨 must match the cell of 𝕩"); if (ia==0) { ptr_dec(r.c); return x; } // only safe as r would have 0 items too usz csz = arr_csz(x); for (usz i = 0; i < csz; i++) r.a[i] = c2(f, wget(w,i), xget(x,i)); for (usz i = csz; i < ia; i++) r.a[i] = c2(f, inc(r.a[i-csz]), xget(x,i)); dec(w); } else { - if (xr!=1) return err("`: if 𝕨 is scalar, 𝕩 must be a vector"); + if (xr!=1) thrM("`: shape of 𝕨 must match the cell of 𝕩"); if (ia==0) { ptr_dec(r.c); return x; } B pr = r.a[0] = c2(f, w, xget(x,0)); for (usz i = 1; i < ia; i++) r.a[i] = pr = c2(f, inc(pr), xget(x,i)); diff --git a/src/mm_2buddy.c b/src/mm_2buddy.c index 82d4382f..f95bc6a4 100644 --- a/src/mm_2buddy.c +++ b/src/mm_2buddy.c @@ -37,7 +37,7 @@ struct EmptyValue { // needs set: mmInfo; type=t_empty; next; everything else ca u64 currObjCounter; #endif void* mm_allocN(usz sz, u8 type) { - assert(sz>12); + assert(sz>=16); onAlloc(sz, type); u8 b1 = 64-__builtin_clzl(sz-1ull); Value* r; diff --git a/src/mm_buddy.c b/src/mm_buddy.c index 0d8c752c..63cff641 100644 --- a/src/mm_buddy.c +++ b/src/mm_buddy.c @@ -23,7 +23,7 @@ struct EmptyValue { // needs set: mmInfo; type=t_empty; next; everything else ca u64 currObjCounter; #endif void* mm_allocN(usz sz, u8 type) { - assert(sz>8); + assert(sz>=16); onAlloc(sz, type); Value* r = mm_allocL(BSZI(sz), type); #ifdef OBJ_COUNTER diff --git a/src/mm_buddyTemplate.c b/src/mm_buddyTemplate.c index 48a90bf3..c66b54ba 100644 --- a/src/mm_buddyTemplate.c +++ b/src/mm_buddyTemplate.c @@ -56,20 +56,18 @@ static NOINLINE EmptyValue* BN(makeEmpty)(u8 bucket) { // result->next is garbag void BN(free)(Value* x) { onFree(x); - EmptyValue* c = (EmptyValue*) x; - #ifdef DONT_FREE - if (c->type!=t_freed) c->flags = c->type; - #else - u8 b = c->mmInfo&63; - c->next = buckets[b]; - buckets[b] = c; - #endif - c->type = t_empty; #ifdef USE_VALGRIND - VALGRIND_MAKE_MEM_NOACCESS(x, BSZ(c->mmInfo&63)); - VALGRIND_MAKE_MEM_DEFINED(&x->type, 1); + VALGRIND_MAKE_MEM_UNDEFINED(x, BSZ(x->mmInfo&63)); VALGRIND_MAKE_MEM_DEFINED(&x->mmInfo, 1); #endif + #ifdef DONT_FREE + if (x->type!=t_freed) x->flags = x->type; + #else + u8 b = x->mmInfo&63; + ((EmptyValue*)x)->next = buckets[b]; + buckets[b] = (EmptyValue*)x; + #endif + x->type = t_empty; } void* BN(allocL)(u8 bucket, u8 type) { diff --git a/src/sysfn.c b/src/sysfn.c index 0d80ac06..22afcc1c 100644 --- a/src/sysfn.c +++ b/src/sysfn.c @@ -107,15 +107,13 @@ B asrt_c1(B t, B x) { if (isI32(x) && 1==(i32)x.u) return x; if (isF64(x) && 1==x.f) return x; dec(x); - return err("assertion error"); + thrM("assertion error"); } B asrt_c2(B t, B w, B x) { if (isI32(x) && 1==(u32)x.u) { dec(w); return x; } if (isF64(x) && 1==x.f) { dec(w); return x; } dec(x); - printf("Assertion error: "); fflush(stdout); print(w); printf("\n"); - dec(w); - return err("assertion error with message"); + thr(w); } B internal_c2(B t, B w, B x) { diff --git a/src/vm.c b/src/vm.c index 50b676d5..55d1c4f4 100644 --- a/src/vm.c +++ b/src/vm.c @@ -257,7 +257,7 @@ i32* vmStack; i32 bcCtr = 0; #endif -B* gStack; +B* gStack; // points to after end B* gStackStart; B* gStackEnd; @@ -518,3 +518,58 @@ void print_vmStack() { printf("\n"); fflush(stdout); #endif } + + + +typedef struct CatchFrame { + jmp_buf jmp; + u64 gStackDepth; + u64 cfDepth; +} CatchFrame; +CatchFrame* cf; // points to after end +CatchFrame* cfStart; +CatchFrame* cfEnd; + +jmp_buf* prepareCatch() { // in the case of returning false, must call popCatch(); + if (cf==cfEnd) { + u64 n = cfEnd-cfStart; + n = n<8? 8 : n*2; + u64 d = cfStart-cf; + cfStart = realloc(cfStart, n*sizeof(CatchFrame)); + cf = cfStart+d; + cfEnd = cfStart+n; + } + cf->cfDepth = cf-cfStart; + cf->gStackDepth = gStack-gStackStart; + return &(cf++)->jmp; +} +void popCatch() { + assert(cf>cfStart); + cf--; +} + +NORETURN void thr(B msg) { + if (cf>cfStart) { + catchMessage = msg; + cf--; + + B* gStackNew = gStackStart + cf->gStackDepth; + if (gStackNew>gStack) err("bad catch gStack"); + // while (gStack!=gStackNew) dec(*--gStack); + gStack = gStackNew; + + cf = cfStart + cf->cfDepth; + longjmp(cf->jmp, 1); + printf("wat\n"); + } + assert(cf==cfStart); + printf("Error: "); + print(msg); + puts(""); + // exit(1); + __builtin_trap(); +} + +NORETURN void thrM(char* s) { + thr(fromUTF8(s, strlen(s))); +} \ No newline at end of file