c-repl/src/interpreter.cpp

206 lines
8.0 KiB
C++

#include <vector>
#include <string>
#include <iostream>
#include "include/parser.h"
#include "include/interpreter.h"
#include "include/memory.h"
using namespace std;
EvalResult eval(Node &ast, Memory &memory) {
if (holds_alternative<InnerNode>(ast)) {
InnerNode node = get<InnerNode>(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<int>(eval(node.children[0], memory));
if (cond) {
eval(node.children[1], memory);
}
return {};
} break;
case NodeType::IfElse: {
int cond = get<int>(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<int>(eval(node.children[0], memory));
int e2 = get<int>(eval(node.children[1], memory));
return e1 + e2;
} break;
case NodeType::Minus: {
int e1 = get<int>(eval(node.children[0], memory));
int e2 = get<int>(eval(node.children[1], memory));
return e1 - e2;
} break;
case NodeType::Mult: {
int e1 = get<int>(eval(node.children[0], memory));
int e2 = get<int>(eval(node.children[1], memory));
return e1 * e2;
} break;
case NodeType::Div: {
int e1 = get<int>(eval(node.children[0], memory));
int e2 = get<int>(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<int>(eval(node.children[0], memory));
int e2 = get<int>(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<int>(eval(node.children[0], memory));
return +e1;
} break;
case NodeType::UnaryMinus: {
int e1 = get<int>(eval(node.children[0], memory));
return -e1;
} break;
case NodeType::Declaration: {
Token typeTok = get<Token>(node.children[0]);
Token identifierTok = get<Token>(node.children[1]);
string identifier = get<string>(identifierTok.data);
memory_set(memory, identifier, { });
return {};
} break;
case NodeType::AssignedDeclaration: {
Token typeTok = get<Token>(node.children[0]);
Token identifierTok = get<Token>(node.children[1]);
// Type type = get<Type>(typeTok.data);
string identifier = get<string>(identifierTok.data);
EvalResult value = eval(node.children[2], memory);
memory_set(memory, identifier, value);
return value;
} break;
case NodeType::Assignment: {
Token identifierTok = get<Token>(node.children[0]);
string identifier = get<string>(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<Token>(node.children[0]);
string identifier = get<string>(identifierTok.data);
if (!memory_contains(memory, identifier)) throw RuntimeError("Unknown identifier \""+identifier+"\"", identifierTok.pos);
EvalResult value = memory_get(memory, identifier);
if (holds_alternative<int>(value)) {
memory_update(memory, identifier, get<int>(value) + 1);
return memory_get(memory, identifier);
}
else if (holds_alternative<monostate>(value)) {
throw RuntimeError("Accessing uninitialized identifier \""+identifier+"\"", identifierTok.pos);
}
return value;
}
case NodeType::RIncr: {
Token identifierTok = get<Token>(node.children[0]);
string identifier = get<string>(identifierTok.data);
if (!memory_contains(memory, identifier)) throw RuntimeError("Unknown identifier \""+identifier+"\"", identifierTok.pos);
EvalResult value = memory_get(memory, identifier);
if (holds_alternative<int>(memory_get(memory, identifier))) {
memory_update(memory, identifier, get<int>(value) + 1);
}
else if (holds_alternative<monostate>(value)) {
throw RuntimeError("Accessing uninitialized identifier \""+identifier+"\"", identifierTok.pos);
}
return value;
}
case NodeType::LDecr: {
Token identifierTok = get<Token>(node.children[0]);
string identifier = get<string>(identifierTok.data);
if (!memory_contains(memory, identifier)) throw RuntimeError("Unknown identifier \""+identifier+"\"", identifierTok.pos);
EvalResult value = memory_get(memory, identifier);
if (holds_alternative<int>(value)) {
memory_update(memory, identifier, get<int>(value) - 1);
return memory_get(memory, identifier);
}
else if (holds_alternative<monostate>(value)) {
throw RuntimeError("Accessing uninitialized identifier \""+identifier+"\"", identifierTok.pos);
}
return value;
}
case NodeType::RDecr: {
Token identifierTok = get<Token>(node.children[0]);
string identifier = get<string>(identifierTok.data);
if (!memory_contains(memory, identifier)) throw RuntimeError("Unknown identifier \""+identifier+"\"", identifierTok.pos);
EvalResult value = memory_get(memory, identifier);
if (holds_alternative<int>(memory_get(memory, identifier))) {
memory_update(memory, identifier, get<int>(value) - 1);
}
else if (holds_alternative<monostate>(value)) {
throw RuntimeError("Accessing uninitialized identifier \""+identifier+"\"", identifierTok.pos);
}
return value;
}
}
}
else {
Token token = get<Token>(ast);
switch (token.type) {
case TokenType::Int: {
return get<int>(token.data);
} break;
case TokenType::Identifier: {
string identifier = get<string>(token.data);
if (!memory_contains(memory, identifier)) throw RuntimeError("Unknown identifier \""+identifier+"\"", token.pos);
EvalResult value = memory_get(memory, identifier);
if (holds_alternative<monostate>(value)) throw RuntimeError("Accessing uninitialized identifier \""+identifier+"\"", token.pos);
return value;
} break;
default:
throw;
break;
}
}
return {};
}