diff options
Diffstat (limited to 'internal/interpreter/interpreter.ha')
| -rw-r--r-- | internal/interpreter/interpreter.ha | 56 |
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]))?))?; +}; |
