Commit | Line | Data |
---|---|---|
3934e3f8 HT |
1 | import 'types.dart'; |
2 | ||
3 | class Env { | |
4 | final Env outer; | |
5 | ||
6 | final data = <MalSymbol, MalType>{}; | |
7 | ||
8 | Env([this.outer, List<MalSymbol> binds, List<MalType> exprs]) { | |
9 | if (binds == null) { | |
10 | assert(exprs == null); | |
11 | } else { | |
12 | assert(exprs != null && | |
13 | (binds.length == exprs.length || binds.contains(new MalSymbol('&')))); | |
14 | for (var i = 0; i < binds.length; i++) { | |
15 | if (binds[i] == new MalSymbol('&')) { | |
16 | set(binds[i + 1], new MalList(exprs.sublist(i))); | |
17 | break; | |
18 | } | |
19 | set(binds[i], exprs[i]); | |
20 | } | |
21 | } | |
22 | } | |
23 | ||
24 | void set(MalSymbol key, MalType value) { | |
25 | data[key] = value; | |
26 | } | |
27 | ||
28 | Env find(MalSymbol key) { | |
29 | if (data[key] != null) { | |
30 | return this; | |
31 | } | |
32 | if (outer != null) { | |
33 | return outer.find(key); | |
34 | } | |
35 | return null; | |
36 | } | |
37 | ||
38 | MalType get(MalSymbol key) { | |
39 | var env = find(key); | |
40 | if (env != null) { | |
41 | return env.data[key]; | |
42 | } | |
43 | throw new NotFoundException(key.value); | |
44 | } | |
45 | } | |
46 | ||
47 | class NotFoundException implements Exception { | |
48 | /// The name of the symbol that was not found. | |
49 | final String value; | |
50 | ||
51 | NotFoundException(this.value); | |
52 | ||
53 | String toString() => "'$value' not found"; | |
54 | } |