diff options
-rw-r--r-- | apl9.h | 8 | ||||
-rw-r--r-- | array.c | 15 | ||||
-rw-r--r-- | eval.c | 74 | ||||
-rw-r--r-- | functions.c | 179 | ||||
-rw-r--r-- | lexer.c | 17 | ||||
-rw-r--r-- | print.c | 2 |
6 files changed, 255 insertions, 40 deletions
@@ -12,8 +12,6 @@ typedef enum BoundFunctionTag, /* Function with left arg bound */ LParTag, RParTag, - LBracketTag, - RBracketTag, ArrowTag, AssignmentTag, NameTag, @@ -70,6 +68,7 @@ struct Statement { int ntoks; Datum *toks; + Statement *guard; Statement *next; }; @@ -170,6 +169,7 @@ int commontype(Array *, Array *, Array **, Array **, int); Array *arrayitem(Array *, int); Array *simplifyarray(Array *); int comparearray(Array *, Array *, int); +Array *fillelement(Array *); /* eval.c */ Datum *eval(Statement *); @@ -189,6 +189,7 @@ void incref(Array *); /* functions.c */ Array *runfunc(Function, Array *,Array *); +Array *rundfn(Rune *, Array *, Array *); /* quadnames.c */ Datum quadnamedatum(QuadnameDef); @@ -196,6 +197,8 @@ Datum quadnamedatum(QuadnameDef); /* Monadic functions from function.c */ Array *fnSame(Array *); Array *fnTally(Array *); +Array *fnMix(Array *); +Array *fnSplit(Array *); Array *fnEnclose(Array *); Array *fnNest(Array *); Array *fnGradeUp(Array *); @@ -218,6 +221,7 @@ Array *fnLogarithm(Array *, Array *); Array *fnLeft(Array *, Array *); Array *fnRight(Array *, Array *); Array *fnMatch(Array *, Array *); +Array *fnTake(Array *, Array *); Array *fnIndex(Array *, Array *); Array *fnCatenateFirst(Array *, Array *); Array *fnReshape(Array *, Array *); @@ -264,4 +264,19 @@ comparearray(Array *a, Array *b, int checkshapes) return -1; else return 0; +} + +Array * +fillelement(Array *a) +{ + switch(a->type){ + case AtypeInt: return mkscalarint(0); + case AtypeFloat: return mkscalarfloat(0); + case AtypeRune: return mkscalarrune(' '); + case AtypeArray: + default: + print("Can't make fill element of array type %d\n", a->type); + exits(nil); + return 0; + } }
\ No newline at end of file @@ -21,38 +21,34 @@ Datum monadop(Datum, Datum); Datum dyadop(Datum, Datum); Datum *lookup(Datum); -int bindingstrengths[13][13] = { -/* A F H MO DO AF ( ) [ ] ← IS N */ - 6, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* A */ - 2, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F */ - 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* H */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* MO */ - 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* DO */ - 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* AF */ - 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, /* ( */ - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, /* ) */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* [ */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ] */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ← */ - 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* IS */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, /* N */ +int bindingstrengths[11][11] = { +/* A F H MO DO AF ( ) ← IS N */ + 6, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, /* A */ + 2, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, /* F */ + 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, /* H */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* MO */ + 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, /* DO */ + 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* AF */ + 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, /* ( */ + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, /* ) */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ← */ + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* IS */ + 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, /* N */ }; -evalfn evalfns[13][13] = { -/* A F H MO DO AF ( ) [ ] ← IS N */ - strand, dyadfun, 0, monadop, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* A */ - monadfun, 0, 0, monadop, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F */ - 0, 0, 0, monadop, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* H */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* MO */ - dyadop, dyadop, dyadop, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* DO */ - monadfun, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* AF */ - 0, 0, 0, 0, 0, 0, 0, parens, 0, 0, 0, 0, 0, /* ( */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ) */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* [ */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ] */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ← */ - assign, assign, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* IS */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, nameis, 0, 0, /* N */ +evalfn evalfns[11][11] = { +/* A F H MO DO AF ( ) ← IS N */ + strand, dyadfun, 0, monadop, 0, 0, 0, 0, 0, 0, 0, /* A */ + monadfun, 0, 0, monadop, 0, 0, 0, 0, 0, 0, 0, /* F */ + 0, 0, 0, monadop, 0, 0, 0, 0, 0, 0, 0, /* H */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* MO */ + dyadop, dyadop, dyadop, 0, 0, 0, 0, 0, 0, 0, 0, /* DO */ + monadfun, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* AF */ + 0, 0, 0, 0, 0, 0, 0, parens, 0, 0, 0, /* ( */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ) */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ← */ + assign, assign, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* IS */ + 0, 0, 0, 0, 0, 0, 0, 0, nameis, 0, 0, /* N */ }; Datum * @@ -107,6 +103,7 @@ retry: return nil; }else{ Datum new = fn(stmt->toks[offset],stmt->toks[offset+1]); + traceprint("handler fn done\n"); if(stmt->toks[offset].tag == ArrayTag) freearray(stmt->toks[offset].array); if(stmt->toks[offset+1].tag == ArrayTag) @@ -125,6 +122,23 @@ retry: } } if(stmt->ntoks == 1){ + if(stmt->guard){ + int guardOK = 1; + if(stmt->toks[0].tag != ArrayTag) + guardOK = 0; + else if(stmt->toks[0].array->size != 1) + guardOK = 0; + else if(stmt->toks[0].array->type != AtypeInt) + guardOK = 0; + else if(stmt->toks[0].array->intdata[0] != 0 && stmt->toks[0].array->intdata[0] != 1) + guardOK = 0; + if(!guardOK){ + print("Guard expected single valued boolean\n"); + exits(nil); + } + if(stmt->toks[0].array->intdata[0] == 1) + return eval(stmt->guard); + } if(stmt->next) return eval(stmt->next); else diff --git a/functions.c b/functions.c index 9649e27..7d8b46c 100644 --- a/functions.c +++ b/functions.c @@ -36,8 +36,8 @@ fnmonad monadfunctiondefs[] = { 0, /* ∧ */ 0, /* ⍲ */ 0, /* ⍱ */ - 0, /* ↑ */ - 0, /* ↓ */ + fnMix, /* ↑ */ + fnSplit, /* ↓ */ fnEnclose, /* ⊂ */ 0, /* ⊃ */ fnNest, /* ⊆ */ @@ -91,7 +91,7 @@ fndyad dyadfunctiondefs[] = { 0, /* ∧ */ 0, /* ⍲ */ 0, /* ⍱ */ - 0, /* ↑ */ + fnTake, /* ↑ */ 0, /* ↓ */ 0, /* ⊂ */ 0, /* ⊃ */ @@ -156,6 +156,15 @@ runfunc(Function f, Array *left, Array *right) } } +Array * +rundfn(Rune *code, Array *left, Array *right) +{ + Function dfn; + dfn.type = FunctypeDfn; + dfn.dfn = code; + return runfunc(dfn, left, right); +} + /* Monadic functions */ Array * @@ -172,6 +181,110 @@ fnTally(Array *right) } Array * +fnMix(Array *right) +{ + if(right->type != AtypeArray || right->size == 0) + return fnSame(right); + + int commonrank = 0; + int i,j; + for(i = 0; i < right->size; i++) + if(right->arraydata[i]->rank > commonrank) + commonrank = right->arraydata[i]->rank; + + Array *commonshape = allocarray(AtypeInt, 1, commonrank); + commonshape->shape[0] = commonrank; + for(i = 0; i < commonrank; i++) + commonshape->intdata[i] = 0; + + for(i = 0; i < right->size; i++){ + Array *a = right->arraydata[i]; + for(j = 0; j < a->rank; j++){ + if(a->shape[a->rank-1-j] > commonshape->intdata[commonrank-1-j]) + commonshape->intdata[commonrank-1-j] = a->shape[a->rank-1-j]; + } + } + + int size = 1; + int commonsize = 1; + for(i = 0; i < right->rank; i++) + size *= right->shape[i]; + for(i = 0; i < commonshape->size; i++){ + size *= commonshape->intdata[i]; + commonsize *= commonshape->intdata[i]; + } + + /* TODO: think about types */ + Array *result = allocarray(right->arraydata[0]->type, right->rank + commonrank, size); + for(i = 0; i < right->rank; i++) + result->shape[i] = right->shape[i]; + for(j = 0; j < commonshape->size; j++) + result->shape[i+j] = commonshape->intdata[j]; + + int *index = malloc(sizeof(int) * commonrank); + int offset; + for(i = 0; i < size/commonsize; i++){ + print("COPY CELL %d\n", i); + Array *a = right->arraydata[i]; + Array *fill = fillelement(a); + if(a->rank == 0){ + print("Copy scalar :-)\n"); + memcpy( + result->rawdata + i * commonsize * datasizes[a->type], + a->rawdata, datasizes[a->type]); + if(a->type == AtypeArray) + incref(a->arraydata[0]); + for(j = 1; j < commonsize; j++){ + memcpy(result->rawdata + (i * commonsize + j) * datasizes[a->type], + fill->rawdata, datasizes[a->type]); + if(fill->type == AtypeArray) + incref(fill->arraydata[0]); + } + }else{ + for(j = 0; j < commonrank; j++) + index[j] = 0; + for(j = 0, offset = 0; offset < commonsize; j++){ + for(int k = 0; index[commonrank-1-k] == a->shape[a->rank-1-k]; k++){ + int nfill = commonshape->intdata[commonrank-1-k] - a->shape[a->rank-1-k]; + if(nfill) + print("Adding %d fills\n", nfill); + while(nfill--){ + memcpy(result->rawdata + (i * commonsize + offset) * datasizes[a->type], + fill->rawdata, datasizes[a->type]); + if(fill->type == AtypeArray) + incref(fill->arraydata[0]); + offset++; + } + index[commonrank-1-k] = 0; + index[commonrank-2-k]++; + } + if(offset < commonsize){ + print("Copying from %d to %d\n", j, commonsize*i+offset); + memcpy( + result->rawdata + (i * commonsize + offset) * datasizes[a->type], + a->rawdata + j * datasizes[a->type], datasizes[a->type]); + if(a->type == AtypeArray) + incref(a->arraydata[j]); + offset++; + index[commonrank-1]++; + } + } + } + freearray(fill); + } + free(index); + free(commonshape); + return result; +} + +Array * +fnSplit(Array *right) +{ + Rune *code = L"0≡≢⍴⍵: ⍵ ⋄ (⊂⍵)⌷⍨¨⍳≢⍵"; + return rundfn(code, nil, right); +} + +Array * fnEnclose(Array *right) { incref(right); @@ -565,6 +678,66 @@ fnMatch(Array *left, Array *right) } Array * +fnTake(Array *left, Array *right) +{ + if(left->type != AtypeInt || left->rank > 1 || left->size > right->rank){ + print("Invalid left arg to ↑\n"); + exits(nil); + } + + int i; + if(left->size == right->rank) + left = fnSame(left); + else{ + Array *old = left; + left = fnShape(right); + for(i = 0; i < old->size; i++) + left->intdata[i] = old->intdata[i]; + } + + if(right->rank == 0){ + Array *leftshape = fnShape(left); + right = fnReshape(leftshape, right); + freearray(leftshape); + } + right = fnSame(right); + + int *shape = malloc(sizeof(int) * left->size); + int size = 1; + for(i = 0; i < left->size; i++){ + int s = left->intdata[i]; + shape[i] = s < 0 ? -s : s; + size *= shape[i]; + } + + Array *result = allocarray(right->type, right->rank, size); + for(i = 0; i < right->rank; i++) + result->shape[i] = shape[i]; + + int *index = mallocz(sizeof(int) * left->size, 1); + int offset; + for(i = 0, offset = 0; offset < size; i++){ + for(int j = left->size-1; index[j] == shape[j]; j--){ + index[j] = 0; + index[j-1]++; + } + print("Result Index: "); + for(int j = 0; j < left->size; j++) + print("%d ", index[j]); + print("\n"); + + /* if index is part of left vector, select those places */ + + offset++; + index[left->size-1]++; + } + + freearray(left); + freearray(right); + return result; +} + +Array * fnIndex(Array *left, Array *right) { int io = currentsymtab->io; @@ -14,6 +14,7 @@ lexline(Rune *line) Statement *stmt = emalloc(sizeof(Statement)); stmt->ntoks = 0; stmt->toks = mallocz(sizeof(Datum) * MAX_LINE_TOKENS, 1); + stmt->guard = nil; stmt->next = nil; while(offset < len){ @@ -21,10 +22,8 @@ lexline(Rune *line) if(isspacerune(line[offset])){ offset++; continue; - }else if(runestrchr(L"[]←⋄⍝⍬", line[offset])){ + }else if(runestrchr(L"←⋄⍝⍬", line[offset])){ switch(line[offset]){ - case '[': stmt->toks[stmt->ntoks].tag = LBracketTag; break; - case ']': stmt->toks[stmt->ntoks].tag = RBracketTag; break; case L'←': stmt->toks[stmt->ntoks].tag = ArrowTag; break; case L'⋄': stmt->next = lexline(&line[offset+1]); goto end; case L'⍝': goto end; @@ -35,6 +34,18 @@ lexline(Rune *line) break; } offset++; + }else if(line[offset] == ':'){ + Rune buf[MAX_LINE_LENGTH]; + Rune *p = buf; + offset++; + while(line[offset] != L'⋄' && offset < len){ + *p = line[offset]; + p++; + offset++; + } + *p = 0; + stmt->guard = lexline(buf); + stmt->ntoks--; }else if(line[offset] == '{'){ Rune buf[MAX_LINE_LENGTH]; Rune *p = buf; @@ -37,8 +37,6 @@ ppdatum(Datum d) break; case LParTag: result = runestrdup(L"("); break; case RParTag: result = runestrdup(L")"); break; - case LBracketTag: result = runestrdup(L"["); break; - case RBracketTag: result = runestrdup(L"]"); break; case ArrowTag: result = runestrdup(L"←"); break; case AssignmentTag: result = runesmprint("%S←", d.symbol->name); break; case NameTag: result = runestrdup(d.symbol->name); break; |