end
def free?(key)
- (not local?(key)) && (not global?(key))
+ (defined? key) and (not local? key) and (not global? key)
end
def merge!(env)
env[expr.args[i].name] = { :loc => expr.loc, :type => t }
end
itype = infer_block(env, expr.body, false)
- error(expr.loc, "expected #{type}, received #{etype}") if itype != type.last
+ expr.freevars = env.freevars
+ pp expr
+ error(expr.loc, "expected #{type}, received #{itype}") if itype != type.last
type.last
end
def self.infer_symbol(env, expr)
error(expr.loc, "undefined symbol '#{expr.name}'") if not env.defined? expr.name
env.freevars << expr.name if env.free? expr.name
- pp env.freevars
expr.type = env[expr.name][:type]
end
end
def self.infer_block(env, expr, clone = true)
- env = env.clone if clone
+ newenv = (clone ? env.clone : env)
types = expr.exprs.map do |e|
if e.is_a? Parser::Ann
- infer_annotation(env, e, true)
+ infer_annotation(newenv, e, true)
else
- infer(env, e)
+ infer(newenv, e)
end
end
+ env.freevars = (env.freevars + newenv.freevars).uniq
+ pp "free", env.freevars
types.last
end