From 000bf0a9b3caaaaf6d237f72ab18991ea828afe4 Mon Sep 17 00:00:00 2001 From: Torsten Ruger Date: Tue, 15 May 2018 19:29:06 +0300 Subject: [PATCH] separate SlotDefinition into own file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit what started as three lines has grown up to demand it’s own file and tests --- Guardfile | 2 +- lib/mom/instruction/slot_definition.rb | 81 ++++++++++++++++++++++++++ lib/mom/instruction/slot_load.rb | 67 +-------------------- 3 files changed, 84 insertions(+), 66 deletions(-) create mode 100644 lib/mom/instruction/slot_definition.rb diff --git a/Guardfile b/Guardfile index 5bf2111e..2b2f9eb6 100644 --- a/Guardfile +++ b/Guardfile @@ -28,7 +28,7 @@ guard :minitest do # with Minitest::Unit watch(%r{^lib/vool/statements/send_statement.rb}) { [ Dir["test/vool/to_mom/send/test_*.rb"] , "test/vool/statements/test_send_statement.rb"] } - #message setup + # message setup watch(%r{^lib/mom/instruction/message_setup.rb}) { Dir["test/mom/send/test_setup*.rb"] } end diff --git a/lib/mom/instruction/slot_definition.rb b/lib/mom/instruction/slot_definition.rb new file mode 100644 index 00000000..942d206f --- /dev/null +++ b/lib/mom/instruction/slot_definition.rb @@ -0,0 +1,81 @@ +module Mom + # A SlotDefinition defines a slot. A bit like a variable name but for objects. + # + # PS: for the interested: A "developement" of Smalltalk was the + # prototype based language (read: JavaScript equivalent) + # called Self https://en.wikipedia.org/wiki/Self_(programming_language) + # + # SlotDefinitions are the instance names of objects. But since the language is dynamic + # what is it that we can say about instance names at runtime? + # Start with a known object like the Message (in register one), we know all it's + # variables. But there is a Message in there, and for that we know the instances + # too. And off course for _all_ objects we know where the type is. + # + # The definiion is an array of symbols that we can resolve to SlotLoad + # Instructions. Or in the case of constants to ConstantLoad + # + class SlotDefinition + attr_reader :known_object , :slots + # is an array of symbols, that specifies the first the object, and then the Slot. + # The first element is either a known type name (Capitalized symbol of the class name) , + # or the symbol :message + # And subsequent symbols must be instance variables on the previous type. + # Examples: [:message , :receiver] or [:Space , :next_message] + def initialize( object , slots) + raise "No slots #{object}" unless slots + slots = [slots] unless slots.is_a?(Array) + @known_object , @slots = object , slots + raise "Not known #{slots}" unless object + end + + def to_s + names = [known_name] + @slots + "[#{names.join(',')}]" + end + + def known_name + case known_object + when Constant , Parfait::Object + known_object.class.short_name + when Risc::Label + known_object.to_s + when Symbol + known_object + else + "unknown" + end + end + def to_register(compiler, instruction) + type = known_object.respond_to?(:ct_type) ? known_object.ct_type : :Object + right = compiler.use_reg( type ) + case known_object + when Constant + parfait = known_object.to_parfait(compiler) + const = Risc.load_constant(instruction, parfait , right) + raise "Can't have slots into Constants" if slots.length > 0 + when Parfait::Object , Risc::Label + const = Risc.load_constant(instruction, known_object , right) + if slots.length > 0 + # desctructively replace the existing value to be loaded if more slots + index = Risc.resolve_to_index(known_object , slots[0] ,compiler) + const << Risc::SlotToReg.new( instruction , right ,index, right) + end + when Symbol + const = Risc::SlotToReg.new( instruction , Risc.resolve_to_register(known_object) , + Risc.resolve_to_index(:message , slots[0]), right) + else + raise "We have a #{self} #{known_object}" + end + if slots.length > 1 + # desctructively replace the existing value to be loaded if more slots + index = Risc.resolve_to_index(slots[0] , slots[1] ,compiler) + const << Risc::SlotToReg.new( instruction , right ,index, right) + if slots.length > 2 + raise "3 slots only for type #{slots}" unless slots[2] == :type + const << Risc::SlotToReg.new( instruction , right , 0, right) + end + end + const + end + end +end diff --git a/lib/mom/instruction/slot_load.rb b/lib/mom/instruction/slot_load.rb index e2e0f7ae..5d6f981d 100644 --- a/lib/mom/instruction/slot_load.rb +++ b/lib/mom/instruction/slot_load.rb @@ -12,7 +12,7 @@ module Mom # (* off course all class objects are global, and so they are allowed too) # # A maybe not immediately obvious corrolar of this design is the total absence of - # general purpose instance variable accessors. Ie only inside an object's functions + # general external instance variable accessors. Ie only inside an object's functions # can a method access instance variables, because only inside the method is the type # guaranteed. # From the outside a send is neccessary, both for get and set, (which goes through the method @@ -73,68 +73,5 @@ module Mom end end - class SlotDefinition - attr_reader :known_object , :slots - # is an array of symbols, that specifies the first the object, and then the Slot. - # The first element is either a known type name (Capitalized symbol of the class name) , - # or the symbol :message - # And subsequent symbols must be instance variables on the previous type. - # Examples: [:message , :receiver] or [:Space , :next_message] - def initialize( object , slots) - @known_object , @slots = object , slots - slot = [slot] unless slot.is_a?(Array) - raise "Not known #{slots}" unless object - raise "No slots #{object}" unless slots - end - - def to_s - names = [known_name] + @slots - "[#{names.join(',')}]" - end - - def known_name - case known_object - when Constant , Parfait::Object - known_object.class.short_name - when Risc::Label - known_object.to_s - when Symbol - known_object - else - "unknown" - end - end - def to_register(compiler, instruction) - type = known_object.respond_to?(:ct_type) ? known_object.ct_type : :Object - right = compiler.use_reg( type ) - case known_object - when Constant - parfait = known_object.to_parfait(compiler) - const = Risc.load_constant(instruction, parfait , right) - raise "Can't have slots into Constants" if slots.length > 0 - when Parfait::Object , Risc::Label - const = Risc.load_constant(instruction, known_object , right) - if slots.length > 0 - # desctructively replace the existing value to be loaded if more slots - index = Risc.resolve_to_index(known_object , slots[0] ,compiler) - const << Risc::SlotToReg.new( instruction , right ,index, right) - end - when Symbol - const = Risc::SlotToReg.new( instruction , Risc.resolve_to_register(known_object) , - Risc.resolve_to_index(:message , slots[0]), right) - else - raise "We have a #{self} #{known_object}" - end - if slots.length > 1 - # desctructively replace the existing value to be loaded if more slots - index = Risc.resolve_to_index(slots[0] , slots[1] ,compiler) - const << Risc::SlotToReg.new( instruction , right ,index, right) - if slots.length > 2 - raise "3 slots only for type #{slots}" unless slots[2] == :type - const << Risc::SlotToReg.new( instruction , right , 1, right) - end - end - const - end - end end +require_relative "slot_definition"