hachem.wtf
aboutsummaryrefslogtreecommitdiff
path: root/eval.c
diff options
context:
space:
mode:
Diffstat (limited to 'eval.c')
-rw-r--r--eval.c73
1 files changed, 73 insertions, 0 deletions
diff --git a/eval.c b/eval.c
new file mode 100644
index 0000000..5841566
--- /dev/null
+++ b/eval.c
@@ -0,0 +1,73 @@
+#include <assert.h>
+#include <stdio.h>
+
+#include "eval.h"
+
+static int evaluate_value(const struct Node* node, long* out)
+{
+ switch (node->kind)
+ {
+ case VALUE_DIFFERENCE:
+ *out = (long)node->first->character - (long)node->second->character;
+ return 0;
+ default: break;
+ }
+
+ assert(!"the parser handed a non-value where a value goes");
+ return 1;
+}
+
+static int evaluate_type(const struct Node* node, struct Type* out)
+{
+ out->kind = KIND_VOID;
+ out->number = 0;
+ switch (node->kind)
+ {
+ case TYPE_DECLTYPE:
+ if (evaluate_value(node->first, &out->number))
+ return 1;
+ out->kind = KIND_VALUE;
+ return 0;
+ default: break;
+ }
+
+ assert(!"the parser handed a non-type where a type goes");
+ return 1;
+}
+
+static enum RunStatus emit(const struct Node* node)
+{
+ struct Type type;
+ if (evaluate_type(node->first, &type))
+ return RUN_FAILED;
+
+ if (type.kind == KIND_VALUE)
+ (void)printf("%ld\n", type.number);
+ return RUN_DONE;
+}
+
+static enum RunStatus execute_one(const struct Node* node)
+{
+ switch (node->kind)
+ {
+ case STMT_EMIT: return emit(node);
+ default: break;
+ }
+
+ assert(!"the parser handed a non-statement where a statement goes");
+ return RUN_FAILED;
+}
+
+enum RunStatus execute(const struct Node* statement)
+{
+ while (statement != NULL)
+ {
+ enum RunStatus status = execute_one(statement);
+ if (status != RUN_DONE)
+ return status;
+
+ statement = statement->next;
+ }
+
+ return RUN_DONE;
+}