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 Evaluates the AST, returning the latest calulated value
*/ */
EvalResult eval(Node &ast, Memory<EvalResult>& memory); EvalResult eval(Node &ast, Memory& memory);
#endif #endif

View File

@ -5,7 +5,6 @@
#include "types.h" #include "types.h"
using namespace std; using namespace std;
template <typename MemoryEntry>
class Memory { class Memory {
public: public:
bool contains(string identifier); bool contains(string identifier);
@ -13,9 +12,9 @@ class Memory {
void add_scope(ScopeType type); void add_scope(ScopeType type);
void remove_scope(void); void remove_scope(void);
MemoryEntry get(string identifier); MemoryVar& get(string identifier);
void declare(string identifier, MemoryEntry value); void declare(string identifier, Type type);
void update(string identifier, MemoryEntry value); void update(string identifier, EvalResult value);
Scope& _debug_top(void); Scope& _debug_top(void);
@ -25,74 +24,4 @@ class Memory {
list<Scope> scopes; 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 #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 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 }; enum class Type { Int, Double };
using TokenData = variant<int, double, string>; using TokenData = variant<int, double, string, Type>;
struct CodePosition { struct CodePosition {
int line; int line;
@ -165,8 +165,14 @@ using EvalResult = variant<monostate, int, double>;
enum class ScopeType { Block, Function, For }; enum class ScopeType { Block, Function, For };
struct MemoryVar {
EvalResult value;
Type type;
bool initialized;
};
struct Scope { struct Scope {
unordered_map<string, EvalResult> vars; unordered_map<string, MemoryVar> vars;
int depth; int depth;
ScopeType type; 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)) { if (holds_alternative<InnerNode>(ast)) {
InnerNode node = get<InnerNode>(ast); InnerNode node = get<InnerNode>(ast);
switch (node.type) { switch (node.type) {
@ -253,24 +253,27 @@ EvalResult eval(Node &ast, Memory<EvalResult> &memory) {
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);
if (memory.contains_top(identifier)) throw RuntimeError("Identifier \""+identifier+"\" was already declared in this scope", identifierTok.pos); memory.declare(identifier, type);
memory.declare(identifier, { });
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); Type type = get<Type>(typeTok.data);
string identifier = get<string>(identifierTok.data); string identifier = get<string>(identifierTok.data);
EvalResult value = eval(node.children[2], memory); 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, type);
if (type == Type::Int) {
memory.declare(identifier, value); memory.update(identifier, int_cast(value));
}
else if (type == Type::Double) {
memory.update(identifier, double_cast(value));
}
return value; return value;
} break; } break;
@ -279,9 +282,14 @@ EvalResult eval(Node &ast, Memory<EvalResult> &memory) {
string identifier = get<string>(identifierTok.data); string identifier = get<string>(identifierTok.data);
EvalResult value = eval(node.children[1], memory); 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; return value;
} break; } break;
@ -289,71 +297,71 @@ EvalResult eval(Node &ast, Memory<EvalResult> &memory) {
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);
if (!memory.contains(identifier)) throw RuntimeError("Unknown identifier \""+identifier+"\"", identifierTok.pos); MemoryVar& var = memory.get(identifier);
EvalResult value = memory.get(identifier); if (!var.initialized) {
if (holds_alternative<int>(value)) {
memory.update(identifier, get<int>(value) + 1);
return memory.get(identifier);
}
else if (holds_alternative<monostate>(value)) {
throw RuntimeError("Accessing uninitialized identifier \""+identifier+"\"", identifierTok.pos); throw RuntimeError("Accessing uninitialized identifier \""+identifier+"\"", identifierTok.pos);
} }
else if (var.type == Type::Int) {
return value; memory.update(identifier, get<int>(var.value) + 1);
return var.value;
}
else {
return var.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);
if (!memory.contains(identifier)) throw RuntimeError("Unknown identifier \""+identifier+"\"", identifierTok.pos); MemoryVar& var = memory.get(identifier);
EvalResult value = memory.get(identifier); if (!var.initialized) {
if (holds_alternative<int>(memory.get(identifier))) {
memory.update(identifier, get<int>(value) + 1);
}
else if (holds_alternative<monostate>(value)) {
throw RuntimeError("Accessing uninitialized identifier \""+identifier+"\"", identifierTok.pos); throw RuntimeError("Accessing uninitialized identifier \""+identifier+"\"", identifierTok.pos);
} }
else if (var.type == Type::Int) {
return value; int oldVal = get<int>(var.value);
memory.update(identifier, oldVal + 1);
return oldVal;
}
else {
return var.value;
}
} }
case NodeType::LDecr: { case NodeType::LDecr: {
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);
if (!memory.contains(identifier)) throw RuntimeError("Unknown identifier \""+identifier+"\"", identifierTok.pos); MemoryVar& var = memory.get(identifier);
EvalResult value = memory.get(identifier); if (!var.initialized) {
if (holds_alternative<int>(value)) {
memory.update(identifier, get<int>(value) - 1);
return memory.get(identifier);
}
else if (holds_alternative<monostate>(value)) {
throw RuntimeError("Accessing uninitialized identifier \""+identifier+"\"", identifierTok.pos); throw RuntimeError("Accessing uninitialized identifier \""+identifier+"\"", identifierTok.pos);
} }
else if (var.type == Type::Int) {
return value; memory.update(identifier, get<int>(var.value) - 1);
return var.value;
}
else {
return var.value;
}
} }
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);
if (!memory.contains(identifier)) throw RuntimeError("Unknown identifier \""+identifier+"\"", identifierTok.pos); MemoryVar& var = memory.get(identifier);
EvalResult value = memory.get(identifier); if (!var.initialized) {
if (holds_alternative<int>(memory.get(identifier))) {
memory.update(identifier, get<int>(value) - 1);
}
else if (holds_alternative<monostate>(value)) {
throw RuntimeError("Accessing uninitialized identifier \""+identifier+"\"", identifierTok.pos); throw RuntimeError("Accessing uninitialized identifier \""+identifier+"\"", identifierTok.pos);
} }
else if (var.type == Type::Int) {
return value; int oldVal = get<int>(var.value);
memory.update(identifier, oldVal - 1);
return oldVal;
}
else {
return var.value;
}
} }
default: { default: {
throw RuntimeError("Not Implemented", node.pos); throw RuntimeError("Not Implemented", node.pos);
@ -376,13 +384,11 @@ EvalResult eval(Node &ast, Memory<EvalResult> &memory) {
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 \""+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; } break;
default: default:
throw; throw;

View File

@ -24,7 +24,7 @@ int main(int argc, char* argv[]) {
vector<string> input; vector<string> input;
vector<Token> tokens; vector<Token> tokens;
Memory<EvalResult> memory; Memory memory;
while (true) { while (true) {
try { 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::LParenthese },
{ ")", TokenType::RParenthese }, { ")", TokenType::RParenthese },
{ "{", TokenType::LCurlyBracket }, { "{", 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) { void _debug_print_token(Token token) {
switch (token.type) { switch (token.type) {
case TokenType::Litteral: case TokenType::Litteral:
@ -51,6 +94,9 @@ void _debug_print_token(Token token) {
case TokenType::Identifier: case TokenType::Identifier:
cout << "Identifier(" << get<string>(token.data) << ")"; cout << "Identifier(" << get<string>(token.data) << ")";
break; break;
case TokenType::Type:
cout << "Type("+_debug_get_type_name(get<Type>(token.data))+")";
break;
case TokenType::Plus: case TokenType::Plus:
cout << "+"; cout << "+";
break; break;
@ -129,40 +175,9 @@ void _debug_print_token(Token token) {
case TokenType::For: case TokenType::For:
cout << "For"; cout << "For";
break; break;
} case TokenType::Comma:
} cout << "Comma";
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";
} }
} }

View File

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

View File

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

View File

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

View File

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

View File

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