diff options
-rw-r--r-- | apl9.h | 8 | ||||
-rw-r--r-- | eval.c | 8 | ||||
-rw-r--r-- | functions.c | 73 | ||||
-rw-r--r-- | lexer.c | 2 | ||||
-rw-r--r-- | operators.c | 18 | ||||
-rw-r--r-- | symbol.c | 122 |
6 files changed, 178 insertions, 53 deletions
@@ -183,6 +183,10 @@ struct DfnFrame { Rune *code; Symtab *symtab; + Datum *left; + Array *right; + Datum *lefto; + Datum *righto; DfnFrame *prev; }; @@ -226,7 +230,7 @@ Datum *eval(Statement *, int); Symbol *getsym(Rune *, int); void initsymtab(void); DfnFrame *getcurrentdfn(void); -DfnFrame *pushdfnframe(Rune *); +DfnFrame *pushdfnframe(Rune *, Datum *, Datum *, Array *, Array *); void popdfnframe(void); vlong globalIO(void); void globalIOset(vlong); @@ -243,7 +247,7 @@ void incref(Array *); /* functions.c */ Array *runfunc(Function, Array *,Array *); -Array *rundfn(Rune *, Array *, Array *); +Array *rundfn(Rune *, Datum *, Datum *, Array *, Array *); Array *runtrain(Function *, int, Array *, Array *, Array *); /* quadnames.c */ @@ -151,6 +151,7 @@ lookup(Datum var) incref(val->array); /* since the value is now in the var AND in the code */ } val->shy = 0; + traceprint("VAR %S = %S\n", var.symbol->name, ppdatum(*val)); return val; } @@ -225,11 +226,7 @@ nameis(Datum left, Datum right) Datum assign(Datum left, Datum right) { - if(runestrcmp(left.symbol->name, L"⍵") == 0) - throwerror(nil, ESyntax); - else if(runestrcmp(left.symbol->name, L"⍺") == 0 && !left.symbol->undefined) - goto end; - else if(left.symbol->setfn != nil) + if(left.symbol->setfn != nil) left.symbol->setfn(right); else{ if(left.symbol->undefined == 0 && left.symbol->value.tag == ArrayTag) @@ -241,7 +238,6 @@ assign(Datum left, Datum right) incref(right.array); /* for the binding */ } } -end: right.shy = 1; if(right.tag == ArrayTag) incref(right.array); /* for the returned array */ diff --git a/functions.c b/functions.c index 37cafa1..34f5db1 100644 --- a/functions.c +++ b/functions.c @@ -128,39 +128,20 @@ runfunc(Function f, Array *left, Array *right) Array *result; if(f.type == FunctypeDfn || (f.type == FunctypeOp && f.operator.type == OperatortypeDop)){ Rune *code; + Datum *lefto = nil; + Datum *righto = nil; if(f.type == FunctypeDfn) code = f.dfn; else{ + lefto = f.operator.left; + righto = f.operator.right; code = f.operator.dop; } - pushdfnframe(code); - if(left){ - Symbol *alpha = getsym(L"⍺", 1); - alpha->value.tag = ArrayTag; - alpha->value.array = left; - alpha->undefined = 0; - incref(left); - } - - Symbol *omega = getsym(L"⍵", 1); - omega->value.tag = ArrayTag; - omega->value.array = right; - omega->undefined = 0; - incref(right); - - if(f.type == FunctypeOp){ - if(f.operator.dyadic){ - Symbol *omegaop = getsym(L"⍹", 1); - omegaop->value = *f.operator.right; - omegaop->undefined = 0; - } - Symbol *alphaop = getsym(L"⍶", 1); - alphaop->value = *f.operator.left; - alphaop->undefined = 0; - } + pushdfnframe(code, lefto, righto, left, right); Datum *dfnres = evalline(code, nil, 0); popdfnframe(); + result = (*dfnres).array; /* TODO what if the evaluation failed */ }else if(f.type == FunctypePrim){ if(left){ @@ -236,12 +217,26 @@ runfunc(Function f, Array *left, Array *right) } Array * -rundfn(Rune *code, Array *left, Array *right) +rundfn(Rune *code, Datum *lefto, Datum *righto, Array *left, Array *right) { - Function dfn; - dfn.type = FunctypeDfn; - dfn.dfn = code; - return runfunc(dfn, left, right); + if(lefto == nil && righto == nil){ + Function dfn; + dfn.type = FunctypeDfn; + dfn.dfn = code; + return runfunc(dfn, left, right); + }else if(lefto != nil){ + Function dop; + dop.type = FunctypeOp; + dop.operator.type = OperatortypeDop; + dop.operator.left = lefto; + dop.operator.right = righto; + dop.operator.dyadic = righto != nil; + dop.operator.dop = code; + return runfunc(dop, left, right); + }else{ + throwerror(L"Malformed call to rundfn", ENotImplemented); + return nil; + } } Array * @@ -286,19 +281,19 @@ runtrain(Function *funcs, int nfuncs, Array *left, Array *right, Array *acc) Array * fnNegate(Array *right) { - return rundfn(L"0-⍵", nil, right); + return rundfn(L"0-⍵", nil, nil, nil, right); } Array * fnSign(Array *right) { - return rundfn(L"(¯1×⍵<0)+⍵>0", nil, right); + return rundfn(L"(¯1×⍵<0)+⍵>0", nil, nil, nil, right); } Array * fnRecip(Array *right) { - return rundfn(L"1÷⍵", nil, right); + return rundfn(L"1÷⍵", nil, nil, nil, right); } Array * @@ -331,13 +326,13 @@ fnPiTimes(Array *right) Array * fnMagnitude(Array *right) { - return rundfn(L"⍵××⍵", nil, right); + return rundfn(L"⍵××⍵", nil, nil, nil, right); } Array * fnCeiling(Array *right) { - return rundfn(L"-⌊-⍵", nil, right); + return rundfn(L"-⌊-⍵", nil, nil, nil, right); } Array * @@ -478,7 +473,7 @@ Array * fnSplit(Array *right) { Rune *code = L"0≡≢⍴⍵: ⍵ ⋄ (⊂⍵)⌷⍨¨⍳≢⍵"; - return rundfn(code, nil, right); + return rundfn(code, nil, nil, nil, right); } Array * @@ -714,7 +709,7 @@ fnSelfRef1(Array *right) { DfnFrame *dfn = getcurrentdfn(); if(dfn) - return rundfn(dfn->code, nil, right); + return rundfn(dfn->code, nil, nil, nil, right); else{ throwerror(nil, ESyntax); return nil; @@ -1111,7 +1106,7 @@ fnIndex(Array *left, Array *right) Array * fnCatenateLast(Array *left, Array *right) { - return rundfn(L"⍉(⍉⍺)⍪⍉⍵", left, right); + return rundfn(L"⍉(⍉⍺)⍪⍉⍵", nil, nil, left, right); } Array * @@ -1255,7 +1250,7 @@ fnSelfRef2(Array *left, Array *right) { DfnFrame *dfn = getcurrentdfn(); if(dfn) - return rundfn(dfn->code, left, right); + return rundfn(dfn->code, nil, nil, left, right); else{ throwerror(nil, ESyntax); return nil; @@ -180,7 +180,7 @@ get_digits: }else if(runestrchr(L"⍺⍵⍶⍹", peek)){ Rune name[2] = {peek, 0}; stmt->toks[stmt->ntoks].tag = NameTag; - stmt->toks[stmt->ntoks].symbol = getsym(name, 1); + stmt->toks[stmt->ntoks].symbol = getsym(name, 0); }else if(isalpharune(peek)){ Rune buf[64]; Rune *p = buf; diff --git a/operators.c b/operators.c index c46e627..8feda34 100644 --- a/operators.c +++ b/operators.c @@ -79,8 +79,13 @@ opSwitch(Datum *lefto, Array *left, Array *right) Array * opSelfReference1(Datum *lefto, Array *left, Array *right) { - throwerror(L"∆", ESyntax); - return nil; + DfnFrame *dfn = getcurrentdfn(); + if(dfn) + return rundfn(dfn->code, lefto, nil, left, right); + else{ + throwerror(nil, ESyntax); + return nil; + } } /* Dyadic operators */ @@ -174,6 +179,11 @@ opOver(Datum *lefto, Datum *righto, Array *left, Array *right) Array * opSelfReference2(Datum *lefto, Datum *righto, Array *left, Array *right) { - throwerror(L"⍙", ESyntax); - return nil; + DfnFrame *dfn = getcurrentdfn(); + if(dfn) + return rundfn(dfn->code, lefto, righto, left, right); + else{ + throwerror(nil, ESyntax); + return nil; + } }
\ No newline at end of file @@ -10,6 +10,13 @@ DfnFrame *currentdfn; 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) { @@ -70,6 +77,26 @@ void initsymtab(void) { globalsymtab = newsymtab(); + Symbol *s; + s = getsym(L"⍺", 1); + s->getfn = getalpha; + s->setfn = setalpha; + s->undefined = 0; + + s = getsym(L"⍵", 1); + s->getfn = getomega; + s->setfn = setsyntaxerr; + s->undefined = 0; + + s = getsym(L"⍶", 1); + s->getfn = getalphao; + s->setfn = setsyntaxerr; + s->undefined = 0; + + s = getsym(L"⍹", 1); + s->getfn = getomegao; + s->setfn = setsyntaxerr; + s->undefined = 0; } DfnFrame * @@ -79,11 +106,20 @@ getcurrentdfn(void) } DfnFrame * -pushdfnframe(Rune *code) +pushdfnframe(Rune *code, Datum *lefto, Datum *righto, Array *left, Array *right) { DfnFrame *new = malloc(sizeof(DfnFrame)); new->code = code; new->symtab = newsymtab(); + new->lefto = lefto; + new->righto = righto; + if(left){ + new->left = mallocz(sizeof(Datum), 1); + new->left->tag = ArrayTag; + new->left->array = left; + }else + new->left = nil; + new->right = right; new->prev = currentdfn; currentdfn = new; return new; @@ -138,4 +174,88 @@ globalDIVset(int div) currentdfn->symtab->div = div; else globalsymtab->div = div; +} + +/* getters and setters for ⍺⍵⍶⍹ */ +Datum * +getalpha(void) +{ + DfnFrame *dfn = getcurrentdfn(); + Datum *res = nil; + if(dfn == nil) + throwerror(nil, ESyntax); + else{ + res = malloc(sizeof(Datum)); + *res = *dfn->left; + if(res->tag == ArrayTag) + incref(res->array); + return res; + } + return res; +} + +Datum * +getomega(void) +{ + DfnFrame *dfn = getcurrentdfn(); + Datum *res = nil; + if(dfn == nil) + throwerror(nil, ESyntax); + else{ + res = mallocz(sizeof(Datum), 1); + res->tag = ArrayTag; + res->array = dfn->right; + incref(res->array); + } + return res; +} + +Datum * +getalphao(void) +{ + DfnFrame *dfn = getcurrentdfn(); + Datum *res = nil; + if(dfn == nil) + throwerror(nil, ESyntax); + else{ + res = malloc(sizeof(Datum)); + *res = *dfn->lefto; + if(res->tag == ArrayTag) + incref(res->array); + } + return res; +} + +Datum * +getomegao(void) +{ + DfnFrame *dfn = getcurrentdfn(); + Datum *res = nil; + if(dfn == nil) + throwerror(nil, ESyntax); + else{ + res = malloc(sizeof(Datum)); + *res = *dfn->righto; + if(res->tag == ArrayTag) + incref(res->array); + } + return res; +} + +void +setalpha(Datum new) +{ + DfnFrame *dfn = getcurrentdfn(); + if(dfn == nil) + throwerror(nil, ESyntax); + if(dfn->left == nil){ + dfn->left = malloc(sizeof(Datum)); + *dfn->left = new; + } +} + +void +setsyntaxerr(Datum) +{ + throwerror(nil, ESyntax); }
\ No newline at end of file |