extended variables, REPL support

This commit is contained in:
dzaima 2021-05-27 04:05:17 +03:00
parent 48229571ba
commit 3b017648d8
9 changed files with 167 additions and 32 deletions

View File

@ -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)"); }

View File

@ -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

10
src/h.h
View File

@ -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; }

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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

115
src/vm.c
View File

@ -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 (i<ga) { sc->vars[i] = svar[i]; i++; }
while (i<varAm) sc->vars[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;i<sc->varAm;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;

View File

@ -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;