diff --git a/src/include/memory.h b/src/include/memory.h index 7ed3d6f..0de55cf 100644 --- a/src/include/memory.h +++ b/src/include/memory.h @@ -5,14 +5,23 @@ #include "types.h" using namespace std; -Memory new_memory(void); +class Memory { + public: + bool contains(string identifier); + bool contains_top(string identifier); + void add_scope(void); + void remove_scope(void); -bool memory_contains(Memory& memory, string identifier); + EvalResult get(string identifier); + void declare(string identifier, EvalResult value); + void update(string identifier, EvalResult value); -EvalResult memory_get(Memory& memory, string identifier); + Scope& _debug_top(void); -void memory_set(Memory& memory, string identifier, EvalResult value); + Memory(void); -void memory_update(Memory& memory, string identifier, EvalResult value); + private: + list scopes; +}; #endif \ No newline at end of file diff --git a/src/include/types.h b/src/include/types.h index f16947c..c1dba6a 100644 --- a/src/include/types.h +++ b/src/include/types.h @@ -138,9 +138,6 @@ using EvalResult = variant; struct Scope { unordered_map vars; int depth; - string name; }; -using Memory = list; - #endif \ No newline at end of file diff --git a/src/interpreter.cpp b/src/interpreter.cpp index 6e4bb96..b12b561 100644 --- a/src/interpreter.cpp +++ b/src/interpreter.cpp @@ -39,7 +39,10 @@ EvalResult eval(Node &ast, Memory &memory) { return {}; } break; case NodeType::Bloc: { - + memory.add_scope(); + eval(node.children[0], memory); + memory.remove_scope(); + return {}; } break; case NodeType::Plus: { int e1 = get(eval(node.children[0], memory)); @@ -81,7 +84,9 @@ EvalResult eval(Node &ast, Memory &memory) { Token identifierTok = get(node.children[1]); string identifier = get(identifierTok.data); - memory_set(memory, identifier, { }); + if (memory.contains_top(identifier)) throw RuntimeError("Identifier \""+identifier+"\" was already declared in this scope", identifierTok.pos); + + memory.declare(identifier, { }); return {}; } break; @@ -92,7 +97,9 @@ EvalResult eval(Node &ast, Memory &memory) { string identifier = get(identifierTok.data); EvalResult value = eval(node.children[2], memory); - memory_set(memory, identifier, value); + if (memory.contains_top(identifier)) throw RuntimeError("Identifier \""+identifier+"\" was already declared in this scope", identifierTok.pos); + + memory.declare(identifier, value); return value; } break; @@ -101,9 +108,9 @@ EvalResult eval(Node &ast, Memory &memory) { string identifier = get(identifierTok.data); EvalResult value = eval(node.children[1], memory); - if (!memory_contains(memory, identifier)) throw RuntimeError("Unknown identifier \""+identifier+"\"", identifierTok.pos); + if (!memory.contains(identifier)) throw RuntimeError("Unknown identifier \""+identifier+"\"", identifierTok.pos); - memory_update(memory, identifier, value); + memory.update(identifier, value); return value; } break; @@ -111,13 +118,13 @@ EvalResult eval(Node &ast, Memory &memory) { Token identifierTok = get(node.children[0]); string identifier = get(identifierTok.data); - if (!memory_contains(memory, identifier)) throw RuntimeError("Unknown identifier \""+identifier+"\"", identifierTok.pos); + if (!memory.contains(identifier)) throw RuntimeError("Unknown identifier \""+identifier+"\"", identifierTok.pos); - EvalResult value = memory_get(memory, identifier); + EvalResult value = memory.get(identifier); if (holds_alternative(value)) { - memory_update(memory, identifier, get(value) + 1); - return memory_get(memory, identifier); + memory.update(identifier, get(value) + 1); + return memory.get(identifier); } else if (holds_alternative(value)) { throw RuntimeError("Accessing uninitialized identifier \""+identifier+"\"", identifierTok.pos); @@ -129,12 +136,12 @@ EvalResult eval(Node &ast, Memory &memory) { Token identifierTok = get(node.children[0]); string identifier = get(identifierTok.data); - if (!memory_contains(memory, identifier)) throw RuntimeError("Unknown identifier \""+identifier+"\"", identifierTok.pos); + if (!memory.contains(identifier)) throw RuntimeError("Unknown identifier \""+identifier+"\"", identifierTok.pos); - EvalResult value = memory_get(memory, identifier); + EvalResult value = memory.get(identifier); - if (holds_alternative(memory_get(memory, identifier))) { - memory_update(memory, identifier, get(value) + 1); + if (holds_alternative(memory.get(identifier))) { + memory.update(identifier, get(value) + 1); } else if (holds_alternative(value)) { throw RuntimeError("Accessing uninitialized identifier \""+identifier+"\"", identifierTok.pos); @@ -146,13 +153,13 @@ EvalResult eval(Node &ast, Memory &memory) { Token identifierTok = get(node.children[0]); string identifier = get(identifierTok.data); - if (!memory_contains(memory, identifier)) throw RuntimeError("Unknown identifier \""+identifier+"\"", identifierTok.pos); + if (!memory.contains(identifier)) throw RuntimeError("Unknown identifier \""+identifier+"\"", identifierTok.pos); - EvalResult value = memory_get(memory, identifier); + EvalResult value = memory.get(identifier); if (holds_alternative(value)) { - memory_update(memory, identifier, get(value) - 1); - return memory_get(memory, identifier); + memory.update(identifier, get(value) - 1); + return memory.get(identifier); } else if (holds_alternative(value)) { throw RuntimeError("Accessing uninitialized identifier \""+identifier+"\"", identifierTok.pos); @@ -164,12 +171,12 @@ EvalResult eval(Node &ast, Memory &memory) { Token identifierTok = get(node.children[0]); string identifier = get(identifierTok.data); - if (!memory_contains(memory, identifier)) throw RuntimeError("Unknown identifier \""+identifier+"\"", identifierTok.pos); + if (!memory.contains(identifier)) throw RuntimeError("Unknown identifier \""+identifier+"\"", identifierTok.pos); - EvalResult value = memory_get(memory, identifier); + EvalResult value = memory.get(identifier); - if (holds_alternative(memory_get(memory, identifier))) { - memory_update(memory, identifier, get(value) - 1); + if (holds_alternative(memory.get(identifier))) { + memory.update(identifier, get(value) - 1); } else if (holds_alternative(value)) { throw RuntimeError("Accessing uninitialized identifier \""+identifier+"\"", identifierTok.pos); @@ -188,9 +195,9 @@ EvalResult eval(Node &ast, Memory &memory) { case TokenType::Identifier: { string identifier = get(token.data); - if (!memory_contains(memory, identifier)) throw RuntimeError("Unknown identifier \""+identifier+"\"", token.pos); + if (!memory.contains(identifier)) throw RuntimeError("Unknown identifier \""+identifier+"\"", token.pos); - EvalResult value = memory_get(memory, identifier); + EvalResult value = memory.get(identifier); if (holds_alternative(value)) throw RuntimeError("Accessing uninitialized identifier \""+identifier+"\"", token.pos); diff --git a/src/main.cpp b/src/main.cpp index 204d6d0..b39b9b5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -24,7 +24,7 @@ int main(int argc, char* argv[]) { vector input; vector tokens; - Memory memory = new_memory(); + Memory memory = Memory(); while (true) { try { diff --git a/src/memory.cpp b/src/memory.cpp index 20c9868..b20ae52 100644 --- a/src/memory.cpp +++ b/src/memory.cpp @@ -2,18 +2,13 @@ #include "include/memory.h" using namespace std; -Memory new_memory(void) { - Memory memory; - - memory.emplace_back(); - memory.back().depth = 0; - memory.back().name = "global"; - - return memory; +Memory::Memory(void) { + scopes.emplace_back(); + scopes.back().depth = 0; } -bool memory_contains(Memory& memory, string identifier) { - for (auto rit = memory.rbegin(); rit != memory.rend(); ++rit) { +bool Memory::contains(string identifier) { + for (auto rit = scopes.rbegin(); rit != scopes.rend(); ++rit) { Scope& scope = *rit; if (scope.vars.contains(identifier)) return true; } @@ -21,8 +16,24 @@ bool memory_contains(Memory& memory, string identifier) { return false; } -EvalResult memory_get(Memory& memory, string identifier) { - for (auto rit = memory.rbegin(); rit != memory.rend(); ++rit) { +bool Memory::contains_top(string identifier) { + Scope& top = scopes.back(); + return top.vars.contains(identifier); +} + +void Memory::add_scope(void) { + Scope& top = scopes.back(); + scopes.emplace_back(); + scopes.back().depth = top.depth + 1; +} + +void Memory::remove_scope(void) { + scopes.pop_back(); +} + + +EvalResult 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]; } @@ -30,13 +41,13 @@ EvalResult memory_get(Memory& memory, string identifier) { throw; } -void memory_set(Memory& memory, string identifier, EvalResult value) { - Scope& top = memory.back(); +void Memory::declare(string identifier, EvalResult value) { + Scope& top = scopes.back(); top.vars[identifier] = value; } -void memory_update(Memory& memory, string identifier, EvalResult value) { - for (auto rit = memory.rbegin(); rit != memory.rend(); ++rit) { +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; @@ -45,4 +56,9 @@ void memory_update(Memory& memory, string identifier, EvalResult value) { } throw; +} + +Scope& Memory::_debug_top(void) { + Scope& top = scopes.back(); + return top; } \ No newline at end of file diff --git a/test/expr_arithmetiques.cpp b/test/expr_arithmetiques.cpp index 4c8b373..766ab28 100644 --- a/test/expr_arithmetiques.cpp +++ b/test/expr_arithmetiques.cpp @@ -6,7 +6,7 @@ #include "../src/include/interpreter.h" int execute(string s) { - Memory memory = new_memory(); + Memory memory = Memory(); vector tokens = tokenize({ s }); Node ast = parse(tokens); EvalResult res = eval(ast, memory); diff --git a/test/variables.cpp b/test/variables.cpp index b3daff2..ce08e61 100644 --- a/test/variables.cpp +++ b/test/variables.cpp @@ -6,7 +6,7 @@ #include "../src/include/interpreter.h" int execute(string s) { - Memory memory = new_memory(); + Memory memory = Memory(); vector tokens = tokenize({ s }); Node ast = parse(tokens); EvalResult res = eval(ast, memory);