Repository navigation
Expand file tree
/
Copy pathEnvironment.cpp
More file actions
75 lines (65 loc) · 1.89 KB
/
Copy pathEnvironment.cpp
File metadata and controls
75 lines (65 loc) · 1.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include "Environment.h"
Environment::Environment() = default;
Environment::~Environment() = default;
void Environment::setEnclosing(Environment *enclosing) {
if (this->enclosing) {
throw std::runtime_error("Environment already set");
}
this->enclosing = enclosing;
}
Environment* Environment::ancestor(const unsigned int depth) {
Environment* env = this;
for (unsigned int i = 0; i < depth; i++) {
env = env->ancestor(i);
if (env == nullptr) {
return nullptr;
}
}
return env;
}
void Environment::clear() {
this->enclosing = nullptr;
values.clear();
}
void Environment::define(const std::string &name, const ObjPtr &value) {
values[name] = value;
}
ObjPtr Environment::get(const Token &token) {
const auto it = values.find(token.lexeme);
if (it == values.end()) {
if (enclosing != nullptr) {
return enclosing->get(token);
}
throw RuntimeError(token, "Undefined variable '" + token.lexeme + "'.");
}
return it->second;
}
ObjPtr Environment::getAt(const unsigned int depth, const Token &token) {
Environment* env = ancestor(depth);
if (env == nullptr) {
throw std::runtime_error("Environment unavailable depth.");
}
return env->get(token);
}
void Environment::assign(const Token &token, const ObjPtr &value) {
const auto it = values.find(token.lexeme);
if (it != values.end()) {
it->second = value;
return;
}
if (enclosing != nullptr) {
enclosing->assign(token, value);
return;
}
throw RuntimeError(token, "Undefined variable '" + token.lexeme + "'.");
}
void Environment::assignAt(const unsigned int depth, const Token &token, const ObjPtr &value) {
Environment* env = ancestor(depth);
if (env == nullptr) {
throw std::runtime_error("Environment unavailable depth.");
}
env->assign(token, value);
}
size_t Environment::memoryUsage() const {
return (sizeof(ObjPtr) + sizeof(Object)) * values.size();
}