From 1ef3119fe613823a2145126c58948361ca7d3cd8 Mon Sep 17 00:00:00 2001 From: Peter Mikkelsen Date: Sat, 8 Jan 2022 22:45:00 +0000 Subject: Add initial code, just to get started --- apl9.h | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ array.c | 29 +++++++++++++++++++++++++++++ eval.c | 15 +++++++++++++++ lexer.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ main.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ mkfile | 16 ++++++++++++++++ print.c | 25 +++++++++++++++++++++++++ 7 files changed, 277 insertions(+) create mode 100644 apl9.h create mode 100644 array.c create mode 100644 eval.c create mode 100644 lexer.c create mode 100644 main.c create mode 100644 mkfile create mode 100644 print.c diff --git a/apl9.h b/apl9.h new file mode 100644 index 0000000..6b5445c --- /dev/null +++ b/apl9.h @@ -0,0 +1,65 @@ +/* Global definitions of limits and constants */ +#define MAX_LINE_LENGTH 1024 +#define MAX_LINE_TOKENS 1024 + +typedef enum +{ + ArrayTag, + FunctionTag, + HybridTag, + MonadicOpTag, + DyadicOpTag, + BoundFunctionTag, /* Function with left arg bound */ + LParTag, + RParTag, + LCurlTag, + RCurlTag, + LBracketTag, + RBracketTag +} datumTag; + +typedef enum +{ + AtypeInt +} arrayDataType; + +/* Data types */ +typedef struct Array Array; +typedef struct Datum Datum; + +struct Array +{ + arrayDataType type; + int rank; + int *shape; + union { + char *rawdata; + vlong *intdata; + }; +}; + +struct Datum +{ + datumTag tag; + Rune *strrep; + union { + Array *array; + }; +}; + +/* Function prototypes for the different source files */ +/* print.c */ +Rune *ppdatum(Datum); +Rune *ppdatums(Datum *, int); + +/* lexer.c */ +Datum *lexline(Rune *, int *); + +/* array.c */ +Array *mkscalarint(vlong); + +/* eval.c */ +Datum *eval(Datum *, int *); + +/* Global variables */ +Rune *errormsg; /* eval.c */ \ No newline at end of file diff --git a/array.c b/array.c new file mode 100644 index 0000000..766ccd8 --- /dev/null +++ b/array.c @@ -0,0 +1,29 @@ +#include +#include +#include + +#include "apl9.h" + +int datasizes[] = { + [AtypeInt] = sizeof(vlong) +}; + +Array * +mkarray(arrayDataType t, int rank, int size) +{ + Array *a = malloc(sizeof(Array)); + a->rank = rank; + a->shape = malloc(sizeof(int) * rank); + a->rawdata = malloc(datasizes[t] * size); + a->type = t; + return a; +} + +Array * +mkscalarint(vlong i) +{ + Array *a = mkarray(AtypeInt, 0, 1); + a->intdata[0] = i; + + return a; +} \ No newline at end of file diff --git a/eval.c b/eval.c new file mode 100644 index 0000000..baabf21 --- /dev/null +++ b/eval.c @@ -0,0 +1,15 @@ +#include +#include +#include + +#include "apl9.h" + +Rune *errormsg; + +Datum * +eval(Datum *tokens, int *ntoks) +{ + *ntoks = 0; + errormsg = L"Evaluator not written yet"; + return tokens; +} \ No newline at end of file diff --git a/lexer.c b/lexer.c new file mode 100644 index 0000000..68e925b --- /dev/null +++ b/lexer.c @@ -0,0 +1,65 @@ +#include +#include +#include + +#include "apl9.h" + +Rune primfuncnames[] = L"+-×÷*⍟⌹○!?|⌈⌊⊥⊤⊣⊢=≠≤<>≥≡≢∨∧⍲⍱↑↓⊂⊃⊆⌷⍋⍒⍳⍸∊⍷∪∩~,⍪⍴⌽⊖⍉⍎⍕"; +Rune primmonopnames[] = L"¨⍨⌸⌶&"; +Rune primdyadopnames[] = L"⍣.∘⍤⍥@⍠⌺"; +Rune primhybridnames[] = L"/\⌿⍀"; + +Datum * +lexline(Rune *line, int *ntoks) +{ + int offset = 0; + int len = runestrlen(line); + Datum *tokens = mallocz(sizeof(Datum) * MAX_LINE_TOKENS, 1); + *ntoks = 0; + while(offset < len){ + if(isspacerune(line[offset])){ + offset++; + continue; + }else if(runestrchr(L"(){}[]", line[offset])){ + switch(line[offset]){ + case '(': tokens[*ntoks].tag = LParTag; break; + case ')': tokens[*ntoks].tag = RParTag; break; + case '{': tokens[*ntoks].tag = LCurlTag; break; + case '}': tokens[*ntoks].tag = RCurlTag; break; + case '[': tokens[*ntoks].tag = LBracketTag; break; + case ']': tokens[*ntoks].tag = RBracketTag; break; + } + tokens[*ntoks].strrep = runesmprint("%C", line[offset]); + offset++; + }else if(runestrchr(primfuncnames, line[offset])){ + tokens[*ntoks].tag = FunctionTag; + tokens[*ntoks].strrep = runesmprint("%C", line[offset]); + offset++; + }else if(runestrchr(primmonopnames, line[offset])){ + tokens[*ntoks].tag = MonadicOpTag; + tokens[*ntoks].strrep = runesmprint("%C", line[offset]); + offset++; + }else if(runestrchr(primdyadopnames, line[offset])){ + tokens[*ntoks].tag = DyadicOpTag; + tokens[*ntoks].strrep = runesmprint("%C", line[offset]); + offset++; + }else if(isdigitrune(line[offset])){ + char buf[64]; + char *p = buf; + while(isdigitrune(line[offset])){ + p += runetochar(p, &line[offset]); + offset++; + } + *p = 0; + tokens[*ntoks].tag = ArrayTag; + tokens[*ntoks].array = mkscalarint(atoll(buf)); + tokens[*ntoks].strrep = runesmprint("%s", buf); + }else{ + print("Can't lex: %S\n", &line[offset]); + *ntoks = 0; + break; + } + (*ntoks)++; + } + return tokens; +} \ No newline at end of file diff --git a/main.c b/main.c new file mode 100644 index 0000000..04264b1 --- /dev/null +++ b/main.c @@ -0,0 +1,62 @@ +#include +#include +#include + +#include "apl9.h" + +Rune *prompt(Rune *); +Datum *evalline(Rune *); + +Biobuf *stdin; + +void +main(void) +{ + int off = 0; + stdin = Bfdopen(0, OREAD); + + while(!off){ + Rune *input = prompt(L"\t"); + Datum *result = evalline(input); + if(result == nil){ + if(errormsg == nil) + off = 1; + else + print("ERROR: %S\n", errormsg); + }else{ + ppdatum(*result); + free(result); + } + } + exits(nil); +} + +Rune * +prompt(Rune *pr) +{ + Rune line[MAX_LINE_LENGTH]; + + print("%S",pr); + + int i = 0; + line[0] = 0; + while(i == 0 || line[i-1] != '\n') + line[i++] = Bgetrune(stdin); + line[i-1] = 0; + return runestrdup(line); +} + +Datum * +evalline(Rune *line) +{ + int ntoks; + Datum *tokens = lexline(line, &ntoks); + print("Evaluating line (n=%d): %S\n", ntoks, ppdatums(tokens, ntoks)); + Datum *result = eval(tokens, &ntoks); + if(ntoks == 1) + return result; + else{ + free(tokens); + return nil; + } +} \ No newline at end of file diff --git a/mkfile b/mkfile new file mode 100644 index 0000000..266453c --- /dev/null +++ b/mkfile @@ -0,0 +1,16 @@ + +#include +#include + +#include "apl9.h" + +Rune * +ppdatum(Datum d) +{ + return runestrdup(d.strrep); +} + +Rune * +ppdatums(Datum *ds, int n) +{ + int i; + Rune *res = runesmprint(""); + Rune *tmp; + for(i = 0; i < n; i++){ + tmp = res; + res = runesmprint("%S %S", res, ppdatum(ds[i])); + free(tmp); + } + return res; +} \ No newline at end of file -- cgit v1.2.3