summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apl9.h8
-rw-r--r--eval.c8
-rw-r--r--functions.c73
-rw-r--r--lexer.c2
-rw-r--r--operators.c18
-rw-r--r--symbol.c122
6 files changed, 178 insertions, 53 deletions
diff --git a/apl9.h b/apl9.h
index 092c8ce..b19c686 100644
--- a/apl9.h
+++ b/apl9.h
@@ -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 */
diff --git a/eval.c b/eval.c
index 60c2e0d..a2d4d43 100644
--- a/eval.c
+++ b/eval.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;
diff --git a/lexer.c b/lexer.c
index 54e6e9b..38dc0a2 100644
--- a/lexer.c
+++ b/lexer.c
@@ -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
diff --git a/symbol.c b/symbol.c
index e10ee7a..2edb572 100644
--- a/symbol.c
+++ b/symbol.c
@@ -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