diff options
author | glenda <glenda@cirno> | 2022-09-18 19:58:41 +0000 |
---|---|---|
committer | glenda <glenda@cirno> | 2022-09-18 19:58:41 +0000 |
commit | e275bf9ff105bbb3e12fcf15e3ab755ed0cd26cf (patch) | |
tree | 8db2ea862204c026c2fe5670a15deaaeadc88960 /symbol.c | |
parent | 269c81f0217999367b4180e6a795142cbb2d02e7 (diff) |
Chain the symbol tables, not the dfn frames
Diffstat (limited to 'symbol.c')
-rw-r--r-- | symbol.c | 104 |
1 files changed, 55 insertions, 49 deletions
@@ -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 |