summaryrefslogtreecommitdiff
path: root/src/eval.c
diff options
context:
space:
mode:
authorKai Stevenson <kai@kaistevenson.com>2023-02-16 14:32:56 -0800
committerKai Stevenson <kai@kaistevenson.com>2023-02-16 14:32:56 -0800
commit05540fc6038f452f5dc5f18412c918c33ad96027 (patch)
treebb9f572a1cc6f3a66cbf9835593f62db87481e0a /src/eval.c
parent10a1f7e4ad1bc90436f58269a52cddfd0587be33 (diff)
changed project structure
Diffstat (limited to 'src/eval.c')
-rw-r--r--src/eval.c134
1 files changed, 134 insertions, 0 deletions
diff --git a/src/eval.c b/src/eval.c
new file mode 100644
index 0000000..b1d4e0a
--- /dev/null
+++ b/src/eval.c
@@ -0,0 +1,134 @@
+#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(sym_t** symbols, int count) {
+ for (int i = 0; i < count; i++) {
+ /* dispose of result */
+ eval(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 */
+ exec_all(symbol->args, symbol->argCount);
+ 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 = symbol->args[0];
+ pair_t* p = init_pair(k, (void*)v);
+ hashtable_add_pair(ht, 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]);
+ /* 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]);
+ if (symtoi(v) != 0) {
+ exec_all(symbol->args + 1, symbol->argCount - 1);
+ return &trueSym;
+ }
+ return &falseSym;
+ }
+ else if (hash == get_hash("not")) {
+ sym_t* v = eval(symbol->args[0]);
+ int b = symtoi(v);
+ return b ? &falseSym : &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;
+ }
+}