#include #include #include #include #include "apl9.h" Symtab *globalsymtab; Symtab *newsymtab(void); 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; } 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; td->currentdfn = new; return new; } void popdfnframe(void) { ThreadData *td = getthreaddata(); if(td->currentdfn != nil){ DfnFrame *prev = td->currentdfn->prev; freesymtab(td->currentdfn->symtab); freedatum(td->currentdfn->lefto); freedatum(td->currentdfn->righto); freedatum(td->currentdfn->left); freearray(td->currentdfn->right); free(td->currentdfn); 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); }