From f9f7b92fdda17efe2dca455d6f641a424a97b2db Mon Sep 17 00:00:00 2001 From: ubq323 Date: Wed, 12 Jul 2023 02:22:10 +0100 Subject: more code --- run.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 run.c (limited to 'run.c') 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 +#include + +// 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; + } +} + -- cgit v1.2.3