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