From 6993e337bfc78db7fc1d3901250c13fc69f001b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torsten=20R=C3=BCger?= Date: Mon, 23 Sep 2019 20:42:46 +0300 Subject: [PATCH] Fix meta_class, sis lass instance variables and class methods after some serious recursive thinking it now actually makes sense The key was to change the actual type of the class that the meta_class manages For objects it's (still) ok just to change the instance_type, but since the class object exists and has type, when adding instance variables, that actual type has to change --- lib/parfait/behaviour.rb | 17 +++++++--- lib/parfait/meta_class.rb | 6 ++++ lib/risc/parfait_adapter.rb | 14 ++------ test/parfait/test_meta_class.rb | 17 ++++++---- .../risc/interpreter/class/test_class_inst.rb | 4 +-- .../interpreter/class/test_class_inst_set.rb | 2 +- test/vool/class_send/test_class_instance.rb | 32 +++++++++++++++---- .../class_send/test_class_send_inherited.rb | 2 +- 8 files changed, 60 insertions(+), 34 deletions(-) diff --git a/lib/parfait/behaviour.rb b/lib/parfait/behaviour.rb index 492c3858..66b3032d 100644 --- a/lib/parfait/behaviour.rb +++ b/lib/parfait/behaviour.rb @@ -1,8 +1,17 @@ -# Behaviour is something that has methods, basically class and modules superclass - -# instance_methods is the attribute in the including class that has the methods - module Parfait + # Behaviour is the old smalltalk name for the duperclass of class and meta_class + # + # Classes and meta_classes are in fact very similar, in that they manage + # - the type of instances + # - the methods for instances + # + # The main way they differ is that Classes manage type for a class of objects (ie many) + # whereas meta_class, or singleton_class manages the type of only one object (here a class) + # + # Singleton classes can manage the type/methods of any single object, and in the + # future off course they will, just not yet. Most single objects don't need that, + # only Classes and Modules _always _ do, so that's where we start. + # class Behaviour < Object attr_reader :instance_type , :instance_methods diff --git a/lib/parfait/meta_class.rb b/lib/parfait/meta_class.rb index da4324e7..cbcfb64b 100644 --- a/lib/parfait/meta_class.rb +++ b/lib/parfait/meta_class.rb @@ -43,6 +43,12 @@ module Parfait inspect end + # adding an instance changes the instance_type to include that variable + def add_instance_variable( name , type) + super(name,type) + @clazz.set_type(@instance_type) + end + # Nil name means no superclass, and so nil returned def super_class return nil diff --git a/lib/risc/parfait_adapter.rb b/lib/risc/parfait_adapter.rb index dd527a98..36dfd265 100644 --- a/lib/risc/parfait_adapter.rb +++ b/lib/risc/parfait_adapter.rb @@ -85,14 +85,14 @@ module Parfait # 0 -based index def get_internal_word(index) return @type if index == Parfait::TYPE_INDEX - name = Parfait.name_for_index(self , index) + name = self.type.names[index] return nil unless name instance_eval("@#{name}") end # 0 -based index def set_internal_word(index , value) - name = Parfait.name_for_index(self , index) + name = self.type.names[index] #unless name.is_a?(Symbol) raise "not sym for #{index} in #{self}:#{self.type}:#{name.class}" unless name.is_a?(Symbol) instance_eval("@#{name}=value" ) value @@ -100,16 +100,6 @@ module Parfait end - def self.name_for_index(object , index) - return :type if index == 0 - clazz = object.class.name.split("::").last.to_sym - cl = self.type_names[clazz] - keys = cl.keys - keys[index - 1] # -1 because type is excluded in the lists (FIX) - # FIXME Now that we use instance variables in parfait, they should be parsed - # and the type_names generated automatically - end - # new list from ruby array to be precise def self.new_list array list = Parfait::List.new diff --git a/test/parfait/test_meta_class.rb b/test/parfait/test_meta_class.rb index 3a284194..71d67b1b 100644 --- a/test/parfait/test_meta_class.rb +++ b/test/parfait/test_meta_class.rb @@ -36,15 +36,18 @@ module Parfait assert_raises{ @try.add_instance_method(nil)} end def test_add_instance_variable_changes_type - before = @space.get_class.instance_type - @space.get_class.add_instance_variable(:counter , :Integer) - assert before != @space.get_class.instance_type + before = @try.instance_type + @try.add_instance_variable(:counter , :Integer) + assert before != @try.instance_type end def test_add_instance_variable_changes_type_hash - before = @space.get_class.instance_type.hash - @space.get_class.add_instance_variable(:counter , :Integer) - assert before != @space.get_class.instance_type.hash + before = @try.instance_type.hash + @try.add_instance_variable(:counter , :Integer) + assert before != @try.instance_type.hash + end + def test_add_instance_variable_changes_class_type + @try.add_instance_variable(:counter , :Integer) + assert_equal @try.clazz.type , @try.instance_type end - end end diff --git a/test/risc/interpreter/class/test_class_inst.rb b/test/risc/interpreter/class/test_class_inst.rb index fdfe4b2d..e549102a 100644 --- a/test/risc/interpreter/class/test_class_inst.rb +++ b/test/risc/interpreter/class/test_class_inst.rb @@ -1,7 +1,7 @@ require_relative "../helper" module Risc - class InterpreterSetters < MiniTest::Test + class InterpreterGetters < MiniTest::Test include Ticker def setup @@ -19,7 +19,7 @@ module Risc MAIN super end - +#Space type is wrong, shold be same as meta_class.instance_type def test_chain #show_main_ticks # get output of what is run_input @string_input diff --git a/test/risc/interpreter/class/test_class_inst_set.rb b/test/risc/interpreter/class/test_class_inst_set.rb index 32b0c2f1..a50b7ef9 100644 --- a/test/risc/interpreter/class/test_class_inst_set.rb +++ b/test/risc/interpreter/class/test_class_inst_set.rb @@ -23,7 +23,7 @@ MAIN super end - def est_chain + def test_chain #show_main_ticks # get output of what is run_input @string_input assert_equal 5 , get_return diff --git a/test/vool/class_send/test_class_instance.rb b/test/vool/class_send/test_class_instance.rb index 71767e59..f34ff75d 100644 --- a/test/vool/class_send/test_class_instance.rb +++ b/test/vool/class_send/test_class_instance.rb @@ -12,7 +12,7 @@ module Vool return @inst end def main(arg) - return Space.one_plus + return Space.some_inst end end eos @@ -20,16 +20,34 @@ module Vool def setup ret = RubyX::RubyXCompiler.new(RubyX.default_test_options).ruby_to_mom(class_main) - @ins = ret.compilers.find{|c|c.callable.name==:some_inst}.mom_instructions.next + @compiler = ret.compilers.find{|c|c.callable.name==:some_inst} + @main = ret.compilers.find{|c|c.callable.name==:main} + @ins = @compiler.mom_instructions.next end def test_class_inst - space_class = Parfait.object_space.get_class - assert_equal :Space , space_class.name - names = space_class.meta_class.instance_type.names - assert names.index_of(:inst) , names + space_class = Parfait.object_space.get_class + assert_equal :Space , space_class.name + names = space_class.meta_class.instance_type.names + assert names.index_of(:inst) , names + end + def test_compiler + assert_equal Mom::MethodCompiler, @compiler.class + assert_equal Parfait::Type, @compiler.callable.self_type.class + assert_equal 6, @compiler.callable.self_type.names.index_of(:inst) , @compiler.callable.self_type.names end def test_array - check_array [SlotLoad, ReturnJump, Label, ReturnSequence, Label] , @ins + check_array [SlotLoad, ReturnJump, Label, ReturnSequence, Label] , @ins + end + def test_main_array + check_array [MessageSetup, ArgumentTransfer, SimpleCall, SlotLoad, ReturnJump , + Label, ReturnSequence, Label] , @main.mom_instructions.next + end + def test_main_args + args = @main.mom_instructions.next(2) + assert_equal Parfait::Class , args.receiver.known_object.class + assert_equal :Space , args.receiver.known_object.name + assert_equal :some_inst , args.receiver.known_object.type.method_names.first + assert_equal :inst , args.receiver.known_object.type.names.last end def test_load_inst assert_equal SlotLoad, @ins.class diff --git a/test/vool/class_send/test_class_send_inherited.rb b/test/vool/class_send/test_class_send_inherited.rb index f78641ae..54c431f5 100644 --- a/test/vool/class_send/test_class_send_inherited.rb +++ b/test/vool/class_send/test_class_send_inherited.rb @@ -40,7 +40,7 @@ module Vool assert_equal SimpleCall, @ins.next(2).class assert_equal :one_plus, @ins.next(2).method.name assert_equal Parfait::Type, @ins.next(2).method.self_type.class - assert_equal :Object, @ins.next(2).method.self_type.object_class.name + assert_equal :Class, @ins.next(2).method.self_type.object_class.name end end end