diff options
-rw-r--r-- | apl9.h | 32 | ||||
-rw-r--r-- | eval.c | 128 | ||||
-rw-r--r-- | lexer.c | 22 | ||||
-rw-r--r-- | main.c | 3 | ||||
-rw-r--r-- | mkfile | 1 | ||||
-rw-r--r-- | print.c | 12 | ||||
-rw-r--r-- | symbol.c | 31 |
7 files changed, 181 insertions, 48 deletions
@@ -15,7 +15,10 @@ typedef enum LCurlTag, RCurlTag, LBracketTag, - RBracketTag + RBracketTag, + ArrowTag, + AssignmentTag, + NameTag, } datumTag; typedef enum @@ -24,12 +27,13 @@ typedef enum AtypeArray, } arrayDataType; - /* Data types */ typedef struct Array Array; typedef struct Expr Expr; typedef struct Function Function; typedef struct Datum Datum; +typedef struct Symbol Symbol; +typedef struct Symtab Symtab; struct Array { @@ -65,12 +69,25 @@ struct Datum datumTag tag; union { Array *array; - int code; Expr expr; Function func; + Symbol *symbol; }; }; +struct Symbol +{ + int undefined; + Rune *name; + Datum value; +}; + +struct Symtab +{ + int nsyms; + Symbol **syms; +}; + typedef Array* (*fnmonad)(Array*); typedef Array* (*fndyad)(Array*, Array*); @@ -81,7 +98,7 @@ Rune *ppdatums(Datum *, int); Rune *pparray(Array *); /* lexer.c */ -Datum *lexline(Rune *, int *); +Datum *lexline(Rune *, int *, Symtab *); /* array.c */ Array *mkarray(int, int, int); @@ -93,6 +110,10 @@ int simplescalar(Array *); /* eval.c */ Datum *eval(Datum *, int *); +/* symbol.c */ +Symbol *getsym(Symtab *, Rune *); +Symtab *newsymtab(void); + /* Monadic functions from functions.h */ Array *fnTally(Array *); Array *fnEnclose(Array *); @@ -113,4 +134,5 @@ extern Rune primmonopnames[]; /* lexer.c */ extern Rune primdyadopnames[]; /* lexer.c */ extern Rune primhybridnames[]; /* lexer.c */ extern fnmonad monadfunctiondefs[]; /* function.c */ -extern fndyad dyadfunctiondefs[]; /* function.c */
\ No newline at end of file +extern fndyad dyadfunctiondefs[]; /* function.c */ +extern Symtab *globalsymtab; /* symbol.c */
\ No newline at end of file @@ -16,42 +16,62 @@ Datum monadfun(Datum, Datum); Datum dyadfun(Datum, Datum); Datum lpar(Datum, Datum); Datum rpar(Datum, Datum); +Datum nameis(Datum, Datum); +Datum assign(Datum, Datum); +Datum *lookup(Datum); -int bindingstrengths[12][12] = { -/* A F H MO DO AF ( ) { } [ ] */ - 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* A */ - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* H */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* MO */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* DO */ - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* AF */ - 4, 4, 4, 4, 4, 4, 0, 5, 4, 4, 4, 4, /* ( */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ) */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* { */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* } */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* [ */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ] */ +int bindingstrengths[15][15] = { +/* A F H MO DO AF ( ) { } [ ] ← IS N */ + 4, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* A */ + 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* H */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* MO */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* DO */ + 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* AF */ + 5, 5, 5, 5, 5, 5, 0, 6, 5, 5, 5, 5, 5, 5, 5, /* ( */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ) */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* { */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* } */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* [ */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ] */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ← */ + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* IS */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, /* N */ }; -evalfn evalfns[12][12] = { -/* A F H MO DO AF ( ) { } [ ] */ - strand, dyadfun, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* A */ - monadfun, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* H */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* MO */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* DO */ - monadfun, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* AF */ - lpar, lpar, lpar, lpar, lpar, 0, lpar, rpar, lpar, lpar, lpar, lpar, /* ( */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ) */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* { */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* } */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* [ */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ] */ +evalfn evalfns[15][15] = { +/* A F H MO DO AF ( ) { } [ ] ← IS N */ + strand, dyadfun, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* A */ + monadfun, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* H */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* MO */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* DO */ + monadfun, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* AF */ + lpar, lpar, lpar, lpar, lpar, 0, lpar, rpar, lpar, lpar, lpar, lpar, lpar, lpar, lpar, /* ( */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ) */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* { */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* } */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* [ */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ] */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ← */ + assign, assign, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* IS */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, nameis, 0, 0, /* N */ }; Datum * eval(Datum *tokens, int *ntoks) { + errormsg = nil; + + /* start by looking up first variable if needed */ + if(*ntoks > 0 && tokens[(*ntoks)-1].tag == NameTag){ + Datum *value = lookup(tokens[(*ntoks)-1]); + if(value == nil) + *ntoks = 0; + else + tokens[(*ntoks)-1] = *value; + } + while(*ntoks > 1){ int maxlevel = 0; int offset; @@ -59,6 +79,7 @@ eval(Datum *tokens, int *ntoks) traceprint("CURRENT: %S\n", ppdatums(tokens, *ntoks)); for(offset = (*ntoks)-1; offset >= 0; offset--){ int level; +retry: if(offset == 0) level = 0; else{ @@ -66,11 +87,21 @@ eval(Datum *tokens, int *ntoks) Datum right = tokens[offset]; level = bindingstrengths[left.tag][right.tag]; } - if(level < maxlevel){ + + if(level == 0 && tokens[offset-1].tag == NameTag){ + Datum *value = lookup(tokens[offset-1]); + if(value == nil){ + *ntoks = 0; + return tokens; + }else{ + tokens[offset-1] = *value; + goto retry; + } + }else if(level < maxlevel){ Datum left = tokens[offset]; Datum right = tokens[offset+1]; fn = evalfns[left.tag][right.tag]; - traceprint("Reducing %S and %S\n", ppdatum(left), ppdatum(right)); + traceprint("Reducing %S and %S (fn=%p, level=%d, max=%d)\n", ppdatum(left), ppdatum(right), fn, level, maxlevel); break; }else if(level > maxlevel) maxlevel = level; @@ -88,10 +119,21 @@ eval(Datum *tokens, int *ntoks) return tokens; } +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 + return &var.symbol->value; +} + Datum strand(Datum left, Datum right) { - traceprint("Stranding\n"); + traceprint("Stranding (%d %d)\n", left.array->stranded, right.array->stranded); Datum result; Array *leftarr = left.array->stranded ? left.array : fnEnclose(left.array); Array *rightarr = right.array->stranded ? right.array : fnEnclose(right.array); @@ -110,9 +152,9 @@ monadfun(Datum left, Datum right) /* TODO handle undefined functions here */ if(left.func.left) - result.array = dyadfunctiondefs[left.code](left.func.left, right.array); + result.array = dyadfunctiondefs[left.func.code](left.func.left, right.array); else - result.array = monadfunctiondefs[left.code](right.array); + result.array = monadfunctiondefs[left.func.code](right.array); return result; } @@ -147,4 +189,24 @@ rpar(Datum left, Datum right) Datum *result = eval(left.expr.toks, &left.expr.ntoks); result[0].array->stranded = 0; return result[0]; /* TODO handle error if ntoks != 1 */ +} + +Datum +nameis(Datum left, Datum right) +{ + traceprint("NAME SYMBOL %p\n", left.symbol); + traceprint("NAMEIS %S←\n", left.symbol->name); + right.tag = AssignmentTag; + right.symbol = left.symbol; + return right; +} + +Datum +assign(Datum left, Datum right) +{ + left.symbol->value = right; /* TODO think about this*/ + left.symbol->undefined = 0; + if(left.symbol->value.tag == ArrayTag) + left.symbol->value.array->stranded = 0; + return right; }
\ No newline at end of file @@ -9,7 +9,7 @@ Rune primdyadopnames[] = L"⍣.∘⍤⍥@⍠⌺"; Rune primhybridnames[] = L"/\⌿⍀"; Datum * -lexline(Rune *line, int *ntoks) +lexline(Rune *line, int *ntoks, Symtab *symtab) { int offset = 0; int len = runestrlen(line); @@ -20,7 +20,7 @@ lexline(Rune *line, int *ntoks) if(isspacerune(line[offset])){ offset++; continue; - }else if(runestrchr(L"(){}[]", line[offset])){ + }else if(runestrchr(L"(){}[]←", line[offset])){ switch(line[offset]){ case '(': tokens[*ntoks].tag = LParTag; break; case ')': tokens[*ntoks].tag = RParTag; break; @@ -28,19 +28,20 @@ lexline(Rune *line, int *ntoks) case '}': tokens[*ntoks].tag = RCurlTag; break; case '[': tokens[*ntoks].tag = LBracketTag; break; case ']': tokens[*ntoks].tag = RBracketTag; break; + case L'←': tokens[*ntoks].tag = ArrowTag; break; } offset++; }else if(p = runestrchr(primfuncnames, line[offset])){ tokens[*ntoks].tag = FunctionTag; - tokens[*ntoks].code = p-primfuncnames; + tokens[*ntoks].func.code = p-primfuncnames; offset++; }else if(p = runestrchr(primmonopnames, line[offset])){ tokens[*ntoks].tag = MonadicOpTag; - tokens[*ntoks].code = p-primmonopnames; + tokens[*ntoks].func.code = p-primmonopnames; offset++; }else if(p = runestrchr(primdyadopnames, line[offset])){ tokens[*ntoks].tag = DyadicOpTag; - tokens[*ntoks].code = p-primdyadopnames; + tokens[*ntoks].func.code = p-primdyadopnames; offset++; }else if(isdigitrune(line[offset])){ char buf[64]; @@ -52,6 +53,17 @@ lexline(Rune *line, int *ntoks) *p = 0; tokens[*ntoks].tag = ArrayTag; tokens[*ntoks].array = mkscalarint(atoll(buf)); + }else if(isalpharune(line[offset])){ + Rune buf[64]; + Rune *p = buf; + while(isalpharune(line[offset])){ + *p = line[offset]; + p++; + offset++; + } + *p = 0; + tokens[*ntoks].tag = NameTag; + tokens[*ntoks].symbol = getsym(symtab, buf); }else{ print("Can't lex: %S\n", &line[offset]); *ntoks = 0; @@ -14,6 +14,7 @@ main(int argc, char *argv[]) { int off = 0; stdin = Bfdopen(0, OREAD); + globalsymtab = newsymtab(); traceeval = 0; ARGBEGIN{ @@ -57,7 +58,7 @@ Datum * evalline(Rune *line) { int ntoks; - Datum *tokens = lexline(line, &ntoks); + Datum *tokens = lexline(line, &ntoks, globalsymtab); Datum *result = eval(tokens, &ntoks); if(ntoks == 1) return result; @@ -8,6 +8,7 @@ OFILES=\ print.$O\ array.$O\ functions.$O\ + symbol.$O\ HFILES=\ apl9.h\ @@ -10,16 +10,20 @@ ppdatum(Datum d) Rune *result; switch(d.tag){ case ArrayTag: result = pparray(d.array); break; - case FunctionTag: result = runesmprint("%C", primfuncnames[d.code]); break; - case HybridTag: result = runesmprint("%C", primhybridnames[d.code]); break; - case MonadicOpTag: result = runesmprint("%C", primmonopnames[d.code]); break; - case DyadicOpTag: result = runesmprint("%C", primdyadopnames[d.code]); break; + case FunctionTag: result = runesmprint("%C", primfuncnames[d.func.code]); break; + case HybridTag: result = runesmprint("%C", primhybridnames[d.func.code]); break; + case MonadicOpTag: result = runesmprint("%C", primmonopnames[d.func.code]); break; + case DyadicOpTag: result = runesmprint("%C", primdyadopnames[d.func.code]); break; + case BoundFunctionTag: result = runesmprint("%S∘%C", pparray(d.func.left), primfuncnames[d.func.code]); break; case LParTag: result = runestrdup(L"("); break; case RParTag: result = runestrdup(L")"); break; case LCurlTag: result = runestrdup(L"{"); break; case RCurlTag: result = runestrdup(L"}"); break; case LBracketTag: result = runestrdup(L"["); break; case RBracketTag: result = runestrdup(L"]"); break; + case ArrowTag: result = runestrdup(L"←"); break; + case AssignmentTag: result = runesmprint("%S←", d.symbol->name); break; + case NameTag: result = runestrdup(d.symbol->name); break; default: result = runesmprint("<not printable %d>", d.tag); } return result; diff --git a/symbol.c b/symbol.c new file mode 100644 index 0000000..a9d1d1f --- /dev/null +++ b/symbol.c @@ -0,0 +1,31 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> + +#include "apl9.h" + +Symtab *globalsymtab; + +Symbol * +getsym(Symtab *tab, Rune *name) +{ + for(int i = 0; i < tab->nsyms; i++) + if(runestrcmp(tab->syms[i]->name, name) == 0) + return tab->syms[i]; + + tab->nsyms++; + tab->syms = realloc(tab->syms, sizeof(Symbol *) * tab->nsyms); + tab->syms[tab->nsyms-1] = malloc(sizeof(Symbol)); + tab->syms[tab->nsyms-1]->name = runestrdup(name); + tab->syms[tab->nsyms-1]->undefined = 1; + return tab->syms[tab->nsyms-1]; +} + +Symtab * +newsymtab(void) +{ + Symtab *tab = malloc(sizeof(Symtab)); + tab->nsyms = 0; + tab->syms = nil; + return tab; +}
\ No newline at end of file |