#include #include #include #include "include/parser.h" #include "include/interpreter.h" #include "include/memory.h" using namespace std; EvalResult eval(Node &ast, Memory &memory) { if (holds_alternative(ast)) { InnerNode node = get(ast); switch (node.type) { case NodeType::Prog: eval(node.children[0], memory); return eval(node.children[1], memory); break; case NodeType::Epsilon: return {}; break; case NodeType::If: { int cond = get(eval(node.children[0], memory)); if (cond) { eval(node.children[1], memory); } return {}; } break; case NodeType::IfElse: { int cond = get(eval(node.children[0], memory)); if (cond) { eval(node.children[1], memory); } else { eval(node.children[2], memory); } return {}; } break; case NodeType::Bloc: { } break; case NodeType::Plus: { int e1 = get(eval(node.children[0], memory)); int e2 = get(eval(node.children[1], memory)); return e1 + e2; } break; case NodeType::Minus: { int e1 = get(eval(node.children[0], memory)); int e2 = get(eval(node.children[1], memory)); return e1 - e2; } break; case NodeType::Mult: { int e1 = get(eval(node.children[0], memory)); int e2 = get(eval(node.children[1], memory)); return e1 * e2; } break; case NodeType::Div: { int e1 = get(eval(node.children[0], memory)); int e2 = get(eval(node.children[1], memory)); if (e2 == 0) throw RuntimeError("Division by 0", node.pos); return e1 / e2; } break; case NodeType::Mod: { int e1 = get(eval(node.children[0], memory)); int e2 = get(eval(node.children[1], memory)); if (e2 == 0) throw RuntimeError("Modulo by 0", node.pos); return e1 % e2; } break; case NodeType::UnaryPlus: { int e1 = get(eval(node.children[0], memory)); return +e1; } break; case NodeType::UnaryMinus: { int e1 = get(eval(node.children[0], memory)); return -e1; } break; case NodeType::Declaration: { Token typeTok = get(node.children[0]); Token identifierTok = get(node.children[1]); string identifier = get(identifierTok.data); memory_set(memory, identifier, { }); return {}; } break; case NodeType::AssignedDeclaration: { Token typeTok = get(node.children[0]); Token identifierTok = get(node.children[1]); // Type type = get(typeTok.data); string identifier = get(identifierTok.data); EvalResult value = eval(node.children[2], memory); memory_set(memory, identifier, value); return value; } break; case NodeType::Assignment: { Token identifierTok = get(node.children[0]); string identifier = get(identifierTok.data); EvalResult value = eval(node.children[1], memory); if (!memory_contains(memory, identifier)) throw RuntimeError("Unknown identifier \""+identifier+"\"", identifierTok.pos); memory_update(memory, identifier, value); return value; } break; case NodeType::LIncr: { Token identifierTok = get(node.children[0]); string identifier = get(identifierTok.data); if (!memory_contains(memory, identifier)) throw RuntimeError("Unknown identifier \""+identifier+"\"", identifierTok.pos); EvalResult value = memory_get(memory, identifier); if (holds_alternative(value)) { memory_update(memory, identifier, get(value) + 1); return memory_get(memory, identifier); } else if (holds_alternative(value)) { throw RuntimeError("Accessing uninitialized identifier \""+identifier+"\"", identifierTok.pos); } return value; } case NodeType::RIncr: { Token identifierTok = get(node.children[0]); string identifier = get(identifierTok.data); if (!memory_contains(memory, identifier)) throw RuntimeError("Unknown identifier \""+identifier+"\"", identifierTok.pos); EvalResult value = memory_get(memory, identifier); if (holds_alternative(memory_get(memory, identifier))) { memory_update(memory, identifier, get(value) + 1); } else if (holds_alternative(value)) { throw RuntimeError("Accessing uninitialized identifier \""+identifier+"\"", identifierTok.pos); } return value; } case NodeType::LDecr: { Token identifierTok = get(node.children[0]); string identifier = get(identifierTok.data); if (!memory_contains(memory, identifier)) throw RuntimeError("Unknown identifier \""+identifier+"\"", identifierTok.pos); EvalResult value = memory_get(memory, identifier); if (holds_alternative(value)) { memory_update(memory, identifier, get(value) - 1); return memory_get(memory, identifier); } else if (holds_alternative(value)) { throw RuntimeError("Accessing uninitialized identifier \""+identifier+"\"", identifierTok.pos); } return value; } case NodeType::RDecr: { Token identifierTok = get(node.children[0]); string identifier = get(identifierTok.data); if (!memory_contains(memory, identifier)) throw RuntimeError("Unknown identifier \""+identifier+"\"", identifierTok.pos); EvalResult value = memory_get(memory, identifier); if (holds_alternative(memory_get(memory, identifier))) { memory_update(memory, identifier, get(value) - 1); } else if (holds_alternative(value)) { throw RuntimeError("Accessing uninitialized identifier \""+identifier+"\"", identifierTok.pos); } return value; } } } else { Token token = get(ast); switch (token.type) { case TokenType::Int: { return get(token.data); } break; case TokenType::Identifier: { string identifier = get(token.data); if (!memory_contains(memory, identifier)) throw RuntimeError("Unknown identifier \""+identifier+"\"", token.pos); EvalResult value = memory_get(memory, identifier); if (holds_alternative(value)) throw RuntimeError("Accessing uninitialized identifier \""+identifier+"\"", token.pos); return value; } break; default: throw; break; } } return {}; }