diff options
| author | Kai Stevenson <kai@kaistevenson.com> | 2023-02-16 19:24:20 -0800 |
|---|---|---|
| committer | Kai Stevenson <kai@kaistevenson.com> | 2023-02-16 19:24:20 -0800 |
| commit | deeb6aa4aa60e22190087a9615447e742c84a19c (patch) | |
| tree | 11d8ae0e6c684ed5a14657a0fb048a28d45be945 /src | |
| parent | 7410d984ae270528ea4f3f16d3473acf807ef92c (diff) | |
added scoping and a lot of memory leaks
Diffstat (limited to 'src')
| -rw-r--r-- | src/eval.c | 66 | ||||
| -rw-r--r-- | src/eval.h | 9 | ||||
| -rw-r--r-- | src/hashtable.c | 33 | ||||
| -rw-r--r-- | src/hashtable.h | 14 | ||||
| -rw-r--r-- | src/parse.h | 1 | ||||
| -rw-r--r-- | src/precedent.c | 4 | ||||
| -rw-r--r-- | src/scope.c | 17 | ||||
| -rw-r--r-- | src/scope.h | 8 |
8 files changed, 75 insertions, 77 deletions
@@ -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; @@ -1,9 +1,8 @@ #include "parse.h" #ifndef EVAL #define EVAL -void init_eval(void); -void throw(char* error, int symbolLocale); -void exec_all(sym_t** symbols, int count); -sym_t* eval(sym_t* symbol); -sym_t* try_eval_internal(sym_t* symbol); +void throw_e(char* error, int symbolLocale); +sym_t* eval(sym_t* symbol, hashtable_t* parentScope); +void exec_all(sym_t** symbols, int count, hashtable_t* symbolScope); +sym_t* try_eval_internal(sym_t* symbol, hashtable_t* symbolScope); #endif diff --git a/src/hashtable.c b/src/hashtable.c index 7cb253c..2f4ca64 100644 --- a/src/hashtable.c +++ b/src/hashtable.c @@ -5,18 +5,23 @@ const unsigned int fnvPrime = 16777619; const unsigned int fnvOffset = 2166136261U; -pair_t* init_pair(char* key, void* value) { - pair_t* p = malloc(sizeof(pair_t)); - p->key = key; - p->value = value; +pair_t init_pair(char* key, void* value) { + pair_t p; + p.key = key; + p.value = value; return p; } -hashtable_t* init_hashtable(unsigned int capacity) { +hashtable_t* init_hashtable(unsigned int capacity, hashtable_t* parent) { hashtable_t* ht = malloc(sizeof(hashtable_t)); - ht->pairs = calloc(capacity, sizeof(pair_t*)); + ht->pairs = calloc(capacity, sizeof(pair_t)); ht->capacity = capacity; + ht->parent = parent; return ht; } +void destroy_hashtable(hashtable_t* hashtable) { + free(hashtable->pairs); + free(hashtable); +} //FNV-1a hash unsigned int get_hash(char* str) { unsigned int hash = fnvOffset; @@ -28,12 +33,22 @@ unsigned int get_hash(char* str) { } /* TODO: handle collision TODO: return 0 if something goes wrong */ -unsigned int hashtable_add_pair(hashtable_t* hashtable, pair_t* pair) { - unsigned int hash = get_hash(pair->key); +unsigned int hashtable_add_pair(hashtable_t* hashtable, pair_t pair) { + unsigned int hash = get_hash(pair.key); hashtable->pairs[hash % hashtable->capacity] = pair; return hash; } -pair_t* hashtable_get_pair(hashtable_t* hashtable, char* key) { +pair_t hashtable_get_pair(hashtable_t* hashtable, char* key) { unsigned int hash = get_hash(key); return hashtable->pairs[hash % hashtable->capacity]; } +pair_t hashtable_get_pair_recurse(hashtable_t* origin, char* key) { + pair_t pair = hashtable_get_pair(origin, key); + if (pair.key != NULL) { + return pair; + } + if (origin->parent != NULL) { + return hashtable_get_pair_recurse(origin->parent, key); + } + return pair; +} diff --git a/src/hashtable.h b/src/hashtable.h index 43ab23a..3e4d9d9 100644 --- a/src/hashtable.h +++ b/src/hashtable.h @@ -5,15 +5,19 @@ typedef struct HashPair { char* key; void* value; } pair_t; -pair_t* init_pair(char* key, void* value); +pair_t init_pair(char* key, void* value); typedef struct HashTable { - pair_t** pairs; + pair_t* pairs; int capacity; int itemCount; + struct HashTable* parent; } hashtable_t; -hashtable_t* init_hashtable(unsigned int capacity); +hashtable_t* init_hashtable(unsigned int capacity, hashtable_t* parent); +void destroy_hashtable(hashtable_t* hashtable); +hashtable_t* clone_hashtable(hashtable_t* hashtable); unsigned int get_hash(char* str); -unsigned int hashtable_add_pair(hashtable_t* hashtable, pair_t* pair); -pair_t* hashtable_get_pair(hashtable_t* hashtable, char* key); +unsigned int hashtable_add_pair(hashtable_t* hashtable, pair_t pair); +pair_t hashtable_get_pair(hashtable_t* hashtable, char* key); +pair_t hashtable_get_pair_recurse(hashtable_t* origin, char* key); #endif diff --git a/src/parse.h b/src/parse.h index 59c27b7..218f9a1 100644 --- a/src/parse.h +++ b/src/parse.h @@ -1,3 +1,4 @@ +#include "hashtable.h" #ifndef PARSE #define PARSE diff --git a/src/precedent.c b/src/precedent.c index 8be2ad3..7460a0a 100644 --- a/src/precedent.c +++ b/src/precedent.c @@ -49,8 +49,8 @@ int main(int argc, char** argv) { write_symbol_visual(finalSymbol, 0); printf("--END VISUALIZATION--\n"); } - init_eval(); - eval(finalSymbol); + hashtable_t* rootTable = init_hashtable(500, NULL); + eval(finalSymbol, rootTable); return 0; } char* read_file(char* path) { diff --git a/src/scope.c b/src/scope.c index afb9d5c..f2b9f79 100644 --- a/src/scope.c +++ b/src/scope.c @@ -1,20 +1,3 @@ #include <stdlib.h> #include "scope.h" #include "hashtable.h" - -scope_t* init_scope(scope_t parent) { - scope_t* scope = malloc(sizeof(scope_t)); - scope->hashtable = init_hashtable(1000); - *(scope->parent) = parent; - return scope; -} -pair_t* get_pair_global(scope_t* scope, char* key) { - while (scope->parent != NULL) { - pair_t* pair = hashtable_get_pair(scope->hashtable, key); - if (pair != NULL) { - return pair; - } - scope = scope->parent; - } - return NULL; -} diff --git a/src/scope.h b/src/scope.h index d1cda0d..a687015 100644 --- a/src/scope.h +++ b/src/scope.h @@ -2,12 +2,4 @@ #ifndef SCOPE #define SCOPE -typedef struct Scope { - hashtable_t* hashtable; - struct Scope* parent; -} scope_t; -scope_t* init_scope(scope_t parent); -pair_t* get_pair_global(scope_t* scope, char* key); -pair_t* get_pair_local(scope_t* scope, char* key); - #endif |
