]> git.mdlowis.com Git - proto/sclpl-rb.git/commitdiff
funcs now have a free variable list
authorMichael D. Lowis <mike@mdlowis.com>
Tue, 14 Jul 2020 11:04:00 +0000 (07:04 -0400)
committerMichael D. Lowis <mike@mdlowis.com>
Tue, 14 Jul 2020 11:04:00 +0000 (07:04 -0400)
lib/dyn.rb

index f82d06d2a87d825c24c3c5d92b3ad1b9a724273d..5f568ca89d1be4f4dcf5f2ae8ecd9dec6b43cc1c 100755 (executable)
@@ -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