Add block scopes

This commit is contained in:
ala89 2023-11-22 14:32:22 +01:00
parent 24228f80f5
commit ce431b5453
7 changed files with 79 additions and 50 deletions

View File

@ -5,14 +5,23 @@
#include "types.h" #include "types.h"
using namespace std; 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<Scope> scopes;
};
#endif #endif

View File

@ -138,9 +138,6 @@ using EvalResult = variant<monostate, int, double>;
struct Scope { struct Scope {
unordered_map<string, EvalResult> vars; unordered_map<string, EvalResult> vars;
int depth; int depth;
string name;
}; };
using Memory = list<Scope>;
#endif #endif

View File

@ -39,7 +39,10 @@ EvalResult eval(Node &ast, Memory &memory) {
return {}; return {};
} break; } break;
case NodeType::Bloc: { case NodeType::Bloc: {
memory.add_scope();
eval(node.children[0], memory);
memory.remove_scope();
return {};
} break; } break;
case NodeType::Plus: { case NodeType::Plus: {
int e1 = get<int>(eval(node.children[0], memory)); int e1 = get<int>(eval(node.children[0], memory));
@ -81,7 +84,9 @@ EvalResult eval(Node &ast, Memory &memory) {
Token identifierTok = get<Token>(node.children[1]); Token identifierTok = get<Token>(node.children[1]);
string identifier = get<string>(identifierTok.data); string identifier = get<string>(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 {}; return {};
} break; } break;
@ -92,7 +97,9 @@ EvalResult eval(Node &ast, Memory &memory) {
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);
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; return value;
} break; } break;
@ -101,9 +108,9 @@ EvalResult eval(Node &ast, Memory &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(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; return value;
} break; } break;
@ -111,13 +118,13 @@ EvalResult eval(Node &ast, Memory &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(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<int>(value)) { if (holds_alternative<int>(value)) {
memory_update(memory, identifier, get<int>(value) + 1); memory.update(identifier, get<int>(value) + 1);
return memory_get(memory, identifier); return memory.get(identifier);
} }
else if (holds_alternative<monostate>(value)) { else if (holds_alternative<monostate>(value)) {
throw RuntimeError("Accessing uninitialized identifier \""+identifier+"\"", identifierTok.pos); throw RuntimeError("Accessing uninitialized identifier \""+identifier+"\"", identifierTok.pos);
@ -129,12 +136,12 @@ EvalResult eval(Node &ast, Memory &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(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<int>(memory_get(memory, identifier))) { if (holds_alternative<int>(memory.get(identifier))) {
memory_update(memory, identifier, get<int>(value) + 1); memory.update(identifier, get<int>(value) + 1);
} }
else if (holds_alternative<monostate>(value)) { else if (holds_alternative<monostate>(value)) {
throw RuntimeError("Accessing uninitialized identifier \""+identifier+"\"", identifierTok.pos); throw RuntimeError("Accessing uninitialized identifier \""+identifier+"\"", identifierTok.pos);
@ -146,13 +153,13 @@ EvalResult eval(Node &ast, Memory &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(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<int>(value)) { if (holds_alternative<int>(value)) {
memory_update(memory, identifier, get<int>(value) - 1); memory.update(identifier, get<int>(value) - 1);
return memory_get(memory, identifier); return memory.get(identifier);
} }
else if (holds_alternative<monostate>(value)) { else if (holds_alternative<monostate>(value)) {
throw RuntimeError("Accessing uninitialized identifier \""+identifier+"\"", identifierTok.pos); throw RuntimeError("Accessing uninitialized identifier \""+identifier+"\"", identifierTok.pos);
@ -164,12 +171,12 @@ EvalResult eval(Node &ast, Memory &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(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<int>(memory_get(memory, identifier))) { if (holds_alternative<int>(memory.get(identifier))) {
memory_update(memory, identifier, get<int>(value) - 1); memory.update(identifier, get<int>(value) - 1);
} }
else if (holds_alternative<monostate>(value)) { else if (holds_alternative<monostate>(value)) {
throw RuntimeError("Accessing uninitialized identifier \""+identifier+"\"", identifierTok.pos); throw RuntimeError("Accessing uninitialized identifier \""+identifier+"\"", identifierTok.pos);
@ -188,9 +195,9 @@ EvalResult eval(Node &ast, Memory &memory) {
case TokenType::Identifier: { case TokenType::Identifier: {
string identifier = get<string>(token.data); string identifier = get<string>(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<monostate>(value)) throw RuntimeError("Accessing uninitialized identifier \""+identifier+"\"", token.pos); if (holds_alternative<monostate>(value)) throw RuntimeError("Accessing uninitialized identifier \""+identifier+"\"", token.pos);

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 memory = new_memory(); Memory memory = Memory();
while (true) { while (true) {
try { try {

View File

@ -2,18 +2,13 @@
#include "include/memory.h" #include "include/memory.h"
using namespace std; using namespace std;
Memory new_memory(void) { Memory::Memory(void) {
Memory memory; scopes.emplace_back();
scopes.back().depth = 0;
memory.emplace_back();
memory.back().depth = 0;
memory.back().name = "global";
return memory;
} }
bool memory_contains(Memory& memory, string identifier) { bool Memory::contains(string identifier) {
for (auto rit = memory.rbegin(); rit != memory.rend(); ++rit) { for (auto rit = scopes.rbegin(); rit != scopes.rend(); ++rit) {
Scope& scope = *rit; Scope& scope = *rit;
if (scope.vars.contains(identifier)) return true; if (scope.vars.contains(identifier)) return true;
} }
@ -21,8 +16,24 @@ bool memory_contains(Memory& memory, string identifier) {
return false; return false;
} }
EvalResult memory_get(Memory& memory, string identifier) { bool Memory::contains_top(string identifier) {
for (auto rit = memory.rbegin(); rit != memory.rend(); ++rit) { 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; Scope& scope = *rit;
if (scope.vars.contains(identifier)) return scope.vars[identifier]; if (scope.vars.contains(identifier)) return scope.vars[identifier];
} }
@ -30,13 +41,13 @@ EvalResult memory_get(Memory& memory, string identifier) {
throw; throw;
} }
void memory_set(Memory& memory, string identifier, EvalResult value) { void Memory::declare(string identifier, EvalResult value) {
Scope& top = memory.back(); Scope& top = scopes.back();
top.vars[identifier] = value; top.vars[identifier] = value;
} }
void memory_update(Memory& memory, string identifier, EvalResult value) { void Memory::update(string identifier, EvalResult value) {
for (auto rit = memory.rbegin(); rit != memory.rend(); ++rit) { for (auto rit = scopes.rbegin(); rit != scopes.rend(); ++rit) {
Scope& scope = *rit; Scope& scope = *rit;
if (scope.vars.contains(identifier)) { if (scope.vars.contains(identifier)) {
scope.vars[identifier] = value; scope.vars[identifier] = value;
@ -45,4 +56,9 @@ void memory_update(Memory& memory, string identifier, EvalResult value) {
} }
throw; throw;
}
Scope& Memory::_debug_top(void) {
Scope& top = scopes.back();
return top;
} }

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 memory = new_memory(); 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 memory = new_memory(); 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);