summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apl9.h14
-rw-r--r--concurrency.c10
-rw-r--r--eval.c2
-rw-r--r--functions.c4
-rw-r--r--lexer.c4
-rw-r--r--memory.c7
-rw-r--r--print.c3
-rw-r--r--symbol.c104
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("<nil>");
+
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