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:
Torsten Rüger 2019-09-29 12:06:37 +03:00
parent 1e5073200c
commit 17f87f7464
9 changed files with 51 additions and 38 deletions

View File

@ -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 )

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -70,7 +70,7 @@ module RubyX
end
MAIN
@preload = "all"
# ticks = run_input(code)
ticks = run_input(code)
# assert_equal "" , @interpreter.stdout
end
break

View File

@ -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