diff --git a/genRuntime b/genRuntime index 16c98b92..1591902b 100755 --- a/genRuntime +++ b/genRuntime @@ -5,7 +5,7 @@ args←•args path←⊑•args CC ← {𝕨 •FChars ⟨1,path,𝕩⟩ •Import "cc.bqn"} "src/gen/src" •FChars "#define RT_SRC 0"∾@+10 - "src/gen/compiler"CC"c" + "src/gen/compiles"CC"cc" "src/gen/runtime0"CC"r0" "src/gen/runtime1"CC"r1" "src/gen/formatter"CC"f" diff --git a/makefile b/makefile index 8a802ed2..85cf1036 100644 --- a/makefile +++ b/makefile @@ -124,8 +124,8 @@ ${bd}/%.o: src/builtins/%.c src/gen/customRuntime: @echo "Copying precompiled bytecode from the bytecode branch" - git checkout remotes/origin/bytecode src/gen/{compiler,formatter,runtime0,runtime1,src} - git reset src/gen/{compiler,formatter,runtime0,runtime1,src} + git checkout remotes/origin/bytecode src/gen/{compiles,formatter,runtime0,runtime1,src} + git reset src/gen/{compiles,formatter,runtime0,runtime1,src} ${bd}/load.o: src/gen/customRuntime diff --git a/src/builtins/sysfn.c b/src/builtins/sysfn.c index 2b76ce0e..488b1774 100644 --- a/src/builtins/sysfn.c +++ b/src/builtins/sysfn.c @@ -520,13 +520,15 @@ B getRandNS() { return incG(randNS); } static NFnDesc* reBQNDesc; +static B ns_getNUf(B ns, B field) { + B r = ns_getNU(ns, field, false); dec(field); return r; +} B reBQN_c1(B t, B x) { if (!isNsp(x)) thrM("•ReBQN: Argument must be a namespace"); - B replStr = m_str8l("repl"); - B repl = ns_getNU(x, replStr, false); dec(replStr); + B repl = ns_getNUf(x, m_str8l("repl")); + B prim = ns_getNUf(x, m_str8l("primitives")); 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"); - dec(x); Block* initBlock = bqn_comp(m_str8l("\"(REPL initializer)\""), inc(cdPath), m_f64(0)); B scVal; if (replVal==0) { @@ -536,30 +538,17 @@ B reBQN_c1(B t, B x) { scVal = tag(sc,OBJ_TAG); } ptr_dec(initBlock); - return m_nfn(reBQNDesc, m_hVec2(m_f64(replVal), scVal)); + 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); + dec(x); + return m_nfn(reBQNDesc, d.b); } B repl_c2(B t, B w, B x) { vfyStr(x, "REPL", "𝕩"); - B o = nfn_objU(t); - B* op = harr_ptr(o); - i32 replMode = o2iu(op[0]); - Scope* sc = c(Scope, op[1]); - B fullpath; B args = args_path(&fullpath, w, "REPL"); - - B res; - if (replMode>0) { - Block* block = bqn_compSc(x, fullpath, args, sc, replMode==2); - ptr_dec(sc->body); - sc->body = ptr_inc(block->bodies[0]); - res = execBlockInline(block, sc); - ptr_dec(block); - } else { - res = bqn_exec(x, fullpath, args); - } - - return res; + return rebqn_exec(x, fullpath, args, nfn_objU(t)); } B repl_c1(B t, B x) { return repl_c2(t, emptyHVec(), x); @@ -807,6 +796,7 @@ B sh_c2(B t, B w, B x) { B getInternalNS(void); B getMathNS(void); +B getPrimitives(void); static Body* file_nsGen; B sys_c1(B t, B x) { @@ -859,6 +849,7 @@ B sys_c1(B t, B x) { else if (eqStr(c, U"makerand")) r.a[i] = incG(bi_makeRand); else if (eqStr(c, U"rand")) r.a[i] = getRandNS(); else if (eqStr(c, U"rebqn")) r.a[i] = incG(bi_reBQN); + else if (eqStr(c, U"primitives")) r.a[i] = getPrimitives(); else if (eqStr(c, U"fromutf8")) r.a[i] = incG(bi_fromUtf8); else if (eqStr(c, U"path")) r.a[i] = inc(REQ_PATH); else if (eqStr(c, U"name")) r.a[i] = inc(REQ_NAME); diff --git a/src/core/harr.h b/src/core/harr.h index d8c885e1..5f0cd824 100644 --- a/src/core/harr.h +++ b/src/core/harr.h @@ -63,6 +63,7 @@ static void harr_abandon(HArr_p p) { VTY(p.b, t_harrPartial); value_free((Value*)p.c); } +// unsafe-ish things - don't allocate/GC anything before having written to all items static HArr_p m_harrUv(usz ia) { HArr* r = m_arr(fsizeof(HArr,a,B,ia), t_harr, ia); arr_shVec((Arr*)r); diff --git a/src/load.c b/src/load.c index f507df23..e61faa46 100644 --- a/src/load.c +++ b/src/load.c @@ -100,6 +100,7 @@ i64 comp_currEnvPos; B comp_currPath; B comp_currArgs; B comp_currSrc; +B comp_currRe; 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; @@ -124,8 +125,10 @@ Block* load_compImport(B bc, B objs, B blocks, B bodies) { // consumes all #endif B load_comp; +B load_compgen; B load_rtObj; B load_compArg; +B load_glyphs; #if FORMATTER B load_fmt, load_repr; @@ -148,15 +151,16 @@ void load_gcFn() { mm_visit(comp_currPath); mm_visit(comp_currArgs); mm_visit(comp_currSrc); + mm_visit(comp_currRe); mm_visit(rt_invFnReg); mm_visit(rt_invFnSwap); } -NOINLINE Block* bqn_comp(B str, B path, B args) { // consumes all +static NOINLINE Block* bqn_compc(B str, B path, B args, B comp, B compArg) { // consumes str,path,args B prevPath = comp_currPath ; comp_currPath = path; B prevArgs = comp_currArgs ; comp_currArgs = args; B prevSrc = comp_currSrc ; comp_currSrc = str; i64 prevEnvPos = comp_currEnvPos; comp_currEnvPos = envCurr-envStart; - Block* r = load_compObj(c2(load_comp, incG(load_compArg), inc(str)), str, path, NULL); + Block* r = load_compObj(c2(comp, incG(compArg), inc(str)), str, path, NULL); dec(path); dec(args); comp_currPath = prevPath; comp_currArgs = prevArgs; @@ -164,7 +168,10 @@ NOINLINE Block* bqn_comp(B str, B path, B args) { // consumes all comp_currEnvPos = prevEnvPos; return r; } -NOINLINE Block* bqn_compSc(B str, B path, B args, Scope* sc, bool repl) { // consumes str,path,args +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 B prevPath = comp_currPath ; comp_currPath = path; B prevArgs = comp_currArgs ; comp_currArgs = args; B prevSrc = comp_currSrc ; comp_currSrc = str; @@ -191,7 +198,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_hVec4(incG(load_rtObj), incG(bi_sys), vName, vDepth), inc(str)), str, path, sc); + Block* r = load_compObj(c2(comp, m_hVec4(incG(rt), incG(bi_sys), vName, vDepth), inc(str)), str, path, sc); dec(path); dec(args); comp_currPath = prevPath; comp_currArgs = prevArgs; @@ -199,6 +206,9 @@ NOINLINE Block* bqn_compSc(B str, B path, B args, Scope* sc, bool repl) { // con comp_currEnvPos = prevEnvPos; 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); +} B bqn_exec(B str, B path, B args) { // consumes all Block* block = bqn_comp(str, path, args); @@ -206,11 +216,102 @@ B bqn_exec(B str, B path, B args) { // consumes all ptr_dec(block); return res; } -void bqn_setComp(B comp) { // consumes; doesn't unload old comp, but whatever - load_comp = comp; - gc_add(load_comp); + +void init_comp(B* set, B prim) { + if (q_N(prim)) { + set[0] = inc(load_comp); + set[1] = inc(load_rtObj); + set[2] = inc(load_glyphs); + } else { + if (!isArr(prim) || rnk(prim)!=1) thrM("•ReBQN: 𝕩.primitives must be a list"); + usz pia = a(prim)->ia; + usz np[3] = {0}; // number of functions, 1-modifiers, and 2-modifiers + SGetU(prim); + for (usz i = 0; i < pia; i++) { // check and count + B p = GetU(prim, i); + if (!isArr(p) || rnk(p)!=1 || a(p)->ia!=2) thrM("•ReBQN: 𝕩.primitives must consist of glyph-primitive pairs"); + if (!isC32(IGet(p, 0))) thrM("•ReBQN 𝕩.primitives: Glyphs must be characters"); + B v = IGetU(p, 1); + i32 t = isFun(v)? 0 : isMd1(v) ? 1 : isMd2(v) ? 2 : 3; + if (t==3) thrM("•ReBQN 𝕩.primitives: Primitives must be operations"); + np[t]+= 1; + } + + usz i = 0; + HArr_p r = m_harrs(3, &i); + u32* gl[3]; + usz sum = 0; + for (; i < 3; i++) { + usz l = np[i]; + r.a[i] = m_c32arrv(gl+i, l); + np[i] = sum; + sum+= l; + } + harr_fv(r); + + i = 0; + HArr_p prh = m_harrs(pia, &i); + B* rt = prh.a; + for (; i < pia; i++) { + B gv = GetU(prim, i); + B v = IGet(gv, 1); + i32 t = isFun(v) ? 0 : isMd1(v) ? 1 : isMd2(v) ? 2 : 3; + *(gl[t]++) = o2cu(IGet(gv, 0)); + rt[np[t]++] = v; + } + + set[1] = harr_fv(prh); + set[2] = inc(r.b); + set[0] = c1(load_compgen, r.b); + } +} +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]; + } + B* pr = harr_ptr(r); + B* gg = harr_ptr(g); + usz pi = 0; + HArr_p ph = m_harrs(a(r)->ia, &pi); + for (usz gi = 0; gi < 3; gi++) { + usz l = a(gg[gi])->ia; + u32* gp = c32arr_ptr(gg[gi]); + for (usz i = 0; i < l; i++) { + ph.a[pi] = m_hVec2(m_c32(gp[i]), inc(pr[i])); + pi++; + } + pr+= l; + } + return harr_fv(ph); } +B rebqn_exec(B str, B path, B args, B o) { + B prevRe = comp_currRe; comp_currRe = inc(o); + B* op = harr_ptr(o); + i32 replMode = o2iu(op[0]); + Scope* sc = c(Scope, op[1]); + B res; + if (replMode>0) { + Block* 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); + dec(rtsys); + comp_currRe = prevRe; + res = m_funBlock(block, 0); + ptr_dec(block); + } + dec(o); + return res; +} static NOINLINE B m_lvB_0( ) { return emptyHVec(); } static NOINLINE B m_lvB_1(B a ) { return m_hVec1(a); } @@ -227,6 +328,7 @@ void load_init() { // very last init function comp_currPath = bi_N; comp_currArgs = bi_N; comp_currSrc = bi_N; + comp_currRe = 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, @@ -356,11 +458,13 @@ void load_init() { // very last init function B prevAsrt = runtime[n_asrt]; runtime[n_asrt] = bi_casrt; // horrible but GC is off so it's fiiiiiine Block* comp_b = load_compImport( - #include "gen/compiler" + #include "gen/compiles" ); runtime[n_asrt] = prevAsrt; - load_comp = m_funBlock(comp_b, 0); ptr_dec(comp_b); - gc_add(load_comp); + load_glyphs = m_hVec3(m_str32(U"+-×÷⋆√⌊⌈|¬∧∨<>≠=≤≥≡≢⊣⊢⥊∾≍⋈↑↓↕«»⌽⍉/⍋⍒⊏⊑⊐⊒∊⍷⊔!"), m_str32(U"˙˜˘¨⌜⁼´˝`"), m_str32(U"∘○⊸⟜⌾⊘◶⎉⚇⍟⎊")); + load_compgen = m_funBlock(comp_b, 0); ptr_dec(comp_b); + load_comp = c1(load_compgen, inc(load_glyphs)); + gc_add(load_compgen); gc_add(load_comp); gc_add(load_glyphs); #if FORMATTER diff --git a/src/vm.h b/src/vm.h index a0d76ed3..36dc6152 100644 --- a/src/vm.h +++ b/src/vm.h @@ -141,11 +141,13 @@ struct Scope { B vars[]; }; -Block* bqn_comp(B str, B path, B args); -Block* bqn_compSc(B str, B path, B args, Scope* sc, bool repl); +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* 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 varIDs and nsDesc uninitialized +void init_comp(B* set, B prim); // 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 typedef struct Nvm_res { u8* p; B refs; } Nvm_res; Nvm_res m_nvm(Body* b);