load-file: accept empty file or final comment, return nil
[jackhill/mal.git] / crystal / env.cr
CommitLineData
b26be022 1require "./types"
2c76c2ff 2require "./error"
b26be022 3
4module 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 66end