disallow •ReBQN constructing namespaces, ignore RETD in interactive REPL

This commit is contained in:
dzaima 2023-05-27 16:34:44 +03:00
parent da5280021c
commit c03dd349e4
4 changed files with 41 additions and 21 deletions

View File

@ -105,12 +105,12 @@ B comp_currRe; // ⟨REPL mode ⋄ scope ⋄ compiler ⋄ runtime ⋄ glyphs ⋄
B rt_undo, rt_select, rt_slash, rt_insert, rt_depth, B rt_undo, rt_select, rt_slash, rt_insert, rt_depth,
rt_group, rt_under, rt_find; 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) SGet(x)
usz xia = IA(x); usz xia = IA(x);
if (xia!=6 & xia!=4) thrM("load_compObj: bad item count"); 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) 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); : compileAll(Get(x,0),Get(x,1),Get(x,2),Get(x,3),bi_N, bi_N, src, inc(path), sc, nsResult);
decG(x); decG(x);
return r; return r;
} }
@ -121,11 +121,11 @@ Block* load_compObj(B x, B src, B path, Scope* sc) { // consumes x,src
#if RT_SRC #if RT_SRC
Block* load_compImport(char* name, B bc, B objs, B blocks, B bodies, B inds, B src) { // consumes all 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 #else
Block* load_compImport(char* name, B bc, B objs, B blocks, B bodies) { // consumes all 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 #endif
@ -145,7 +145,7 @@ void switchComp(void) {
} }
#endif #endif
B compObj_c1(B t, B x) { 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); B res = evalFunBlock(block, 0);
ptr_dec(block); ptr_dec(block);
return res; 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 static NOINLINE Block* bqn_compc(B str, B path, B args, B comp, B compArg) { // consumes str,path,args
str = chr_squeeze(str); str = chr_squeeze(str);
PUSH_COMP; 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); dec(path); dec(args);
POP_COMP; popCatch(); POP_COMP; popCatch();
return r; 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 Block* bqn_comp(B str, B path, B args) { // consumes all
return bqn_compc(str, path, args, load_comp, load_compArg); 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); str = chr_squeeze(str);
PUSH_COMP; PUSH_COMP;
B vName = emptyHVec(); B vName = emptyHVec();
B vDepth = emptyIVec(); B vDepth = emptyIVec();
if (repl && (!sc || sc->psc)) thrM("VM compiler: REPL mode must be used at top level scope"); if (loose && (!sc || sc->psc)) thrM("VM compiler: REPL mode must be used at top level scope");
i32 depth = repl? -1 : 0; i32 depth = loose? -1 : 0;
Scope* csc = sc; Scope* csc = sc;
while (csc) { while (csc) {
B vars = listVars(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; csc = csc->psc;
depth++; 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); dec(path); dec(args);
POP_COMP; popCatch(); POP_COMP; popCatch();
return r; return r;
} }
NOINLINE Block* bqn_compSc(B str, B path, B args, Scope* sc, bool repl) { // consumes str,path,args 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 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; B res;
Block* block; Block* block;
if (replMode>0) { 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; comp_currRe = prevRe;
ptr_dec(sc->body); ptr_dec(sc->body);
sc->body = ptr_inc(block->bodies[0]); sc->body = ptr_inc(block->bodies[0]);
@ -512,7 +512,7 @@ void load_init() { // very last init function
#ifdef PRECOMP #ifdef PRECOMP
Block* c = compileAll( Block* c = compileAll(
#include "../build/interp" #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); B interp = evalFunBlock(c, 0); ptr_dec(c);
printI(interp); printI(interp);

View File

@ -141,7 +141,8 @@ typedef struct NextRequest {
static B emptyARMM; 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); usz blIA = IA(block);
if (blIA!=3) thrM("VM compiler: Bad block info size"); if (blIA!=3) thrM("VM compiler: Bad block info size");
SGetU(block) SGetU(block)
@ -314,8 +315,15 @@ Block* compileBlock(B block, Comp* comp, bool* bDone, u32* bc, usz bcIA, B allBl
ret = true; ret = true;
break; 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"); 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); if (nsResult!=0 && depth==0) {
TSADD(newBC, RETD); 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; ret = true;
break; break;
case DFND: { 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 ((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"); if (bDone[id]) thrM("VM compiler: DFND of the same block in multiple places");
bDone[id] = true; 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); TSADD(newBC, bl->ty==0? DFND0 : bl->ty==1? DFND1 : DFND2);
A64(ptr2u64(bl)); A64(ptr2u64(bl));
TSADD(usedBlocks, 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) // 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 // 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); usz bIA = IA(allBlocks);
I32Arr* bca = toI32Arr(bcq); I32Arr* bca = toI32Arr(bcq);
u32* bc = (u32*)bca->a; 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); TALLOC(bool,bDone,bIA);
for (usz i = 0; i < bIA; i++) bDone[i] = false; 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); TFREE(bDone);
ptr_dec(comp); decG(allBlocks); decG(allBodies); dec(tokenInfo); ptr_dec(comp); decG(allBlocks); decG(allBodies); dec(tokenInfo);
return ret; return ret;

View File

@ -154,7 +154,7 @@ struct Scope {
Block* bqn_comp(B str, B path, B args); // consumes all 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* 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); 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 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 void init_comp(B* set, B prim, B sys); // doesn't consume; writes into first 3 elements of set

View File

@ -13,8 +13,20 @@
f•ReBQN {system"all"} F "•internal.Type ↕10" %% "i8arr" f•ReBQN {system"all"} F "•internal.Type ↕10" %% "i8arr"
!"Unknown system function •internal" % f•ReBQN {system"none"} F "•internal.Type ↕10" !"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 {system"range" "add"+ "reverse"} F "•Reverse ¯5 •Add •Range 10" %% 4-10
f•ReBQN{} F "Ah"•internal.Variation"1↑""""" %% " " f•ReBQN{} F "Ah"•internal.Variation"1↑""""" %% " "
F(•ReBQN{repl"none" })({𝕩˜𝕩@+10}•CurrentError) F"a←↕2", F"a←↕3", F"a" %% 01,012,"Undefined identifier"
F(•ReBQN{repl"loose" })({𝕩˜𝕩@+10}•CurrentError) F"a←↕2", F"a←↕3", F"a" %% 01,012,012
F(•ReBQN{repl"strict"})({𝕩˜𝕩@+10}•CurrentError) F"a←↕2", F"a←↕3", F"a" %% 01,"Redefinition",01
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 # •primitives
!´2=•Type¨ ¨•primitives !´2=•Type¨ ¨•primitives
!¨ (•Type¨1¨•primitives)345 !¨ (•Type¨1¨•primitives)345