Skip to content

Commit

Permalink
Finish moving self_type to scope
Browse files Browse the repository at this point in the history
  • Loading branch information
Ryan Brown committed Jun 24, 2010
1 parent bb4b193 commit 8339c94
Show file tree
Hide file tree
Showing 7 changed files with 26 additions and 41 deletions.
7 changes: 2 additions & 5 deletions lib/duby/ast.rb
Expand Up @@ -261,7 +261,7 @@ def containing_scope
end

module ClassScoped
def scope
def class_scope
@scope ||= begin
scope = parent
scope = scope.parent until scope.nil? || ClassDefinition === scope
Expand Down Expand Up @@ -411,10 +411,7 @@ def infer(typer)
class Self < Node
include Scoped
def infer(typer)
@inferred_type ||= typer.self_type
unless typer.self_type == scope.static_scope.self_type
raise "scope: #{scope.static_scope.self_type} typer: #{@inferred_type}"
end
@inferred_type ||= scope.static_scope.self_type
end
end

Expand Down
16 changes: 2 additions & 14 deletions lib/duby/ast/call.rb
Expand Up @@ -60,17 +60,8 @@ def target
end

def infer(typer)
@self_type ||= if scope.kind_of?(MethodDefinition)
scope.defining_class
else
# TODO this should probably be the meta type
typer.self_type
end

unless @inferred_type
unless @self_type == scope.static_scope.self_type
raise "scope: #{scope.static_scope.self_type} typer: #{@self_type}"
end
@self_type ||= scope.static_scope.self_type
receiver_type = @self_type
should_defer = false

Expand Down Expand Up @@ -201,10 +192,7 @@ def name
end

def infer(typer)
@self_type ||= typer.self_type.superclass
unless typer.self_type == scope.static_scope.self_type
raise "scope: #{scope.static_scope.self_type} typer: #{typer.self_type}"
end
@self_type ||= scope.static_scope.self_type.superclass

unless @inferred_type
receiver_type = @call_parent.defining_class.superclass
Expand Down
8 changes: 4 additions & 4 deletions lib/duby/ast/class.rb
Expand Up @@ -171,7 +171,7 @@ def infer(typer)
@inferred_type = typer.known_types[type]
if @inferred_type
resolved!
typer.learn_field_type(scope, name, @inferred_type)
typer.learn_field_type(class_scope, name, @inferred_type)
else
typer.defer(self)
end
Expand All @@ -196,7 +196,7 @@ def initialize(parent, position, name, annotations=[], &block)

def infer(typer)
unless resolved?
@inferred_type = typer.learn_field_type(scope, name, typer.infer(value))
@inferred_type = typer.learn_field_type(class_scope, name, typer.infer(value))

@inferred_type ? resolved! : typer.defer(self)
end
Expand All @@ -218,7 +218,7 @@ def initialize(parent, position, name, annotations=[], &block)

def infer(typer)
unless resolved?
@inferred_type = typer.field_type(scope, name)
@inferred_type = typer.field_type(class_scope, name)

@inferred_type ? resolved! : typer.defer(self)
end
Expand All @@ -234,7 +234,7 @@ class AccessLevel < Node
def initialize(parent, line_number, name)
super(parent, line_number)
@name = name
scope.current_access_level = name.to_sym
class_scope.current_access_level = name.to_sym
end

def infer(typer)
Expand Down
7 changes: 2 additions & 5 deletions lib/duby/ast/intrinsics.rb
Expand Up @@ -85,10 +85,7 @@ def initialize(parent, line_number, name, &block)

def infer(typer)
resolve_if(typer) do
self_type = typer.self_type
unless self_type == scope.static_scope.self_type
raise "scope: #{scope.static_scope.self_type} typer:#{typer.self_type}"
end
self_type = scope.static_scope.self_type
extension_name = "%s$%s" % [self_type.name,
typer.transformer.tmp("Extension%s")]
klass = build_and_load_extension(self_type,
Expand All @@ -102,7 +99,7 @@ def infer(typer)
macro = self_type.add_compiled_macro(klass, name, arg_types)
if arguments[-1].kind_of?(BlockArgument) && arguments[-1].optional?
arg_types.pop
typer.self_type.add_method(name, arg_types, macro)
self_type.add_method(name, arg_types, macro)
end
proxy.__inline__(Noop.new(parent, position))
proxy.infer(typer)
Expand Down
14 changes: 5 additions & 9 deletions lib/duby/ast/method.rb
Expand Up @@ -116,6 +116,7 @@ class MethodDefinition < Node
include Annotated
include Named
include Scope
include Scoped
include ClassScoped
include Binding

Expand All @@ -130,7 +131,7 @@ def initialize(parent, line_number, name, annotations=[], &block)
@annotations = annotations
super(parent, line_number, &block)
@name = name
@visibility = (scope && scope.current_access_level) || :public
@visibility = (class_scope && class_scope.current_access_level) || :public
end

def name
Expand All @@ -140,11 +141,10 @@ def name
def infer(typer)
resolve_if(typer) do
@defining_class ||= begin
klass = typer.self_type
static_scope.self_type = if static?
klass.meta
scope.static_scope.self_type.meta
else
klass
scope.static_scope.self_type
end
end
typer.infer(arguments)
Expand Down Expand Up @@ -200,11 +200,7 @@ def resolve_if(typer)
end

def abstract?
node = parent
while node && !node.kind_of?(Scope)
node = node.parent
end
InterfaceDeclaration === node
InterfaceDeclaration === scope
end

def static?
Expand Down
6 changes: 5 additions & 1 deletion lib/duby/ast/structure.rb
Expand Up @@ -72,7 +72,11 @@ def prepare(typer, method)
['binding', binding]) do |c|
duby.eval("@binding = binding", '-', c, 'binding')
end


# TODO We need a special scope here that allows access to the
# outer class.
static_scope.self_type = typer.infer(klass)

# find all methods which would not otherwise be on java.lang.Object
impl_methods = find_methods(interface).select do |m|
begin
Expand Down
9 changes: 6 additions & 3 deletions test/test_typer.rb
Expand Up @@ -108,20 +108,22 @@ def test_call

assert_equal(typer.string_type, ast.inferred_type)

ast = AST.parse("def bar(a, b); {a => :fixnum, b => :string}; 1.0; end; def baz; bar(1, 'x'); end").body
ast = AST.parse("def bar(a, b); {a => :fixnum, b => :string}; 1.0; end; def baz; bar(1, 'x'); end")

ast.infer(typer)
ast = ast.body

assert_equal(typer.float_type, typer.method_type(typer.self_type, "bar", [typer.fixnum_type, typer.string_type]))
assert_equal(typer.float_type, typer.method_type(typer.self_type, "baz", []))
assert_equal(typer.float_type, ast.children[0].inferred_type)
assert_equal(typer.float_type, ast.children[1].inferred_type)

# Reverse the order, ensure deferred inference succeeds
ast = AST.parse("def baz; bar(1, 'x'); end; def bar(a, b); {a => :fixnum, b => :string}; 1.0; end").body
ast = AST.parse("def baz; bar(1, 'x'); end; def bar(a, b); {a => :fixnum, b => :string}; 1.0; end")
typer = Typer::Simple.new("bar")

ast.infer(typer)
ast = ast.body

assert_equal(typer.default_type, typer.method_type(typer.self_type, "baz", []))
assert_equal(typer.float_type, typer.method_type(typer.self_type, "bar", [typer.fixnum_type, typer.string_type]))
Expand All @@ -137,10 +139,11 @@ def test_call
assert_equal(typer.float_type, ast.children[1].inferred_type)

# modify bar call to have bogus types, ensure resolution fails
ast = AST.parse("def baz; bar(1, 1); end; def bar(a, b); {a => :fixnum, b => :string}; 1.0; end").body
ast = AST.parse("def baz; bar(1, 1); end; def bar(a, b); {a => :fixnum, b => :string}; 1.0; end")
typer = Typer::Simple.new("bar")

ast.infer(typer)
ast = ast.body

assert_equal(typer.default_type, typer.method_type(typer.self_type, "baz", []))
assert_equal(typer.float_type, typer.method_type(typer.self_type, "bar", [typer.fixnum_type, typer.string_type]))
Expand Down

0 comments on commit 8339c94

Please sign in to comment.