From a4446716bf5740dfbaa3bca1aef6d9239fe5df4d Mon Sep 17 00:00:00 2001 From: dzaima Date: Sun, 27 Jun 2021 20:23:48 +0300 Subject: [PATCH] compiler errors --- src/builtins/sysfn.c | 27 ++++++++++++++- src/core/stuff.c | 6 ++-- src/core/stuff.h | 9 +++-- src/h.h | 1 - src/load.c | 15 +++++++-- src/main.c | 2 +- src/utils/builtins.h | 2 +- src/vm.c | 79 +++++++++++++++++++++++++++++++++++--------- src/vm.h | 5 ++- 9 files changed, 118 insertions(+), 28 deletions(-) diff --git a/src/builtins/sysfn.c b/src/builtins/sysfn.c index 4b62a473..4d55de0c 100644 --- a/src/builtins/sysfn.c +++ b/src/builtins/sysfn.c @@ -115,7 +115,7 @@ 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); - thrM("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; } @@ -123,6 +123,31 @@ B asrt_c2(B t, B w, B x) { dec(x); thr(w); } +B casrt_c1(B t, B x) { + if (isI32(x) && 1==(i32)x.u) return x; + if (isF64(x) && 1==x.f) return x; + unwindCompiler(); + dec(x); + thrM("Compilation error"); +} +B casrt_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; } + unwindCompiler(); + dec(x); + if (isArr(w) && a(w)->ia==2) { + B w0 = TI(w).getU(w,0); + if (!isArr(w0) || a(w0)->ia<2) goto base; + B s = TI(w).get(w,1); + BS2B w0getU = TI(w0).getU; + AFMT("\n "); + s = vm_fmtPoint(comp_currSrc, s, o2s(w0getU(w0,0)), o2s(w0getU(w0,1))+1); + dec(w); + thr(s); + } + base: + thr(w); +} B sys_c1(B t, B x); B out_c1(B t, B x) { printRaw(x); putchar('\n'); return x; } diff --git a/src/core/stuff.c b/src/core/stuff.c index 261e573f..dc035df9 100644 --- a/src/core/stuff.c +++ b/src/core/stuff.c @@ -113,14 +113,14 @@ NOINLINE B append_fmt(B s, char* p, ...) { char* lp = p; while (*p != 0) { c = *p++; if (c!='%') continue; - if (lp!=p-1) s = vec_join(s, fromUTF8(lp, p-1-lp)); + if (lp!=p-1) AJOIN(fromUTF8(lp, p-1-lp)); switch(c = *p++) { default: printf("Unknown format character '%c'", c); UD; case 'R': { // TODO proper B b = va_arg(a, B); if (isNum(b)) { AFMT("%f", o2f(b)); } else { assert(isArr(b) && rnk(b)==1); - s = vec_join(s, inc(b)); + AJOIN(inc(b)); } break; } @@ -203,7 +203,7 @@ NOINLINE B append_fmt(B s, char* p, ...) { } lp = p; } - if (lp!=p) s = vec_join(s, fromUTF8(lp, p-lp)); + if (lp!=p) AJOIN(fromUTF8(lp, p-lp)); va_end(a); return s; } diff --git a/src/core/stuff.h b/src/core/stuff.h index 1072bcf6..fa528b5a 100644 --- a/src/core/stuff.h +++ b/src/core/stuff.h @@ -103,8 +103,11 @@ static bool isNumEl(u8 elt) { return elt==el_i32 | elt==el_f64; } B m_str8l(char* s); B fromUTF8l(char* x); -#define A8(X) s = vec_join(s,m_str8l(X)) -#define AU(X) s = vec_join(s,fromUTF8l(X)) +#define AJOIN(X) s = vec_join(s,X) // consumes X +#define AOBJ(X) s = vec_add(s,X) // consumes X +#define ACHR(X) AOBJ(m_c32(X)) +#define A8(X) AJOIN(m_str8l(X)) +#define AU(X) AJOIN(fromUTF8l(X)) #define AFMT(...) s = append_fmt(s, __VA_ARGS__) NOINLINE B append_fmt(B s, char* p, ...); @@ -255,5 +258,7 @@ static inline void onFree(Value* x) { } +extern _Thread_local i64 comp_envPos; extern _Thread_local B comp_currPath; extern _Thread_local B comp_currArgs; +extern _Thread_local B comp_currSrc; diff --git a/src/h.h b/src/h.h index c146ef8d..8ec2675f 100644 --- a/src/h.h +++ b/src/h.h @@ -265,7 +265,6 @@ jmp_buf* prepareCatch(); #endif void popCatch(); extern B catchMessage; -extern u64 envPrevHeight; // envStart+prevEnvHeight will give the original envCurr diff --git a/src/load.c b/src/load.c index 3da583fa..4a70ba40 100644 --- a/src/load.c +++ b/src/load.c @@ -53,8 +53,10 @@ B r1Objs[rtLen]; B rtWrap_wrap(B x); // consumes +_Thread_local i64 comp_envPos; _Thread_local B comp_currPath; _Thread_local B comp_currArgs; +_Thread_local B comp_currSrc; B rt_merge, rt_undo, rt_select, rt_slash, rt_join, rt_ud, rt_pick,rt_take, rt_drop, rt_group, rt_under, rt_reverse, rt_indexOf, rt_count, rt_memberOf, rt_find, rt_cell; @@ -95,19 +97,24 @@ B bqn_repr(B x) { // consumes void load_gcFn() { mm_visit(comp_currPath); mm_visit(comp_currArgs); + mm_visit(comp_currSrc); } NOINLINE Block* bqn_comp(B str, B path, B args) { // consumes all comp_currPath = path; comp_currArgs = args; + comp_currSrc = str; + comp_envPos = envCurr-envStart; Block* r = load_compObj(c2(load_comp, inc(load_compArg), inc(str)), str, NULL); dec(path); dec(args); - comp_currArgs = comp_currPath = bi_N; + comp_currPath = comp_currArgs = comp_currSrc = bi_N; return r; } NOINLINE Block* bqn_compSc(B str, B path, B args, Scope* sc, bool repl) { // consumes str,path,args comp_currPath = path; comp_currArgs = args; + comp_currSrc = str; + comp_envPos = envCurr-envStart; B vName = inc(bi_emptyHVec); B vDepth = inc(bi_emptyIVec); if (repl && (!sc || sc->psc)) thrM("VM compiler: REPL mode must be used at top level scope"); @@ -129,7 +136,7 @@ NOINLINE Block* bqn_compSc(B str, B path, B args, Scope* sc, bool repl) { // con } Block* r = load_compObj(c2(load_comp, m_v4(inc(load_rtObj), inc(bi_sys), vName, vDepth), inc(str)), str, sc); dec(path); dec(args); - comp_currArgs = comp_currPath = bi_N; + comp_currPath = comp_currArgs = comp_currSrc = bi_N; return r; } @@ -147,6 +154,7 @@ void bqn_setComp(B comp) { // consumes; doesn't unload old comp, but whatever static inline void load_init() { // very last init function comp_currPath = bi_N; comp_currArgs = bi_N; + comp_currSrc = bi_N; gc_addFn(load_gcFn); B fruntime[] = { /* +-×÷⋆√⌊⌈|¬ */ bi_add , bi_sub , bi_mul , bi_div , bi_pow , bi_root , bi_floor, bi_ceil , bi_stile , bi_not, @@ -265,9 +273,12 @@ static inline void load_init() { // very last init function printAllocStats(); exit(0); #else // use compiler + B prevAsrt = runtime[42]; + runtime[42] = bi_casrt; // horrible but GC is off so it's fiiiiiine Block* comp_b = load_compImport( #include "gen/compiler" ); + runtime[42] = prevAsrt; load_comp = m_funBlock(comp_b, 0); ptr_dec(comp_b); gc_add(load_comp); diff --git a/src/main.c b/src/main.c index 592f21ff..8f8dd306 100644 --- a/src/main.c +++ b/src/main.c @@ -141,7 +141,7 @@ int main(int argc, char* argv[]) { if (startREPL) { repl_init(); while (CATCH) { - printf("Error: "); print(catchMessage); putchar('\n'); + printf("Error: "); printErrMsg(catchMessage); putchar('\n'); vm_pst(envCurr+1, envStart+envPrevHeight); dec(catchMessage); #ifdef HEAP_VERIFY diff --git a/src/utils/builtins.h b/src/utils/builtins.h index 953f9141..ff2682bb 100644 --- a/src/utils/builtins.h +++ b/src/utils/builtins.h @@ -7,7 +7,7 @@ /* sfns.c*/A(shape,"⥊") A(pick,"⊑") A(pair,"{𝕨‿𝕩}") A(select,"⊏") A(slash,"/") A(join,"∾") A(couple,"≍") A(shiftb,"»") A(shifta,"«") A(take,"↑") A(drop,"↓") A(group,"⊔") A(reverse,"⌽") \ /* sort.c*/A(gradeUp,"⍋") A(gradeDown,"⍒") \ /* sysfn.c*/M(type,"•Type") M(decp,"•Decompose") M(primInd,"•PrimInd") M(glyph,"•Glyph") A(fill,"•FillFn") M(sys,"•getsys") A(grLen,"•GroupLen") D(grOrd,"•groupOrd") \ -/* sysfn.c*/M(repr,"•Repr") A(asrt,"!") M(out,"•Out") M(show,"•Show") M(bqn,"•BQN") D(cmp,"•Cmp") A(hash,"•Hash") M(delay,"•Delay") M(makeRand,"•MakeRand") M(exit,"•Exit") \ +/* sysfn.c*/M(repr,"•Repr") A(asrt,"!") A(casrt,"!") M(out,"•Out") M(show,"•Show") M(bqn,"•BQN") D(cmp,"•Cmp") A(hash,"•Hash") M(delay,"•Delay") M(makeRand,"•MakeRand") M(exit,"•Exit") \ /*internal.c*/M(itype,"•internal.Type") M(refc,"•internal.Refc") M(squeeze,"•internal.Squeeze") M(isPure,"•internal.IsPure") A(info,"•internal.Info") \ /*internal.c*/D(variation,"•internal.Variation") A(listVariations,"•internal.ListVariations") M(clearRefs,"•internal.ClearRefs") M(unshare,"•internal.Unshare") diff --git a/src/vm.c b/src/vm.c index 23217ae5..9f5c9cea 100644 --- a/src/vm.c +++ b/src/vm.c @@ -5,6 +5,11 @@ #include "ns.h" #include "utils/utf.h" #include "utils/talloc.h" +#include "utils/mut.h" + +#ifndef UNWIND_COMPILER // whether to hide stackframes of the compiler in compiling errors + #define UNWIND_COMPILER 1 +#endif #define FOR_BC(F) F(PUSH) F(VARO) F(VARM) F(ARRO) F(ARRM) F(FN1C) F(FN2C) F(OP1D) F(OP2D) F(TR2D) \ F(TR3D) F(SETN) F(SETU) F(SETM) F(POPS) F(DFND) F(FN1O) F(FN2O) F(CHKV) F(TR3O) \ @@ -815,26 +820,50 @@ void popCatch() { #endif } +NOINLINE B vm_fmtPoint(B src, B prepend, usz cs, usz ce) { // consumes prepend + BS2B srcGetU = TI(src).getU; + i64 padEnd = (i64)a(prepend)->ia; + i64 padStart = padEnd; + while (padStart>0 && o2cu(srcGetU(prepend,padStart-1))!='\n') padStart--; + B s = prepend; + usz srcL = a(src)->ia; + usz srcS = cs; + while (srcS>0 && o2cu(srcGetU(src,srcS-1))!='\n') srcS--; + usz srcE = srcS; + while (srcEsrcE) ce = srcE; + B srcSl = TI(src).slice(inc(src),srcS); arr_shVec(srcSl, srcE-srcS); + AJOIN(srcSl); + cs-= srcS; + ce-= srcS; + ACHR('\n'); + for (i64 i = padStart; i < padEnd; i++) ACHR(' '); + for (i32 i = 0; i < cs; i++) ACHR(o2cu(srcGetU(src, srcS+i))=='\t'? '\t' : ' '); // ugh tabs + for (i32 i = cs; i < ce; i++) ACHR('^'); + return s; +} + NOINLINE void vm_printPos(Comp* comp, i32 bcPos, i64 pos) { B src = comp->src; if (!isNothing(src) && !isNothing(comp->indices)) { B inds = TI(comp->indices).getU(comp->indices, 0); usz cs = o2s(TI(inds).getU(inds,bcPos)); B inde = TI(comp->indices).getU(comp->indices, 1); usz ce = o2s(TI(inde).getU(inde,bcPos))+1; - int start = pos==-1? 0 : printf(N64d": ", pos); - usz srcL = a(src)->ia; - BS2B srcGetU = TI(src).getU; - usz srcS = cs; - while (srcS>0 && o2cu(srcGetU(src,srcS-1))!='\n') srcS--; - usz srcE = srcS; - while (srcEsrcE) ce = srcE; - cs-= srcS; - ce-= srcS; + // printf(" bcPos=%d\n", bcPos); // in case the pretty error generator is broken + // printf(" inds:%d…%d\n", cs, ce); + // int start = pos==-1? 0 : printf(N64d": ", pos); + // usz srcL = a(src)->ia; + // BS2B srcGetU = TI(src).getU; + // usz srcS = cs; while (srcS>0 && o2cu(srcGetU(src,srcS-1))!='\n') srcS--; + // usz srcE = srcS; while (srcEsrcE) ce = srcE; + // cs-= srcS; ce-= srcS; + // putchar('\n'); + // for (i32 i = 0; i < cs+start; i++) putchar(' '); + // for (i32 i = cs; i < ce; i++) putchar('^'); + // putchar('\n'); + B s = inc(bi_emptyCVec); if (pos!=-1) AFMT("%l: ", pos); + printRaw(vm_fmtPoint(src, s, cs, ce)); putchar('\n'); - for (i32 i = 0; i < cs+start; i++) putchar(' '); - for (i32 i = cs; i < ce; i++) putchar('^'); - putchar('\n'); - // printf(" inds:%d…%d\n", cinds, cinde); } else { if (pos!=-1) printf(N64d": ", pos); printf("source unknown\n"); @@ -861,13 +890,31 @@ NOINLINE void vm_pstLive() { vm_pst(envStart, envCurr+1); } -static void unwindEnv(Env* envNew) { // envNew==envStart-1 for emptying the env stack +void unwindEnv(Env* envNew) { assert(envNew<=envCurr); while (envCurr!=envNew) { envCurr->bcV = BCPOS(envCurr->sc->body, envCurr->bcL); envCurr--; } } +void unwindCompiler() { + #if UNWIND_COMPILER + unwindEnv(envStart+comp_envPos); + #endif +} + +NOINLINE void printErrMsg(B msg) { + if (isArr(msg)) { + BS2B msgGetU = TI(msg).getU; + usz msgLen = a(msg)->ia; + for (usz i = 0; i < msgLen; i++) if (!isC32(msgGetU(msg,i))) goto base; + printRaw(msg); + return; + } + base: + print(msg); +} + NOINLINE NORETURN void thr(B msg) { // printf("gStack %p-%p:\n", gStackStart, gStack); B* c = gStack; @@ -888,7 +935,7 @@ NOINLINE NORETURN void thr(B msg) { longjmp(cf->jmp, 1); } assert(cf==cfStart); - printf("Error: "); print(msg); putchar('\n'); fflush(stdout); + printf("Error: "); printErrMsg(msg); putchar('\n'); fflush(stdout); Env* envEnd = envCurr+1; unwindEnv(envStart-1); vm_pst(envCurr+1, envEnd); diff --git a/src/vm.h b/src/vm.h index c3441b40..6e004e23 100644 --- a/src/vm.h +++ b/src/vm.h @@ -167,7 +167,10 @@ static inline void popEnv() { void vm_pst(Env* s, Env* e); void vm_pstLive(); void vm_printPos(Comp* comp, i32 bcPos, i64 pos); - +NOINLINE B vm_fmtPoint(B src, B prepend, usz cs, usz ce); // consumes prepend +NOINLINE void printErrMsg(B msg); +NOINLINE void unwindEnv(Env* envNew); // envNew==envStart-1 for emptying the env stack +NOINLINE void unwindCompiler(); // unwind to the env of the invocation of the compiler; UB when not in compiler! typedef struct FldAlias {