require "./expr" require "./error" module Crisp class Env property data def initialize(@outer : Env? = nil) @data = {} of String => Crisp::Expr end def initialize(@outer, binds, exprs : Array(Crisp::Expr)) @data = {} of String => Crisp::Expr Crisp.eval_error "binds must be list or vector" unless binds.is_a? Array # Note: # Array#zip() can't be used because overload resolution failed (0...binds.size).each do |idx| sym = binds[idx].unwrap Crisp.eval_error "bind name must be symbol" unless sym.is_a? Crisp::Symbol if sym.str == "&" Crisp.eval_error "missing variable parameter name" if binds.size == idx next_param = binds[idx + 1].unwrap Crisp.eval_error "bind name must be symbol" unless next_param.is_a? Crisp::Symbol var_args = Crisp::List.new exprs[idx..-1].each { |e| var_args << e } if idx < exprs.size @data[next_param.str] = Crisp::Expr.new var_args break end @data[sym.str] = exprs[idx] end end def dump puts "ENV BEGIN".colorize.red @data.each do |k, v| puts " #{k} -> #{print(v)}".colorize.red end puts "ENV END".colorize.red end def set(key, value) @data[key] = value end def find(key) return self if @data.has_key? key if o = @outer o.find key else nil end end def get(key) e = find key Crisp.eval_error "'#{key}' not found" unless e e.data[key] end end end