From deeb6aa4aa60e22190087a9615447e742c84a19c Mon Sep 17 00:00:00 2001 From: Kai Stevenson Date: Thu, 16 Feb 2023 19:24:20 -0800 Subject: added scoping and a lot of memory leaks --- src/eval.c | 66 +++++++++++++++++++++++++++++++++----------------------------- 1 file changed, 35 insertions(+), 31 deletions(-) (limited to 'src/eval.c') diff --git a/src/eval.c b/src/eval.c index b1d4e0a..dffd289 100644 --- a/src/eval.c +++ b/src/eval.c @@ -5,70 +5,74 @@ #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) { +sym_t* eval(sym_t* symbol, hashtable_t* parentScope) { if (symbol->province == LITERAL) { return(symbol); } else if (symbol->province == KEY_REF) { - sym_t* ir = try_eval_internal(symbol); + sym_t* returnV = NULL; + /* entering new scope, so create a new table */ + hashtable_t* newScope = init_hashtable(500, parentScope); + sym_t* ir = try_eval_internal(symbol, newScope); if (ir != NULL) { - return ir; + returnV = 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); + pair_t p = hashtable_get_pair_recurse(parentScope, (char*)symbol->name); + if (p.key != NULL) { + returnV = eval((sym_t*)p.value, newScope); } else { printf("no matching pair in hashtable\n"); - return NULL; } } + /* clear new scope, then return */ + destroy_hashtable(newScope); + return returnV; } else { printf("no symbol province\n"); return NULL; } } +void exec_all(sym_t** symbols, int count, hashtable_t* symbolScope) { + for (int i = 0; i < count; i++) { + eval(symbols[i], symbolScope); + destroy_sym(symbols[i]); + } +} /* internal functions? this function has side-effects */ -sym_t* try_eval_internal(sym_t* symbol) { +sym_t* try_eval_internal(sym_t* symbol, hashtable_t* symbolScope) { 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; + /* execute all args as roots except for the last */ + /* return last arg, that's the function return line */ + exec_all(symbol->args, symbol->argCount - 1, symbolScope); + return eval(symbol->args[symbol->argCount - 1], symbolScope); + } + else if (hash == get_hash("arg")) { + /* get positional arg in current scope */ + return NULL; } 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])); + char* k = symtos(eval(symbol->args[1], symbolScope)); sym_t* v = symbol->args[0]; - pair_t* p = init_pair(k, (void*)v); - hashtable_add_pair(ht, p); + pair_t p = init_pair(k, (void*)v); + hashtable_add_pair(symbolScope->parent, p); return &trueSym; } /* TODO: release()/free() method? */ @@ -76,7 +80,7 @@ sym_t* try_eval_internal(sym_t* symbol) { litType_t type = NO_TYPE; void* lastVal = NULL; for (int i = 0; i < symbol->argCount; i++) { - sym_t* v = eval(symbol->args[i]); + sym_t* v = eval(symbol->args[i], symbolScope); /* initialize */ if (type == NO_TYPE) { type = v->litType; @@ -100,20 +104,20 @@ sym_t* try_eval_internal(sym_t* symbol) { return &trueSym; } else if (hash == get_hash("if")) { - sym_t* v = eval(symbol->args[0]); + sym_t* v = eval(symbol->args[0], symbolScope); if (symtoi(v) != 0) { - exec_all(symbol->args + 1, symbol->argCount - 1); + exec_all(symbol->args + 1, symbol->argCount - 1, symbolScope); return &trueSym; } return &falseSym; } else if (hash == get_hash("not")) { - sym_t* v = eval(symbol->args[0]); + sym_t* v = eval(symbol->args[0], symbolScope); int b = symtoi(v); return b ? &falseSym : &trueSym; } else if (hash == get_hash("print")) { - sym_t* v = eval(symbol->args[0]); + sym_t* v = eval(symbol->args[0], symbolScope); switch (v->litType) { case NO_TYPE: break; -- cgit v1.3.1