Starting to fix resolve mechanism
resolve had the wrong approach, sort of class based oo It took methods from "derived" types and just used them To be correct, those methods would have to be recompiled for the current type, rubyx is type, not class based. Started on that, still soe strange hang though Later, type and method analysis may reveal "compatible" types (down only off course) where one could use the exact same code, but that is phase 2
This commit is contained in:
parent
1e5073200c
commit
17f87f7464
@ -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 )
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -70,7 +70,7 @@ module RubyX
|
||||
end
|
||||
MAIN
|
||||
@preload = "all"
|
||||
# ticks = run_input(code)
|
||||
ticks = run_input(code)
|
||||
# assert_equal "" , @interpreter.stdout
|
||||
end
|
||||
break
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user