Add block scopes
This commit is contained in:
parent
24228f80f5
commit
ce431b5453
@ -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
|
@ -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
|
@ -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);
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
@ -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;
|
||||||
}
|
}
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user