diff --git a/src/builtins/sysfn.c b/src/builtins/sysfn.c index 2a9910a3..7d1fe9a7 100644 --- a/src/builtins/sysfn.c +++ b/src/builtins/sysfn.c @@ -131,6 +131,7 @@ B internal_c2(B t, B w, B x) { else if (isC32(x)) r = m_str32(U"tagged c32"); else if (isTag(x)) r = m_str32(U"tagged tag"); else if (isVar(x)) r = m_str32(U"tagged var"); + else if (isExt(x)) r = m_str32(U"tagged extvar"); else r = m_str32(U"tagged unknown"); } } else if(id==1) { r = isVal(x)? m_i32(v(x)->mmInfo & 0x7f) : m_str32(U"(not heap-allocated)"); } diff --git a/src/core/stuff.c b/src/core/stuff.c index fb4209e2..5b9a56db 100644 --- a/src/core/stuff.c +++ b/src/core/stuff.c @@ -88,6 +88,7 @@ NOINLINE void print(B x) { TI(x).print(x); } else if (isVar(x)) printf("(var d=%d i=%d)", (u16)(x.u>>32), (i32)x.u); + else if (isExt(x)) printf("(extvar d=%d i=%d)", (u16)(x.u>>32), (i32)x.u); else if (x.u==bi_N.u) printf("·"); else if (x.u==bi_optOut.u) printf("(value optimized out)"); else if (x.u==bi_noVar.u) printf("(unset variable placeholder)"); @@ -337,7 +338,7 @@ char* format_type(u8 u) { case t_md1D:return"md1D"; case t_md2D:return"md2D"; case t_md2H:return"md2H"; case t_harr :return"harr" ; case t_i8arr :return"i8arr" ; case t_i32arr :return"i32arr" ; case t_fillarr :return"fillarr" ; case t_c32arr :return"c32arr" ; case t_f64arr :return"f64arr" ; case t_hslice:return"hslice"; case t_i8slice:return"i8slice"; case t_i32slice:return"i32slice"; case t_fillslice:return"fillslice"; case t_c32slice:return"c32slice"; case t_f64slice:return"f64slice"; - case t_comp:return"comp"; case t_block:return"block"; case t_body:return"body"; case t_scope:return"scope"; case t_blBlocks: return "block list"; + case t_comp:return"comp"; case t_block:return"block"; case t_body:return"body"; case t_scope:return"scope"; case t_scopeExt:return"scope extension"; case t_blBlocks: return "block list"; case t_ns:return"ns"; case t_nsDesc:return"nsDesc"; case t_fldAlias:return"alias"; case t_hashmap:return"hashmap"; case t_temp:return"temporary"; case t_freed:return"(freed by GC)"; case t_harrPartial:return"partHarr"; #ifdef RT_WRAP diff --git a/src/h.h b/src/h.h index 7ea1b70e..663a789c 100644 --- a/src/h.h +++ b/src/h.h @@ -104,6 +104,7 @@ CTR_FOR(F) static const u16 C32_TAG = 0b0111111111110001; // 0111111111110001................00000000000ccccccccccccccccccccc char static const u16 TAG_TAG = 0b0111111111110010; // 0111111111110010................nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn special value (0=nothing, 1=undefined var, 2=bad header; 3=optimized out; 4=error?; 5=no fill) static const u16 VAR_TAG = 0b0111111111110011; // 0111111111110011ddddddddddddddddnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn variable reference +static const u16 EXT_TAG = 0b0111111111110100; // 0111111111110011ddddddddddddddddnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn extended variable reference static const u16 I32_TAG = 0b0111111111110111; // 0111111111110111................nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn 32-bit int; unused static const u16 MD1_TAG = 0b1111111111110010; // 1111111111110010ppppppppppppppppppppppppppppppppppppppppppppp000 1-modifier static const u16 MD2_TAG = 0b1111111111110011; // 1111111111110011ppppppppppppppppppppppppppppppppppppppppppppp000 2-modifier @@ -135,11 +136,11 @@ enum Type { /*13*/ t_harr , t_i8arr , t_i32arr , t_fillarr , t_c32arr , t_f64arr , /*19*/ t_hslice, t_i8slice, t_i32slice, t_fillslice, t_c32slice, t_f64slice, - /*25*/ t_comp, t_block, t_body, t_scope, t_blBlocks, - /*30*/ t_ns, t_nsDesc, t_fldAlias, t_hashmap, t_temp, - /*35*/ t_freed, t_harrPartial, + /*25*/ t_comp, t_block, t_body, t_scope, t_scopeExt, t_blBlocks, + /*31*/ t_ns, t_nsDesc, t_fldAlias, t_hashmap, t_temp, + /*36*/ t_freed, t_harrPartial, #ifdef RT_WRAP - /*37*/ t_funWrap, t_md1Wrap, t_md2Wrap, + /*38*/ t_funWrap, t_md1Wrap, t_md2Wrap, #endif t_COUNT }; @@ -304,6 +305,7 @@ static inline bool isFun(B x) { return (x.u>>48) == FUN_TAG; } static inline bool isArr(B x) { return (x.u>>48) == ARR_TAG; } static inline bool isC32(B x) { return (x.u>>48) == C32_TAG; } static inline bool isVar(B x) { return (x.u>>48) == VAR_TAG; } +static inline bool isExt(B x) { return (x.u>>48) == EXT_TAG; } static inline bool isTag(B x) { return (x.u>>48) == TAG_TAG; } static inline bool isMd1(B x) { return (x.u>>48) == MD1_TAG; } static inline bool isMd2(B x) { return (x.u>>48) == MD2_TAG; } diff --git a/src/load.c b/src/load.c index 1a596ac6..e48639e4 100644 --- a/src/load.c +++ b/src/load.c @@ -1,5 +1,7 @@ #include "core.h" #include "vm.h" +#include "ns.h" +#include "utils/mut.h" #include "utils/file.h" u64 mm_heapMax = HEAP_MAX; @@ -26,12 +28,12 @@ _Thread_local B comp_currArgs; B rt_sortDsc, 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; -Block* load_compObj(B x, B src) { // consumes +Block* load_compObj(B x, B src, Scope* sc) { // consumes x,src BS2B xget = TI(x).get; usz xia = a(x)->ia; if (xia!=5 & xia!=3) thrM("load_compObj: bad item count"); - Block* r = xia==5? compile(xget(x,0),xget(x,1),xget(x,2),xget(x,3),xget(x,4), src, NULL) - : compile(xget(x,0),xget(x,1),xget(x,2),bi_N, bi_N, src, NULL); + Block* r = xia==5? compile(xget(x,0),xget(x,1),xget(x,2),xget(x,3),xget(x,4), src, sc) + : compile(xget(x,0),xget(x,1),xget(x,2),bi_N, bi_N, src, sc); dec(x); return r; } @@ -47,6 +49,7 @@ Block* load_compImport(B bc, B objs, B blocks) { // consumes all #endif B load_comp; +B load_rtObj; B load_compArg; #ifdef FORMATTER @@ -67,7 +70,34 @@ void load_gcFn() { NOINLINE Block* bqn_comp(B str, B path, B args) { // consumes all comp_currPath = path; comp_currArgs = args; - Block* r = load_compObj(c2(load_comp, inc(load_compArg), inc(str)), str); + Block* r = load_compObj(c2(load_comp, inc(load_compArg), inc(str)), str, NULL); + dec(path); dec(args); + comp_currArgs = comp_currPath = bi_N; + return r; +} +NOINLINE Block* bqn_compSc(B str, B path, B args, Scope* sc, bool repl) { // consumes str,path,args + comp_currPath = path; + comp_currArgs = args; + B vName = inc(bi_emptyHVec); + B vDepth = inc(bi_emptyIVec); + if (repl && (!sc || sc->psc)) thrM("VM compiler: REPL mode must be used at top level scope"); + i32 depth = repl? -1 : 0; + Scope* csc = sc; + while (csc) { + for (i32 i = 0; i < csc->varAm; i++) { + i32 nameID = csc->body->varIDs[i]; + B nl = csc->body->nsDesc->nameList; + vName = vec_add(vName, TI(nl).get(nl, nameID)); + vDepth = vec_add(vDepth, m_i32(depth)); + } + if (csc->ext) for (i32 i = 0; i < csc->ext->varAm; i++) { + vName = vec_add(vName, inc(csc->ext->vars[i+csc->ext->varAm])); + vDepth = vec_add(vDepth, m_i32(depth)); + } + csc = csc->psc; + depth++; + } + Block* r = load_compObj(c2(load_comp, m_v4(inc(load_rtObj), inc(bi_sys), vName, vDepth), inc(str)), str, sc); dec(path); dec(args); comp_currArgs = comp_currPath = bi_N; return r; @@ -180,7 +210,8 @@ static inline void load_init() { // very last init function B* runtime = runtimeH.a; B rtObj = runtimeH.b; dec(c1(rtFinish, m_v2(inc(bi_decp), inc(bi_primInd)))); dec(rtFinish); - load_compArg = m_v2(FAKE_RUNTIME? frtObj : rtObj, inc(bi_sys)); gc_add(FAKE_RUNTIME? rtObj : frtObj); + load_rtObj = FAKE_RUNTIME? frtObj : rtObj; + load_compArg = m_v2(load_rtObj, inc(bi_sys)); gc_add(FAKE_RUNTIME? rtObj : frtObj); gc_add(load_compArg); #else B* runtime = fruntime; diff --git a/src/main.c b/src/main.c index c9a69661..84e8a79f 100644 --- a/src/main.c +++ b/src/main.c @@ -4,6 +4,7 @@ // TODO these are hacks around not needing tiny headers Block* bqn_comp(B str, B path, B args); +Block* bqn_compSc(B str, B path, B args, Scope* sc, bool repl); void rtWrap_print(); int main(int argc, char* argv[]) { @@ -126,6 +127,9 @@ int main(int argc, char* argv[]) { if (startREPL) { INIT; B replPath = m_str32(U"REPL"); gc_add(replPath); + Block* gscInit = bqn_comp(m_str32(U"1"), inc(replPath), m_f64(0)); + Scope* gsc = m_scope(gscInit->body, NULL, 0); gc_add(tag(gsc,OBJ_TAG)); + ptr_dec(gscInit); while (CATCH) { printf("Error: "); print(catchMessage); putchar('\n'); vm_pst(envCurr, envStart+envPrevHeight); @@ -140,16 +144,16 @@ int main(int argc, char* argv[]) { size_t gl = 0; i64 read = getline(&ln, &gl, stdin); if (read<=0 || ln[0]==0 || ln[0]==10) break; - Block* block = bqn_comp(fromUTF8(ln, strlen(ln)), inc(replPath), inc(bi_emptyHVec)); + Block* block = bqn_compSc(fromUTF8(ln, strlen(ln)), inc(replPath), inc(bi_emptyHVec), gsc, true); free(ln); #ifdef TIME u64 sns = nsTime(); - B res = m_funBlock(block, 0); + B res = evalBC(block->body, gsc); u64 ens = nsTime(); printf("%fms\n", (ens-sns)/1e6); #else - B res = m_funBlock(block, 0); + B res = evalBC(block->body, gsc); #endif ptr_dec(block); diff --git a/src/ns.c b/src/ns.c index 5147e052..96ae591d 100644 --- a/src/ns.c +++ b/src/ns.c @@ -57,6 +57,18 @@ B ns_getU(B ns, B cNL, i32 nameID) { } thrM("No key found"); } +B ns_getNU(B ns, B name) { + NS* n = c(NS, ns); + NSDesc* d = n->desc; + i32 dVarAm = d->varAm; + B dNL = d->nameList; + BS2B dNLgetU = TI(dNL).getU; + for (i32 i = 0; i < dVarAm; i++) { + i32 dID = d->expIDs[i]; + if (dID>=0 && equal(dNLgetU(dNL, dID), name)) return n->sc->vars[i]; + } + thrM("No key found"); +} B ns_nameList(NSDesc* d) { return d->nameList; diff --git a/src/ns.h b/src/ns.h index 944cae6b..d5f4124f 100644 --- a/src/ns.h +++ b/src/ns.h @@ -17,3 +17,4 @@ typedef struct NS { 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_getNU(B ns, B name); // doesn't consume anything, doesn't increment result diff --git a/src/vm.c b/src/vm.c index 8306048d..d1af817b 100644 --- a/src/vm.c +++ b/src/vm.c @@ -37,12 +37,14 @@ enum { RETD = 29, // return a namespace of exported items SYSV = 30, // N; get system function N LOCU = 31, // N0,N1; like LOCO but overrides the slot with bi_optOut + EXTO, EXTM, EXTU, // alternate versions of LOC_ for extended variables BC_SIZE = 32 }; #define FOR_BC(F) F(PUSH) F(VARO) F(VARM) F(ARRO) F(ARRM) F(FN1C) F(FN2C) F(OP1D) F(OP2D) F(TR2D) \ F(TR3D) F(SETN) F(SETU) F(SETM) F(POPS) F(DFND) F(FN1O) F(FN2O) F(CHKV) F(TR3O) \ - F(OP2H) F(LOCO) F(LOCM) F(VFYM) F(SETH) F(RETN) F(FLDO) F(FLDM) F(NSPM) F(RETD) F(SYSV) F(LOCU) + F(OP2H) F(LOCO) F(LOCM) F(VFYM) F(SETH) F(RETN) F(FLDO) F(FLDM) F(NSPM) F(RETD) F(SYSV) F(LOCU) \ + F(EXTO) F(EXTM) F(EXTU) i32* nextBC(i32* p) { switch(*p) { @@ -57,13 +59,14 @@ i32* nextBC(i32* p) { case SYSV: case NSPM: return p+2; case LOCO: case LOCM: case LOCU: + case EXTO: case EXTM: case EXTU: return p+3; default: return 0; } } i32 stackDiff(i32* p) { switch(*p) { - case PUSH: case VARO: case VARM: case DFND: case LOCO: case LOCM: case LOCU: case SYSV: return 1; + case PUSH: case VARO: case VARM: case DFND: case LOCO: case LOCM: case LOCU: case EXTO: case EXTM: case EXTU: case SYSV: return 1; case CHKV: case VFYM: case FLDO: case FLDM: case RETD: case NSPM: return 0; case FN1C: case OP1D: case TR2D: case SETN: case SETU: case POPS: case FN1O: case OP2H: case SETH: case RETN: return -1; case FN2C: case OP2D: case TR3D: case SETM: case FN2O: case TR3O: return -2; @@ -133,6 +136,29 @@ Block* compileBlock(B block, Comp* comp, bool* bDone, i32* bc, usz bcIA, B block TSALLOC(Block*, nBlT, 2); TSALLOC(i32, nBCT, 20); TSALLOC(i32, mapT, 20); + if (depth==0 && sc && vam > sc->varAm) { + if (cIA==4) thrM("VM compiler: full block info must be provided for extending scopes"); + i32 regAm = sc->varAm; + ScopeExt* oE = sc->ext; + if (oE==NULL || vam > regAm + oE->varAm) { + i32 nSZ = vam - regAm; + ScopeExt* nE = mm_allocN(fsizeof(ScopeExt, vars, B, nSZ*2), t_scopeExt); + nE->varAm = nSZ; + i32 oSZ = 0; + if (oE) { + oSZ = oE->varAm; + memcpy(nE->vars , oE->vars , oSZ*sizeof(B)); + memcpy(nE->vars+nSZ, oE->vars+oSZ, oSZ*sizeof(B)); + mm_free((Value*)oE); + } + B varIDs = bgetU(block,4); + for (i32 i = oSZ; i < nSZ; i++) { + nE->vars[i] = bi_noVar; + nE->vars[i+nSZ] = TI(nameList).get(nameList, o2s(TI(varIDs).getU(varIDs, regAm+i))); + } + sc->ext = nE; + } + } i32* c = bc+idx; while (true) { i32* n = nextBC(c); @@ -159,10 +185,21 @@ Block* compileBlock(B block, Comp* comp, bool* bDone, i32* bc, usz bcIA, B block break; } case LOCO: case LOCM: case LOCU: { - if (c[1]>mpsc) mpsc = c[1]; - TSADD(nBCT, c[0]); - TSADD(nBCT, c[1]); - TSADD(nBCT, c[2]); + i32 ins = c[0]; + i32 cdepth = c[1]; + i32 cpos = c[2]; + if (cdepth>mpsc) mpsc = cdepth; + if (sc && cdepth>=depth) { + Scope* csc = sc; + for (i32 i = depth; i < cdepth; i++) if (!(csc = csc->psc)) thrM("VM compiler: LOC_ has an out-of-bounds depth"); + if (cpos >= csc->varAm) { + cpos-= csc->varAm; + ins = ins==LOCO? EXTO : ins==LOCM? EXTM : EXTU; + } + } + TSADD(nBCT, ins); + TSADD(nBCT, cdepth); + TSADD(nBCT, cpos); break; } default: { @@ -211,9 +248,10 @@ Block* compileBlock(B block, Comp* comp, bool* bDone, i32* bc, usz bcIA, B block return bl; } -NOINLINE Block* compile(B bcq, B objs, B blocks, B indices, B tokenInfo, B src, Scope* sc) { // consumes all; assumes arguments are valid (verifies some stuff, but definitely not everything) +// consumes all; assumes arguments are valid (verifies some stuff, but definitely not everything) +// if sc isn't NULL, this block must only be evaluated directly in that scope precisely once +NOINLINE Block* compile(B bcq, B objs, B blocks, B indices, B tokenInfo, B src, Scope* sc) { usz bIA = a(blocks)->ia; - I32Arr* bca = toI32Arr(bcq); i32* bc = bca->a; usz bcIA = bca->ia; @@ -261,10 +299,16 @@ void v_set(Scope* pscs[], B s, B x, bool upd) { // doesn't consume if (upd) { if (prev.u==bi_noVar.u) thrM("↩: Updating undefined variable"); dec(prev); - } else { - if (prev.u!=bi_noVar.u) thrM("←: Redefining variable"); - } + } // else if (prev.u!=bi_noVar.u) thrM("←: Redefining variable"); sc->vars[(u32)s.u] = inc(x); + } else if (isExt(s)) { + Scope* sc = pscs[(u16)(s.u>>32)]; + B prev = sc->ext->vars[(u32)s.u]; + if (upd) { + if (prev.u==bi_noVar.u) thrM("↩: Updating undefined variable"); + dec(prev); + } // else if (prev.u!=bi_noVar.u) thrM("←: Redefining variable"); + sc->ext->vars[(u32)s.u] = inc(x); } else { VTY(s, t_harr); B* sp = harr_ptr(s); @@ -277,6 +321,9 @@ void v_set(Scope* pscs[], B s, B x, bool upd) { // doesn't consume 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); + } 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]), upd); } else if (isObj(c)) { assert(v(c)->type == t_fldAlias); Scope* sc = pscs[0]; @@ -298,6 +345,11 @@ B v_get(Scope* pscs[], B s) { // get value representing s, replacing with bi_opt B r = sc->vars[(u32)s.u]; sc->vars[(u32)s.u] = bi_optOut; return r; + } else if (isExt(s)) { + Scope* sc = pscs[(u16)(s.u>>32)]; + B r = sc->ext->vars[(u32)s.u]; + sc->ext->vars[(u32)s.u] = bi_optOut; + return r; } else { VTY(s, t_harr); usz ia = a(s)->ia; @@ -441,6 +493,22 @@ B evalBC(Body* b, Scope* sc) { // doesn't consume vars[p] = bi_optOut; break; } + case EXTM: { i32 d = *bc++; i32 p = *bc++; + ADD(tag((u64)d<<32 | (u32)p, EXT_TAG)); + break; + } + case EXTO: { i32 d = *bc++; i32 p = *bc++; + B l = pscs[d]->ext->vars[p]; + if(l.u==bi_noVar.u) { POS_UPD; thrM("Reading variable before its defined"); } + ADD(inc(l)); + break; + } + case EXTU: { i32 d = *bc++; i32 p = *bc++; + B* vars = pscs[d]->ext->vars; + ADD(vars[p]); + vars[p] = bi_optOut; + break; + } case SETN: { P(s) P(x) GS_UPD; POS_UPD; v_set(pscs, s, x, false); dec(s); ADD(x); break; } case SETU: { P(s) P(x) GS_UPD; POS_UPD; v_set(pscs, s, x, true ); dec(s); ADD(x); break; } case SETM: { P(s)P(f)P(x) GS_UPD; POS_UPD; @@ -498,13 +566,20 @@ B evalBC(Body* b, Scope* sc) { // doesn't consume #undef GS_UPD } -B actualExec(Block* bl, Scope* psc, i32 ga, B* svar) { // consumes svar contents - Body* body = bl->body; - Scope* sc = mm_allocN(fsizeof(Scope, vars, B, body->varAm), t_scope); +Scope* m_scope(Body* body, Scope* psc, u16 varAm) { // doesn't consume + Scope* sc = mm_allocN(fsizeof(Scope, vars, B, varAm), t_scope); sc->body = body; ptr_inc(body); sc->psc = psc; if(psc) ptr_inc(psc); - u16 varAm = sc->varAm = body->varAm; + sc->varAm = varAm; + sc->ext = NULL; + return sc; +} + +B actualExec(Block* bl, Scope* psc, i32 ga, B* svar) { // consumes svar contents + Body* body = bl->body; + u16 varAm = body->varAm; assert(varAm>=ga); + Scope* sc = m_scope(body, psc, varAm); i32 i = 0; while (ivars[i] = svar[i]; i++; } while (ivars[i++] = bi_noVar; @@ -565,6 +640,7 @@ B m_md2Block(Block* bl, Scope* psc) { void scope_free(Value* x) { Scope* c = (Scope*)x; if (c->psc) ptr_decR(c->psc); + if (c->ext) ptr_decR(c->ext); ptr_decR(c->body); u16 am = c->varAm; for (u32 i = 0; i < am; i++) dec(c->vars[i]); @@ -576,11 +652,13 @@ void funBl_free(Value* x) { FunBlock* c = (FunBlock*)x; ptr_decR(c->sc); ptr_dec void md1Bl_free(Value* x) { Md1Block* c = (Md1Block*)x; ptr_decR(c->sc); ptr_decR(c->bl); } void md2Bl_free(Value* x) { Md2Block* c = (Md2Block*)x; ptr_decR(c->sc); ptr_decR(c->bl); } void alias_free(Value* x) { dec(((FldAlias*)x)->obj); } -void bBlks_free(Value* x) { BlBlocks* c = (BlBlocks*)x; u16 am = c->am; for (u32 i = 0; i < am; i++) ptr_dec(c->a[i]); } +void bBlks_free(Value* x) { BlBlocks* c = (BlBlocks*)x; u16 am = c->am; for (i32 i = 0; i < am; i++) ptr_dec(c->a[i]); } +void scExt_free(Value* x) { ScopeExt* c = (ScopeExt*)x; u16 am = c->varAm*2; for (i32 i = 0; i < am; i++) dec(c->vars[i]); } void scope_visit(Value* x) { Scope* c = (Scope*)x; if (c->psc) mm_visitP(c->psc); + if (c->ext) mm_visitP(c->ext); mm_visitP(c->body); u16 am = c->varAm; for (u32 i = 0; i < am; i++) mm_visit(c->vars[i]); @@ -592,7 +670,8 @@ void funBl_visit(Value* x) { FunBlock* c = (FunBlock*)x; mm_visitP(c->sc); mm_vi 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); } void alias_visit(Value* x) { mm_visit(((FldAlias*)x)->obj); } -void bBlks_visit(Value* x) { BlBlocks* c = (BlBlocks*)x; u16 am = c->am; for (u32 i = 0; i < am; i++) mm_visitP(c->a[i]); } +void bBlks_visit(Value* x) { BlBlocks* c = (BlBlocks*)x; u16 am = c->am; for (i32 i = 0; i < am; i++) mm_visitP(c->a[i]); } +void scExt_visit(Value* x) { ScopeExt* c = (ScopeExt*)x; u16 am = c->varAm*2; for (i32 i = 0; i < am; i++) mm_visit(c->vars[i]); } void comp_print (B x) { printf("(%p: comp)",v(x)); } void body_print (B x) { printf("(%p: body varam=%d)",v(x),c(Body,x)->varAm); } @@ -600,6 +679,7 @@ void block_print(B x) { printf("(%p: block for %p)",v(x),c(Block,x)->body); } void scope_print(B x) { printf("(%p: scope; vars:",v(x));Scope*sc=c(Scope,x);for(u64 i=0;ivarAm;i++){printf(" ");print(sc->vars[i]);}printf(")"); } void alias_print(B x) { printf("(alias %d of ", c(FldAlias,x)->p); print(c(FldAlias,x)->obj); printf(")"); } void bBlks_print(B x) { printf("(block list)"); } +void scExt_print(B x) { printf("(scope extension with %d vars)", c(ScopeExt,x)->varAm); } // void funBl_print(B x) { printf("(%p: function"" block bl=%p sc=%p)",v(x),c(FunBlock,x)->bl,c(FunBlock,x)->sc); } // void md1Bl_print(B x) { printf("(%p: 1-modifier block bl=%p sc=%p)",v(x),c(Md1Block,x)->bl,c(Md1Block,x)->sc); } @@ -639,6 +719,7 @@ void comp_init() { ti[t_body ].free = body_free; ti[t_body ].visit = body_visit; ti[t_body ].print = body_print; ti[t_block ].free = block_free; ti[t_block ].visit = block_visit; ti[t_block ].print = block_print; ti[t_scope ].free = scope_free; ti[t_scope ].visit = scope_visit; ti[t_scope ].print = scope_print; + ti[t_scopeExt ].free = scExt_free; ti[t_scopeExt ].visit = scExt_visit; ti[t_scopeExt ].print = scExt_print; ti[t_blBlocks ].free = bBlks_free; ti[t_blBlocks ].visit = bBlks_visit; ti[t_blBlocks ].print = bBlks_print; ti[t_fldAlias ].free = alias_free; ti[t_fldAlias ].visit = alias_visit; ti[t_fldAlias ].print = alias_print; ti[t_fun_block].free = funBl_free; ti[t_fun_block].visit = funBl_visit; ti[t_fun_block].print = funBl_print; ti[t_fun_block].decompose = block_decompose; diff --git a/src/vm.h b/src/vm.h index f154df9e..3a15263e 100644 --- a/src/vm.h +++ b/src/vm.h @@ -44,8 +44,9 @@ struct Body { }; struct ScopeExt { + struct Value; u16 varAm; - B vars[]; + B vars[]; // vars has length varAm*2; position varAm and onwards are corresponding names to variables at regular indexes }; struct Scope { @@ -59,7 +60,8 @@ struct Scope { Block* compile(B bcq, B objs, B blocksq, B indices, B tokenInfo, B src, Scope* sc); - +Scope* m_scope(Body* body, Scope* psc, u16 varAm); +B evalBC(Body* b, Scope* sc); // doesn't consume; executes bytecode of the body directly in the scope typedef struct Env { Scope* sc;