-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlenv.cpp
90 lines (72 loc) · 2.23 KB
/
lenv.cpp
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#include "lenv.hpp"
#include <algorithm>
#include "lval.hpp"
#include "lval_error.hpp"
using std::string;
using std::vector;
auto error = lval::error;
lenv::lenv() { this->parent = nullptr; }
lenv::lenv(const lenv &other): symbols(table_type(other.symbols)) {
this->parent = other.parent;
for (auto it = this->symbols.begin(); it != this->symbols.end(); ++it) {
it->second = new lval(it->second);
}
}
lenv::lenv(const lenv *const other): lenv(*other) {}
lenv::~lenv() {
for (auto entry: this->symbols) {
delete entry.second;
}
}
vector<string> lenv::keys() const {
vector<string> keys;
keys.reserve(symbols.size());
std::transform(symbols.begin(), symbols.end(), std::back_inserter(keys),
[](auto it) { return it.first; });
return keys;
}
vector<const string *> lenv::keys(const string &prefix) const {
vector<const string *> keys;
keys.reserve(symbols.size());
for (auto it = symbols.begin(); it != symbols.end(); ++it) {
auto &sym = it->first;
if (prefix.size() <= sym.size() &&
std::equal(prefix.begin(), prefix.end(), sym.begin())) {
keys.push_back(&sym);
}
}
return keys;
}
lval *lenv::get(const string &sym) const {
auto it = symbols.find(sym);
if (it != symbols.end()) {
return new lval(it->second);
}
if (parent) {
return parent->get(sym);
}
return error(lerr::unknown_sym(sym));
}
void lenv::put(const string &sym, const lval *const v) {
auto it = symbols.find(sym);
if (it != symbols.end()) {
delete it->second;
it->second = new lval(v);
} else {
symbols.insert(std::make_pair(sym, new lval(v)));
}
}
void lenv::def(const string &sym, const lval *const v) {
auto e = this;
while (e->parent) e = e->parent;
e->put(sym, v);
}
void lenv::add_builtin_function(const string &name, lbuiltin func) {
symbols.insert(std::make_pair(name, lval::function(func)));
}
void lenv::add_builtin_macro(const string &name, lbuiltin func) {
symbols.insert(std::make_pair(name, lval::macro(func)));
}
void lenv::add_builtin_command(const string &name, lbuiltin func) {
symbols.insert(std::make_pair(name, lval::command(func)));
}