From e275bf9ff105bbb3e12fcf15e3ab755ed0cd26cf Mon Sep 17 00:00:00 2001 From: glenda Date: Sun, 18 Sep 2022 19:58:41 +0000 Subject: Chain the symbol tables, not the dfn frames --- apl9.h | 14 ++++---- concurrency.c | 10 +++--- eval.c | 2 ++ functions.c | 4 +-- lexer.c | 4 +-- memory.c | 7 ++++ print.c | 3 ++ symbol.c | 104 +++++++++++++++++++++++++++++++--------------------------- 8 files changed, 85 insertions(+), 63 deletions(-) diff --git a/apl9.h b/apl9.h index 69d50b6..99f9f98 100644 --- a/apl9.h +++ b/apl9.h @@ -134,7 +134,7 @@ struct Operator int code; Rune *dop; }; - DfnFrame *scope; + Symtab *scope; Datum *left; Datum *right; }; @@ -155,7 +155,7 @@ struct Function QuadnameDef *quad; FunctionTrain train; }; - DfnFrame *scope; + Symtab *scope; Array *left; }; @@ -188,6 +188,8 @@ struct Symtab int nsyms; int io; /* index origin */ int div; /* division method */ + uvlong refs; + Symtab *chain; Symbol **syms; }; @@ -228,8 +230,6 @@ struct DfnFrame Datum *righto; ErrorGuard *errorguards; /* a linked list of error handlers */ DfnFrame *prev; /* prev in the call stack */ - DfnFrame *chain; /* prev in the lexical scope */ - int keep; /* prevents it from being freed */ }; struct ThreadData @@ -296,7 +296,7 @@ Datum *eval(Statement *, int); Symbol *getsym(Rune *, int); void initsymtab(void); DfnFrame *getcurrentdfn(void); -DfnFrame *pushdfnframe(Rune *, DfnFrame *, Datum *, Datum *, Array *, Array *); +DfnFrame *pushdfnframe(Rune *, Symtab *, Datum *, Datum *, Array *, Array *); DfnFrame *dupdfnframe(DfnFrame *); void freedfnframe(DfnFrame *, int); void popdfnframe(void); @@ -304,7 +304,9 @@ vlong globalIO(void); void globalIOset(vlong); int globalDIV(void); void globalDIVset(int); -DfnFrame *dupscope(DfnFrame *); +Symtab *dupscope(Symtab *); +Symtab *getcurrentsymtab(void); +void freesymtab(Symtab *); /* memory.c */ void *emalloc(ulong); diff --git a/concurrency.c b/concurrency.c index f4709e9..08dfdbc 100644 --- a/concurrency.c +++ b/concurrency.c @@ -66,14 +66,18 @@ spawnthread(Function f, Array *name, Array *left, Array *right) unlock datastructures exit proc */ + + SpawnData *sp = emallocz(sizeof(SpawnData), 1); sp->func = dupfunction(f); - sp->func.scope = dupscope(f.scope); + Symtab *scope = dupscope(f.scope); + freesymtab(sp->func.scope); + sp->func.scope = scope; sp->name = duparray(name); sp->left = left ? duparray(left) : nil; sp->right = duparray(right); sp->done.l = &sp->lock; - + qlock(&sp->lock); int id = rfork(RFPROC|RFMEM); if(id == 0){ /* in new process*/ @@ -221,8 +225,6 @@ newprocfn(SpawnData *sp) freearray(sp->left); freearray(sp->right); freefunction(sp->func); - if(sp->func.scope) - freedfnframe(sp->func.scope, 0); free(sp); free(td); exits(nil); diff --git a/eval.c b/eval.c index cd9b95a..9df4f4a 100644 --- a/eval.c +++ b/eval.c @@ -362,6 +362,8 @@ monadop(Datum *left, Datum *right) incdatumref(left); result->func.left = nil; result->func.scope = right->operator.scope; + if(result->func.scope) + result->func.scope->refs++; return result; } diff --git a/functions.c b/functions.c index 30a7dd1..0dd898d 100644 --- a/functions.c +++ b/functions.c @@ -233,7 +233,7 @@ rundfn(Rune *code, Datum *lefto, Datum *righto, Array *left, Array *right) Function dfn; dfn.type = FunctypeDfn; dfn.dfn = code; - dfn.scope = getcurrentdfn(); + dfn.scope = getcurrentsymtab(); return runfunc(dfn, left, right); }else if(lefto != nil){ Function dop; @@ -243,7 +243,7 @@ rundfn(Rune *code, Datum *lefto, Datum *righto, Array *left, Array *right) dop.operator.right = righto; dop.operator.dyadic = righto != nil; dop.operator.dop = code; - dop.scope = getcurrentdfn(); + dop.scope = getcurrentsymtab(); return runfunc(dop, left, right); }else{ throwerror(L"Malformed call to rundfn", ENotImplemented); diff --git a/lexer.c b/lexer.c index 45f5f5f..f684e51 100644 --- a/lexer.c +++ b/lexer.c @@ -129,13 +129,13 @@ lexline(InputStream *input, int toplevel) stmt->toks[stmt->ntoks] = allocdatum(FunctionTag, 0); stmt->toks[stmt->ntoks]->func.type = FunctypeDfn; stmt->toks[stmt->ntoks]->func.dfn = runestrdup(buf); - stmt->toks[stmt->ntoks]->func.scope = getcurrentdfn(); + stmt->toks[stmt->ntoks]->func.scope = getcurrentsymtab(); }else{ stmt->toks[stmt->ntoks] = allocdatum(oplevel == 1 ? MonadicOpTag : DyadicOpTag, 0); stmt->toks[stmt->ntoks]->operator.type = OperatortypeDop; stmt->toks[stmt->ntoks]->operator.dyadic = oplevel == 2; stmt->toks[stmt->ntoks]->operator.dop = runestrdup(buf); - stmt->toks[stmt->ntoks]->operator.scope = getcurrentdfn(); + stmt->toks[stmt->ntoks]->operator.scope = getcurrentsymtab(); } }else if(peek == '('){ int unclosed = 1; diff --git a/memory.c b/memory.c index e55485a..3416ea4 100644 --- a/memory.c +++ b/memory.c @@ -167,6 +167,7 @@ void freefunction(Function f) { freearray(f.left); + freesymtab(f.scope); switch(f.type){ case FunctypeDfn: free(f.dfn); @@ -197,6 +198,7 @@ freeoperator(Operator o) { freedatum(o.left); freedatum(o.right); + freesymtab(o.scope); switch(o.type){ case OperatortypeDop: free(o.dop); @@ -226,6 +228,8 @@ dupfunction(Function f) Function g = f; if(g.left) incarrayref(g.left); + if(g.scope) + g.scope->refs++; switch(f.type){ case FunctypeDfn: @@ -259,6 +263,9 @@ Operator dupoperator(Operator o) { Operator p = o; + if(p.scope) + p.scope->refs++; + if(p.left) incdatumref(p.left); if(p.right) diff --git a/print.c b/print.c index 075d372..b8b617d 100644 --- a/print.c +++ b/print.c @@ -13,6 +13,9 @@ Rune *strline(Rune *, int); Rune * ppdatum(Datum *d) { + if(d == nil) + return runesmprint(""); + Rune *result; switch(d->tag){ case ArrayTag: result = pparray(d->array); break; diff --git a/symbol.c b/symbol.c index 5d88f96..3cb8a9b 100644 --- a/symbol.c +++ b/symbol.c @@ -6,10 +6,9 @@ Symtab *globalsymtab; -Symtab *newsymtab(void); +Symtab *newsymtab(Symtab *); Symbol *dupsymbol(Symbol *); Symtab *dupsymtab(Symtab *); -void freesymtab(Symtab *); Datum *getalpha(void); Datum *getomega(void); @@ -21,28 +20,21 @@ void setsyntaxerr(Datum *); Symbol * getsym(Rune *name, int fresh) { - ThreadData *td = getthreaddata(); - DfnFrame *dfn = td->currentdfn; Symtab *tab; - int done = 0; - do{ - if(dfn != nil) - tab = dfn->symtab; - else - tab = globalsymtab; + for(tab = getcurrentsymtab(); tab; tab = tab->chain){ for(int i = 0; i < tab->nsyms; i++){ - if(runestrcmp(tab->syms[i]->name, name) == 0) + if(runestrcmp(tab->syms[i]->name, name) == 0){ + freesymtab(tab); return tab->syms[i]; + } } - if(dfn) - dfn = dfn->chain; - else - done = 1; - }while(!done && !fresh); + if(fresh) + break; + } /* make sure to allocate in the most local scope if the symbol is not found */ - if(td->currentdfn) - tab = td->currentdfn->symtab; + freesymtab(tab); + tab = getcurrentsymtab(); tab->nsyms++; tab->syms = erealloc(tab->syms, sizeof(Symbol *) * tab->nsyms); @@ -51,17 +43,23 @@ getsym(Rune *name, int fresh) tab->syms[tab->nsyms-1]->getfn = nil; tab->syms[tab->nsyms-1]->setfn = nil; tab->syms[tab->nsyms-1]->value = nil; + + freesymtab(tab); return tab->syms[tab->nsyms-1]; } Symtab * -newsymtab(void) +newsymtab(Symtab *chain) { Symtab *tab = emalloc(sizeof(Symtab)); tab->nsyms = 0; tab->syms = nil; tab->io = globalIO(); tab->div = globalDIV(); + tab->refs = 1; + tab->chain = chain; + if(chain) + chain->refs++; return tab; } @@ -80,8 +78,9 @@ dupsymbol(Symbol *s) Symtab * dupsymtab(Symtab *tab) { - Symtab *new = newsymtab(); + Symtab *new = newsymtab(tab->chain); memcpy(new, tab, sizeof(Symtab)); + new->refs = 1; new->syms = emalloc(sizeof(Symbol*) * new->nsyms); for(int i = 0; i < tab->nsyms; i++) new->syms[i] = dupsymbol(tab->syms[i]); @@ -91,12 +90,21 @@ dupsymtab(Symtab *tab) void freesymtab(Symtab *tab) { + if(tab == nil) + return; + if(tab->refs-- > 1) + return; + + if(tab == globalsymtab) + return; + int i; for(i = 0; i < tab->nsyms; i++){ Symbol *s = tab->syms[i]; freedatum(s->value); free(s->name); } + freesymtab(tab->chain); free(tab->syms); free(tab); } @@ -104,7 +112,7 @@ freesymtab(Symtab *tab) void initsymtab(void) { - globalsymtab = newsymtab(); + globalsymtab = newsymtab(nil); Symbol *s; s = getsym(L"⍺", 1); s->getfn = getalpha; @@ -131,12 +139,12 @@ getcurrentdfn(void) } DfnFrame * -pushdfnframe(Rune *code, DfnFrame *scope, Datum *lefto, Datum *righto, Array *left, Array *right) +pushdfnframe(Rune *code, Symtab *scope, Datum *lefto, Datum *righto, Array *left, Array *right) { ThreadData *td = getthreaddata(); DfnFrame *new = emalloc(sizeof(DfnFrame)); new->code = code; - new->symtab = newsymtab(); + new->symtab = newsymtab(scope); new->lefto = lefto; new->righto = righto; if(lefto) @@ -153,7 +161,6 @@ pushdfnframe(Rune *code, DfnFrame *scope, Datum *lefto, Datum *righto, Array *le if(right) incarrayref(right); new->prev = td->currentdfn; - new->chain = scope; new->errorguards = nil; td->currentdfn = new; return new; @@ -180,9 +187,6 @@ dupdfnframe(DfnFrame *f) void freedfnframe(DfnFrame *f, int keeperrorguards) { - if(f->keep) - return; - freesymtab(f->symtab); freedatum(f->lefto); freedatum(f->righto); @@ -324,37 +328,39 @@ setsyntaxerr(Datum *) throwerror(nil, ESyntax); } -DfnFrame * -dupscope(DfnFrame *dfn) +Symtab * +dupscope(Symtab *old) { - if(dfn == nil) - return nil; - - DfnFrame *new = emallocz(sizeof(DfnFrame), 1); - new->symtab = newsymtab(); + Symtab *new = newsymtab(globalsymtab); /* copy ALL symbols which are in scope, into the new symtab */ - for(DfnFrame *d = dfn; d != nil; d = d->chain){ + for(Symtab *o = old; o != globalsymtab; o = o->chain){ /* Add all new symbols */ - for(int i = 0; i < d->symtab->nsyms; i++){ - Symbol *sym = d->symtab->syms[i]; + for(int i = 0; i < o->nsyms; i++){ + Symbol *sym = o->syms[i]; int found = 0; - for(int j = 0; j < new->symtab->nsyms && !found; j++) - if(runestrcmp(new->symtab->syms[j]->name, d->symtab->syms[i]->name) == 0) + for(int j = 0; j < new->nsyms && !found; j++) + if(runestrcmp(new->syms[j]->name, o->syms[i]->name) == 0) found = 1; if(!found){ - new->symtab->nsyms++; - new->symtab->syms = erealloc(new->symtab->syms, sizeof(Symbol *) * new->symtab->nsyms); - new->symtab->syms[new->symtab->nsyms-1] = dupsymbol(sym); - sym = new->symtab->syms[new->symtab->nsyms-1]; - if(sym->value){ - if(sym->value->tag == FunctionTag) - sym->value->func.scope->keep = 1; - if(sym->value->tag == MonadicOpTag || sym->value->tag == DyadicOpTag) - sym->value->operator.scope->keep = 1; - } + new->nsyms++; + new->syms = erealloc(new->syms, sizeof(Symbol *) * new->nsyms); + new->syms[new->nsyms-1] = dupsymbol(sym); } } } return new; +} + +Symtab * +getcurrentsymtab(void) +{ + DfnFrame *dfn = getcurrentdfn(); + if(dfn == nil){ + globalsymtab->refs++; + return globalsymtab; + }else{ + dfn->symtab->refs++; + return dfn->symtab; + } } \ No newline at end of file -- cgit v1.2.3