diff options
author | Peter Mikkelsen <petermikkelsen10@gmail.com> | 2022-01-15 22:46:56 +0000 |
---|---|---|
committer | Peter Mikkelsen <petermikkelsen10@gmail.com> | 2022-01-15 22:46:56 +0000 |
commit | f02e90b27e37f91d4409842dd21cd00c999c805d (patch) | |
tree | 26117d12dadf2a15cc57bfc8b34c221ae0378dec | |
parent | d464a1d3a62d620b6336131c355467bdc273e3c5 (diff) |
Implement quad names for variables
-rw-r--r-- | apl9.h | 22 | ||||
-rw-r--r-- | eval.c | 40 | ||||
-rw-r--r-- | lexer.c | 29 | ||||
-rw-r--r-- | main.c | 3 | ||||
-rw-r--r-- | mkfile | 1 | ||||
-rw-r--r-- | quadnames.c | 77 | ||||
-rw-r--r-- | symbol.c | 14 |
7 files changed, 152 insertions, 34 deletions
@@ -46,7 +46,7 @@ typedef struct Function Function; typedef struct Datum Datum; typedef struct Symbol Symbol; typedef struct Symtab Symtab; - +typedef struct QuadnameDef QuadnameDef; struct Array { arrayDataType type; @@ -110,11 +110,14 @@ struct Symbol int undefined; Rune *name; Datum value; + Datum *(*getfn)(void); + int (*setfn)(Datum); }; struct Symtab { int nsyms; + int io; /* index origin */ Symbol **syms; }; @@ -123,9 +126,22 @@ typedef Array* (*fndyad)(Array*, Array*); typedef Array* (*opmonad)(Datum *, Array *, Array *); typedef Array* (*opdyad)(Datum *, Datum *, Array *, Array *); +struct QuadnameDef +{ + Rune *name; + datumTag tag; + Datum *(*get)(void); + int (*set)(Datum); + fnmonad monadfn; + fnmonad dyadfn; + opmonad monadop; + opdyad dyadop; +}; + /* Function prototypes for the different source files */ /* main.c */ Datum *evalline(Rune *); +Rune *prompt(Rune *); /* print.c */ Rune *ppdatum(Datum); @@ -166,6 +182,9 @@ void incref(Array *); /* functions.c */ Array *runfunc(Function, Array *,Array *); +/* quadnames.c */ +Datum quadnamedatum(QuadnameDef); + /* Monadic functions from function.c */ Array *fnSame(Array *); Array *fnTally(Array *); @@ -210,3 +229,4 @@ extern opdyad dyadoperatordefs[]; /* operators.c */ extern Symtab *globalsymtab; /* symbol.c */ extern Symtab *currentsymtab; /* symbol.c */ extern int alloccounts; /* memory.c */ +extern QuadnameDef quadnames[]; /* quadnames.c */ @@ -137,16 +137,22 @@ Datum * lookup(Datum var) { traceprint("VAR LOOKUP %S\n", var.symbol->name); + if(var.symbol->undefined){ errormsg = runesmprint("Variable undefined: %S\n", var.symbol->name); return nil; - }else{ - Datum *val = &var.symbol->value; - val->shy = 0; + } + + Datum *val; + if(var.symbol->getfn != nil) + val = var.symbol->getfn(); + else{ + val = &var.symbol->value; if(val->tag == ArrayTag) incref(val->array); /* since the value is now in the var AND in the code */ - return val; } + val->shy = 0; + return val; } Datum @@ -215,17 +221,25 @@ nameis(Datum left, Datum right) Datum assign(Datum left, Datum right) { - if(left.symbol->undefined == 0) - freearray(left.symbol->value.array); - - left.symbol->value = right; - left.symbol->undefined = 0; - if(left.symbol->value.tag == ArrayTag){ - left.symbol->value.array->stranded = 0; - incref(right.array); /* for the binding */ - incref(right.array); /* for the returned array */ + if(left.symbol->setfn != nil){ + int ok = left.symbol->setfn(right); + if(!ok){ + print("Assignment failed\n"); + exits(nil); + } + }else{ + if(left.symbol->undefined == 0 && left.symbol->value.tag == ArrayTag) + freearray(left.symbol->value.array); + left.symbol->value = right; + left.symbol->undefined = 0; + if(left.symbol->value.tag == ArrayTag){ + left.symbol->value.array->stranded = 0; + incref(right.array); /* for the binding */ + } } right.shy = 1; + if(right.tag == ArrayTag) + incref(right.array); /* for the returned array */ return right; } @@ -101,21 +101,36 @@ lexline(Rune *line) stmt->toks[stmt->ntoks].tag = NameTag; stmt->toks[stmt->ntoks].symbol = getsym(currentsymtab, name); offset++; - }else if(isalpharune(line[offset]) || line[offset] == L'⎕'){ - int quadname = L'⎕' == line[offset]; + }else if(isalpharune(line[offset])){ Rune buf[64]; Rune *p = buf; - while(isalpharune(line[offset]) || (line[offset] == L'⎕' && p == buf)){ - if(quadname) - *p = toupperrune(line[offset]); - else - *p = line[offset]; + while(isalpharune(line[offset])){ + *p = line[offset]; p++; offset++; } *p = 0; stmt->toks[stmt->ntoks].tag = NameTag; stmt->toks[stmt->ntoks].symbol = getsym(currentsymtab, buf); + }else if(runestrchr(L"⎕⍞", line[offset])){ + /* quad names */ + Rune buf[64]; + Rune *p = buf; + *p++ = line[offset++]; + while(isalpharune(line[offset])) + *p++ = toupperrune(line[offset++]); + *p = 0; + int valid = 0; + for(int i = 0; quadnames[i].name != nil && !valid; i++){ + if(runestrcmp(buf, quadnames[i].name) != 0) + continue; + valid = 1; + stmt->toks[stmt->ntoks] = quadnamedatum(quadnames[i]); + } + if(!valid){ + offset -= runestrlen(buf); + goto syntax_error; + } }else{ syntax_error: print("Can't lex: %S\n", &line[offset]); @@ -5,9 +5,6 @@ #include "apl9.h" -Rune *prompt(Rune *); -Datum *evalline(Rune *); - Biobuf *stdin; void @@ -11,6 +11,7 @@ OFILES=\ symbol.$O\ memory.$O\ operators.$O\ + quadnames.$O\ HFILES=\ apl9.h\ diff --git a/quadnames.c b/quadnames.c new file mode 100644 index 0000000..b765e58 --- /dev/null +++ b/quadnames.c @@ -0,0 +1,77 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> + +#include "apl9.h" + +Datum *getquad(void); +int setquad(Datum); +Datum *getio(void); +int setio(Datum); + +QuadnameDef quadnames[] = { + {L"⎕", NameTag, getquad, setquad, nil, nil}, + {L"⎕IO", NameTag, getio, setio, nil, nil}, + {nil, 0, nil, nil, nil, nil} /* MUST BE LAST */ +}; + +Datum +quadnamedatum(QuadnameDef q) +{ + Datum d; + d.tag = q.tag; + switch(q.tag){ + case NameTag: + d.symbol = getsym(currentsymtab, q.name); + d.symbol->getfn = q.get; + d.symbol->setfn = q.set; + d.symbol->undefined = 0; + break; + case FunctionTag: + case MonadicOpTag: + case DyadicOpTag: + default: + print("Can't use quad names with type=%d\n", q.tag); + exits("quadname"); + } + return d; +} + +/* ⎕ */ +Datum * +getquad(void) +{ + Rune *input = prompt(L"⎕:\n\t"); + Datum *result = evalline(input); + /* TODO check that the expression doesn't fail */ + return result; +} + +int +setquad(Datum new) +{ + print("%S\n", ppdatum(new)); + return 1; +} + +/* ⎕IO */ +Datum * +getio(void) +{ + Datum *d = mallocz(sizeof(Datum), 1); + d->tag = ArrayTag; + d->array = mkscalarint(globalIO()); + return d; +} + +int +setio(Datum new) +{ + if(new.tag != ArrayTag || new.array->rank != 0 || new.array->type != AtypeInt || (new.array->intdata[0] != 0 && new.array->intdata[0] != 1)){ + print("⎕IO: domain error\n"); + return 0; + }else{ + currentsymtab->io = new.array->intdata[0]; + return 1; + } +}
\ No newline at end of file @@ -19,6 +19,8 @@ getsym(Symtab *tab, Rune *name) tab->syms[tab->nsyms-1] = emalloc(sizeof(Symbol)); tab->syms[tab->nsyms-1]->name = runestrdup(name); tab->syms[tab->nsyms-1]->undefined = 1; + tab->syms[tab->nsyms-1]->getfn = nil; + tab->syms[tab->nsyms-1]->setfn = nil; return tab->syms[tab->nsyms-1]; } @@ -28,12 +30,7 @@ newsymtab(void) Symtab *tab = emalloc(sizeof(Symtab)); tab->nsyms = 0; tab->syms = nil; - - Symbol *io = getsym(tab, L"⎕IO"); - io->value.tag = ArrayTag; - io->value.array = mkscalarint(currentsymtab ? globalIO() : 1); - io->value.shy = 0; - io->undefined = 0; + tab->io = currentsymtab ? globalIO() : 1; return tab; } @@ -41,7 +38,6 @@ newsymtab(void) void freesymtab(Symtab *tab) { - print("Freeing symtab\n"); int i; for(i = 0; i < tab->nsyms; i++){ Symbol *s = tab->syms[i]; @@ -50,12 +46,10 @@ freesymtab(Symtab *tab) } free(tab->syms); free(tab); - print("Done freeing symtab\n"); } vlong globalIO(void) { - Symbol *s = getsym(currentsymtab, L"⎕IO"); - return s->value.array->intdata[0]; + return currentsymtab->io; }
\ No newline at end of file |