#include #include #include #include "eval.h" #include "hashtable.h" #include "parse.h" 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}; /* TODO: read base hashtable from file to allow modularity pair value value? */ sym_t* eval(sym_t* symbol, hashtable_t* parentScope) { if (symbol->province == LITERAL) { return(symbol); } else if (symbol->province == KEY_REF) { sym_t* returnV = NULL; /* entering new scope, so create a new table */ hashtable_t* newScope = init_hashtable(50, parentScope); sym_t* ir = try_eval_internal(symbol, newScope); if (ir != NULL) { returnV = ir; } else { /* not an internal function, search hashtable for next symbol */ /* TODO: scope */ pair_t p = hashtable_get_pair_recurse(parentScope, (char*)symbol->name); if (p.key != NULL) { sym_t* nextSym = (sym_t*)p.value; /* add params */ for (int i = 0; i < symbol->argCount && i < 100; i++) { char* keyName = malloc(6 * sizeof(char)); strcpy(keyName, "arg"); char index[3]; snprintf(index, 3, "%d", i); strcat(keyName, index); pair_t argPair = init_pair(keyName, eval(symbol->args[i], parentScope)); hashtable_add_pair(newScope, argPair); } returnV = eval(nextSym, newScope); } else { printf("no matching pair in hashtable\n"); } } /* 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, hashtable_t* symbolScope) { unsigned int hash = get_hash((char*)symbol->name); if (hash == get_hash("root")) { /* 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); } /* TODO: rename storel */ else if (hash == get_hash("store")) { /* first arg is value, remaining args are names */ /* TODO: recursion for multiple pairs */ 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(symbolScope->parent, 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], symbolScope); /* 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], symbolScope); if (symtoi(v) != 0) { 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], symbolScope); int b = symtoi(v); return b ? &falseSym : &trueSym; } else if (hash == get_hash("sum")) { int* sum = calloc(1, sizeof(int)); for (int i = 0; i < symbol->argCount; i++) { sym_t* v = eval(symbol->args[i], symbolScope); *sum += symtoi(v); } return init_sym(LITERAL, INT, sum); } else if (hash == get_hash("print")) { sym_t* v = eval(symbol->args[0], symbolScope); 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; } }