From: Michael D. Lowis Date: Mon, 13 Jul 2020 20:51:49 +0000 (-0400) Subject: added start of free variable tracking to type checker X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=176f87017b26838b1fa862092df97ee2b4f3ed29;p=proto%2Fsclpl-rb.git added start of free variable tracking to type checker --- diff --git a/lib/dyn.rb b/lib/dyn.rb index dbeab15..d86cf19 100755 --- a/lib/dyn.rb +++ b/lib/dyn.rb @@ -26,9 +26,12 @@ end class SymTable < Hash attr_accessor :is_func + attr_accessor :freevars def initialize(parent = nil) @parent = (parent || {}) + @is_func = false + @freevars = [] end def clone @@ -75,6 +78,11 @@ class SymTable < Hash end end + def free?(key) + puts "#{key}: local? #{local? key} global? #{global? key}" + (not local?(key)) && (not global?(key)) + end + def merge!(env) env.each {|k,v| self[k] = v } end @@ -227,7 +235,7 @@ class Parser Ident = Struct.new(:loc, :type, :name) Val = Struct.new(:loc, :type, :value) Def = Struct.new(:loc, :type, :name, :value) - Func = Struct.new(:loc, :type, :args, :body) + Func = Struct.new(:loc, :type, :args, :body, :freevars) Call = Struct.new(:loc, :type, :func, :args) IfExpr = Struct.new(:loc, :type, :cond, :br1, :br2) Ann = Struct.new(:loc, :type, :expr) @@ -329,7 +337,7 @@ class Parser expect(",") if not matches(")") end expect(")") - Func.new(loc, nil, args, block()) + Func.new(loc, nil, args, block(), nil) end def constant() @@ -561,7 +569,9 @@ module TypeChecker def self.check_call(env, expr, type) error(expr.loc, "object being applied is not a function (has type: #{type.to_s})") if not type.is_a? Array + error(expr.loc, "wrong number of arguments to function call") if (type.length - 1) != expr.args.length type[0..-2].each_with_index do |t,i| + pp expr check(env, expr.args[i], t) end expr.type = type.last @@ -593,6 +603,8 @@ 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 @@ -807,3 +819,26 @@ class Codegen var end end + +STRING = <<-eos + +a = 123 + +foo : int -> int +foo = fun(b){ + bar : int -> int + bar = fun(c){ + a + b + c + } + bar(1) +} + +eos + +#syms = SymTable.new +#syms[:a] = {} +#pp syms.global? :a + +tree = Parser.new.parse_string(STRING) +TypeChecker.infer_block(SymTable.new, tree, false) +