summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apl9.h65
-rw-r--r--array.c29
-rw-r--r--eval.c15
-rw-r--r--lexer.c65
-rw-r--r--main.c62
-rw-r--r--mkfile16
-rw-r--r--print.c25
7 files changed, 277 insertions, 0 deletions
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 <u.h>
+#include <libc.h>
+#include <bio.h>
+
+#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 <u.h>
+#include <libc.h>
+#include <bio.h>
+
+#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 <u.h>
+#include <libc.h>
+#include <bio.h>
+
+#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 <u.h>
+#include <libc.h>
+#include <bio.h>
+
+#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 @@
+</$objtype/mkfile
+
+TARG=apl9
+OFILES=\
+ main.$O\
+ lexer.$O\
+ eval.$O\
+ print.$O\
+ array.$O\
+
+HFILES=\
+ apl9.h\
+
+BIN=/$objtype/bin
+
+</sys/src/cmd/mkone
diff --git a/print.c b/print.c
new file mode 100644
index 0000000..c457647
--- /dev/null
+++ b/print.c
@@ -0,0 +1,25 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+#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