diff --git a/src/load.c b/src/load.c index 101edbe7..0d3969f2 100644 --- a/src/load.c +++ b/src/load.c @@ -105,12 +105,12 @@ B comp_currRe; // ⟨REPL mode ⋄ scope ⋄ compiler ⋄ runtime ⋄ glyphs ⋄ B rt_undo, rt_select, rt_slash, rt_insert, rt_depth, rt_group, rt_under, rt_find; -Block* load_compObj(B x, B src, B path, Scope* sc) { // consumes x,src +Block* load_compObj(B x, B src, B path, Scope* sc, i32 nsResult) { // consumes x,src SGet(x) usz xia = IA(x); if (xia!=6 & xia!=4) thrM("load_compObj: bad item count"); - Block* r = xia==6? compileAll(Get(x,0),Get(x,1),Get(x,2),Get(x,3),Get(x,4),Get(x,5), src, inc(path), sc) - : compileAll(Get(x,0),Get(x,1),Get(x,2),Get(x,3),bi_N, bi_N, src, inc(path), sc); + Block* r = xia==6? compileAll(Get(x,0),Get(x,1),Get(x,2),Get(x,3),Get(x,4),Get(x,5), src, inc(path), sc, nsResult) + : compileAll(Get(x,0),Get(x,1),Get(x,2),Get(x,3),bi_N, bi_N, src, inc(path), sc, nsResult); decG(x); return r; } @@ -121,11 +121,11 @@ Block* load_compObj(B x, B src, B path, Scope* sc) { // consumes x,src #if RT_SRC Block* load_compImport(char* name, B bc, B objs, B blocks, B bodies, B inds, B src) { // consumes all - return compileAll(bc, objs, blocks, bodies, inds, bi_N, src, m_c8vec_0(name), NULL); + return compileAll(bc, objs, blocks, bodies, inds, bi_N, src, m_c8vec_0(name), NULL, 0); } #else Block* load_compImport(char* name, B bc, B objs, B blocks, B bodies) { // consumes all - return compileAll(bc, objs, blocks, bodies, bi_N, bi_N, bi_N, m_c8vec_0(name), NULL); + return compileAll(bc, objs, blocks, bodies, bi_N, bi_N, bi_N, m_c8vec_0(name), NULL, 0); } #endif @@ -145,7 +145,7 @@ void switchComp(void) { } #endif B compObj_c1(B t, B x) { - Block* block = load_compObj(x, bi_N, bi_N, NULL); + Block* block = load_compObj(x, bi_N, bi_N, NULL, 0); B res = evalFunBlock(block, 0); ptr_dec(block); return res; @@ -188,7 +188,7 @@ B bqn_repr(B x) { static NOINLINE Block* bqn_compc(B str, B path, B args, B comp, B compArg) { // consumes str,path,args str = chr_squeeze(str); PUSH_COMP; - Block* r = load_compObj(c2G(comp, incG(compArg), inc(str)), str, path, NULL); + Block* r = load_compObj(c2G(comp, incG(compArg), inc(str)), str, path, NULL, 0); dec(path); dec(args); POP_COMP; popCatch(); return r; @@ -196,13 +196,13 @@ static NOINLINE Block* bqn_compc(B str, B path, B args, B comp, B compArg) { // Block* bqn_comp(B str, B path, B args) { // consumes all return bqn_compc(str, path, args, load_comp, load_compArg); } -Block* bqn_compScc(B str, B path, B args, Scope* sc, B comp, B rt, bool repl) { // consumes str,path,args +Block* bqn_compScc(B str, B path, B args, Scope* sc, B comp, B rt, bool loose, bool noNS) { // consumes str,path,args str = chr_squeeze(str); PUSH_COMP; B vName = emptyHVec(); B vDepth = emptyIVec(); - if (repl && (!sc || sc->psc)) thrM("VM compiler: REPL mode must be used at top level scope"); - i32 depth = repl? -1 : 0; + if (loose && (!sc || sc->psc)) thrM("VM compiler: REPL mode must be used at top level scope"); + i32 depth = loose? -1 : 0; Scope* csc = sc; while (csc) { B vars = listVars(csc); @@ -212,13 +212,13 @@ Block* bqn_compScc(B str, B path, B args, Scope* sc, B comp, B rt, bool repl) { csc = csc->psc; depth++; } - Block* r = load_compObj(c2G(comp, m_hvec4(incG(rt), incG(bi_sys), vName, vDepth), inc(str)), str, path, sc); + Block* r = load_compObj(c2G(comp, m_hvec4(incG(rt), incG(bi_sys), vName, vDepth), inc(str)), str, path, sc, sc!=NULL? (noNS? -1 : 1) : 0); dec(path); dec(args); POP_COMP; popCatch(); return r; } NOINLINE Block* bqn_compSc(B str, B path, B args, Scope* sc, bool repl) { // consumes str,path,args - return bqn_compScc(str, path, args, sc, load_comp, load_rtObj, repl); + return bqn_compScc(str, path, args, sc, load_comp, load_rtObj, repl, false); } B bqn_exec(B str, B path, B args) { // consumes all @@ -335,7 +335,7 @@ B rebqn_exec(B str, B path, B args, B o) { B res; Block* block; if (replMode>0) { - block = bqn_compScc(str, path, args, sc, op[2], op[3], replMode==2); + block = bqn_compScc(str, path, args, sc, op[2], op[3], replMode==2, true); comp_currRe = prevRe; ptr_dec(sc->body); sc->body = ptr_inc(block->bodies[0]); @@ -512,7 +512,7 @@ void load_init() { // very last init function #ifdef PRECOMP Block* c = compileAll( #include "../build/interp" - , bi_N, bi_N, bi_N, bi_N, NULL + , bi_N, bi_N, bi_N, bi_N, NULL, 0 ); B interp = evalFunBlock(c, 0); ptr_dec(c); printI(interp); diff --git a/src/vm.c b/src/vm.c index fe00e57a..a7d099f0 100644 --- a/src/vm.c +++ b/src/vm.c @@ -141,7 +141,8 @@ typedef struct NextRequest { static B emptyARMM; -Block* compileBlock(B block, Comp* comp, bool* bDone, u32* bc, usz bcIA, B allBlocks, B allBodies, B nameList, Scope* sc, i32 depth, i32 myPos) { +Block* compileBlock(B block, Comp* comp, bool* bDone, u32* bc, usz bcIA, B allBlocks, B allBodies, B nameList, Scope* sc, i32 depth, i32 myPos, i32 nsResult) { + assert(sc!=NULL || nsResult==0); usz blIA = IA(block); if (blIA!=3) thrM("VM compiler: Bad block info size"); SGetU(block) @@ -314,8 +315,15 @@ Block* compileBlock(B block, Comp* comp, bool* bDone, u32* bc, usz bcIA, B allBl ret = true; break; case RETD: if(h!=1&h!=0) thrM("VM compiler: RETD expected to be called with no more than 1 item on the stack"); - if (h==1) TSADD(newBC, POPS); - TSADD(newBC, RETD); + if (nsResult!=0 && depth==0) { + if (nsResult==-1) thrM("Cannot construct a namespace for a REPL result"); + assert(nsResult==1); + if (h==0) thrM("No value for REPL expression to return"); + TSADD(newBC, RETN); + } else { + if (h==1) TSADD(newBC, POPS); + TSADD(newBC, RETD); + } ret = true; break; case DFND: { @@ -323,7 +331,7 @@ Block* compileBlock(B block, Comp* comp, bool* bDone, u32* bc, usz bcIA, B allBl if ((u32)id >= IA(allBlocks)) thrM("VM compiler: DFND index out-of-bounds"); if (bDone[id]) thrM("VM compiler: DFND of the same block in multiple places"); bDone[id] = true; - Block* bl = compileBlock(IGetU(allBlocks,id), comp, bDone, bc, bcIA, allBlocks, allBodies, nameList, sc, depth+1, c-bc); + Block* bl = compileBlock(IGetU(allBlocks,id), comp, bDone, bc, bcIA, allBlocks, allBodies, nameList, sc, depth+1, c-bc, 0); TSADD(newBC, bl->ty==0? DFND0 : bl->ty==1? DFND1 : DFND2); A64(ptr2u64(bl)); TSADD(usedBlocks, bl); @@ -444,7 +452,7 @@ Block* compileBlock(B block, Comp* comp, bool* bDone, u32* bc, usz bcIA, B allBl // 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* compileAll(B bcq, B objs, B allBlocks, B allBodies, B indices, B tokenInfo, B src, B path, Scope* sc) { +NOINLINE Block* compileAll(B bcq, B objs, B allBlocks, B allBodies, B indices, B tokenInfo, B src, B path, Scope* sc, i32 nsResult) { usz bIA = IA(allBlocks); I32Arr* bca = toI32Arr(bcq); u32* bc = (u32*)bca->a; @@ -481,7 +489,7 @@ NOINLINE Block* compileAll(B bcq, B objs, B allBlocks, B allBodies, B indices, B } TALLOC(bool,bDone,bIA); for (usz i = 0; i < bIA; i++) bDone[i] = false; - Block* ret = compileBlock(IGetU(allBlocks, 0), comp, bDone, bc, bcIA, allBlocks, allBodies, nameList, sc, 0, 0); + Block* ret = compileBlock(IGetU(allBlocks, 0), comp, bDone, bc, bcIA, allBlocks, allBodies, nameList, sc, 0, 0, nsResult); TFREE(bDone); ptr_dec(comp); decG(allBlocks); decG(allBodies); dec(tokenInfo); return ret; diff --git a/src/vm.h b/src/vm.h index 18046451..56512e65 100644 --- a/src/vm.h +++ b/src/vm.h @@ -154,7 +154,7 @@ struct Scope { Block* bqn_comp(B str, B path, B args); // consumes all Block* bqn_compSc(B str, B path, B args, Scope* sc, bool repl); // consumes str,path,args -Block* compileAll(B bcq, B objs, B blocks, B bodies, B indices, B tokenInfo, B src, B path, Scope* sc); +Block* compileAll(B bcq, B objs, B blocks, B bodies, B indices, B tokenInfo, B src, B path, Scope* sc, i32 nsResult); // nsResult: 0: accept; -1: error; 1: convert to regular RETN Scope* m_scope(Body* body, Scope* psc, u16 varAm, i32 initVarAm, B* initVars); Body* m_body(i32 vam, i32 pos, u32 maxStack, u16 maxPSC); // leaves varData uninitialized void init_comp(B* set, B prim, B sys); // doesn't consume; writes into first 3 elements of set diff --git a/test/cases/system.bqn b/test/cases/system.bqn index 02c2fe20..6875e455 100644 --- a/test/cases/system.bqn +++ b/test/cases/system.bqn @@ -13,8 +13,20 @@ f←•ReBQN {system⇐"all"} ⋄ F "•internal.Type ↕10" %% "i8arr" !"Unknown system function •internal" % f←•ReBQN {system⇐"none"} ⋄ F "•internal.Type ↕10" f←•ReBQN {system⇐⟨"range"‿↕ ⋄ "add"‿+ ⋄ "reverse"‿⌽⟩} ⋄ F "•Reverse ¯5 •Add •Range 10" %% 4-↕10 + f←•ReBQN{⇐} ⋄ F "Ah"•internal.Variation"1↑""""" %% " " +F←(•ReBQN{repl⇐"none" })⎊({𝕩↑˜⊑𝕩⊐@+10}•CurrentError) ⋄ ⟨F"a←↕2", F"a←↕3", F"a"⟩ %% ⟨0‿1,0‿1‿2,"Undefined identifier"⟩ +F←(•ReBQN{repl⇐"loose" })⎊({𝕩↑˜⊑𝕩⊐@+10}•CurrentError) ⋄ ⟨F"a←↕2", F"a←↕3", F"a"⟩ %% ⟨0‿1,0‿1‿2,0‿1‿2⟩ +F←(•ReBQN{repl⇐"strict"})⎊({𝕩↑˜⊑𝕩⊐@+10}•CurrentError) ⋄ ⟨F"a←↕2", F"a←↕3", F"a"⟩ %% ⟨0‿1,"Redefinition",0‿1⟩ + +f ← •ReBQN{repl⇐"none"} ⋄ !6≡•Type F "a⇐1" +f ← •ReBQN{repl⇐"none"} ⋄ !6≡•Type F "⇐" +!"Cannot construct a namespace for a REPL result" % f ← •ReBQN{repl⇐"loose"} ⋄ F "a⇐1" +!"Cannot construct a namespace for a REPL result" % f ← •ReBQN{repl⇐"loose"} ⋄ F "⇐" +!"Cannot construct a namespace for a REPL result" % f ← •ReBQN{repl⇐"strict"} ⋄ F "a⇐1" +!"Cannot construct a namespace for a REPL result" % f ← •ReBQN{repl⇐"strict"} ⋄ F "⇐" + # •primitives !∧´2=•Type¨ ⊑¨•primitives !¨ (•Type¨1⊑¨•primitives)∊3‿4‿5