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"
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

View File

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

View File

@ -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<int>(eval(node.children[0], memory));
@ -81,7 +84,9 @@ EvalResult eval(Node &ast, Memory &memory) {
Token identifierTok = get<Token>(node.children[1]);
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 {};
} break;
@ -92,7 +97,9 @@ EvalResult eval(Node &ast, Memory &memory) {
string identifier = get<string>(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<string>(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<Token>(node.children[0]);
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)) {
memory_update(memory, identifier, get<int>(value) + 1);
return memory_get(memory, identifier);
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);
@ -129,12 +136,12 @@ EvalResult eval(Node &ast, Memory &memory) {
Token identifierTok = get<Token>(node.children[0]);
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))) {
memory_update(memory, identifier, get<int>(value) + 1);
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);
@ -146,13 +153,13 @@ EvalResult eval(Node &ast, Memory &memory) {
Token identifierTok = get<Token>(node.children[0]);
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)) {
memory_update(memory, identifier, get<int>(value) - 1);
return memory_get(memory, identifier);
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);
@ -164,12 +171,12 @@ EvalResult eval(Node &ast, Memory &memory) {
Token identifierTok = get<Token>(node.children[0]);
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))) {
memory_update(memory, identifier, get<int>(value) - 1);
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);
@ -188,9 +195,9 @@ EvalResult eval(Node &ast, Memory &memory) {
case TokenType::Identifier: {
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);

View File

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

View File

@ -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;
}

View File

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