summaryrefslogtreecommitdiff
path: root/functions.c
diff options
context:
space:
mode:
Diffstat (limited to 'functions.c')
-rw-r--r--functions.c50
1 files changed, 37 insertions, 13 deletions
diff --git a/functions.c b/functions.c
index bc4d96c..c8bff78 100644
--- a/functions.c
+++ b/functions.c
@@ -4,7 +4,7 @@
#include "apl9.h"
-Rune primfuncnames[] = L"+-×÷*⍟⌹○!?|⌈⌊⊥⊤⊣⊢=≠≤<>≥≡≢∨∧⍲⍱↑↓⊂⊃⊆⌷⍋⍒⍳⍸∊⍷∪∩~,⍪⍴⌽⊖⍉⍎⍕";
+Rune primfuncnames[] = L"+-×÷*⍟⌹○!?|⌈⌊⊥⊤⊣⊢=≠≤<>≥≡≢∨∧⍲⍱↑↓⊂⊃⊆⌷⍋⍒⍳⍸∊⍷∪∩~,⍪⍴⌽⊖⍉⍎⍕∇";
fnmonad monadfunctiondefs[] = {
fnSame, /* + */
@@ -59,6 +59,7 @@ fnmonad monadfunctiondefs[] = {
fnTranspose, /* ⍉ */
0, /* ⍎ */
0, /* ⍕ */
+ fnSelfRef1, /* ∇ */
};
fndyad dyadfunctiondefs[] = {
@@ -114,8 +115,11 @@ fndyad dyadfunctiondefs[] = {
0, /* ⍉ */
0, /* ⍎ */
0, /* ⍕ */
+ fnSelfRef2, /* ∇ */
};
+DfnFrame *currentdfn; /* a stack of active dnf calls */
+
vlong gcd_int(vlong, vlong);
double gcd_float(double, double);
@@ -125,26 +129,23 @@ runfunc(Function f, Array *left, Array *right)
{
Array *result;
if(f.type == FunctypeDfn){
- Symtab *tmpsymtab = currentsymtab;
- currentsymtab = newsymtab();
-
+ pushdfnframe(f.dfn);
if(left){
- Symbol *alpha = getsym(currentsymtab, L"⍺");
+ Symbol *alpha = getsym(L"⍺");
alpha->value.tag = ArrayTag;
alpha->value.array = left;
alpha->undefined = 0;
incref(left);
}
- Symbol *omega = getsym(currentsymtab, L"⍵");
+ Symbol *omega = getsym(L"⍵");
omega->value.tag = ArrayTag;
omega->value.array = right;
omega->undefined = 0;
incref(right);
Datum *dfnres = evalline(f.dfn, 0);
- freesymtab(currentsymtab);
- currentsymtab = tmpsymtab;
+ popdfnframe();
result = (*dfnres).array; /* TODO what if the evaluation failed */
}else if(f.type == FunctypePrim){
if(left){
@@ -496,12 +497,13 @@ fnGradeUp(Array *right)
int i,j;
int len = right->shape[0];
Array **elems = malloc(sizeof(Array *) * len);
- Array *index = mkscalarint(currentsymtab->io);
+ Array *index = mkscalarint(globalIO());
Array *order = allocarray(AtypeInt, 1, len);
order->shape[0] = len;
+ vlong io = globalIO();
for(i = 0; i < len; i++, index->intdata[0]++){
- order->intdata[i] = currentsymtab->io + i;
+ order->intdata[i] = io + i;
elems[i] = fnIndex(index, right);
}
@@ -541,7 +543,7 @@ fnIndexGenerator(Array *right)
vlong n = right->intdata[0];
Array *res = allocarray(AtypeInt, 1, n);
res->shape[0] = n;
- vlong io = currentsymtab->io;
+ vlong io = globalIO();
for(vlong i = 0; i < n; i++)
res->intdata[i] = i + io;
return res;
@@ -692,6 +694,17 @@ fnTranspose(Array *right)
return res;
}
+Array *
+fnSelfRef1(Array *right)
+{
+ if(currentdfn != nil)
+ return rundfn(currentdfn->code, nil, right);
+ else{
+ throwerror(nil, ESyntax);
+ return nil;
+ }
+}
+
/* Dyadic functions */
/* macro to define dyadic scalar functions */
@@ -747,7 +760,7 @@ SCALAR_FUNCTION_2(fnTimes, 0, left->type,
SCALAR_FUNCTION_2(fnDivide, 1, left->type,
case AtypeFloat:
if(right->floatdata[i] == 0){
- if(currentsymtab->div)
+ if(globalDIV())
res->floatdata[i] = 0;
else
throwerror(nil, EDomain);
@@ -994,7 +1007,7 @@ fnTake(Array *left, Array *right)
Array *
fnIndex(Array *left, Array *right)
{
- int io = currentsymtab->io;
+ int io = globalIO();
int i;
if(left->rank > 1)
@@ -1221,6 +1234,17 @@ fnReshape(Array *left, Array *right)
return res;
}
+Array *
+fnSelfRef2(Array *left, Array *right)
+{
+ if(currentdfn != nil)
+ return rundfn(currentdfn->code, left, right);
+ else{
+ throwerror(nil, ESyntax);
+ return nil;
+ }
+}
+
/* helper functions */
vlong
gcd_int(vlong a, vlong b)