From: Michael D. Lowis Date: Tue, 14 Jul 2020 11:04:00 +0000 (-0400) Subject: funcs now have a free variable list X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=c28aaeb8435d7a190936b7380322d0b516d0a2df;p=proto%2Fsclpl-rb.git funcs now have a free variable list --- diff --git a/lib/dyn.rb b/lib/dyn.rb index f82d06d..5f568ca 100755 --- a/lib/dyn.rb +++ b/lib/dyn.rb @@ -79,7 +79,7 @@ class SymTable < Hash end def free?(key) - (not local?(key)) && (not global?(key)) + (defined? key) and (not local? key) and (not global? key) end def merge!(env) @@ -562,7 +562,9 @@ module TypeChecker 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 @@ -602,7 +604,6 @@ module TypeChecker 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 @@ -629,14 +630,16 @@ module TypeChecker 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