Merge branch 'master' into chuck-implementation
[jackhill/mal.git] / rpython / env.py
1 from mal_types import MalType, MalSym, MalList, throw_str
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:
10 assert isinstance(binds, MalList) and isinstance(exprs, MalList)
11 for i in range(len(binds)):
12 bind = binds[i]
13 if not isinstance(bind, MalSym):
14 throw_str("env bind value is not a symbol")
15 if bind.value == u"&":
16 bind = binds[i+1]
17 if not isinstance(bind, MalSym):
18 throw_str("env bind value is not a symbol")
19 self.data[bind.value] = exprs.slice(i)
20 break
21 else:
22 self.data[bind.value] = exprs[i]
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)
39 if not env: throw_str("'" + str(key.value) + "' not found")
40 return env.data[key.value]