#include #include #include #include "apl9.h" Rune primmonopnames[] = L"¨⍨⌸⌶&∆"; Rune primdyadopnames[] = L"⍣.∘⍤⍥@⍠⌺⍙"; opmonad monadoperatordefs[] = { opEach, /* ¨ */ opSwitch, /* ⍨ */ 0, /* ⌸ */ 0, /* ⌶ */ 0, /* & */ opSelfReference1, /* ∆ */ }; opdyad dyadoperatordefs[] = { 0, /* ⍣ */ 0, /* . */ opBind, /* ∘ */ opAtop, /* ⍤ */ opOver, /* ⍥ */ 0, /* @ */ 0, /* ⍠ */ 0, /* ⌺ */ opSelfReference2, /* ⍙ */ }; /* Monadic operators */ Array * opEach(Datum *lefto, Array *left, Array *right) { int i; if(lefto->tag != FunctionTag) return nil; Array *leftarr; Array *rightarr; if(left){ int rankok = scalarextend(left, right, &leftarr, &rightarr); if(!rankok) throwerror(nil, ERank); }else{ leftarr = nil; rightarr = fnSame(right); } Array *result = allocarray(AtypeArray, rightarr->rank, rightarr->size); for(i = 0; i < rightarr->rank; i++) result->shape[i] = rightarr->shape[i]; for(i = 0; i < rightarr->size; i++){ Array *elem1 = leftarr ? arrayitem(leftarr, i) : nil; Array *elem2 = arrayitem(rightarr, i); result->arraydata[i] = runfunc(lefto->func, elem1, elem2); freearray(elem1); freearray(elem2); } freearray(leftarr); freearray(rightarr); return result; } Array * opSwitch(Datum *lefto, Array *left, Array *right) { if(lefto->tag == ArrayTag){ incref(lefto->array); return lefto->array; }else if(lefto->tag == FunctionTag){ if(left) return runfunc(lefto->func, right, left); else return runfunc(lefto->func, right, right); }else return nil; } Array * opSelfReference1(Datum *lefto, Array *left, Array *right) { throwerror(L"∆", ESyntax); return nil; } /* Dyadic operators */ Array * opBind(Datum *lefto, Datum *righto, Array *left, Array *right) { if(lefto->tag == FunctionTag && righto->tag == FunctionTag){ Array *right1 = runfunc(righto->func, nil, right); Array *result = runfunc(lefto->func, left, right1); freearray(right1); return result; }else if(lefto->tag == FunctionTag && righto->tag == ArrayTag){ if(left) throwerror(L"The function doesn't take a left argument", ESyntax); return runfunc(lefto->func, right, righto->array); }else if(lefto->tag == ArrayTag && righto->tag == FunctionTag){ if(left) throwerror(L"The function doesn't take a left argument", ESyntax); return runfunc(righto->func, lefto->array, right); }else return nil; } Array * opAtop(Datum *lefto, Datum *righto, Array *left, Array *right) { if(lefto->tag == FunctionTag && righto->tag == FunctionTag){ Array *right1; if(left) right1 = runfunc(righto->func, left, right); else right1 = runfunc(righto->func, nil, right); Array *result = runfunc(lefto->func, nil, right1); freearray(right1); return result; }else if(lefto->tag == FunctionTag && righto->tag == ArrayTag){ Array *ranks = righto->array; if(ranks->rank > 1) throwerror(nil, ERank); if(ranks->type != AtypeInt) throwerror(nil, EType); if(ranks->size < 1 || ranks->size > 3) throwerror(nil, ELength); int p,q,r; switch(ranks->size){ case 1: p = q = r = ranks->intdata[0]; break; case 2: q = ranks->intdata[0]; p = r = ranks->intdata[1]; break; case 3: p = ranks->intdata[0]; q = ranks->intdata[1]; r = ranks->intdata[2]; break; default: p = q = r = 0; } print("Running %S with ranks %d %d %d\n", ppdatum(*lefto), p, q, r); if(left) throwerror(nil, ENotImplemented); else{ } throwerror(nil, ENotImplemented); return nil; }else return nil; } Array * opOver(Datum *lefto, Datum *righto, Array *left, Array *right) { if(lefto->tag != FunctionTag || righto->tag != FunctionTag) return nil; if(left){ Array *r = runfunc(righto->func, nil, right); Array *l = runfunc(righto->func, nil, left); Array *res = runfunc(lefto->func, l, r); freearray(r); freearray(l); return res; }else{ Array *tmp = runfunc(righto->func, nil, right); Array *res = runfunc(lefto->func, nil, tmp); freearray(tmp); return res; } } Array * opSelfReference2(Datum *lefto, Datum *righto, Array *left, Array *right) { throwerror(L"⍙", ESyntax); return nil; }