summaryrefslogtreecommitdiff
path: root/symbol.c
diff options
context:
space:
mode:
Diffstat (limited to 'symbol.c')
-rw-r--r--symbol.c104
1 files changed, 55 insertions, 49 deletions
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