diff --git a/lib/parfait/behaviour.rb b/lib/parfait/behaviour.rb index 133321c9..b36e554b 100644 --- a/lib/parfait/behaviour.rb +++ b/lib/parfait/behaviour.rb @@ -60,12 +60,23 @@ module Parfait raise "resolve_method #{m_name}.#{m_name.class}" unless m_name.is_a?(Symbol) method = get_instance_method(m_name) return method if method - if( super_class_name && super_class_name != :Object ) - method = @super_class.resolve_method(m_name) + if( s_class = super_class ) + method = s_class.resolve_method(m_name) end method end + # assume resolving is needed, ie getting has failed, raise if it hasnt + def resolve_method!( m_name ) + method = get_instance_method(m_name) + if method + tm = @instance_type.method_names + raise "resolve_method #{name}.#{m_name} has #{tm}" + end + return nil unless( s_class = super_class ) + s_class.resolve_method(m_name) + end + # adding an instance changes the instance_type to include that variable def add_instance_variable( name , type) @instance_type = @instance_type.add_instance_variable( name , type ) diff --git a/lib/parfait/class.rb b/lib/parfait/class.rb index be29dc4b..95be1300 100644 --- a/lib/parfait/class.rb +++ b/lib/parfait/class.rb @@ -48,7 +48,7 @@ module Parfait # or the super classs is nil. # Use only for non Object base class def super_class! - raise "No super_class for class #{@name}" unless @super_class_name + raise "No super_class for class #{@name}" if is_object? s = super_class raise "superclass not found for class #{@name} (#{@super_class_name})" unless s s @@ -58,10 +58,13 @@ module Parfait # we only store the name, and so have to resolve. # Nil name means no superclass, and so nil is a valid return value def super_class - return nil unless @super_class_name + return nil if is_object? Object.object_space.get_class_by_name(@super_class_name) end + def is_object? + @name == :Object + end # ruby 2.1 list (just for reference, keep at bottom) #:allocate, :new, :superclass diff --git a/lib/parfait/type.rb b/lib/parfait/type.rb index 59f9b814..9acd2cc4 100644 --- a/lib/parfait/type.rb +++ b/lib/parfait/type.rb @@ -152,21 +152,6 @@ module Parfait nil end - # resolve according to normal oo logic, ie look up in superclass if not present - # NOTE: this will probably not work in future as the code for the superclass - # method, being bound to a different type, will assume that types (not the run-time - # actual types) layout. Either need to enforce some c++ style upwards compatibility (buuh) - # or copy the methods and recompile them for the actual type. (maybe still later dynamically) - # But for now we walk up, as it should really just be to object - def resolve_method( fname ) - method = get_method(fname) - return method if method - return nil if object_class.name == :Object - sup = object_class.super_class - return nil unless sup - sup.instance_type.resolve_method(fname) - end - def methods_length return 0 unless @methods len = 0 diff --git a/lib/parfait/vool_method.rb b/lib/parfait/vool_method.rb index 18da906b..114d5463 100644 --- a/lib/parfait/vool_method.rb +++ b/lib/parfait/vool_method.rb @@ -39,5 +39,11 @@ module Parfait compiler.add_code(head) compiler end + def to_s + "def #{name}(#{args_type.names})\n---" + + source.statements.first.source + "::" + + source.statements.collect{|s| s.to_s}.join("--::--") + + "\n---end" + end end end diff --git a/lib/vool/send_statement.rb b/lib/vool/send_statement.rb index 187c7a28..ecbe251b 100644 --- a/lib/vool/send_statement.rb +++ b/lib/vool/send_statement.rb @@ -34,15 +34,35 @@ module Vool # A Send breaks down to 2 steps: # - Setting up the next message, with receiver, arguments, and (importantly) return address # - a CachedCall , or a SimpleCall, depending on wether the receiver type can be determined + # + # A slight complication occurs for methods defined in superclasses. Since we are + # type, not class, based, these are not part of our type. + # So we check, and if find, add the source (vool_method) to the class and start + # compiling the vool for the receiver_type + # def to_mom( compiler ) @receiver = SelfExpression.new(compiler.receiver_type) if @receiver.is_a?(SelfExpression) if(@receiver.ct_type) - method = @receiver.ct_type.resolve_method(self.name) + method = @receiver.ct_type.get_method(@name) + method = create_method_from_source(compiler) unless( method ) return simple_call(compiler, method) if method end cached_call(compiler) end + # If a method is found in the class (not the type) + # we add it to the class that the receiver type represents, and create a compiler + # to compile the vool for the specific type (the receiver) + def create_method_from_source(compiler) + vool_method = @receiver.ct_type.object_class.resolve_method!(@name) + return nil unless vool_method + puts "#{vool_method} , adding to #{@receiver.ct_type.object_class.name}" + @receiver.ct_type.object_class.add_instance_method(vool_method) + new_compiler = vool_method.compiler_for(@receiver.ct_type) + compiler.add_method_compiler(new_compiler) + new_compiler.callable + end + def message_setup(compiler,called_method) setup = Mom::MessageSetup.new( called_method ) mom_receive = @receiver.to_slot(compiler) diff --git a/test/parfait/type/test_basic.rb b/test/parfait/type/test_basic.rb index 00a4644f..f10f8f46 100644 --- a/test/parfait/type/test_basic.rb +++ b/test/parfait/type/test_basic.rb @@ -79,5 +79,9 @@ module Parfait def test_class_name assert_equal :Message , @type.class_name end + def test_class_object_type + int_class = @space.get_type_by_class_name(:Integer) + assert_equal :Integer, int_class.object_class.name + end end end diff --git a/test/parfait/type/test_method_api.rb b/test/parfait/type/test_method_api.rb index f71bd23b..ab990a9f 100644 --- a/test/parfait/type/test_method_api.rb +++ b/test/parfait/type/test_method_api.rb @@ -67,21 +67,5 @@ module Parfait test_get_instance assert_equal :foo , @space.get_method!(:Object , :foo).name end - def test_resolve_on_object - add_foo_to :Object - assert_equal :foo , object_type.resolve_method( :foo ).name - end - def test_resolve_super - add_foo_to :Object - assert_equal :foo , @try_class.instance_type.resolve_method( :foo ).name - end - def test_resolve_is_get - add_foo_to - assert_equal :foo , @try_class.instance_type.resolve_method( :foo ).name - assert_equal :foo , @try_class.instance_type.get_method( :foo ).name - end - def test_resolve_fail - assert_nil object_type.resolve_method( :foo ) - end end end diff --git a/test/rubyx/rt_parfait/test_object.rb b/test/rubyx/rt_parfait/test_object.rb index d365fb92..99a8eb7a 100644 --- a/test/rubyx/rt_parfait/test_object.rb +++ b/test/rubyx/rt_parfait/test_object.rb @@ -70,7 +70,7 @@ module RubyX end MAIN @preload = "all" -# ticks = run_input(code) + ticks = run_input(code) # assert_equal "" , @interpreter.stdout end break diff --git a/test/vool/class_send/test_send_class.rb b/test/vool/class_send/test_send_class.rb index fbd9672f..c904abca 100644 --- a/test/vool/class_send/test_send_class.rb +++ b/test/vool/class_send/test_send_class.rb @@ -40,7 +40,7 @@ module Vool assert_equal :get_internal_word, @ins.next(2).method.name end def test_call_has_right_receiver - assert_equal "Object_Type", @ins.next(2).method.self_type.name + assert_equal "Class_Type", @ins.next(2).method.self_type.name end end end