From 0dede67d2ae5aeae6e594d4971d95af5147feda3 Mon Sep 17 00:00:00 2001 From: dzaima Date: Sun, 9 May 2021 16:00:02 +0300 Subject: [PATCH] namespaces --- src/h.h | 6 ++- src/main.c | 24 ++++++----- src/md2.c | 2 +- src/ns.c | 115 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/ns.h | 9 ++++ src/stuff.c | 2 +- src/vm.c | 103 +++++++++++++++++++++++++++++++++------------- 7 files changed, 218 insertions(+), 43 deletions(-) create mode 100644 src/ns.c create mode 100644 src/ns.h diff --git a/src/h.h b/src/h.h index bc2dfe29..c476475c 100644 --- a/src/h.h +++ b/src/h.h @@ -69,9 +69,10 @@ enum Type { /*18*/ t_hslice, t_i32slice, t_fillslice, t_c32slice, t_f64slice, /*22*/ t_comp, t_block, t_body, t_scope, - /*26*/ t_freed, t_harrPartial, + /*26*/ t_ns, t_nsDesc, + /*27*/ t_freed, t_harrPartial, #ifdef RT_PERF - /*28*/ t_funPerf, t_md1Perf, t_md2Perf, + /*29*/ t_funPerf, t_md1Perf, t_md2Perf, #endif t_COUNT }; @@ -346,6 +347,7 @@ i32 o2cu (B x) { return (u32)x.u; } usz o2su (B x) { return (usz)x.f; } f64 o2fu (B x) { return x.f; } i64 o2i64u(B x) { return (i64)x.f; } +bool o2b (B x) { usz t=o2s(x); if(t!=0&t!=1)thrM("Expected boolean"); return t; } bool q_i32(B x) { return isI32(x) | (isF64(x) && x.f==(f64)(i32)x.f); } bool q_f64(B x) { return isF64(x) || isI32(x); } diff --git a/src/main.c b/src/main.c index 0e026a41..c1c0534e 100644 --- a/src/main.c +++ b/src/main.c @@ -50,6 +50,7 @@ #include "md1.c" #include "md2.c" #include "vm.c" +#include "ns.c" #include "rtPerf.c" void pr(char* a, B b) { @@ -60,12 +61,15 @@ void pr(char* a, B b) { fflush(stdout); } -Block* ca3(B x) { - B* xp = harr_ptr(x); - Block* r = compile(inc(xp[0]),inc(xp[1]),inc(xp[2])); +Block* compB(B x) { + BS2B xget = TI(x).get; + Block* r = compile(xget(x,0),xget(x,1),xget(x,2),xget(x,3),xget(x,4)); dec(x); return r; } +Block* compile3(B bc, B objs, B blocks) { + return compile(bc, objs, blocks, bi_N, bi_N); +} int main() { @@ -99,14 +103,14 @@ int main() { #ifndef ALL_R0 B runtime_0[] = {bi_floor,bi_ceil,bi_stile,bi_lt,bi_gt,bi_ne,bi_ge,bi_rtack,bi_ltack,bi_join,bi_take,bi_drop,bi_select,bi_const,bi_swap,bi_each,bi_fold,bi_atop,bi_over,bi_before,bi_after,bi_cond,bi_repeat}; #else - Block* runtime0_b = compile( + Block* runtime0_b = compile3( #include "runtime0" ); B r0r = m_funBlock(runtime0_b, 0); ptr_dec(runtime0_b); B* runtime_0 = toHArr(r0r)->a; #endif - Block* runtime_b = compile( + Block* runtime_b = compile3( #include "runtime1" ); @@ -153,14 +157,14 @@ int main() { // uncomment to use src/interp; needed for test.bqn - // Block* c = ca3( + // Block* c = compB( // #include "interp" // ); // B interp = m_funBlock(c, 0); ptr_dec(c); // pr("result: ", interp); // exit(0); - Block* comp_b = compile( + Block* comp_b = compile3( #include "compiler" ); B comp = m_funBlock(comp_b, 0); ptr_dec(comp_b); @@ -168,7 +172,7 @@ int main() { #ifdef FORMATTER - Block* fmt_b = compile( + Block* fmt_b = compile3( #include "formatter" ); B fmtM = m_funBlock(fmt_b, 0); ptr_dec(fmt_b); @@ -195,7 +199,7 @@ int main() { // } // if (c_src) { // B cbc = c2(comp, inc(compArg), fromUTF8(c_src, c_len)); - // Block* cbc_b = ca3(cbc); + // Block* cbc_b = compB(cbc); // comp = m_funBlock(cbc_b, 0); ptr_dec(cbc_b); // gc_add(comp); // free(c_src); @@ -215,7 +219,7 @@ int main() { if (ln[0]==0 || ln[0]==10) break; B cbc = c2(comp, inc(compArg), fromUTF8(ln, strlen(ln))); free(ln); - Block* cbc_b = ca3(cbc); + Block* cbc_b = compB(cbc); #ifdef TIME u64 sns = nsTime(); diff --git a/src/md2.c b/src/md2.c index 1751215a..def30f2c 100644 --- a/src/md2.c +++ b/src/md2.c @@ -78,7 +78,7 @@ B repeat_replace(B g, B* q) { // doesn't consume if (min) { \ B x2 = inc(x); \ B fi = m1_d(inc(rt_undo), inc(f)); \ - for (u64 i = 0; i < min; i++) q[-1-i] = inc(x2 = CN(fi, __VA_ARGS__ x2)); \ + for (i64 i = 0; i < min; i++) q[-1-i] = inc(x2 = CN(fi, __VA_ARGS__ x2)); \ dec(x2); \ dec(fi); \ } \ diff --git a/src/ns.c b/src/ns.c new file mode 100644 index 00000000..372acebf --- /dev/null +++ b/src/ns.c @@ -0,0 +1,115 @@ +#include "ns.h" + +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 +} 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 + 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; + if (vam != body->varAm) thrM("Bad namespace description information"); + + NSDesc* rc = c(NSDesc, mm_alloc(fsizeof(NSDesc, expIDs, i32, vam), t_nsDesc, ftag(OBJ_TAG))); + rc->nameList = nameList; + rc->varAm = vam; + BS2B getIDU = TI(varIDs).getU; + BS2B getOnU = TI(exported).getU; + for (i32 i = 0; i < off; i++) { + body->varIDs[i] = -1; + rc ->expIDs[i] = -1; + } + for (usz i = 0; i < ia; i++) { + i32 cid = o2i(getIDU(varIDs, i)); + bool cexp = o2b(getOnU(exported, i)); + body->varIDs[i+off] = cid; + rc->expIDs[i+off] = cexp? cid : -1; + } + // printf("def %p:\n", rc); + // for (usz i = 0; i < vam; i++) printf(" %d: %d %d\n", i, body->varIDs[i], rc->expIDs[i]); + body->nsDesc = rc; +} +B m_ns(Scope* sc, NSDesc* desc) { // consumes both + B r = mm_alloc(sizeof(NS), t_ns, ftag(NSP_TAG)); + NS* rc = c(NS,r); + rc->desc = desc; + rc->nameList = rc->desc->nameList; + rc->sc = sc; + return r; +} + +B ns_getU(B ns, B nameList, i32 nameID) { + NS* n = c(NS, ns); + NSDesc* d = n->desc; + if (n->nameList.u != nameList.u) thrM("TODO cross-program namespace access"); + i32 varAm = d->varAm; + // printf("getting from %p with vam=%d\n", d, d->varAm); + assert(nameIDia && nameID>=0); + for (i32 i = 0; i < varAm; i++) { + if (d->expIDs[i]==nameID) return n->sc->vars[i]; + } + thrM("No key found"); +} + +B ns_nameList(NSDesc* d) { + return d->nameList; +} + + + +void ns_free(B x) { + NS* c = c(NS, x); + ptr_decR(c->desc); + ptr_decR(c->sc); +} +void ns_visit(B x) { + NS* c = c(NS, x); + mm_visitP(c->desc); + mm_visitP(c->sc); +} +void ns_print(B x) { + putchar('{'); + NSDesc* desc = c(NS,x)->desc; + Scope* sc = c(NS,x)->sc; + i32 am = desc->varAm; + BS2B getNameU = TI(desc->nameList).getU; + bool first = true; + for (i32 i = 0; i < am; i++) { + i32 id = desc->expIDs[i]; + if (id>=0) { + if (first) first=false; + else printf(" ⋄ "); + printRaw(getNameU(desc->nameList, id)); + printf("⇐"); + print(sc->vars[i]); + } + } + putchar('}'); +} + +void nsDesc_free(B x) { + decR(c(NSDesc,x)->nameList); +} +void nsDesc_visit(B x) { + mm_visit(c(NSDesc,x)->nameList); +} +void nsDesc_print(B x) { + printf("(namespace description)"); +} +static inline void ns_init() { + ti[t_ns].free = ns_free; ti[t_nsDesc].free = nsDesc_free; + ti[t_ns].visit = ns_visit; ti[t_nsDesc].visit = nsDesc_visit; + ti[t_ns].print = ns_print; ti[t_nsDesc].print = nsDesc_print; +} diff --git a/src/ns.h b/src/ns.h new file mode 100644 index 00000000..0670470a --- /dev/null +++ b/src/ns.h @@ -0,0 +1,9 @@ +#pragma once +#include "h.h" +typedef struct Scope Scope; +typedef struct Body Body; +typedef struct NSDesc NSDesc; +void m_nsDesc(Body* body, bool imm, u8 ty, B nameList, B varIDs, B exported); // consumes 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_nameList(NSDesc* d); \ No newline at end of file diff --git a/src/stuff.c b/src/stuff.c index 4d1039e3..2b965fdf 100644 --- a/src/stuff.c +++ b/src/stuff.c @@ -320,7 +320,7 @@ void printAllocStats() { #endif } -#define FOR_INIT(F) F(hdr) F(harr) F(fillarr) F(i32arr) F(c32arr) F(f64arr) F(arith) F(fns) F(sfns) F(md1) F(md2) F(sysfn) F(derv) F(comp) F(rtPerf) +#define FOR_INIT(F) F(hdr) F(harr) F(fillarr) F(i32arr) F(c32arr) F(f64arr) F(arith) F(fns) F(sfns) F(md1) F(md2) F(sysfn) F(derv) F(comp) F(rtPerf) F(ns) #define F(X) static inline void X##_init(); FOR_INIT(F) #undef F diff --git a/src/vm.c b/src/vm.c index 08f9ba2b..ebebee8a 100644 --- a/src/vm.c +++ b/src/vm.c @@ -1,4 +1,5 @@ #include "h.h" +#include "ns.h" // #define GS_REALLOC // whether to dynamically realloc gStack #ifndef GS_SIZE @@ -114,14 +115,15 @@ typedef struct Comp { Block* blocks[]; } Comp; -typedef struct Block { +struct Block { struct Value; bool imm; u8 ty; Body* body; -} Block; +}; -typedef struct Body { +typedef struct NSDesc NSDesc; +struct Body { struct Value; Comp* comp; // B* objs; @@ -129,25 +131,29 @@ typedef struct Body { u32 maxStack; u16 maxPSC; u16 varAm; + u32 endStack; + NSDesc* nsDesc; + i32 varIDs[]; // HArr* vNames; -} Body; +}; -typedef struct Scope { +struct Scope { struct Value; Scope* psc; + Body* body; u16 varAm; #ifdef DEBUG u64 bcInd; // DEBUG: place of this in bytecode array #endif B vars[]; -} Scope; +}; typedef struct FunBlock { struct Fun; Scope* sc; Block* bl; } FunBlock; typedef struct Md1Block { struct Md1; Scope* sc; Block* bl; } Md1Block; typedef struct Md2Block { struct Md2; Scope* sc; Block* bl; } Md2Block; -Block* compile(B bcq, B objs, B blocksq) { // consumes all +Block* compile(B bcq, B objs, B blocksq, B indices, B tokenInfo) { // consumes all HArr* blocksH = toHArr(blocksq); usz bam = blocksH->ia; @@ -162,22 +168,31 @@ Block* compile(B bcq, B objs, B blocksq) { // consumes all comp->objs = toHArr(objs); comp->blockAm = bam; B* blockDefs = blocksH->a; + dec(indices); + B nameList; + if (isNothing(tokenInfo)) { + nameList = bi_emptyHVec; + } else { + B t = TI(tokenInfo).getU(tokenInfo,2); + nameList = TI(t).getU(t,0); + } for (usz i = 0; i < bam; i++) { B cbld = blockDefs[i]; usz cbia = a(cbld)->ia; if (cbia!=4 && cbia!=6) thrM("bad compile block"); - BS2B bget = TI(cbld).get; - usz ty = o2s(bget(cbld,0)); if (ty>2) thrM("bad block type"); - bool imm = o2s(bget(cbld,1)); // todo o2b or something - usz idx = o2s(bget(cbld,2)); if (idx>=bcl) thrM("oob bytecode index"); - usz vam = o2s(bget(cbld,3)); if (vam!=(u16)vam) thrM("too many variables"); + BS2B bgetU = TI(cbld).getU; + usz ty = o2s(bgetU(cbld,0)); if (ty>2) thrM("bad block type"); + bool imm = o2s(bgetU(cbld,1)); // todo o2b or something + usz idx = o2s(bgetU(cbld,2)); if (idx>=bcl) thrM("oob bytecode index"); + usz vam = o2s(bgetU(cbld,3)); if (vam!=(u16)vam) thrM("too many variables"); i32* cbc = bc+idx; - i32* scan = cbc; i32 ssz = 0, mssz=0; i32 mpsc = 0; - while (*scan!=RETN & *scan!=RETD) { + while (true) { + if (*scan==RETN) { if(ssz!=1)thrM("Wrong stack size before RETN"); break; } + if (*scan==RETD) { if(ssz!=1&ssz!=0)thrM("Wrong stack size before RETN"); break; } ssz+= stackDiff(scan); if (ssz>mssz) mssz = ssz; if (*scan==LOCO | *scan==LOCM | *scan==LOCU) { @@ -188,12 +203,17 @@ Block* compile(B bcq, B objs, B blocksq) { // consumes all } if (mpsc>U16_MAX) thrM("LOC_ too deep"); - Body* body = mm_allocN(sizeof(Body), t_body); + Body* body = mm_allocN(fsizeof(Body,varIDs,i32,vam), t_body); body->comp = comp; body->bc = cbc; body->maxStack = mssz; body->maxPSC = (u16)mpsc; + body->endStack = ssz; body->varAm = (u16)vam; + if (cbia==4) { + body->nsDesc = NULL; + for (i32 i = 0; i < vam; i++) body->varIDs[i] = -1; + } else m_nsDesc(body, imm, ty, inc(nameList), bgetU(cbld,4), bgetU(cbld,5)); ptr_inc(comp); Block* bl = mm_allocN(sizeof(Block), t_block); @@ -208,6 +228,7 @@ Block* compile(B bcq, B objs, B blocksq) { // consumes all // for (usz i = 0; i < bam; i++) ptr_dec(comp->blocks[i]); ptr_dec(comp); ptr_dec(blocksH); + dec(tokenInfo); return ret; } @@ -219,14 +240,26 @@ void v_set(Scope* pscs[], B s, B x, bool upd) { // doesn't consume if (prev.u==bi_noVar.u) thrM("↩: Updating undefined variable"); dec(prev); } else { - if (prev.u!=bi_noVar.u) thrM("←: redefining variable"); + if (prev.u!=bi_noVar.u) thrM("←: Redefining variable"); } sc->vars[(u32)s.u] = inc(x); } else { VT(s, t_harr); - if (isAtm(x) || !eqShape(s, x)) thrM("Assignment: Mismatched shape for spread assignment"); - usz ia = a(x)->ia; B* sp = harr_ptr(s); + usz ia = a(s)->ia; + if (isAtm(x) || !eqShape(s, x)) { + if (isNsp(x)) { + for (u64 i = 0; i < ia; i++) { + B c = sp[i]; + if (!isVar(c)) thrM("Assignment: extracting non-name from namespace"); + Scope* sc = pscs[(u16)(c.u>>32)]; + i32 nameID = sc->body->varIDs[(u32)c.u]; + v_set(pscs, c, ns_getU(x, ns_nameList(sc->body->nsDesc), nameID), upd); + } + return; + } + thrM("Assignment: Mismatched shape for spread assignment"); + } BS2B xgetU = TI(x).getU; for (u64 i = 0; i < ia; i++) v_set(pscs, sp[i], xgetU(x,i), upd); } @@ -409,7 +442,9 @@ B evalBC(Body* b, Scope* sc) { // doesn't consume break; } case LOCO: { i32 d = *bc++; i32 p = *bc++; - ADD(inc(pscs[d]->vars[p])); + B l = pscs[d]->vars[p]; + if(l.u==bi_noVar.u) thrM("Reading variable before its defined"); + ADD(inc(l)); break; } case LOCU: { i32 d = *bc++; i32 p = *bc++; @@ -427,14 +462,21 @@ B evalBC(Body* b, Scope* sc) { // doesn't consume ADD(r); break; } - // not implemented: VARO VARM CHKV VFYM SETH FLDO FLDM NSPM RETD SYSV + case RETD: { + if (b->endStack) dec(POP); + ptr_inc(sc); + ptr_inc(b->nsDesc); + ADD(m_ns(sc, b->nsDesc)); + goto end; + } + case RETN: goto end; + // not implemented: VARO VARM CHKV VFYM SETH FLDO FLDM NSPM SYSV default: #ifdef DEBUG printf("todo %d\n", bc[-1]); bc++; break; #else UD; #endif - case RETN: goto end; } #ifdef DEBUG_VM for(i32 i = 0; i < bcDepth; i++) printf(" "); @@ -456,18 +498,19 @@ B evalBC(Body* b, Scope* sc) { // doesn't consume } B actualExec(Block* bl, Scope* psc, i32 ga, B* svar) { // consumes svar contents - Body* bdy = bl->body; - Scope* sc = mm_allocN(fsizeof(Scope, vars, B, bdy->varAm), t_scope); + Body* body = bl->body; + Scope* sc = mm_allocN(fsizeof(Scope, vars, B, body->varAm), t_scope); + sc->body = body; ptr_inc(body); sc->psc = psc; if(psc) ptr_inc(psc); - u16 varAm = sc->varAm = bdy->varAm; + u16 varAm = sc->varAm = body->varAm; assert(varAm>=ga); #ifdef DEBUG - sc->bcInd = bdy->bc-c(I32Arr,bdy->comp->bc)->a; + sc->bcInd = body->bc-c(I32Arr,body->comp->bc)->a; #endif i32 i = 0; while (ivars[i] = svar[i]; i++; } while (ivars[i++] = bi_noVar; - B r = evalBC(bdy, sc); + B r = evalBC(body, sc); ptr_dec(sc); return r; } @@ -505,7 +548,7 @@ B m_md2Block(Block* bl, Scope* psc) { } void comp_free(B x) { - Comp* c = c(Comp ,x); + Comp* c = c(Comp, x); ptr_decR(c->objs); decR(c->bc); u32 am = c->blockAm; for(u32 i = 0; i < am; i++) ptr_dec(c->blocks[i]); @@ -513,10 +556,11 @@ void comp_free(B x) { void scope_free(B x) { Scope* c = c(Scope,x); if (c->psc) ptr_decR(c->psc); + ptr_decR(c->body); u16 am = c->varAm; for (u32 i = 0; i < am; i++) dec(c->vars[i]); } -void body_free(B x) { Body* c = c(Body ,x); ptr_decR(c->comp); } +void body_free(B x) { Body* c = c(Body ,x); ptr_decR(c->comp); if(c->nsDesc)ptr_decR(c->nsDesc); } void block_free(B x) { Block* c = c(Block,x); ptr_decR(c->body); } void funBl_free(B x) { FunBlock* c = c(FunBlock,x); ptr_decR(c->sc); ptr_decR(c->bl); } void md1Bl_free(B x) { Md1Block* c = c(Md1Block,x); ptr_decR(c->sc); ptr_decR(c->bl); } @@ -530,10 +574,11 @@ void comp_visit(B x) { void scope_visit(B x) { Scope* c = c(Scope,x); if (c->psc) mm_visitP(c->psc); + mm_visitP(c->body); u16 am = c->varAm; for (u32 i = 0; i < am; i++) mm_visit(c->vars[i]); } -void body_visit(B x) { Body* c = c(Body ,x); mm_visitP(c->comp); } +void body_visit(B x) { Body* c = c(Body ,x); mm_visitP(c->comp); if(c->nsDesc)mm_visitP(c->nsDesc); } void block_visit(B x) { Block* c = c(Block,x); mm_visitP(c->body); } void funBl_visit(B x) { FunBlock* c = c(FunBlock,x); mm_visitP(c->sc); mm_visitP(c->bl); } void md1Bl_visit(B x) { Md1Block* c = c(Md1Block,x); mm_visitP(c->sc); mm_visitP(c->bl); }