$debug = true
+def error(loc, msg)
+ lines = File.read(loc[0])[0..(loc[1])].split("\n")
+ $stderr.puts "#{loc[0]}:#{lines.length}: #{msg}"
+# raise "" if $debug
+# $stderr.puts "#{lines.last}"
+# $stderr.puts (" " * lines.last.length) + "^"
+ exit 1
+end
+
class SymTable < Hash
def initialize(parent = nil)
- @parent = parent
+ @parent = (parent || {})
end
def clone
SymTable.new(self)
end
+
+ def [](key)
+ (super(key) || @parent[key])
+ end
+
+ def []=(key, value)
+ existing = method(:[]).super_method.call(key)
+ if (not existing.nil?) and existing[:set!]
+ error(value[:loc], "symbol '#{key}' is multiply defined in scope")
+ end
+ super(key,value)
+ end
+
+ def local?(key)
+ (not method(:[]).super_method.call(key).nil?)
+ end
+
+ def global?(key)
+ if @parent.class == Hash
+ local?(key)
+ elsif local? key
+ false
+ else
+ @parent.global? key
+ end
+ end
+
+ def merge!(env)
+ env.each {|k,v| self[k] = v }
+ end
end
class Lexer
"|" => { int: [:int, :int, :int] },
}
- def self.error(loc, msg)
- lines = File.read(loc[0])[0..(loc[1])].split("\n")
- $stderr.puts "#{loc[0]}:#{lines.length}: #{msg}"
- raise "" if $debug
-# $stderr.puts "#{lines.last}"
-# $stderr.puts (" " * lines.last.length) + "^"
- exit 1
- end
-
def self.check(env, expr, type)
if (expr.is_a? Parser::IfExpr)
check_ifexpr(env, expr, type)
end
def self.infer_annotation(env, expr)
- check(env, expr.expr, expr.type)
+ check(env, expr.expr, expr.type)
end
def self.infer_block(env, expr)
- env = env.merge(expr.syms)
+ env.merge!(expr.syms)
types = expr.exprs.map {|e| infer(env, e) }
expr.type = types.last
end
end
block = Parser.new("dyn.src").toplevel
-pp TypeChecker.infer({}, block)
+pp TypeChecker.infer(SymTable.new, block)
# TODO:
# * Check for correct usage of void on function types and elsewhere...
-# * refine rules for use of variables before definition and mutually recursive procedures...
-# * Function args need to be defined in scope
-# * Shadowing of arguments/globals is broken
# * Add support for structs
# * Add support for checked unions
# * Add support for arrays