#include #include #include #include "apl9.h" Rune primmonopnames[] = L"¨⍨⌸⌶&"; Rune primdyadopnames[] = L"⍣.∘⍤⍥@⍠⌺"; opmonad monadoperatordefs[] = { opEach, /* ¨ */ opSwitch, /* ⍨ */ 0, /* ⌸ */ 0, /* ⌶ */ 0, /* & */ }; opdyad dyadoperatordefs[] = { 0, /* ⍣ */ 0, /* . */ opBind, /* ∘ */ 0, /* ⍤ */ opOver, /* ⍥ */ 0, /* @ */ 0, /* ⍠ */ 0, /* ⌺ */ }; /* 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; } /* 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 * 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; } }