c-repl/src/interpreter.cpp

119 lines
4.2 KiB
C++
Raw Normal View History

2023-11-10 13:42:53 +01:00
#include <vector>
2023-11-10 17:35:33 +01:00
#include <iostream>
#include <unordered_map>
#include <string>
2023-11-10 13:42:53 +01:00
#include "include/parser.h"
#include "include/interpreter.h"
using namespace std;
2023-11-10 17:35:33 +01:00
unordered_map<string, int> memory;
2023-11-10 13:42:53 +01:00
2023-11-10 17:35:33 +01:00
EvalResult eval(Node &ast) {
if (ast.index() == 0) {
InnerNode node = get<InnerNode>(ast);
switch (node.type) {
case NodeType::Prog:
eval(node.children[0]);
return eval(node.children[1]);
break;
case NodeType::Epsilon:
return {};
break;
case NodeType::Plus: {
int e1 = get<int>(eval(node.children[0]));
int e2 = get<int>(eval(node.children[1]));
return e1 + e2;
} break;
case NodeType::Minus: {
int e1 = get<int>(eval(node.children[0]));
int e2 = get<int>(eval(node.children[1]));
return e1 - e2;
} break;
case NodeType::Mult: {
int e1 = get<int>(eval(node.children[0]));
int e2 = get<int>(eval(node.children[1]));
return e1 * e2;
} break;
case NodeType::Div: {
int e1 = get<int>(eval(node.children[0]));
int e2 = get<int>(eval(node.children[1]));
2023-11-15 13:40:37 +01:00
if (e2 == 0) throw RuntimeError("Division by 0");
2023-11-10 17:35:33 +01:00
return e1 / e2;
} break;
case NodeType::Mod: {
int e1 = get<int>(eval(node.children[0]));
int e2 = get<int>(eval(node.children[1]));
2023-11-15 13:40:37 +01:00
if (e2 == 0) throw RuntimeError("Modulo by 0");
2023-11-10 17:35:33 +01:00
return e1 % e2;
} break;
case NodeType::UnaryPlus: {
int e1 = get<int>(eval(node.children[0]));
return +e1;
} break;
case NodeType::UnaryMinus: {
int e1 = get<int>(eval(node.children[0]));
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);
2023-11-10 13:42:53 +01:00
2023-11-10 17:35:33 +01:00
memory[identifier] = 0;
return {};
} break;
case NodeType::AssignedDeclaration: {
Token typeTok = get<Token>(node.children[0]);
Token identifierTok = get<Token>(node.children[1]);
string identifier = get<string>(identifierTok.data);
int expr = get<int>(eval(node.children[2]));
memory[identifier] = expr;
return expr;
} break;
case NodeType::Assignment: {
Token identifierTok = get<Token>(node.children[0]);
string identifier = get<string>(identifierTok.data);
int expr = get<int>(eval(node.children[1]));
memory[identifier] = expr;
return expr;
} break;
2023-11-14 19:48:24 +01:00
case NodeType::LIncr:
case NodeType::RIncr: {
Token identifierTok = get<Token>(node.children[0]);
string identifier = get<string>(identifierTok.data);
return node.type == NodeType::LIncr ? ++memory[identifier] : memory[identifier]++;
}
case NodeType::LDecr:
case NodeType::RDecr: {
Token identifierTok = get<Token>(node.children[0]);
string identifier = get<string>(identifierTok.data);
return node.type == NodeType::LDecr ? --memory[identifier] : memory[identifier]--;
}
2023-11-10 17:35:33 +01:00
}
}
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);
2023-11-15 13:40:37 +01:00
if (!memory.contains(identifier)) throw RuntimeError("Unknown identifier");
2023-11-10 17:35:33 +01:00
return memory[identifier];
} break;
default:
throw;
break;
}
}
return {};
2023-11-10 13:42:53 +01:00
}