Upgrade memory
This commit is contained in:
parent
753d179d47
commit
6f71314f3f
@ -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
|
@ -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
|
@ -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;
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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
64
src/memory.cpp
Normal 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;
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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++) {
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user