summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/eval.c66
-rw-r--r--src/eval.h9
-rw-r--r--src/hashtable.c33
-rw-r--r--src/hashtable.h14
-rw-r--r--src/parse.h1
-rw-r--r--src/precedent.c4
-rw-r--r--src/scope.c17
-rw-r--r--src/scope.h8
8 files changed, 75 insertions, 77 deletions
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;
diff --git a/src/eval.h b/src/eval.h
index b91c621..fe1450b 100644
--- a/src/eval.h
+++ b/src/eval.h
@@ -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