diff options
author | Peter Mikkelsen <petermikkelsen10@gmail.com> | 2022-01-23 21:16:02 +0000 |
---|---|---|
committer | Peter Mikkelsen <petermikkelsen10@gmail.com> | 2022-01-23 21:16:02 +0000 |
commit | 9a938d3ce26b2d3728d791c0f858acdbd50223b5 (patch) | |
tree | a64151c171f0c289847c83367a678fd3252f2f99 /functions.c | |
parent | 3aa88a917e8c44ab088498dcfc18c48e66ceb243 (diff) |
Rework symbol lookup to use lexical scoping, and implement recursive function call via ∇
Diffstat (limited to 'functions.c')
-rw-r--r-- | functions.c | 50 |
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) |