b26be022 |
1 | require "./types" |
2c76c2ff |
2 | require "./error" |
b26be022 |
3 | |
4 | module Mal |
5 | |
6 | class Env |
7 | property data |
8 | |
9 | def initialize(@outer) |
10 | @data = {} of String => Mal::Type |
11 | end |
12 | |
095b73ea |
13 | def initialize(@outer, binds, exprs : Array(Mal::Type)) |
14 | @data = {} of String => Mal::Type |
15 | |
2c76c2ff |
16 | eval_error "binds must be list or vector" unless binds.is_a? Array |
095b73ea |
17 | |
18 | # Note: |
19 | # Array#zip() can't be used because overload resolution failed |
bed63064 |
20 | (0...binds.size).each do |idx| |
51be5007 |
21 | sym = binds[idx].unwrap |
22 | eval_error "bind name must be symbol" unless sym.is_a? Mal::Symbol |
4499e5c8 |
23 | |
24 | if sym.str == "&" |
51be5007 |
25 | eval_error "missing variable parameter name" if binds.size == idx |
26 | next_param = binds[idx+1].unwrap |
27 | eval_error "bind name must be symbol" unless next_param.is_a? Mal::Symbol |
28 | var_args = Mal::List.new |
29 | exprs[idx..-1].each{|e| var_args << e} if idx < exprs.size |
30 | @data[next_param.str] = Mal::Type.new var_args |
4499e5c8 |
31 | break |
32 | end |
33 | |
51be5007 |
34 | @data[sym.str] = exprs[idx] |
095b73ea |
35 | end |
36 | end |
37 | |
b9e204b1 |
38 | def dump |
39 | puts "ENV BEGIN".colorize.red |
40 | @data.each do |k, v| |
41 | puts " #{k} -> #{print(v)}".colorize.red |
42 | end |
43 | puts "ENV END".colorize.red |
44 | end |
45 | |
b26be022 |
46 | def set(key, value) |
47 | @data[key] = value |
48 | end |
49 | |
50 | def find(key) |
51 | return self if @data.has_key? key |
52 | |
53 | o = @outer |
54 | if o |
55 | o.find key |
56 | else |
57 | nil |
58 | end |
59 | end |
60 | |
61 | def get(key) |
9bbb8ccc |
62 | e = find key |
1ec34655 |
63 | eval_error "'#{key}' not found" unless e |
b26be022 |
64 | e.data[key] |
65 | end |
66 | end |
67 | |
68 | end |