diff options
Diffstat (limited to 'src/eval.c')
| -rw-r--r-- | src/eval.c | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/src/eval.c b/src/eval.c new file mode 100644 index 0000000..b1d4e0a --- /dev/null +++ b/src/eval.c @@ -0,0 +1,134 @@ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include "eval.h" +#include "hashtable.h" +#include "parse.h" + +hashtable_t* ht; +const int hashtableSize = 1000; +const int trueVal = 1; +sym_t trueSym = {LITERAL, INT, (void*)&trueVal, NULL, 0}; +const int falseVal = 0; +sym_t falseSym = {LITERAL, INT, (void*)&falseVal, NULL, 0}; + +void init_eval() { + ht = init_hashtable(hashtableSize); +} +/* TODO: read base hashtable from file to allow modularity +pair value value? */ +void exec_all(sym_t** symbols, int count) { + for (int i = 0; i < count; i++) { + /* dispose of result */ + eval(symbols[i]); + } +} +sym_t* eval(sym_t* symbol) { + if (symbol->province == LITERAL) { + return(symbol); + } + else if (symbol->province == KEY_REF) { + sym_t* ir = try_eval_internal(symbol); + if (ir != NULL) { + return ir; + } + else { + /* not an internal function, search hashtable for + next symbol */ + /* TODO: scope */ + pair_t* p = hashtable_get_pair(ht, (char*)symbol->name); + if (p != NULL) { + return eval((sym_t*)p->value); + } + else { + printf("no matching pair in hashtable\n"); + return NULL; + } + } + } + else { + printf("no symbol province\n"); + return NULL; + } +} +/* internal functions? +this function has side-effects */ +sym_t* try_eval_internal(sym_t* symbol) { + unsigned int hash = get_hash((char*)symbol->name); + /* TODO: return last arg. that's the function return line */ + if (hash == get_hash("root")) { + /* execute all args as roots */ + exec_all(symbol->args, symbol->argCount); + return &trueSym; + } + else if (hash == get_hash("store")) { + /* TODO: scope */ + /* first arg is value, remaining args are names */ + /* TODO: recursion for multiple pairs */ + char* k = symtos(eval(symbol->args[1])); + sym_t* v = symbol->args[0]; + pair_t* p = init_pair(k, (void*)v); + hashtable_add_pair(ht, p); + return &trueSym; + } + /* TODO: release()/free() method? */ + else if (hash == get_hash("eq")) { + litType_t type = NO_TYPE; + void* lastVal = NULL; + for (int i = 0; i < symbol->argCount; i++) { + sym_t* v = eval(symbol->args[i]); + /* initialize */ + if (type == NO_TYPE) { + type = v->litType; + lastVal = v->name; + } + else { + /* interpret type */ + if (type == INT) { + if (symtoi(v) != *((int*)lastVal)) { + return &falseSym; + } + } + if (type == STRING) { + if (strcmp(symtos(v), (char*)lastVal) != 0) { + return &falseSym; + } + } + /* TODO: float */ + } + } + return &trueSym; + } + else if (hash == get_hash("if")) { + sym_t* v = eval(symbol->args[0]); + if (symtoi(v) != 0) { + exec_all(symbol->args + 1, symbol->argCount - 1); + return &trueSym; + } + return &falseSym; + } + else if (hash == get_hash("not")) { + sym_t* v = eval(symbol->args[0]); + int b = symtoi(v); + return b ? &falseSym : &trueSym; + } + else if (hash == get_hash("print")) { + sym_t* v = eval(symbol->args[0]); + switch (v->litType) { + case NO_TYPE: + break; + case INT: + printf("%d\n", symtoi(v)); + break; + case FLOAT: + break; + case STRING: + printf("%s\n", symtos(v)); + break; + } + return &trueSym; + } + else { + return NULL; + } +} |
