diff options
Diffstat (limited to 'run.c')
-rw-r--r-- | run.c | 121 |
1 files changed, 0 insertions, 121 deletions
@@ -1,121 +0,0 @@ -#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; - } -} - |