summaryrefslogtreecommitdiff
path: root/run.c
diff options
context:
space:
mode:
authorubq323 <ubq323@ubq323.website>2023-07-12 02:22:10 +0100
committerubq323 <ubq323@ubq323.website>2023-07-12 02:22:10 +0100
commitf9f7b92fdda17efe2dca455d6f641a424a97b2db (patch)
tree03f8bfa66a7b944fe9f908972b6ab2dde8b5297f /run.c
parentd9eb793ad606fd47d17a17af24b78b46f2180f84 (diff)
more code
Diffstat (limited to 'run.c')
-rw-r--r--run.c126
1 files changed, 126 insertions, 0 deletions
diff --git a/run.c b/run.c
new file mode 100644
index 0000000..eb65400
--- /dev/null
+++ b/run.c
@@ -0,0 +1,126 @@
+#include "run.h"
+#include "ast.h"
+
+#include <stdio.h>
+#include <string.h>
+
+// static int valueof(AstNode *a) {
+// if (a->ty != AST_NUM) {
+// printf("i need a number\n");
+// return -1;
+// } else {
+// return a->as.num;
+// }
+// }
+
+// void run_thing(AstNode *a) {
+// if (a->ty != AST_LIST)
+// printf("can only run a list\n");
+// else if (a->as.list.len < 3)
+// printf("need at least 3 elements\n");
+// else {
+// AstNode *fn = &a->as.list.vals[0];
+// if (fn->ty != AST_SYMBOL)
+// printf("first el needs to be symbol\n");
+// else if (strcmp(fn->as.str, "+"))
+// printf("can only run +\n");
+// else {
+// int v1 = valueof(&a->as.list.vals[1]);
+// int v2 = valueof(&a->as.list.vals[2]);
+// printf("=> %d\n",v1+v2);
+// }
+// }
+// }
+
+int eval (AstNode a);
+
+// return pointer to nth subnode of AST_LIST node *l.
+// doesn't check that l is a list, or that it has at least n elems.
+#define NTH(l,n) (&(l)->as.list.vals[(n)])
+
+// n is max index
+#define CK_LEN(s, l, n) do { if(l.len-1 != n) { \
+ printf("%s fn requires exactly %d args (%ld provided)",\
+ s, n, l.len-1); return 0; } } while(0);
+static int func_plus(AstVec l) {
+ CK_LEN("+",l,2);
+ return eval(l.vals[1]) + eval(l.vals[2]);
+}
+static int func_id(AstVec l) {
+ CK_LEN("id",l,1);
+ return eval(l.vals[1]);
+}
+static int func_minus(AstVec l) {
+ CK_LEN("-",l,2);
+ return eval(l.vals[1]) - eval(l.vals[2]);
+}
+static int func_mult(AstVec l) {
+ CK_LEN("*",l,2);
+ return eval(l.vals[1]) * eval(l.vals[2]);
+}
+static int func_div(AstVec l) {
+ CK_LEN("/",l,2);
+ return eval(l.vals[1]) / eval(l.vals[2]);
+}
+static int func_print(AstVec l) {
+ CK_LEN("print",l,1);
+ int v = eval(l.vals[1]);
+ printf("%d\n",v);
+ return v;
+}
+
+typedef int (*builtin_func)(AstVec);
+typedef struct {
+ char *name;
+ builtin_func func;
+} BuiltinDesc;
+
+BuiltinDesc builtins[] = {
+ { "+", func_plus },
+ { "-", func_minus },
+ { "*", func_mult },
+ { "/", func_div },
+ { "id", func_id },
+ { "print", func_print },
+ { NULL, NULL },
+};
+
+static int call_builtin(char *name, AstVec arglist) {
+ for (BuiltinDesc *bd = builtins; bd->name != NULL; bd++) {
+ if (0 == strcmp(bd->name, name)) {
+ return bd->func(arglist);
+ }
+ }
+ printf("couldn't find builtin fn %s\n",name);
+ return 0;
+}
+
+
+int eval(AstNode a) {
+ switch (a.ty) {
+ case AST_SYMBOL:
+ printf("cant yet read variable [%s]\n", a.as.str);
+ return 0;
+ break;
+ case AST_NUM:
+ return a.as.num;
+ break;
+ case AST_LIST:;
+ AstVec l = a.as.list;
+ if (l.len < 1) {
+ printf("can't execute empty list\n");
+ return 0;
+ }
+ AstNode *first = &l.vals[0];
+ if (first->ty != AST_SYMBOL) {
+ printf("first element of list must be symbol\n");
+ return 0;
+ }
+ return call_builtin(first->as.str, l);
+ break;
+ default:
+ printf("???\n");
+ return 0;
+ }
+}
+