diff --git a/src/builtins/arithm.c b/src/builtins/arithm.c index 936c351e..9c556d5f 100644 --- a/src/builtins/arithm.c +++ b/src/builtins/arithm.c @@ -2,6 +2,7 @@ #include "../utils/each.h" #include "../builtins.h" #include "../nfns.h" +#include "../ns.h" #include static inline B arith_recm(BB2B f, B x) { @@ -72,12 +73,10 @@ static B mathNS; B getMathNS() { if (mathNS.u == 0) { #define F(X) inc(bi_##X), - B fn = bqn_exec(m_str32(U"{⟨Sin, Cos, Tan, Asin, Acos, Atan ⟩⇐𝕩}"), emptyCVec(), emptySVec()); - B arg = m_caB(6, (B[]){F(sin)F(cos)F(tan)F(asin)F(acos)F(atan)}); + Body* d = m_nnsDesc("sin","cos","tan","asin","acos","atan"); + mathNS = m_nns(d, F(sin)F(cos)F(tan)F(asin)F(acos)F(atan)); #undef F - mathNS = c1(fn,arg); gc_add(mathNS); - dec(fn); } return inc(mathNS); } diff --git a/src/builtins/fns.c b/src/builtins/fns.c index 42e8b763..226bfcd7 100644 --- a/src/builtins/fns.c +++ b/src/builtins/fns.c @@ -343,7 +343,7 @@ i32 str2gid(B s) { B gid2str(i32 n) { B r = IGetU(globalNameList, n); - // print_fmt("gid2str %i → %R", n, r); + // print_fmt("gid2str %i → %R\n", n, r); return r; } diff --git a/src/builtins/internal.c b/src/builtins/internal.c index c6c8565f..f3ab148b 100644 --- a/src/builtins/internal.c +++ b/src/builtins/internal.c @@ -1,6 +1,7 @@ #include "../core.h" #include "../utils/mut.h" #include "../builtins.h" +#include "../ns.h" B itype_c1(B t, B x) { B r; @@ -271,12 +272,10 @@ B getInternalNS() { listVariations_def = m_str8l("if"); gc_addFn(variation_gcRoot); #define F(X) inc(bi_##X), - B fn = bqn_exec(m_str32(U"{⟨ Type, ElType, Refc, Squeeze, IsPure, Info, ListVariations, Variation, ClearRefs, Unshare, DeepSqueeze⟩⇐𝕩}"), emptyCVec(), emptySVec()); - B arg = m_caB(11,(B[]){F(itype)F(elType)F(refc)F(squeeze)F(isPure)F(info)F(listVariations)F(variation)F(clearRefs)F(unshare)F(deepSqueeze)}); + Body* d = m_nnsDesc("type","eltype","refc","squeeze","ispure","info","listvariations","variation","clearrefs","unshare","deepsqueeze"); + internalNS = m_nns(d,F(itype)F(elType)F(refc)F(squeeze)F(isPure)F(info)F(listVariations)F(variation)F(clearRefs)F(unshare)F(deepSqueeze)); #undef F - internalNS = c1(fn,arg); gc_add(internalNS); - dec(fn); } return inc(internalNS); } diff --git a/src/builtins/sysfn.c b/src/builtins/sysfn.c index 93647bb5..2b76ce0e 100644 --- a/src/builtins/sysfn.c +++ b/src/builtins/sysfn.c @@ -297,15 +297,14 @@ B hash_c1(B t, B x) { -static B rand_ns; -static i32 rand_a, rand_b; +static Body* rand_ns; static B rand_rangeName; static NFnDesc* rand_rangeDesc; static B rand_dealName; static NFnDesc* rand_dealDesc; static B rand_subsetName; static NFnDesc* rand_subsetDesc; #define RAND_START Scope* sc = c(NS,nfn_objU(t))->sc; \ - u64 seed = sc->vars[rand_a].u | sc->vars[rand_b].u<<32; -#define RAND_END sc->vars[rand_a].u = seed>>32; \ - sc->vars[rand_a].u = seed&0xFFFFFFFF; + u64 seed = sc->vars[0].u | sc->vars[1].u<<32; +#define RAND_END sc->vars[0].u = seed>>32; \ + sc->vars[1].u = seed&0xFFFFFFFF; B rand_range_c1(B t, B x) { i64 xv = o2i64(x); if (xv<0) thrM("(rand).Range: 𝕩 cannot be negative"); @@ -493,22 +492,19 @@ B rand_subset_c2(B t, B w, B x) { } static NOINLINE void rand_init() { - rand_ns = bqn_exec(m_str32(U"{a←𝕨⋄b←𝕩⋄range⇐0⋄deal⇐0⋄subset⇐0}"), emptyCVec(), emptySVec()); gc_add(rand_ns); + rand_ns = m_nnsDesc("seed1", "seed2", "range", "deal", "subset"); + NSDesc* d = rand_ns->nsDesc; + d->expGIDs[0] = d->expGIDs[1] = -1; rand_rangeName = m_str8l("range"); gc_add(rand_rangeName); rand_rangeDesc = registerNFn(m_str8l("(rand).Range"), rand_range_c1, rand_range_c2); rand_dealName = m_str8l("deal"); gc_add(rand_dealName); rand_dealDesc = registerNFn(m_str8l("(rand).Deal"), rand_deal_c1, rand_deal_c2); rand_subsetName = m_str8l("subset"); gc_add(rand_subsetName); rand_subsetDesc = registerNFn(m_str8l("(rand).Subset"), c1_bad, rand_subset_c2); - B tmp = c2(rand_ns, m_f64(0), m_f64(0)); - rand_a = ns_pos(tmp, m_str8l("a")); - rand_b = ns_pos(tmp, m_str8l("b")); - dec(tmp); } B makeRand_c1(B t, B x) { if (!isNum(x)) thrM("•MakeRand: 𝕩 must be a number"); - if (rand_ns.u==0) rand_init(); - B r = c2(rand_ns, b(x.u>>32), b(x.u&0xFFFFFFFF)); - ns_set(r, rand_rangeName, m_nfn(rand_rangeDesc, incG(r))); - ns_set(r, rand_dealName, m_nfn(rand_dealDesc, incG(r))); - ns_set(r, rand_subsetName, m_nfn(rand_subsetDesc, incG(r))); + if (rand_ns==NULL) rand_init(); + B r = m_nns(rand_ns, b(x.u>>32), b(x.u&0xFFFFFFFF), m_nfn(rand_rangeDesc, bi_N), m_nfn(rand_dealDesc, bi_N), m_nfn(rand_subsetDesc, bi_N)); + Scope* sc = c(NS,r)->sc; + for (i32 i = 2; i < 5; i++) nfn_swapObj(sc->vars[i], inc(r)); return r; } static B randNS; @@ -812,7 +808,7 @@ B sh_c2(B t, B w, B x) { B getInternalNS(void); B getMathNS(void); -static B file_nsGen; +static Body* file_nsGen; B sys_c1(B t, B x) { assert(isArr(x)); usz i = 0; @@ -834,9 +830,8 @@ B sys_c1(B t, B x) { if(!fileNS.u) { REQ_PATH; #define F(X) m_nfn(X##Desc, inc(path)) - B arg = m_caB(6, (B[]){q_N(path)? m_c32(0) : inc(path), F(fileAt), F(list), F(fBytes), F(fChars), F(fLines)}); + fileNS = m_nns(file_nsGen, q_N(path)? m_c32(0) : inc(path), F(fileAt), F(list), F(fBytes), F(fChars), F(fLines)); #undef F - fileNS = c1(file_nsGen,arg); } r.a[i] = inc(fileNS); } @@ -899,5 +894,5 @@ void sysfn_init() { reBQNDesc = registerNFn(m_str8l("(REPL)"), repl_c1, repl_c2); } void sysfnPost_init() { - file_nsGen = bqn_exec(m_str32(U"{⟨path,At,List,Bytes,Chars,Lines⟩⇐𝕩}"), emptyCVec(), emptySVec()); gc_add(file_nsGen); + file_nsGen = m_nnsDesc("path","at","list","bytes","chars","lines"); } diff --git a/src/nfns.h b/src/nfns.h index cea01a28..7ff59e56 100644 --- a/src/nfns.h +++ b/src/nfns.h @@ -21,3 +21,8 @@ static i32 nfn_data(B t) { assert(isVal(t) && v(t)->type == t_nfn); return c(NFn,t)->data; } +static B nfn_swapObj(B t, B n) { // consumes n, returns old value + B p = c(NFn,t)->obj; + c(NFn,t)->obj = n; + return p; +} \ No newline at end of file diff --git a/src/ns.c b/src/ns.c index d6cbbc07..39fd5838 100644 --- a/src/ns.c +++ b/src/ns.c @@ -1,5 +1,6 @@ #include "core.h" #include "ns.h" +#include "vm.h" #include "utils/mut.h" void m_nsDesc(Body* body, bool imm, u8 ty, i32 actualVam, B nameList, B varIDs, B exported) { // doesn't consume nameList @@ -37,15 +38,6 @@ B m_ns(Scope* sc, NSDesc* desc) { // consumes both } -i32 pos2gid(Body* body, i32 pos) { - i32 gid = body->varData[pos]; - if (LIKELY(gid!=-1)) return gid; - - i32 nlIdx = body->varData[pos+body->varAm]; - if (nlIdx==-1) thrM("Cannot use special variable name as namespace key"); - return body->varData[pos] = str2gid(IGetU(body->bl->comp->nameList, nlIdx)); -} - B ns_getU(B ns, i32 gid) { VTY(ns, t_ns); NS* n = c(NS, ns); @@ -93,21 +85,81 @@ void ns_set(B ns, B name, B val) { VTY(ns, t_ns); thrM("No key found"); } -i32 ns_pos(B ns, B name) { VTY(ns, t_ns); - NS* n = c(NS, ns); - Body* body = n->sc->body; + + + +static i32* emptyi32ptr; +static B emptyi32obj; +Body* m_nnsDescF(i32 n, char** names) { + if (emptyi32ptr==NULL) gc_add(emptyi32obj = m_i32arrv(&emptyi32ptr, 0)); + incBy(emptyi32obj, 3); + + usz i = 0; + HArr_p nl = m_harrs(n, &i); + for (; i < n; i++) nl.a[i] = m_str8l(names[i]); + + Comp* comp = mm_alloc(sizeof(Comp), t_comp); + comp->bc = emptyi32obj; + comp->indices = bi_N; + comp->src = bi_N; + comp->path = bi_N; + comp->objs = c(HArr, emptyHVec()); + comp->blockAm = 0; + comp->nameList = harr_fv(nl); + + Block* bl = mm_alloc(fsizeof(Block,bodies,Body*,0), t_block); + bl->ty = 0; bl->imm = true; + bl->comp = comp; + bl->bc = bl->map = emptyi32ptr; + bl->blocks = NULL; + bl->bodyCount = 0; + gc_add(tag(bl, OBJ_TAG)); + + NSDesc* nd = mm_alloc(fsizeof(NSDesc, expGIDs, i32, n<2?2:n), t_nsDesc); + nd->varAm = n; + for (i = 0; i < n; i++) nd->expGIDs[i] = str2gid(nl.a[i]); + + Body* body = m_body(n, 0, 0, 0); + body->nsDesc = nd; + body->bc = (u32*) emptyi32ptr; + body->bl = bl; + for (i = 0; i < n; i++) { + body->varData[i] = nd->expGIDs[i]; + body->varData[i+n] = i; + } + gc_add(tag(body, OBJ_TAG)); + + bl->dyBody = bl->invMBody = bl->invXBody = bl->invWBody = body; + return body; +} + +B m_nnsF(Body* desc, i32 n, B* vals) { + assert(n == desc->varAm); + Scope* sc = m_scope(desc, NULL, n, n, vals); + return m_ns(sc, ptr_inc(desc->nsDesc)); +} + +i32 nns_pos(Body* body, B name) { B nameList = body->bl->comp->nameList; SGetU(nameList); i32 ia = body->varAm; for (i32 i = 0; i < ia; i++) { i32 pos = body->varData[i+ia]; - if (pos>=0 && equal(name, GetU(nameList, pos))) return i; + if (pos>=0 && equal(name, GetU(nameList, pos))) { dec(name); return i; } } thrM("No key found"); } +i32 pos2gid(Body* body, i32 pos) { + i32 gid = body->varData[pos]; + if (LIKELY(gid!=-1)) return gid; + + i32 nlIdx = body->varData[pos+body->varAm]; + if (nlIdx==-1) thrM("Cannot use special variable name as namespace key"); + return body->varData[pos] = str2gid(IGetU(body->bl->comp->nameList, nlIdx)); +} DEF_FREE(ns) { NS* c = (NS*)x; diff --git a/src/ns.h b/src/ns.h index 7f070081..86a36e97 100644 --- a/src/ns.h +++ b/src/ns.h @@ -19,8 +19,15 @@ B ns_getU(B ns, i32 gid); // doesn't consume, doesn't increment result B ns_qgetU(B ns, i32 gid); // ns_getU but return bi_N on fail B ns_getNU(B ns, B name, bool thrEmpty); // doesn't consume anything, doesn't increment result; returns bi_N if doesn't exist and !thrEmpty void ns_set(B ns, B name, B val); // consumes val -i32 ns_pos(B ns, B name); // consumes name; returns an index in sc->vars for any variable, exported or local i32 pos2gid(Body* body, i32 pos); // converts a variable position to a gid; errors on special name variables i32 str2gid(B s); // doesn't consume B gid2str(i32 n); // returns unowned object + + +#define m_nnsDesc(...) ({ char* names_[] = {__VA_ARGS__}; m_nnsDescF(sizeof(names_)/sizeof(char*), names_); }) +#define m_nns(desc, ...) ({ B vals_[] = {__VA_ARGS__}; m_nnsF(desc, sizeof(vals_)/sizeof(char*), vals_); }) + +Body* m_nnsDescF(i32 n, char** names); // adds the result as a permanent GC root +B m_nnsF(Body* desc, i32 n, B* vals); +i32 nns_pos(Body* desc, B name); // consumes name; returns an index in sc->vars for a given variable (exported or local) diff --git a/src/vm.c b/src/vm.c index ebaad598..60d06ddc 100644 --- a/src/vm.c +++ b/src/vm.c @@ -85,7 +85,7 @@ void print_gStack() { } } -static Body* m_body(i32 vam, i32 pos, u32 maxStack, u16 maxPSC) { // leaves varIDs and nsDesc uninitialized +Body* m_body(i32 vam, i32 pos, u32 maxStack, u16 maxPSC) { // leaves varIDs and nsDesc uninitialized Body* body = mm_alloc(fsizeof(Body, varData, i32, vam*2), t_body); #if JIT_START != -1 diff --git a/src/vm.h b/src/vm.h index fb5abe9c..a05a41c9 100644 --- a/src/vm.h +++ b/src/vm.h @@ -144,6 +144,7 @@ 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 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 typedef struct Nvm_res { u8* p; B refs; } Nvm_res; Nvm_res m_nvm(Body* b);