summaryrefslogtreecommitdiff
path: root/internal/interpreter/interpreter.ha
diff options
context:
space:
mode:
Diffstat (limited to 'internal/interpreter/interpreter.ha')
-rw-r--r--internal/interpreter/interpreter.ha56
1 files changed, 56 insertions, 0 deletions
diff --git a/internal/interpreter/interpreter.ha b/internal/interpreter/interpreter.ha
new file mode 100644
index 0000000..5e92461
--- /dev/null
+++ b/internal/interpreter/interpreter.ha
@@ -0,0 +1,56 @@
+use internal::parser;
+use strconv;
+use strings;
+
+export type variable = (str, str);
+export type interpreter = struct {
+ vars: []variable,
+};
+
+export type error = !(interperror | nomem);
+export type interperror = !str;
+
+export fn interpret(it: *interpreter, tree: parser::ast) void = {
+ match (tree.value) {
+ case parser::assign =>
+ assign(it, tree.children)!;
+ };
+};
+
+fn assign(it: *interpreter, nodes: []parser::ast) (void | error) = {
+ const varname = nodes[0].value as parser::varname;
+ const operation = nodes[1].value as parser::operation;
+
+ let value = 0;
+
+ let stack: []int = [];
+
+ for (let i = 0z; i < len(operation.stack); i += 1) {
+ const arg = operation.stack[i];
+ match (arg) {
+ case let i: int =>
+ append(stack, i)?;
+ case let o: parser::operator =>
+ if (len(stack) >= 2) {
+ let last = len(stack) - 1;
+ let val = switch (o) {
+ case parser::operator::ADD =>
+ yield stack[last] + stack[last-1];
+ case parser::operator::SUBTRACT =>
+ yield stack[last] - stack[last-1];
+ case parser::operator::MULTIPLY =>
+ yield stack[last] * stack[last-1];
+ case parser::operator::DIVIDE =>
+ yield stack[last] / stack[last-1];
+ };
+ delete(stack[last-1..]);
+ append(stack, val)?;
+ } else {
+ return "Invalid operation": interperror;
+ };
+ };
+ };
+
+ let last = len(stack) - 1;
+ append(it.vars, (varname, strings::dup(strconv::itos(stack[last]))?))?;
+};