diff --git a/docs/system.md b/docs/system.md index f2e3f150..55ddfbe5 100644 --- a/docs/system.md +++ b/docs/system.md @@ -5,7 +5,7 @@ See [the BQN specification](https://mlochbaum.github.io/BQN/spec/system.html) fo | function | notes | |---------------|-------| | `•BQN` | | -| `•ReBQN` | Supported options: `repl`, `primitives` | +| `•ReBQN` | Supported options: `repl`; `primitives`; `system` that's not `"safe"` | | `•primitives` | | | `•Import` | | | `•FFI` | see [FFI](#ffi) | diff --git a/src/builtins/sysfn.c b/src/builtins/sysfn.c index 2c266a71..8e3c64dc 100644 --- a/src/builtins/sysfn.c +++ b/src/builtins/sysfn.c @@ -563,6 +563,7 @@ B reBQN_c1(B t, B x) { if (!isNsp(x)) thrM("•ReBQN: Argument must be a namespace"); B repl = ns_getC(x, "repl"); B prim = ns_getC(x, "primitives"); + B sys = ns_getC(x, "system"); i32 replVal = q_N(repl) || eqStr(repl,U"none")? 0 : eqStr(repl,U"strict")? 1 : eqStr(repl,U"loose")? 2 : 3; if (replVal==3) thrM("•ReBQN: Invalid repl value"); Block* initBlock = bqn_comp(m_c8vec_0("\"(REPL initializer)\""), inc(cdPath), m_f64(0)); @@ -574,9 +575,9 @@ B reBQN_c1(B t, B x) { scVal = tag(sc,OBJ_TAG); } ptr_dec(initBlock); - HArr_p d = m_harrUv(5); d.a[0] = m_f64(replVal); d.a[1] = scVal; - d.a[2]=d.a[3]=d.a[4]=bi_N; - init_comp(d.a+2, prim); + HArr_p d = m_harrUv(7); d.a[0] = m_f64(replVal); d.a[1] = scVal; + for (usz i=2; i<7; i++) d.a[i] = bi_N; + init_comp(d.a+2, prim, sys); decG(x); return m_nfn(reBQNDesc, d.b); } @@ -1371,6 +1372,7 @@ B getBitNS() { B getInternalNS(void); B getMathNS(void); B getPrimitives(void); +void getSysvals(B* res); static Body* file_nsGen; @@ -1451,14 +1453,12 @@ static void initFileNS() { ffiloadDesc = registerNFn(m_c32vec_0(U"•FFI"), c1_bad, ffiload_c2); } -B dsv_obj; B sys_c1(B t, B x) { assert(isArr(x)); - B sysvals = dsv_obj; - SGetU(sysvals) - B curr_ns = GetU(sysvals,0); - B curr_vs = GetU(sysvals,1); SGetU(curr_vs) + B tmp[2]; getSysvals(tmp); + B curr_ns = tmp[0]; + B curr_vs = tmp[1]; SGetU(curr_vs) B idxs = indexOf_c2(m_f64(0), incG(curr_ns), incG(x)); SGetU(idxs) B fileNS = m_f64(0); @@ -1537,17 +1537,16 @@ static char* dsv_strs[] = { #undef F }; +B dsv_ns, dsv_vs; void sysfn_init() { usz dsv_num = sizeof(dsv_strs)/sizeof(char*); usz i = 0; - HArr_p dsv_vs = m_harrUv(dsv_num); - #define F(L,N,B) dsv_vs.a[i] = inc(B); i++; + HArr_p dsv_ns0 = m_harrUv(dsv_num); dsv_ns=dsv_ns0.b; gc_add(dsv_ns); + for (usz i = 0; i < dsv_num; i++) dsv_ns0.a[i] = m_c8vec_0(dsv_strs[i]); + HArr_p dsv_vs0 = m_harrUv(dsv_num); dsv_vs=dsv_vs0.b; gc_add(dsv_vs); + #define F(L,N,B) dsv_vs0.a[i] = inc(B); i++; FOR_DEFAULT_SYSVALS(F) #undef F - HArr_p dsv_ns = m_harrUv(dsv_num); - for (usz i = 0; i < dsv_num; i++) dsv_ns.a[i] = m_c8vec_0(dsv_strs[i]); - dsv_obj = m_hVec2(dsv_ns.b, dsv_vs.b); - gc_add(dsv_obj); #if CATCH_ERRORS lastErrMsg = bi_N; diff --git a/src/load.c b/src/load.c index bc387339..7063bebf 100644 --- a/src/load.c +++ b/src/load.c @@ -101,7 +101,7 @@ i64 comp_currEnvPos; B comp_currPath; B comp_currArgs; B comp_currSrc; -B comp_currRe; +B comp_currRe; // ⟨REPL mode ⋄ scope ⋄ compiler ⋄ runtime ⋄ glyphs ⋄ sysval names ⋄ sysval values⟩ B rt_undo, rt_select, rt_slash, rt_pick, rt_take, rt_drop, rt_insert, rt_depth, rt_group, rt_under, rt_reverse, rt_indexOf, rt_count, rt_memberOf, rt_find, rt_transp; @@ -212,7 +212,9 @@ B bqn_exec(B str, B path, B args) { // consumes all return res; } -void init_comp(B* set, B prim) { +extern B dsv_ns, dsv_vs; +B str_all, str_none; +void init_comp(B* set, B prim, B sys) { if (q_N(prim)) { set[0] = inc(load_comp); set[1] = inc(load_rtObj); @@ -256,14 +258,36 @@ void init_comp(B* set, B prim) { set[2] = inc(rb); set[0] = c1(load_compgen, rb); } + if (q_N(sys)) { + all_sys: + set[3] = inc(dsv_ns); + set[4] = inc(dsv_vs); + } else { + if (!isArr(sys) || RNK(sys)!=1) thrM("•ReBQN: 𝕩.system must be a list"); + if (str_all.u==0) { gc_add(str_all = m_c8vec("all",3)); gc_add(str_none = m_c8vec("none",4)); } + if (equal(sys, str_all)) goto all_sys; + if (equal(sys, str_none)) { + set[3] = set[4] = emptyHVec(); + } else { + usz ia = IA(sys); SGetU(sys) + M_HARR(r1, ia); + M_HARR(r2, ia); + for (usz i = 0; i < ia; i++) { + B c = GetU(sys,i); + if (!isArr(c) || RNK(c)!=1 || IA(c)!=2) thrM("•ReBQN: 𝕩.system must be either \"all\", \"none\", or a list of pairs"); + SGet(c) + HARR_ADD(r1, i, Get(c,0)); + HARR_ADD(r2, i, Get(c,1)); + } + set[3] = HARR_FV(r1); + set[4] = HARR_FV(r2); + } + } } B getPrimitives() { B g, r; - if (q_N(comp_currRe)) { - g = load_glyphs; r = load_rtObj; - } else { - B* o = harr_ptr(comp_currRe); g = o[4]; r = o[3]; - } + if (q_N(comp_currRe)) { g=load_glyphs; r=load_rtObj; } + else { B* o = harr_ptr(comp_currRe); g=o[4]; r=o[3]; } B* pr = harr_ptr(r); B* gg = harr_ptr(g); M_HARR(ph, IA(r)); @@ -278,6 +302,12 @@ B getPrimitives() { return HARR_FV(ph); } +extern B dsv_ns, dsv_vs; +void getSysvals(B* res) { + if (q_N(comp_currRe)) { res[0]=dsv_ns; res[1]=dsv_vs; } + else { B* o=harr_ptr(comp_currRe); res[0]=o[5]; res[1]=o[6]; } +} + B rebqn_exec(B str, B path, B args, B o) { B prevRe = comp_currRe; if (CATCH) { comp_currRe = prevRe; rethrow(); } @@ -287,21 +317,21 @@ B rebqn_exec(B str, B path, B args, B o) { i32 replMode = o2iG(op[0]); Scope* sc = c(Scope, op[1]); B res; + Block* block; if (replMode>0) { - Block* 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); comp_currRe = prevRe; ptr_dec(sc->body); sc->body = ptr_inc(block->bodies[0]); res = execBlockInline(block, sc); - ptr_dec(block); } else { B rtsys = m_hVec2(inc(op[3]), incG(bi_sys)); - Block* block = bqn_compc(str, path, args, op[2], rtsys); + block = bqn_compc(str, path, args, op[2], rtsys); decG(rtsys); comp_currRe = prevRe; res = evalFunBlock(block, 0); - ptr_dec(block); } + ptr_dec(block); decG(o); popCatch(); diff --git a/src/vm.h b/src/vm.h index dceae4c1..2871e599 100644 --- a/src/vm.h +++ b/src/vm.h @@ -156,7 +156,7 @@ Block* bqn_compSc(B str, B path, B args, Scope* sc, bool repl); // consumes str, Block* compile(B bcq, B objs, B blocks, B bodies, B indices, B tokenInfo, B src, B path, Scope* sc); 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); // 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 B rebqn_exec(B str, B path, B args, B o); // consumes str,path,args B listVars(Scope* sc); // doesn't consume; returns bi_N if not accessable