summaryrefslogtreecommitdiff
path: root/run_old.c
diff options
context:
space:
mode:
authorubq323 <ubq323@ubq323.website>2023-07-31 18:51:46 +0100
committerubq323 <ubq323@ubq323.website>2023-07-31 18:51:46 +0100
commitf80e73ee8d7f7b68f403033001c632e91cb5ac68 (patch)
tree359f785f785949191286214681b56058b4f025c4 /run_old.c
parentcd6edc3cb4423672e92d3daaad8e12965ebc70e3 (diff)
bytecode vm start, can print constants currently
Diffstat (limited to 'run_old.c')
-rw-r--r--run_old.c121
1 files changed, 121 insertions, 0 deletions
diff --git a/run_old.c b/run_old.c
new file mode 100644
index 0000000..e4fa540
--- /dev/null
+++ b/run_old.c
@@ -0,0 +1,121 @@
+#include "run.h"
+#include "ast.h"
+#include "ht.h"
+
+#include <stdio.h>
+#include <string.h>
+
+// 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(Env *s, AstVec l) {
+ CK_LEN("+",l,2);
+ return eval(s, l.vals[1]) + eval(s, l.vals[2]);
+}
+static int func_id(Env *s, AstVec l) {
+ CK_LEN("id",l,1);
+ return eval(s, l.vals[1]);
+}
+static int func_minus(Env *s, AstVec l) {
+ CK_LEN("-",l,2);
+ return eval(s, l.vals[1]) - eval(s, l.vals[2]);
+}
+static int func_mult(Env *s, AstVec l) {
+ CK_LEN("*",l,2);
+ return eval(s, l.vals[1]) * eval(s, l.vals[2]);
+}
+static int func_div(Env *s, AstVec l) {
+ CK_LEN("/",l,2);
+ return eval(s, l.vals[1]) / eval(s, l.vals[2]);
+}
+static int func_print(Env *s, AstVec l) {
+ CK_LEN("print",l,1);
+ int v = eval(s, l.vals[1]);
+ printf("%d\n",v);
+ return v;
+}
+static int func_set(Env *s, AstVec l) {
+ CK_LEN("set", l, 2);
+ if (l.vals[1].ty != AST_SYMBOL) {
+ printf("can only assign to symbols");
+ return 0;
+ }
+ int v = eval(s, l.vals[2]);
+ printf(" %p set %s %d\n", (void*)s, l.vals[1].as.str, v);
+ ht_put(s, l.vals[1].as.str, v);
+ return v;
+}
+static int func_do(Env *s, AstVec l) {
+ for (int i = 1; i < l.len; i++) {
+ eval(s, l.vals[i]);
+ }
+ return 0;
+}
+
+typedef int (*builtin_func)(Env*, 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 },
+ { "set", func_set },
+ { "do", func_do },
+
+ { NULL, NULL },
+};
+
+static int call_builtin(Env *s, char *name, AstVec arglist) {
+ for (BuiltinDesc *bd = builtins; bd->name != NULL; bd++) {
+ if (0 == strcmp(bd->name, name)) {
+ return bd->func(s, arglist);
+ }
+ }
+ printf("couldn't find builtin fn %s\n",name);
+ return 0;
+}
+
+int eval(Env *s, AstNode a) {
+ switch (a.ty) {
+ case AST_SYMBOL:;
+ int v;
+ if (ht_get(s, a.as.str, &v)) {
+ return v;
+ } else {
+ printf("unset 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(s, first->as.str, l);
+ break;
+ default:
+ printf("???\n");
+ return 0;
+ }
+}
+