Upgrade memory

This commit is contained in:
ala89 2023-12-08 15:29:30 +01:00
parent 753d179d47
commit 6f71314f3f
12 changed files with 193 additions and 172 deletions

View File

@ -10,6 +10,6 @@ using namespace std;
/*
Evaluates the AST, returning the latest calulated value
*/
EvalResult eval(Node &ast, Memory<EvalResult>& memory);
EvalResult eval(Node &ast, Memory& memory);
#endif

View File

@ -5,7 +5,6 @@
#include "types.h"
using namespace std;
template <typename MemoryEntry>
class Memory {
public:
bool contains(string identifier);
@ -13,9 +12,9 @@ class Memory {
void add_scope(ScopeType type);
void remove_scope(void);
MemoryEntry get(string identifier);
void declare(string identifier, MemoryEntry value);
void update(string identifier, MemoryEntry value);
MemoryVar& get(string identifier);
void declare(string identifier, Type type);
void update(string identifier, EvalResult value);
Scope& _debug_top(void);
@ -25,74 +24,4 @@ class Memory {
list<Scope> scopes;
};
template <typename MemoryEntry>
Memory<MemoryEntry>::Memory(void) {
scopes.emplace_back();
scopes.back().depth = 0;
}
template <typename MemoryEntry>
bool Memory<MemoryEntry>::contains(string identifier) {
for (auto rit = scopes.rbegin(); rit != scopes.rend(); ++rit) {
Scope& scope = *rit;
if (scope.vars.contains(identifier)) return true;
}
return false;
}
template <typename MemoryEntry>
bool Memory<MemoryEntry>::contains_top(string identifier) {
Scope& top = scopes.back();
return top.vars.contains(identifier);
}
template <typename MemoryEntry>
void Memory<MemoryEntry>::add_scope(ScopeType type) {
Scope& top = scopes.back();
scopes.emplace_back();
scopes.back().depth = top.depth + 1;
scopes.back().type = type;
}
template <typename MemoryEntry>
void Memory<MemoryEntry>::remove_scope(void) {
scopes.pop_back();
}
template <typename MemoryEntry>
MemoryEntry Memory<MemoryEntry>::get(string identifier) {
for (auto rit = scopes.rbegin(); rit != scopes.rend(); ++rit) {
Scope& scope = *rit;
if (scope.vars.contains(identifier)) return scope.vars[identifier];
}
throw;
}
template <typename MemoryEntry>
void Memory<MemoryEntry>::declare(string identifier, MemoryEntry value) {
Scope& top = scopes.back();
top.vars[identifier] = value;
}
template <typename MemoryEntry>
void Memory<MemoryEntry>::update(string identifier, MemoryEntry value) {
for (auto rit = scopes.rbegin(); rit != scopes.rend(); ++rit) {
Scope& scope = *rit;
if (scope.vars.contains(identifier)) {
scope.vars[identifier] = value;
return;
}
}
throw;
}
template <typename MemoryEntry>
Scope& Memory<MemoryEntry>::_debug_top(void) {
Scope& top = scopes.back();
return top;
}
#endif

View File

@ -15,7 +15,7 @@ using namespace std;
enum class TokenType { Type, Identifier, Litteral, Plus, Minus, DoublePlus, DoubleMinus, DoubleEqual, Land, Lor, Lt, Gt, Leq, Geq, NotEqual, Not, Star, Slash, Percent, Equal, Semicolon, LParenthese, RParenthese, LCurlyBracket, RCurlyBracket, If, Else, While, For, Comma };
enum class Type { Int, Double };
using TokenData = variant<int, double, string>;
using TokenData = variant<int, double, string, Type>;
struct CodePosition {
int line;
@ -165,8 +165,14 @@ using EvalResult = variant<monostate, int, double>;
enum class ScopeType { Block, Function, For };
struct MemoryVar {
EvalResult value;
Type type;
bool initialized;
};
struct Scope {
unordered_map<string, EvalResult> vars;
unordered_map<string, MemoryVar> vars;
int depth;
ScopeType type;
};

View File

@ -41,7 +41,7 @@ double double_cast(EvalResult value) {
}
}
EvalResult eval(Node &ast, Memory<EvalResult> &memory) {
EvalResult eval(Node &ast, Memory &memory) {
if (holds_alternative<InnerNode>(ast)) {
InnerNode node = get<InnerNode>(ast);
switch (node.type) {
@ -253,24 +253,27 @@ EvalResult eval(Node &ast, Memory<EvalResult> &memory) {
case NodeType::Declaration: {
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);
if (memory.contains_top(identifier)) throw RuntimeError("Identifier \""+identifier+"\" was already declared in this scope", identifierTok.pos);
memory.declare(identifier, { });
memory.declare(identifier, type);
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);
Type type = get<Type>(typeTok.data);
string identifier = get<string>(identifierTok.data);
EvalResult value = eval(node.children[2], memory);
if (memory.contains_top(identifier)) throw RuntimeError("Identifier \""+identifier+"\" was already declared in this scope", identifierTok.pos);
memory.declare(identifier, value);
memory.declare(identifier, type);
if (type == Type::Int) {
memory.update(identifier, int_cast(value));
}
else if (type == Type::Double) {
memory.update(identifier, double_cast(value));
}
return value;
} break;
@ -279,9 +282,14 @@ EvalResult eval(Node &ast, Memory<EvalResult> &memory) {
string identifier = get<string>(identifierTok.data);
EvalResult value = eval(node.children[1], memory);
if (!memory.contains(identifier)) throw RuntimeError("Unknown identifier \""+identifier+"\"", identifierTok.pos);
Type type = memory.get(identifier).type;
memory.update(identifier, value);
if (type == Type::Int) {
memory.update(identifier, int_cast(value));
}
else if (type == Type::Double) {
memory.update(identifier, double_cast(value));
}
return value;
} break;
@ -289,71 +297,71 @@ EvalResult eval(Node &ast, Memory<EvalResult> &memory) {
Token identifierTok = get<Token>(node.children[0]);
string identifier = get<string>(identifierTok.data);
if (!memory.contains(identifier)) throw RuntimeError("Unknown identifier \""+identifier+"\"", identifierTok.pos);
MemoryVar& var = memory.get(identifier);
EvalResult value = memory.get(identifier);
if (holds_alternative<int>(value)) {
memory.update(identifier, get<int>(value) + 1);
return memory.get(identifier);
}
else if (holds_alternative<monostate>(value)) {
if (!var.initialized) {
throw RuntimeError("Accessing uninitialized identifier \""+identifier+"\"", identifierTok.pos);
}
return value;
else if (var.type == Type::Int) {
memory.update(identifier, get<int>(var.value) + 1);
return var.value;
}
else {
return var.value;
}
}
case NodeType::RIncr: {
Token identifierTok = get<Token>(node.children[0]);
string identifier = get<string>(identifierTok.data);
if (!memory.contains(identifier)) throw RuntimeError("Unknown identifier \""+identifier+"\"", identifierTok.pos);
MemoryVar& var = memory.get(identifier);
EvalResult value = memory.get(identifier);
if (holds_alternative<int>(memory.get(identifier))) {
memory.update(identifier, get<int>(value) + 1);
}
else if (holds_alternative<monostate>(value)) {
if (!var.initialized) {
throw RuntimeError("Accessing uninitialized identifier \""+identifier+"\"", identifierTok.pos);
}
return value;
else if (var.type == Type::Int) {
int oldVal = get<int>(var.value);
memory.update(identifier, oldVal + 1);
return oldVal;
}
else {
return var.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);
MemoryVar& var = memory.get(identifier);
EvalResult value = memory.get(identifier);
if (holds_alternative<int>(value)) {
memory.update(identifier, get<int>(value) - 1);
return memory.get(identifier);
}
else if (holds_alternative<monostate>(value)) {
if (!var.initialized) {
throw RuntimeError("Accessing uninitialized identifier \""+identifier+"\"", identifierTok.pos);
}
return value;
else if (var.type == Type::Int) {
memory.update(identifier, get<int>(var.value) - 1);
return var.value;
}
else {
return var.value;
}
}
case NodeType::RDecr: {
Token identifierTok = get<Token>(node.children[0]);
string identifier = get<string>(identifierTok.data);
if (!memory.contains(identifier)) throw RuntimeError("Unknown identifier \""+identifier+"\"", identifierTok.pos);
MemoryVar& var = memory.get(identifier);
EvalResult value = memory.get(identifier);
if (holds_alternative<int>(memory.get(identifier))) {
memory.update(identifier, get<int>(value) - 1);
}
else if (holds_alternative<monostate>(value)) {
if (!var.initialized) {
throw RuntimeError("Accessing uninitialized identifier \""+identifier+"\"", identifierTok.pos);
}
return value;
else if (var.type == Type::Int) {
int oldVal = get<int>(var.value);
memory.update(identifier, oldVal - 1);
return oldVal;
}
else {
return var.value;
}
}
default: {
throw RuntimeError("Not Implemented", node.pos);
@ -376,13 +384,11 @@ EvalResult eval(Node &ast, Memory<EvalResult> &memory) {
case TokenType::Identifier: {
string identifier = get<string>(token.data);
if (!memory.contains(identifier)) throw RuntimeError("Unknown identifier \""+identifier+"\"", token.pos);
MemoryVar& var = memory.get(identifier);
EvalResult value = memory.get(identifier);
if (!var.initialized) throw RuntimeError("Accessing uninitialized identifier \""+identifier+"\"", token.pos);
if (holds_alternative<monostate>(value)) throw RuntimeError("Accessing uninitialized identifier \""+identifier+"\"", token.pos);
return value;
return var.value;
} break;
default:
throw;

View File

@ -24,7 +24,7 @@ int main(int argc, char* argv[]) {
vector<string> input;
vector<Token> tokens;
Memory<EvalResult> memory;
Memory memory;
while (true) {
try {

64
src/memory.cpp Normal file
View File

@ -0,0 +1,64 @@
#include "include/memory.h"
using namespace std;
Memory::Memory(void) {
scopes.emplace_back();
scopes.back().depth = 0;
}
bool Memory::contains(string identifier) {
for (auto rit = scopes.rbegin(); rit != scopes.rend(); ++rit) {
Scope& scope = *rit;
if (scope.vars.contains(identifier)) return true;
}
return false;
}
bool Memory::contains_top(string identifier) {
Scope& top = scopes.back();
return top.vars.contains(identifier);
}
void Memory::add_scope(ScopeType type) {
Scope& top = scopes.back();
scopes.emplace_back();
scopes.back().depth = top.depth + 1;
scopes.back().type = type;
}
void Memory::remove_scope(void) {
scopes.pop_back();
}
MemoryVar& Memory::get(string identifier) {
for (auto rit = scopes.rbegin(); rit != scopes.rend(); ++rit) {
Scope& scope = *rit;
if (scope.vars.contains(identifier)) return scope.vars[identifier];
}
throw;
}
void Memory::declare(string identifier, Type type) {
Scope& top = scopes.back();
top.vars[identifier].type = type;
}
void Memory::update(string identifier, EvalResult value) {
for (auto rit = scopes.rbegin(); rit != scopes.rend(); ++rit) {
Scope& scope = *rit;
if (scope.vars.contains(identifier)) {
scope.vars[identifier].value = value;
scope.vars[identifier].initialized = true;
return;
}
}
throw;
}
Scope& Memory::_debug_top(void) {
Scope& top = scopes.back();
return top;
}

View File

@ -35,9 +35,52 @@ vector<tuple<string, TokenType>> simpleTokens = {
{ "(", TokenType::LParenthese },
{ ")", TokenType::RParenthese },
{ "{", TokenType::LCurlyBracket },
{ "}", TokenType::RCurlyBracket }
{ "}", TokenType::RCurlyBracket },
{ ",", TokenType::Comma }
};
string _debug_get_type_name(Type type) {
switch (type) {
case Type::Int: return "INT";
case Type::Double: return "DOUBLE";
default: return "Unknown";
}
}
string _debug_get_token_type_name(TokenType type) {
switch (type) {
case TokenType::Identifier: return "Identifier";
case TokenType::Litteral: return "Litteral";
case TokenType::Plus: return "Plus";
case TokenType::Minus: return "Minus";
case TokenType::DoublePlus: return "DoublePlus";
case TokenType::DoubleMinus: return "DoubleMinus";
case TokenType::DoubleEqual: return "DoubleEqual";
case TokenType::Land: return "Land";
case TokenType::Lor: return "Lor";
case TokenType::Lt: return "Lt";
case TokenType::Gt: return "Gt";
case TokenType::Leq: return "Leq";
case TokenType::Geq: return "Geq";
case TokenType::NotEqual: return "NotEqual";
case TokenType::Not: return "Not";
case TokenType::Star: return "Star";
case TokenType::Slash: return "Slash";
case TokenType::Percent: return "Percent";
case TokenType::Equal: return "Equal";
case TokenType::Semicolon: return "Semicolon";
case TokenType::LParenthese: return "LParenthese";
case TokenType::RParenthese: return "RParenthese";
case TokenType::LCurlyBracket: return "LCurlyBracket";
case TokenType::RCurlyBracket: return "RCurlyBracket";
case TokenType::If: return "If";
case TokenType::Else: return "Else";
case TokenType::While: return "While";
case TokenType::For: return "For";
default: return "Unknown";
}
}
void _debug_print_token(Token token) {
switch (token.type) {
case TokenType::Litteral:
@ -51,6 +94,9 @@ void _debug_print_token(Token token) {
case TokenType::Identifier:
cout << "Identifier(" << get<string>(token.data) << ")";
break;
case TokenType::Type:
cout << "Type("+_debug_get_type_name(get<Type>(token.data))+")";
break;
case TokenType::Plus:
cout << "+";
break;
@ -129,40 +175,9 @@ void _debug_print_token(Token token) {
case TokenType::For:
cout << "For";
break;
}
}
string _debug_print_token_type(TokenType type) {
switch (type) {
case TokenType::Identifier: return "Identifier";
case TokenType::Litteral: return "Litteral";
case TokenType::Plus: return "Plus";
case TokenType::Minus: return "Minus";
case TokenType::DoublePlus: return "DoublePlus";
case TokenType::DoubleMinus: return "DoubleMinus";
case TokenType::DoubleEqual: return "DoubleEqual";
case TokenType::Land: return "Land";
case TokenType::Lor: return "Lor";
case TokenType::Lt: return "Lt";
case TokenType::Gt: return "Gt";
case TokenType::Leq: return "Leq";
case TokenType::Geq: return "Geq";
case TokenType::NotEqual: return "NotEqual";
case TokenType::Not: return "Not";
case TokenType::Star: return "Star";
case TokenType::Slash: return "Slash";
case TokenType::Percent: return "Percent";
case TokenType::Equal: return "Equal";
case TokenType::Semicolon: return "Semicolon";
case TokenType::LParenthese: return "LParenthese";
case TokenType::RParenthese: return "RParenthese";
case TokenType::LCurlyBracket: return "LCurlyBracket";
case TokenType::RCurlyBracket: return "RCurlyBracket";
case TokenType::If: return "If";
case TokenType::Else: return "Else";
case TokenType::While: return "While";
case TokenType::For: return "For";
default: return "Unknown";
case TokenType::Comma:
cout << "Comma";
break;
}
}

View File

@ -6,7 +6,7 @@
#include "../src/include/interpreter.h"
int execute(string s) {
Memory<EvalResult> memory;;
Memory memory;;
vector<Token> tokens = tokenize({ s });
Node ast = parse(tokens);
EvalResult res = eval(ast, memory);

View File

@ -6,7 +6,7 @@
#include "../src/include/interpreter.h"
int execute(string s) {
Memory<EvalResult> memory;;
Memory memory;;
vector<Token> tokens = tokenize({ s });
Node ast = parse(tokens);
EvalResult res = eval(ast, memory);

View File

@ -6,7 +6,7 @@
#include "../src/include/interpreter.h"
EvalResult execute(string s) {
Memory<EvalResult> memory;;
Memory memory;;
vector<Token> tokens = tokenize({ s });
Node ast = parse(tokens);
EvalResult res = eval(ast, memory);

View File

@ -11,7 +11,7 @@ int main() {
/* All tokens */
vector<string> inputs = {
"int", "a", "=", "x", "++", "--", "==", "&&", "||", "<", ">", "<=", ">=", "!=", "!", "*", "/", "%", "=", ";", "(", ")", "{", "}", "if", "else", "while", "for"
"int", "a", "=", "x", "++", "--", "==", "&&", "||", "<", ">", "<=", ">=", "!=", "!", "*", "/", "%", "=", ";", "(", ")", "{", "}", "if", "else", "while", "for", ","
};
vector<TokenType> expectedTypes = {
@ -20,7 +20,8 @@ int main() {
TokenType::Lor, TokenType::Lt, TokenType::Gt, TokenType::Leq, TokenType::Geq, TokenType::NotEqual,
TokenType::Not, TokenType::Star, TokenType::Slash, TokenType::Percent, TokenType::Equal,
TokenType::Semicolon, TokenType::LParenthese, TokenType::RParenthese, TokenType::LCurlyBracket,
TokenType::RCurlyBracket, TokenType::If, TokenType::Else, TokenType::While, TokenType::For
TokenType::RCurlyBracket, TokenType::If, TokenType::Else, TokenType::While, TokenType::For,
TokenType::Comma
};
for (size_t i = 0; i < inputs.size(); i++) {

View File

@ -6,7 +6,7 @@
#include "../src/include/interpreter.h"
EvalResult execute(string s) {
Memory<EvalResult> memory;;
Memory memory;;
vector<Token> tokens = tokenize({ s });
Node ast = parse(tokens);
EvalResult res = eval(ast, memory);