Commit | Line | Data |
---|---|---|
9be6d5a6 | 1 | from mal_types import MalType, MalSym, MalList, throw_str |
e6cfacb4 JM |
2 | |
3 | # Environment | |
4 | class Env(): | |
5 | def __init__(self, outer=None, binds=None, exprs=None): | |
6 | self.data = {} | |
7 | self.outer = outer or None | |
8 | ||
9 | if binds: | |
b0a9121d | 10 | assert isinstance(binds, MalList) and isinstance(exprs, MalList) |
e6cfacb4 | 11 | for i in range(len(binds)): |
b0a9121d | 12 | bind = binds[i] |
23fa1b11 JM |
13 | if not isinstance(bind, MalSym): |
14 | throw_str("env bind value is not a symbol") | |
b0a9121d JM |
15 | if bind.value == u"&": |
16 | bind = binds[i+1] | |
23fa1b11 JM |
17 | if not isinstance(bind, MalSym): |
18 | throw_str("env bind value is not a symbol") | |
b0a9121d | 19 | self.data[bind.value] = exprs.slice(i) |
e6cfacb4 JM |
20 | break |
21 | else: | |
b0a9121d | 22 | self.data[bind.value] = exprs[i] |
e6cfacb4 JM |
23 | |
24 | def find(self, key): | |
25 | assert isinstance(key, MalSym) | |
26 | if key.value in self.data: return self | |
27 | elif self.outer: return self.outer.find(key) | |
28 | else: return None | |
29 | ||
30 | def set(self, key, value): | |
31 | assert isinstance(key, MalSym) | |
32 | assert isinstance(value, MalType) | |
33 | self.data[key.value] = value | |
34 | return value | |
35 | ||
36 | def get(self, key): | |
37 | assert isinstance(key, MalSym) | |
38 | env = self.find(key) | |
9be6d5a6 | 39 | if not env: throw_str("'" + str(key.value) + "' not found") |
e6cfacb4 | 40 | return env.data[key.value] |