diff --git a/src/builtins/sysfn.c b/src/builtins/sysfn.c index 4d55de0c..543daff5 100644 --- a/src/builtins/sysfn.c +++ b/src/builtins/sysfn.c @@ -140,8 +140,8 @@ B casrt_c2(B t, B w, B x) { 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); + AFMT("\n"); + s = vm_fmtPoint(comp_currSrc, s, comp_currPath, o2s(w0getU(w0,0)), o2s(w0getU(w0,1))+1); dec(w); thr(s); } diff --git a/src/load.c b/src/load.c index 4a70ba40..326b912e 100644 --- a/src/load.c +++ b/src/load.c @@ -60,23 +60,23 @@ _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; -Block* load_compObj(B x, B src, Scope* sc) { // consumes x,src +Block* load_compObj(B x, B src, B path, Scope* sc) { // consumes x,src BS2B xget = TI(x).get; usz xia = a(x)->ia; if (xia!=5 & xia!=3) thrM("load_compObj: bad item count"); - Block* r = xia==5? compile(xget(x,0),xget(x,1),xget(x,2),xget(x,3),xget(x,4), src, sc) - : compile(xget(x,0),xget(x,1),xget(x,2),bi_N, bi_N, src, sc); + Block* r = xia==5? compile(xget(x,0),xget(x,1),xget(x,2),xget(x,3),xget(x,4), src, path, sc) + : compile(xget(x,0),xget(x,1),xget(x,2),bi_N, bi_N, src, path, sc); dec(x); return r; } #include "gen/src" #if RT_SRC -Block* load_compImport(B bc, B objs, B blocks, B inds, B src) { // consumes all - return compile(bc, objs, blocks, inds, bi_N, src, NULL); +Block* load_compImport(B bc, B objs, B blocks, B inds, B src, B path) { // consumes all + return compile(bc, objs, blocks, inds, bi_N, src, path, NULL); } #else Block* load_compImport(B bc, B objs, B blocks) { // consumes all - return compile(bc, objs, blocks, bi_N, bi_N, bi_N, NULL); + return compile(bc, objs, blocks, bi_N, bi_N, bi_N, bi_N, NULL); } #endif @@ -105,7 +105,7 @@ NOINLINE Block* bqn_comp(B str, B path, B args) { // consumes all comp_currArgs = args; comp_currSrc = str; comp_envPos = envCurr-envStart; - Block* r = load_compObj(c2(load_comp, inc(load_compArg), inc(str)), str, NULL); + Block* r = load_compObj(c2(load_comp, inc(load_compArg), inc(str)), str, inc(path), NULL); dec(path); dec(args); comp_currPath = comp_currArgs = comp_currSrc = bi_N; return r; @@ -134,7 +134,7 @@ NOINLINE Block* bqn_compSc(B str, B path, B args, Scope* sc, bool repl) { // con csc = csc->psc; depth++; } - Block* r = load_compObj(c2(load_comp, m_v4(inc(load_rtObj), inc(bi_sys), vName, vDepth), inc(str)), str, sc); + Block* r = load_compObj(c2(load_comp, m_v4(inc(load_rtObj), inc(bi_sys), vName, vDepth), inc(str)), str, inc(path), sc); dec(path); dec(args); comp_currPath = comp_currArgs = comp_currSrc = bi_N; return r; @@ -259,7 +259,7 @@ static inline void load_init() { // very last init function #ifdef PRECOMP Block* c = load_compObj( #include "gen/interp" - , bi_N + , bi_N, bi_N ); B interp = m_funBlock(c, 0); ptr_dec(c); print(interp); diff --git a/src/main.c b/src/main.c index 41cbf7a3..ae02d93d 100644 --- a/src/main.c +++ b/src/main.c @@ -9,7 +9,7 @@ static bool init = false; static void repl_init() { if (init) return; cbqn_init(); - replPath = m_str32(U"REPL"); gc_add(replPath); + replPath = m_str32(U""); gc_add(replPath); Block* initBlock = bqn_comp(m_str32(U"\"(REPL initializer)\""), inc(replPath), m_f64(0)); gsc = m_scope(initBlock->body, NULL, 0, 0, NULL); gc_add(tag(gsc,OBJ_TAG)); ptr_dec(initBlock); diff --git a/src/vm.c b/src/vm.c index 9f5c9cea..0139d11b 100644 --- a/src/vm.c +++ b/src/vm.c @@ -256,7 +256,7 @@ Block* compileBlock(B block, Comp* comp, bool* bDone, u32* bc, usz bcIA, B block // consumes all; assumes arguments are valid (verifies some stuff, but definitely not everything) // if sc isn't NULL, this block must only be evaluated directly in that scope precisely once -NOINLINE Block* compile(B bcq, B objs, B blocks, B indices, B tokenInfo, B src, Scope* sc) { +NOINLINE Block* compile(B bcq, B objs, B blocks, B indices, B tokenInfo, B src, B path, Scope* sc) { usz bIA = a(blocks)->ia; I32Arr* bca = toI32Arr(bcq); u32* bc = (u32*)bca->a; @@ -265,6 +265,7 @@ NOINLINE Block* compile(B bcq, B objs, B blocks, B indices, B tokenInfo, B src, comp->bc = tag(bca, ARR_TAG); comp->indices = indices; comp->src = src; + comp->path = path; comp->objs = toHArr(objs); comp->blockAm = 0; B nameList; @@ -820,20 +821,26 @@ void popCatch() { #endif } -NOINLINE B vm_fmtPoint(B src, B prepend, usz cs, usz ce) { // consumes prepend +NOINLINE B vm_fmtPoint(B src, B prepend, B path, 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); + + i64 ln = 1; + for (usz i = 0; i < srcS; i++) if(o2cu(srcGetU(src, i))=='\n') ln++; + B s = prepend; + if (isArr(path) && a(path)->ia>0) AFMT("%R:%l:\n ", path, ln); + else AFMT("at "); + i64 padEnd = (i64)a(s)->ia; + i64 padStart = padEnd; + while (padStart>0 && o2cu(srcGetU(s,padStart-1))!='\n') padStart--; + + B slice = TI(src).slice(inc(src),srcS); arr_shVec(slice, srcE-srcS); + AJOIN(slice); cs-= srcS; ce-= srcS; ACHR('\n'); @@ -861,8 +868,8 @@ NOINLINE void vm_printPos(Comp* comp, i32 bcPos, i64 pos) { // 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)); + B s = inc(bi_emptyCVec); + printRaw(vm_fmtPoint(src, s, comp->path, cs, ce)); putchar('\n'); } else { if (pos!=-1) printf(N64d": ", pos); diff --git a/src/vm.h b/src/vm.h index 6e004e23..4d7b295d 100644 --- a/src/vm.h +++ b/src/vm.h @@ -61,6 +61,7 @@ typedef struct Comp { struct Value; B bc; B src; + B path; B indices; HArr* objs; u32 blockAm; @@ -122,7 +123,7 @@ struct Scope { Block* bqn_comp(B str, B path, B args); Block* bqn_compSc(B str, B path, B args, Scope* sc, bool repl); -Block* compile(B bcq, B objs, B blocksq, B indices, B tokenInfo, B src, Scope* sc); +Block* compile(B bcq, B objs, B blocksq, B indices, B tokenInfo, B src, B path, Scope* sc); Scope* m_scope(Body* body, Scope* psc, u16 varAm, i32 initVarAm, B* initVars); B execBodyInline(Body* b, Scope* sc); // doesn't consume; executes bytecode of the body directly in the scope @@ -155,8 +156,8 @@ extern Env* envStart; extern Env* envEnd; extern u64 envPrevHeight; // envStart+prevEnvHeight gives envCurr+1 from before the error static inline void pushEnv(Scope* sc, u32* bc) { + if (envCurr+1==envEnd) thrM("Stack overflow"); envCurr++; - if (envCurr==envEnd) thrM("Stack overflow"); envCurr->sc = sc; envCurr->bcL = bc; } @@ -167,7 +168,7 @@ 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 B vm_fmtPoint(B src, B prepend, B path, 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!