catch errors

This commit is contained in:
dzaima 2021-04-15 01:20:50 +03:00
parent 2d43489cd2
commit 889f633bd3
9 changed files with 99 additions and 36 deletions

View File

@ -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; }

10
src/h.h
View File

@ -6,6 +6,7 @@
#include <string.h>
#include <stddef.h>
#include <stdarg.h>
#include <setjmp.h>
#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)

View File

@ -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;

View File

@ -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 (rr<xr) return err("⌜: result rank too large");
if (rr<xr) thrM("⌜: required result rank too large");
HArr_p r = m_harrp(ria);
usz* rsh = arr_shAlloc(r.b, ria, rr);
if (rsh) {
@ -90,15 +90,14 @@ B tbl_c2(B d, B w, B x) { B f = c(Md1D,d)->f;
}
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));

View File

@ -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;

View File

@ -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

View File

@ -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) {

View File

@ -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) {

View File

@ -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)));
}