diff options
author | ubq323 <ubq323@ubq323.website> | 2023-07-31 18:51:46 +0100 |
---|---|---|
committer | ubq323 <ubq323@ubq323.website> | 2023-07-31 18:51:46 +0100 |
commit | f80e73ee8d7f7b68f403033001c632e91cb5ac68 (patch) | |
tree | 359f785f785949191286214681b56058b4f025c4 /run_old.c | |
parent | cd6edc3cb4423672e92d3daaad8e12965ebc70e3 (diff) |
bytecode vm start, can print constants currently
Diffstat (limited to 'run_old.c')
-rw-r--r-- | run_old.c | 121 |
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; + } +} + |