class Env { const _outer Env var _data StringMap = {} def new(outer Env) { _outer = outer } def new(outer Env, binds List, exprs List) { _outer = outer for i in 0..binds.count { const name = (binds[i] as MalSymbol).val if name == "&" { const restName = (binds[i + 1] as MalSymbol).val _data[restName] = MalList.new(exprs.slice(i)) break } else { _data[name] = exprs[i] } } } def find(key MalSymbol) Env { if key.val in _data { return self } return _outer?.find(key) } def get(key MalSymbol) MalVal { const env = find(key) if env == null { throw MalError.new("'" + key.val + "' not found") } return env._data[key.val] } def set(key MalSymbol, value MalVal) MalVal { _data[key.val] = value return value } }