#include #include #include #include #include "apl9.h" Symtab *globalsymtab; Symtab *newsymtab(void); Symbol *dupsymbol(Symbol *); Symtab *dupsymtab(Symtab *); void freesymtab(Symtab *); Datum *getalpha(void); Datum *getomega(void); Datum *getalphao(void); Datum *getomegao(void); void setalpha(Datum *); 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(int i = 0; i < tab->nsyms; i++){ if(runestrcmp(tab->syms[i]->name, name) == 0) return tab->syms[i]; } if(dfn) dfn = dfn->chain; else done = 1; }while(!done && !fresh); /* make sure to allocate in the most local scope if the symbol is not found */ if(td->currentdfn) tab = td->currentdfn->symtab; tab->nsyms++; tab->syms = erealloc(tab->syms, sizeof(Symbol *) * tab->nsyms); tab->syms[tab->nsyms-1] = emalloc(sizeof(Symbol)); tab->syms[tab->nsyms-1]->name = runestrdup(name); tab->syms[tab->nsyms-1]->getfn = nil; tab->syms[tab->nsyms-1]->setfn = nil; tab->syms[tab->nsyms-1]->value = nil; return tab->syms[tab->nsyms-1]; } Symtab * newsymtab(void) { Symtab *tab = emalloc(sizeof(Symtab)); tab->nsyms = 0; tab->syms = nil; tab->io = globalIO(); tab->div = globalDIV(); return tab; } Symbol * dupsymbol(Symbol *s) { Symbol *new = emalloc(sizeof(Symbol)); memcpy(new, s, sizeof(Symbol)); new->name = runestrdup(s->name); if(new->value) incdatumref(new->value); return new; } Symtab * dupsymtab(Symtab *tab) { Symtab *new = newsymtab(); memcpy(new, tab, sizeof(Symtab)); new->syms = emalloc(sizeof(Symbol*) * new->nsyms); for(int i = 0; i < tab->nsyms; i++) new->syms[i] = dupsymbol(tab->syms[i]); return new; } void freesymtab(Symtab *tab) { int i; for(i = 0; i < tab->nsyms; i++){ Symbol *s = tab->syms[i]; freedatum(s->value); free(s->name); } free(tab->syms); free(tab); } void initsymtab(void) { globalsymtab = newsymtab(); Symbol *s; s = getsym(L"⍺", 1); s->getfn = getalpha; s->setfn = setalpha; s = getsym(L"⍵", 1); s->getfn = getomega; s->setfn = setsyntaxerr; s = getsym(L"⍶", 1); s->getfn = getalphao; s->setfn = setsyntaxerr; s = getsym(L"⍹", 1); s->getfn = getomegao; s->setfn = setsyntaxerr; } DfnFrame * getcurrentdfn(void) { ThreadData *td = getthreaddata(); return td->currentdfn; } DfnFrame * pushdfnframe(Rune *code, DfnFrame *scope, Datum *lefto, Datum *righto, Array *left, Array *right) { ThreadData *td = getthreaddata(); DfnFrame *new = emalloc(sizeof(DfnFrame)); new->code = code; new->symtab = newsymtab(); new->lefto = lefto; new->righto = righto; if(lefto) incdatumref(lefto); if(righto) incdatumref(righto); if(left){ new->left = allocdatum(ArrayTag, 0); new->left->array = left; incarrayref(left); }else new->left = nil; new->right = right; incarrayref(right); new->prev = td->currentdfn; new->chain = scope; new->errorguards = nil; td->currentdfn = new; return new; } DfnFrame * dupdfnframe(DfnFrame *f) { DfnFrame *new = emalloc(sizeof(DfnFrame)); memcpy(new, f, sizeof(DfnFrame)); new->code = runestrdup(f->code); new->symtab = dupsymtab(f->symtab); if(f->lefto) incdatumref(f->lefto); if(f->righto) incdatumref(f->righto); if(f->left) incdatumref(f->left); if(f->right) incarrayref(f->right); return new; } void freedfnframe(DfnFrame *f, int keeperrorguards) { freesymtab(f->symtab); freedatum(f->lefto); freedatum(f->righto); freedatum(f->left); freearray(f->right); if(!keeperrorguards) freeerrorguards(f->errorguards); free(f); } void popdfnframe(void) { ThreadData *td = getthreaddata(); if(td->currentdfn != nil){ DfnFrame *prev = td->currentdfn->prev; freedfnframe(td->currentdfn, 0); td->currentdfn = prev; } } vlong globalIO(void) { ThreadData *td = getthreaddata(); if(td->currentdfn) return td->currentdfn->symtab->io; else if(globalsymtab) return globalsymtab->io; else return 1; } void globalIOset(vlong io) { ThreadData *td = getthreaddata(); if(td->currentdfn) td->currentdfn->symtab->io = io; else globalsymtab->io = io; } int globalDIV(void) { ThreadData *td = getthreaddata(); if(td->currentdfn) return td->currentdfn->symtab->div; else if(globalsymtab) return globalsymtab->div; else return 0; } void globalDIVset(int div) { ThreadData *td = getthreaddata(); if(td->currentdfn) td->currentdfn->symtab->div = div; else globalsymtab->div = div; } /* getters and setters for ⍺⍵⍶⍹ */ Datum * getalpha(void) { DfnFrame *dfn = getcurrentdfn(); Datum *res = nil; if(dfn == nil || dfn->left == nil) throwerror(nil, ESyntax); else{ res = dfn->left; incdatumref(res); } return res; } Datum * getomega(void) { DfnFrame *dfn = getcurrentdfn(); Datum *res = nil; if(dfn == nil || dfn->right == nil) throwerror(nil, ESyntax); else{ res = allocdatum(ArrayTag, 0); res->array = dfn->right; incarrayref(res->array); } return res; } Datum * getalphao(void) { DfnFrame *dfn = getcurrentdfn(); Datum *res = nil; if(dfn == nil || dfn->lefto == nil) throwerror(nil, ESyntax); else{ res = dfn->lefto; incdatumref(res); } return res; } Datum * getomegao(void) { DfnFrame *dfn = getcurrentdfn(); Datum *res = nil; if(dfn == nil || dfn->righto == nil) throwerror(nil, ESyntax); else{ res = dfn->righto; incdatumref(res); } return res; } void setalpha(Datum *new) { DfnFrame *dfn = getcurrentdfn(); if(dfn == nil) throwerror(nil, ESyntax); if(dfn->left == nil){ dfn->left = new; incdatumref(new); } } void setsyntaxerr(Datum *) { throwerror(nil, ESyntax); } DfnFrame * dupscope(DfnFrame *dfn) { if(dfn == nil) return nil; DfnFrame *new = emallocz(sizeof(DfnFrame), 1); new->symtab = newsymtab(); /* copy ALL symbols which are in scope, into the new symtab */ for(DfnFrame *d = dfn; d != nil; d = d->chain){ /* Add all new symbols */ for(int i = 0; i < d->symtab->nsyms; i++){ Symbol *sym = d->symtab->syms[i]; int found = 0; for(int j = 0; j < new->symtab->nsyms && !found; j++) if(runestrcmp(new->symtab->syms[i]->name, d->symtab->syms[j]->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); } } } return new; }