summaryrefslogtreecommitdiff
path: root/eval.c
diff options
context:
space:
mode:
Diffstat (limited to 'eval.c')
-rw-r--r--eval.c123
1 files changed, 123 insertions, 0 deletions
diff --git a/eval.c b/eval.c
new file mode 100644
index 0000000..3cbe987
--- /dev/null
+++ b/eval.c
@@ -0,0 +1,123 @@
+#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(symset_t symset) {
+ for (int i = 0; i < symset.count; i++) {
+ /* dispose of result */
+ eval(symset.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 */
+ symset_t symset;
+ symset.symbols = symbol->args;
+ symset.count = symbol->argCount;
+ exec_all(symset);
+ 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 = eval(symbol->args[0]);
+ pair_t* p = init_pair(k, (void*)v);
+ hashtable_add_pair(ht, p);
+ return &trueSym;
+ }
+ 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("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;
+ }
+}