Memory types

This commit is contained in:
ala89 2023-11-15 15:42:30 +01:00
parent b407b21cde
commit 7b89fcbf1f
4 changed files with 82 additions and 20 deletions

View File

@ -6,12 +6,22 @@
#include <stdexcept> #include <stdexcept>
using namespace std; using namespace std;
using EvalResult = variant<int, monostate>; #include "tokenize.h"
using EvalResult = variant<monostate, int, double>;
struct MemoryEntry {
EvalResult value { };
bool assigned { false };
Type type;
};
class RuntimeError : public runtime_error { class RuntimeError : public runtime_error {
public: public:
explicit RuntimeError(const string& message) explicit RuntimeError(const string& message, CodePosition pos)
: runtime_error(message) {} : runtime_error(message), pos(pos) {}
const CodePosition pos;
}; };
/* /*

View File

@ -25,8 +25,10 @@ struct Token {
class TokenError : public runtime_error { class TokenError : public runtime_error {
public: public:
explicit TokenError(const string& message) explicit TokenError(const string& message, CodePosition pos)
: runtime_error(message) {} : runtime_error(message), pos(pos) {}
const CodePosition pos;
}; };
/* /*

View File

@ -6,7 +6,7 @@
#include "include/interpreter.h" #include "include/interpreter.h"
using namespace std; using namespace std;
unordered_map<string, int> memory; unordered_map<string, MemoryEntry> memory;
EvalResult eval(Node &ast) { EvalResult eval(Node &ast) {
if (ast.index() == 0) { if (ast.index() == 0) {
@ -37,13 +37,13 @@ EvalResult eval(Node &ast) {
case NodeType::Div: { case NodeType::Div: {
int e1 = get<int>(eval(node.children[0])); int e1 = get<int>(eval(node.children[0]));
int e2 = get<int>(eval(node.children[1])); int e2 = get<int>(eval(node.children[1]));
if (e2 == 0) throw RuntimeError("Division by 0"); if (e2 == 0) throw RuntimeError("Division by 0", node.pos);
return e1 / e2; return e1 / e2;
} break; } break;
case NodeType::Mod: { case NodeType::Mod: {
int e1 = get<int>(eval(node.children[0])); int e1 = get<int>(eval(node.children[0]));
int e2 = get<int>(eval(node.children[1])); int e2 = get<int>(eval(node.children[1]));
if (e2 == 0) throw RuntimeError("Modulo by 0"); if (e2 == 0) throw RuntimeError("Modulo by 0", node.pos);
return e1 % e2; return e1 % e2;
} break; } break;
case NodeType::UnaryPlus: { case NodeType::UnaryPlus: {
@ -57,44 +57,92 @@ EvalResult eval(Node &ast) {
case NodeType::Declaration: { case NodeType::Declaration: {
Token typeTok = get<Token>(node.children[0]); Token typeTok = get<Token>(node.children[0]);
Token identifierTok = get<Token>(node.children[1]); Token identifierTok = get<Token>(node.children[1]);
Type type = get<Type>(typeTok.data);
string identifier = get<string>(identifierTok.data); string identifier = get<string>(identifierTok.data);
memory[identifier] = 0; memory[identifier] = {
.type = type
};
return {}; return {};
} break; } break;
case NodeType::AssignedDeclaration: { case NodeType::AssignedDeclaration: {
Token typeTok = get<Token>(node.children[0]); Token typeTok = get<Token>(node.children[0]);
Token identifierTok = get<Token>(node.children[1]); Token identifierTok = get<Token>(node.children[1]);
Type type = get<Type>(typeTok.data);
string identifier = get<string>(identifierTok.data); string identifier = get<string>(identifierTok.data);
int expr = get<int>(eval(node.children[2])); EvalResult expr = eval(node.children[2]);
memory[identifier] = expr; memory[identifier] = {
.value = expr,
.assigned = true,
.type = type,
};
return expr; return expr;
} break; } break;
case NodeType::Assignment: { case NodeType::Assignment: {
Token identifierTok = get<Token>(node.children[0]); Token identifierTok = get<Token>(node.children[0]);
string identifier = get<string>(identifierTok.data); string identifier = get<string>(identifierTok.data);
int expr = get<int>(eval(node.children[1])); EvalResult expr = eval(node.children[1]);
memory[identifier] = expr; if (!memory.contains(identifier)) throw RuntimeError("Unknown identifier \""+identifier+"\"", identifierTok.pos);
memory[identifier].value = expr;
return expr; return expr;
} break; } break;
case NodeType::LIncr: case NodeType::LIncr: {
Token identifierTok = get<Token>(node.children[0]);
string identifier = get<string>(identifierTok.data);
if (!memory.contains(identifier)) throw RuntimeError("Unknown identifier \""+identifier+"\"", identifierTok.pos);
if (memory[identifier].type == Type::Int) {
memory[identifier].value = get<int>(memory[identifier].value) + 1;
}
return memory[identifier].value;
}
case NodeType::RIncr: { case NodeType::RIncr: {
Token identifierTok = get<Token>(node.children[0]); Token identifierTok = get<Token>(node.children[0]);
string identifier = get<string>(identifierTok.data); string identifier = get<string>(identifierTok.data);
return node.type == NodeType::LIncr ? ++memory[identifier] : memory[identifier]++; if (!memory.contains(identifier)) throw RuntimeError("Unknown identifier \""+identifier+"\"", identifierTok.pos);
if (memory[identifier].type == Type::Int) {
EvalResult res = memory[identifier].value;
memory[identifier].value = get<int>(memory[identifier].value) + 1;
return res;
}
return memory[identifier].value;
}
case NodeType::LDecr: {
Token identifierTok = get<Token>(node.children[0]);
string identifier = get<string>(identifierTok.data);
if (!memory.contains(identifier)) throw RuntimeError("Unknown identifier \""+identifier+"\"", identifierTok.pos);
if (memory[identifier].type == Type::Int) {
memory[identifier].value = get<int>(memory[identifier].value) - 1;
}
return memory[identifier].value;
} }
case NodeType::LDecr:
case NodeType::RDecr: { case NodeType::RDecr: {
Token identifierTok = get<Token>(node.children[0]); Token identifierTok = get<Token>(node.children[0]);
string identifier = get<string>(identifierTok.data); string identifier = get<string>(identifierTok.data);
return node.type == NodeType::LDecr ? --memory[identifier] : memory[identifier]--; if (!memory.contains(identifier)) throw RuntimeError("Unknown identifier \""+identifier+"\"", identifierTok.pos);
if (memory[identifier].type == Type::Int) {
EvalResult res = memory[identifier].value;
memory[identifier].value = get<int>(memory[identifier].value) - 1;
return res;
}
return memory[identifier].value;
} }
} }
} }
@ -106,8 +154,10 @@ EvalResult eval(Node &ast) {
} break; } break;
case TokenType::Identifier: { case TokenType::Identifier: {
string identifier = get<string>(token.data); string identifier = get<string>(token.data);
if (!memory.contains(identifier)) throw RuntimeError("Unknown identifier");
return memory[identifier]; if (!memory.contains(identifier)) throw RuntimeError("Unknown identifier \""+identifier+"\"", token.pos);
return memory[identifier].value;
} break; } break;
default: default:
throw; throw;

View File

@ -162,7 +162,7 @@ vector<Token> tokenize(vector<string> input) {
j += 1; j += 1;
} }
else { else {
throw TokenError("Unknown token {}"); throw TokenError("Unknown token {}", pos);
} }
} }
} }