global name list

This commit is contained in:
dzaima 2021-11-29 00:21:41 +02:00
parent 4af5f3d4a6
commit ef5864afbc
7 changed files with 125 additions and 115 deletions

View File

@ -309,7 +309,7 @@ B count_c2(B t, B w, B x) {
return c2(rt_count, w, x);
}
H_b2i* prevImports;
static H_b2i* prevImports;
i32 getPrevImport(B path) { // -1 for unset, -2 for unfinished
if (prevImports==NULL) prevImports = m_b2i(16);
@ -322,12 +322,38 @@ void setPrevImport(B path, i32 pos) {
bool had; i32 prev = mk_b2i(&prevImports, path, &had);
prevImports->a[prev].val = pos;
}
void fun_gcFn() {
if (prevImports!=NULL) mm_visitP(prevImports);
static H_b2i* globalNames;
static B globalNameList;
i32 str2gid(B s) {
if (globalNames==NULL) {
globalNames = m_b2i(32);
globalNameList = emptyHVec();
}
bool had;
u64 p = mk_b2i(&globalNames, s, &had);
// if(had) print_fmt("str2gid %R → %i\n", s, globalNames->a[p].val); else print_fmt("str2gid %R → %i!!\n", s, a(globalNameList)->ia);
if(had) return globalNames->a[p].val;
i32 r = a(globalNameList)->ia;
globalNameList = vec_add(globalNameList, inc(s));
globalNames->a[p].val = r;
return r;
}
B gid2str(i32 n) {
B r = IGetU(globalNameList, n);
// print_fmt("gid2str %i → %R", n, r);
return r;
}
void fun_gcFn() {
if (prevImports!=NULL) mm_visitP(prevImports);
if (globalNames!=NULL) mm_visitP(globalNames);
mm_visit(globalNameList);
}
void fns_init() {
gc_addFn(fun_gcFn);
TIi(t_funBI,print) = print_funBI;

View File

@ -197,7 +197,7 @@ INS void i_SETMv(B f, B x, Scope* sc, u32 p, u32* bc) { POS_UPD; B r = c2(f,v_ge
INS void i_SETCv(B f, Scope* sc, u32 p, u32* bc) { POS_UPD; B r = c1(f,v_getI(sc, p, false) ); dec(f); v_setI(sc, p, r, true, false); }
INS B i_FLDO(B ns, u32 p, Scope* sc) {
if (!isNsp(ns)) thrM("Trying to read a field from non-namespace");
B r = inc(ns_getU(ns, sc->body->nsDesc->nameList, p));
B r = inc(ns_getU(ns, p));
dec(ns);
return r;
}

View File

@ -175,11 +175,14 @@ NOINLINE Block* bqn_compSc(B str, B path, B args, Scope* sc, bool repl) { // con
i32 depth = repl? -1 : 0;
Scope* csc = sc;
while (csc) {
for (u64 i = 0; i < csc->varAm; i++) {
i32 nameID = csc->body->varIDs[i];
B nl = csc->body->nsDesc->nameList;
vName = vec_add(vName, IGet(nl, nameID));
vDepth = vec_add(vDepth, m_i32(depth));
Body* body = csc->body;
if (csc->varAm) {
B nameList = body->bl->comp->nameList; SGetU(nameList);
for (u64 i = 0; i < csc->varAm; i++) {
i32 nameID = body->varData[i + body->varAm];
vName = vec_add(vName, inc(GetU(nameList, nameID)));
vDepth = vec_add(vDepth, m_i32(depth));
}
}
if (csc->ext) for (u64 i = 0; i < csc->ext->varAm; i++) {
vName = vec_add(vName, inc(csc->ext->vars[i+csc->ext->varAm]));

140
src/ns.c
View File

@ -2,109 +2,91 @@
#include "ns.h"
#include "utils/mut.h"
void m_nsDesc(Body* body, bool imm, u8 ty, B nameList, B varIDs, B exported) { // consumes nameList
void m_nsDesc(Body* body, bool imm, u8 ty, i32 actualVam, B nameList, B varIDs, B exported) { // doesn't consume nameList
if (!isArr(varIDs) || !isArr(exported)) thrM("Bad namespace description information");
usz ia = a(varIDs)->ia;
if (ia!=a(exported)->ia) thrM("Bad namespace description information");
i32 off = (ty==0?0:ty==1?2:3) + (imm?0:3);
i32 vam = ia+off;
i32 actualVam = body->varAm;
// if (vam != body->varAm) thrM("Bad namespace description information"); // arg remapping makes body->varAm unrelated to named variable count
NSDesc* r = mm_alloc(fsizeof(NSDesc, expIDs, i32, actualVam), t_nsDesc);
r->nameList = nameList;
NSDesc* r = mm_alloc(fsizeof(NSDesc, expGIDs, i32, actualVam<2?2:actualVam), t_nsDesc);
r->varAm = vam;
SGetU(varIDs)
SGetU(exported)
for (i32 i = 0; i < actualVam; i++) {
body->varIDs[i] = -1;
r ->expIDs[i] = -1;
body->varData[i] = -1;
r ->expGIDs[i] = -1;
body->varData[i+actualVam] = -1;
}
SGetU(nameList)
for (usz i = 0; i < ia; i++) {
i32 cid = o2i(GetU(varIDs, i));
bool cexp = o2b(GetU(exported, i));
body->varIDs[i+off] = cid;
r->expIDs[i+off] = cexp? cid : -1;
body->varData[i+off + actualVam] = cid;
r->expGIDs[i+off] = cexp? str2gid(GetU(nameList, cid)) : -1;
}
// printf("def %p:\n", r);
// for (usz i = 0; i < vam; i++) printf(" %d: %d %d\n", i, body->varIDs[i], r->expIDs[i]);
body->nsDesc = r;
}
B m_ns(Scope* sc, NSDesc* desc) { // consumes both
NS* r = mm_alloc(sizeof(NS), t_ns);
r->desc = desc;
r->nameList = r->desc->nameList;
r->sc = sc;
return tag(r,NSP_TAG);
}
B ns_getU(B ns, B cNL, i32 nameID) { VTY(ns, t_ns);
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);
NSDesc* d = n->desc;
i32 dVarAm = d->varAm;
if (nameID<0) thrM("Cannot read key with special name");
assert((u64)nameID < a(cNL)->ia);
B dNL = d->nameList;
if (cNL.u != dNL.u) {
B cName = IGetU(cNL, nameID);
SGetU(dNL)
for (i32 i = 0; i < dVarAm; i++) {
i32 dID = d->expIDs[i];
if (dID>=0 && equal(GetU(dNL, dID), cName)) return n->sc->vars[i];
}
} else {
for (i32 i = 0; i < dVarAm; i++) {
if (d->expIDs[i]==nameID) return n->sc->vars[i];
}
}
i32 ia = d->varAm;
for (i32 i = 0; i < ia; i++) if (d->expGIDs[i]==gid) return n->sc->vars[i];
thrM("No key found");
}
B ns_qgetU(B ns, B cNL, i32 nameID) { VTY(ns, t_ns); // TODO somehow merge impl with ns_getU
B ns_qgetU(B ns, i32 gid) { VTY(ns, t_ns);
NS* n = c(NS, ns);
NSDesc* d = n->desc;
i32 dVarAm = d->varAm;
if (nameID<0) return bi_N;
assert((u64)nameID < a(cNL)->ia);
B dNL = d->nameList;
if (cNL.u != dNL.u) {
B cName = IGetU(cNL, nameID);
SGetU(dNL)
for (i32 i = 0; i < dVarAm; i++) {
i32 dID = d->expIDs[i];
if (dID>=0 && equal(GetU(dNL, dID), cName)) return n->sc->vars[i];
}
} else {
for (i32 i = 0; i < dVarAm; i++) {
if (d->expIDs[i]==nameID) return n->sc->vars[i];
}
}
i32 ia = d->varAm;
for (i32 i = 0; i < ia; i++) if (d->expGIDs[i]==gid) return n->sc->vars[i];
return bi_N;
}
B ns_getNU(B ns, B name, bool thrEmpty) { VTY(ns, t_ns);
NS* n = c(NS, ns);
NSDesc* d = n->desc;
i32 dVarAm = d->varAm;
B dNL = d->nameList;
SGetU(dNL)
for (i32 i = 0; i < dVarAm; i++) {
i32 dID = d->expIDs[i];
if (dID>=0 && equal(GetU(dNL, dID), name)) return n->sc->vars[i];
}
i32 gid = str2gid(name);
i32 ia = d->varAm;
for (i32 i = 0; i < ia; i++) if (d->expGIDs[i]==gid) return n->sc->vars[i];
if (thrEmpty) thrM("No key found");
return bi_N;
}
void ns_set(B ns, B name, B val) { VTY(ns, t_ns);
NS* n = c(NS, ns);
Scope* sc = n->sc;
NSDesc* d = n->desc;
i32 dVarAm = d->varAm;
B dNL = d->nameList;
SGetU(dNL)
for (i32 i = 0; i < dVarAm; i++) {
i32 dID = d->expIDs[i];
if (dID>=0 && equal(GetU(dNL, dID), name)) {
dec(n->sc->vars[i]);
n->sc->vars[i] = val;
i32 gid = str2gid(name);
i32 ia = d->varAm;
for (i32 i = 0; i < ia; i++) {
if (d->expGIDs[i]==gid) {
dec(sc->vars[i]);
sc->vars[i] = val;
return;
}
}
@ -112,20 +94,18 @@ void ns_set(B ns, B name, B val) { VTY(ns, t_ns);
}
i32 ns_pos(B ns, B name) { VTY(ns, t_ns);
Body* b = c(NS, ns)->sc->body;
B nameList = c(NS, ns)->desc->nameList;
i32 bVarAm = b->varAm;
SGetU(nameList)
for (i32 i = 0; i < bVarAm; i++) {
i32 id = b->varIDs[i];
if (id>=0) if (equal(GetU(nameList, id), name)) { dec(name); return i; }
NS* n = c(NS, ns);
Body* body = n->sc->body;
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;
}
thrM("No key found");
}
B ns_nameList(NSDesc* d) {
return d->nameList;
}
@ -144,14 +124,13 @@ static void ns_print(B x) {
NSDesc* desc = c(NS,x)->desc;
Scope* sc = c(NS,x)->sc;
i32 am = desc->varAm;
B nl = desc->nameList; SGetU(nl)
bool first = true;
for (i32 i = 0; i < am; i++) {
i32 id = desc->expIDs[i];
i32 id = desc->expGIDs[i];
if (id>=0) {
if (first) first=false;
else printf("");
printRaw(GetU(nl, id));
printRaw(gid2str(id));
printf("");
print(sc->vars[i]);
}
@ -163,14 +142,13 @@ B nsFmt(B x) { // consumes
ACHR('{');
NSDesc* desc = c(NS,x)->desc;
i32 am = desc->varAm;
B nl = desc->nameList; SGetU(nl)
bool first = true;
for (i32 i = 0; i < am; i++) {
i32 id = desc->expIDs[i];
i32 id = desc->expGIDs[i];
if (id>=0) {
if (first) first=false;
else ACHR(U'');
AFMT("%R", GetU(nl, id));
AFMT("%R", gid2str(id));
}
}
AU("⇐}");
@ -178,15 +156,13 @@ B nsFmt(B x) { // consumes
return s;
}
DEF_FREE(nsDesc) { decR(((NSDesc*)x)->nameList); }
static void nsDesc_visit(Value* x) { mm_visit(((NSDesc*)x)->nameList); }
static void nsDesc_print(B x) { printf("(namespace description)"); }
void ns_init() {
TIi(t_ns,freeO) = ns_freeO; TIi(t_nsDesc,freeO) = nsDesc_freeO;
TIi(t_ns,freeF) = ns_freeF; TIi(t_nsDesc,freeF) = nsDesc_freeF;
TIi(t_ns,visit) = ns_visit; TIi(t_nsDesc,visit) = nsDesc_visit;
TIi(t_ns,freeO) = ns_freeO;
TIi(t_ns,freeF) = ns_freeF;
TIi(t_ns,visit) = ns_visit; TIi(t_nsDesc,visit) = noop_visit;
TIi(t_ns,print) = ns_print; TIi(t_nsDesc,print) = nsDesc_print;
}

View File

@ -3,21 +3,24 @@
typedef struct NSDesc {
struct Value;
B nameList;
i32 varAm; // number of items in expIDs (currently equal to sc->varAm/body->varAm)
i32 expIDs[]; // each item is an index in nameList (or -1), and its position is the corresponding position in sc->vars
i32 varAm; // number of items in expGIDs (currently equal to sc->varAm/body->varAm)
i32 expGIDs[]; // for each variable; -1 if not exported, otherwise a gid
} NSDesc;
typedef struct NS {
struct Value;
B nameList; // copy of desc->nameList for quick checking; isn't owned
NSDesc* desc;
Scope* sc;
} NS;
void m_nsDesc(Body* body, bool imm, u8 ty, B nameList, B varIDs, B exported); // consumes nameList
void m_nsDesc(Body* body, bool imm, u8 ty, i32 vam, B nameList, B varIDs, B exported); // doesn't consume nameList
B m_ns(Scope* sc, NSDesc* desc); // consumes both
B ns_getU(B ns, B nameList, i32 nameID); // doesn't consume anything, doesn't increment result
B ns_qgetU(B ns, B nameList, i32 nameID); // ns_getU but return bi_N on fail
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

View File

@ -86,7 +86,7 @@ void print_gStack() {
}
static Body* m_body(i32 vam, i32 pos, u32 maxStack, u16 maxPSC) { // leaves varIDs and nsDesc uninitialized
Body* body = mm_alloc(fsizeof(Body,varIDs,i32,vam), t_body);
Body* body = mm_alloc(fsizeof(Body, varData, i32, vam*2), t_body);
#if JIT_START != -1
body->nvm = NULL;
@ -309,6 +309,8 @@ Block* compileBlock(B block, Comp* comp, bool* bDone, u32* bc, usz bcIA, B allBl
TSADD(bodyReqs, ((NextRequest){.off = TSSIZE(newBC), .pos1 = pos1, .pos2 = imm? U32_MAX : pos2}));
A64(0); if(!imm) A64(0); // to be filled in by later bodyReqs handling
break;
case FLDO: TSADD(newBC, FLDO); TSADD(newBC, str2gid(IGetU(nameList, c[1]))); break;
case ALIM: TSADD(newBC, ALIM); TSADD(newBC, str2gid(IGetU(nameList, c[1]))); break;
default: {
u32* ccpy = c;
while (ccpy!=n) TSADD(newBC, *ccpy++);
@ -327,12 +329,13 @@ Block* compileBlock(B block, Comp* comp, bool* bDone, u32* bc, usz bcIA, B allBl
if (mpsc>U16_MAX) thrM("VM compiler: Block too deep");
Body* body = m_body(vam+(remapArgs? argAm : 0), bcStart, (u32)hM, mpsc);
i32 finalVam = vam+(remapArgs? argAm : 0);
Body* body = m_body(finalVam, bcStart, (u32)hM, mpsc);
if (boIA>2) {
m_nsDesc(body, imm, ty, inc(nameList), GetU(bodyRepr,2), GetU(bodyRepr,3));
m_nsDesc(body, imm, ty, finalVam, nameList, GetU(bodyRepr,2), GetU(bodyRepr,3));
} else {
body->nsDesc = NULL;
for (u64 i = 0; i < vam; i++) body->varIDs[i] = -1;
for (u64 i = 0; i < vam*2; i++) body->varData[i] = -1;
}
if (is1) { bodyMap[pos1-1] = body; if (firstM) { firstM=false; startBodies[i ] = body; if(i==0) firstMPos = TSSIZE(bodies); } }
@ -417,6 +420,8 @@ NOINLINE Block* compile(B bcq, B objs, B allBlocks, B allBodies, B indices, B to
B t = IGetU(tokenInfo,2);
nameList = IGetU(t,0);
}
comp->nameList = inc(nameList);
if (!q_N(src) && !q_N(indices)) {
if (isAtm(indices) || rnk(indices)!=1 || a(indices)->ia!=2) thrM("VM compiler: Bad indices");
for (i32 i = 0; i < 2; i++) {
@ -456,16 +461,14 @@ NOINLINE void v_setR(Scope* pscs[], B s, B x, bool upd) {
B c = sp[i];
if (isVar(c)) {
Scope* sc = pscs[(u16)(c.u>>32)];
i32 nameID = sc->body->varIDs[(u32)c.u];
v_set(pscs, c, ns_getU(x, sc->body->nsDesc->nameList, nameID), upd, true);
v_set(pscs, c, ns_getU(x, pos2gid(sc->body, (u32)c.u)), upd, true);
} else if (isExt(c)) {
ScopeExt* ext = pscs[(u16)(c.u>>32)]->ext;
v_set(pscs, c, ns_getNU(x, ext->vars[(u32)c.u + ext->varAm], true), upd, true);
} else if (isObj(c)) {
assert(v(c)->type == t_fldAlias);
Scope* sc = pscs[0];
FldAlias* cf = c(FldAlias,c);
v_set(pscs, cf->obj, ns_getU(x, sc->body->nsDesc->nameList, cf->p), upd, true);
v_set(pscs, cf->obj, ns_getU(x, cf->p), upd, true);
} else thrM("Assignment: extracting non-name from namespace");
}
return;
@ -486,14 +489,12 @@ NOINLINE bool v_sethR(Scope* pscs[], B s, B x) {
B c = sp[i];
if (isVar(c)) {
Scope* sc = pscs[(u16)(c.u>>32)];
i32 nameID = sc->body->varIDs[(u32)c.u];
B g = ns_qgetU(x, sc->body->nsDesc->nameList, nameID);
B g = ns_qgetU(x, pos2gid(sc->body, (u32)c.u));
if (q_N(g) || !v_seth(pscs, c, g)) return false;
} else if (isObj(c) && v(c)->type==t_fldAlias) {
assert(v(c)->type == t_fldAlias);
Scope* sc = pscs[0];
FldAlias* cf = c(FldAlias,c);
B g = ns_qgetU(x, sc->body->nsDesc->nameList, cf->p);
B g = ns_qgetU(x, cf->p);
if (q_N(g) || !v_seth(pscs, cf->obj, g)) return false;
} else return false;
}
@ -730,7 +731,7 @@ B evalBC(Block* bl, Body* b, Scope* sc) { // doesn't consume
case FLDO: { P(ns) GS_UPD; u32 p = *bc++; POS_UPD;
if (!isNsp(ns)) thrM("Trying to read a field from non-namespace");
ADD(inc(ns_getU(ns, sc->body->nsDesc->nameList, p)));
ADD(inc(ns_getU(ns, p)));
dec(ns);
break;
}
@ -875,7 +876,7 @@ DEF_FREE(block) {
i32 am = c->bodyCount;
for (i32 i = 0; i < am; i++) ptr_decR(c->bodies[i]);
}
DEF_FREE(comp) { Comp* c = (Comp *)x; ptr_decR(c->objs); decR(c->bc); decR(c->src); decR(c->indices); decR(c->path); }
DEF_FREE(comp) { Comp* c = (Comp *)x; ptr_decR(c->objs); decR(c->bc); decR(c->src); decR(c->indices); decR(c->path); decR(c->nameList); }
DEF_FREE(funBl) { FunBlock* c = (FunBlock*)x; ptr_dec(c->sc); ptr_decR(c->bl); }
DEF_FREE(md1Bl) { Md1Block* c = (Md1Block*)x; ptr_dec(c->sc); ptr_decR(c->bl); }
DEF_FREE(md2Bl) { Md2Block* c = (Md2Block*)x; ptr_dec(c->sc); ptr_decR(c->bl); }
@ -908,7 +909,7 @@ void block_visit(Value* x) {
i32 am = c->bodyCount;
for (i32 i = 0; i < am; i++) mm_visitP(c->bodies[i]);
}
void comp_visit(Value* x) { Comp* c = (Comp *)x; mm_visitP(c->objs); mm_visit(c->bc); mm_visit(c->src); mm_visit(c->indices); mm_visit(c->path); }
void comp_visit(Value* x) { Comp* c = (Comp *)x; mm_visitP(c->objs); mm_visit(c->bc); mm_visit(c->src); mm_visit(c->indices); mm_visit(c->path); mm_visit(c->nameList); }
void funBl_visit(Value* x) { FunBlock* c = (FunBlock*)x; mm_visitP(c->sc); mm_visitP(c->bl); }
void md1Bl_visit(Value* x) { Md1Block* c = (Md1Block*)x; mm_visitP(c->sc); mm_visitP(c->bl); }
void md2Bl_visit(Value* x) { Md2Block* c = (Md2Block*)x; mm_visitP(c->sc); mm_visitP(c->bl); }

View File

@ -75,6 +75,7 @@ typedef struct Comp {
B src;
B path;
B indices;
B nameList;
HArr* objs;
u32 blockAm;
} Comp;
@ -121,13 +122,13 @@ struct Body {
Block* bl; // non-owned pointer to corresponding block
NSDesc* nsDesc;
u16 varAm;
i32 varIDs[];
i32 varData[]; // length varAm*2; first half is a gid per var (or -1 if not calculated yet), second half is indexes into nameList
};
struct ScopeExt {
struct Value;
u16 varAm;
B vars[]; // vars has length varAm*2; position varAm and onwards are corresponding names to variables at regular indexes
B vars[]; // has length varAm*2; position varAm and onwards are corresponding names to variables at regular indexes
};
struct Scope {