diff --git a/lib/slot_machine/slot.rb b/lib/slot_machine/slot.rb index 07d57593..d0a905c7 100644 --- a/lib/slot_machine/slot.rb +++ b/lib/slot_machine/slot.rb @@ -18,11 +18,13 @@ module SlotMachine attr_reader :name , :next_slot + # initialize with just the name of the slot. Add more to the chain with set_next def initialize( name ) raise "No name" unless name - @name = name + @name = name end + #set the next_slot , but always at the end of the chain def set_next(slot) if(@next_slot) @next_slot.set_next(slot) @@ -31,12 +33,18 @@ module SlotMachine end end + # return the length of chain, ie 1 plus however many more next_slots there are + def length + return 1 unless @next_slot + 1 + @next_slot.length + end + + # name of all the slots, with dot syntax def to_s names = name.to_s names += ".#{@next_slot}" if @next_slot names end - end end diff --git a/lib/slot_machine/slotted.rb b/lib/slot_machine/slotted.rb index ab309001..fb59b06f 100644 --- a/lib/slot_machine/slotted.rb +++ b/lib/slot_machine/slotted.rb @@ -11,27 +11,41 @@ module SlotMachine when Parfait::Object , Risc::Label SlottedObject.new(object , slots) else - raise "not supported type #{object}" + raise "not supported type #{object}:#{object.class}" end end # The first in a possible chain of slots, that name instance variables in the # previous object - attr_reader :slot + attr_reader :slots def initialize( slots ) raise "No slots #{object}" unless slots slots = [slots] unless slots.is_a?(Array) first = slots.shift - @slot = Slot.new(first) + return unless first + @slots = Slot.new(first) until(slots.empty?) - @slot.set_next( Slot.new( slots.shift )) + @slots.set_next( Slot.new( slots.shift )) + end + end + + def slots_length + return 0 unless @slots + 1 + @slots.length + end + + def set_next(slot) + if(@slots) + @slots.set_next(slot) + else + @slots = slot end end def to_s names = known_name.to_s - names += ".#{@slot}" if @slot + names += ".#{@slots}" if @slots names end diff --git a/lib/slot_machine/slotted_constant.rb b/lib/slot_machine/slotted_constant.rb index 9542337a..b8ee9e65 100644 --- a/lib/slot_machine/slotted_constant.rb +++ b/lib/slot_machine/slotted_constant.rb @@ -1,7 +1,6 @@ module SlotMachine class SlottedConstant < Slotted - attr_reader :known_object def initialize( object , slots) @@ -27,11 +26,11 @@ module SlotMachine parfait = known_object.to_parfait(compiler) const = Risc.load_constant(source, parfait , right) compiler.add_code const - if slots.length == 1 - raise "only type allowed for constants, not #{slots[0]}" unless slots[0] == :type + if slots_length == 2 + raise "only type allowed for constants, not #{slots}" unless slots.name == :type compiler.add_code Risc::SlotToReg.new( source , right , Parfait::TYPE_INDEX, right) end - raise "Can't have slots into Constants #{slots}" if slots.length > 1 + raise "Can't have slots into Constants #{slots}" if slots_length > 2 return const.register end diff --git a/lib/slot_machine/slotted_message.rb b/lib/slot_machine/slotted_message.rb index 4986bff4..1407635d 100644 --- a/lib/slot_machine/slotted_message.rb +++ b/lib/slot_machine/slotted_message.rb @@ -1,7 +1,6 @@ module SlotMachine class SlottedMessage < Slotted - def known_name :message end @@ -13,13 +12,13 @@ module SlotMachine def to_register(compiler, source) type = :Message right = compiler.use_reg( type ) - slots = @slot + slots = @slots left = Risc.message_reg left = left.resolve_and_add( slots.name , compiler) reg = compiler.current.register slots = slots.next_slot while( slots ) - left = left.resolve_and_add( slots , compiler) + left = left.resolve_and_add( slots.name , compiler) slots = slots.next_slot end return reg @@ -32,15 +31,14 @@ module SlotMachine # They are very similar (apart from the final reg_to_slot here) and should # most likely be united def reduce_and_load(const_reg , compiler , original_source ) - left_slots = slots.dup raise "Not Message #{object}" unless known_object == :message left = Risc.message_reg - slot = left_slots.shift - while( !left_slots.empty? ) - left = left.resolve_and_add( slot , compiler) - slot = left_slots.shift + slot = slots + while( slot.next_slot ) + left = left.resolve_and_add( slot.name , compiler) + slot = slot.next_slot end - compiler.add_code Risc.reg_to_slot(original_source, const_reg , left, slot) + compiler.add_code Risc.reg_to_slot(original_source, const_reg , left, slot.name) end end diff --git a/lib/slot_machine/slotted_object.rb b/lib/slot_machine/slotted_object.rb index 41b291ef..3ef99b20 100644 --- a/lib/slot_machine/slotted_object.rb +++ b/lib/slot_machine/slotted_object.rb @@ -21,16 +21,16 @@ module SlotMachine right = compiler.use_reg( type ) const = Risc.load_constant(source, known_object , right) compiler.add_code const - if slots.length > 0 + if slots_length > 1 # desctructively replace the existing value to be loaded if more slots - compiler.add_code Risc.slot_to_reg( source , right ,slots[0], right) + compiler.add_code Risc.slot_to_reg( source , right ,slots.name, right) end - if slots.length > 1 + if slots_length > 2 # desctructively replace the existing value to be loaded if more slots - index = Risc.resolve_to_index(slots[0] , slots[1] ,compiler) + index = Risc.resolve_to_index(slots.name , slots.next_slot.name ,compiler) compiler.add_code Risc::SlotToReg.new( source , right ,index, right) - if slots.length > 2 - raise "3 slots only for type #{slots}" unless slots[2] == :type + if slots_length > 3 + raise "3 slots only for type #{slots}" unless slots.next_slot.next_slot.name == :type compiler.add_code Risc::SlotToReg.new( source , right , Parfait::TYPE_INDEX, right) end end @@ -44,7 +44,7 @@ module SlotMachine raise "only cache" unless known_object.is_a?( Parfait::CacheEntry) left = compiler.use_reg( :CacheEntry ) compiler.add_code Risc.load_constant(original_source, known_object , left) - compiler.add_code Risc.reg_to_slot(original_source, const_reg , left, slots.first) + compiler.add_code Risc.reg_to_slot(original_source, const_reg , left, slots.name) end end end diff --git a/lib/sol/assignment.rb b/lib/sol/assignment.rb index 6ae9c70b..7713ffc6 100644 --- a/lib/sol/assignment.rb +++ b/lib/sol/assignment.rb @@ -33,7 +33,7 @@ module Sol # Derived classes do not implement to_slot, only slot_position def to_slot(compiler) to = SlotMachine::Slotted.for(:message , self.slot_position(compiler)) - from = @value.to_slot_definition(compiler) + from = @value.to_slotted(compiler) assign = SlotMachine::SlotLoad.new(self,to,from) return assign unless @value.is_a?(CallStatement) @value.to_slot(compiler) << assign diff --git a/lib/sol/basic_values.rb b/lib/sol/basic_values.rb index f4eb7025..0f710eb3 100644 --- a/lib/sol/basic_values.rb +++ b/lib/sol/basic_values.rb @@ -9,7 +9,7 @@ module Sol def initialize(value) @value = value end - def to_slot_definition(_) + def to_slotted(_) return SlotMachine::Slotted.for(SlotMachine::IntegerConstant.new(@value) , []) end def ct_type @@ -37,7 +37,7 @@ module Sol def ct_type Parfait.object_space.get_type_by_class_name(:True) end - def to_slot_definition(_) + def to_slotted(_) return SlotMachine::Slotted.for(Parfait.object_space.true_object , []) end def to_s(depth = 0) @@ -49,7 +49,7 @@ module Sol def ct_type Parfait.object_space.get_type_by_class_name(:False) end - def to_slot_definition(_) + def to_slotted(_) return SlotMachine::Slotted.for(Parfait.object_space.false_object , []) end def to_s(depth = 0) @@ -61,7 +61,7 @@ module Sol def ct_type Parfait.object_space.get_type_by_class_name(:Nil) end - def to_slot_definition(_) + def to_slotted(_) return SlotMachine::Slotted.for(Parfait.object_space.nil_object , []) end def to_s(depth = 0) @@ -75,7 +75,7 @@ module Sol def initialize(type = nil) @my_type = type end - def to_slot_definition(compiler) + def to_slotted(compiler) @my_type = compiler.receiver_type SlotMachine::Slotted.for(:message , [:receiver]) end @@ -91,7 +91,7 @@ module Sol def initialize(value) @value = value end - def to_slot_definition(_) + def to_slotted(_) return SlotMachine::Slotted.for(SlotMachine::StringConstant.new(@value),[]) end def ct_type diff --git a/lib/sol/call_statement.rb b/lib/sol/call_statement.rb index 0f1dfdfc..62109bc0 100644 --- a/lib/sol/call_statement.rb +++ b/lib/sol/call_statement.rb @@ -10,7 +10,7 @@ module Sol # When used as right hand side, this tells what data to move to get the result into # a varaible. It is (off course) the return value of the message - def to_slot_definition(_) + def to_slotted(_) SlotMachine::Slotted.for(:message ,[ :return_value]) end diff --git a/lib/sol/if_statement.rb b/lib/sol/if_statement.rb index 840b5da2..e2674e0a 100644 --- a/lib/sol/if_statement.rb +++ b/lib/sol/if_statement.rb @@ -32,7 +32,7 @@ module Sol # create the slot lazily, so to_slot gets called first def check_slot(compiler , false_label) - SlotMachine::TruthCheck.new(@condition.to_slot_definition(compiler) , false_label) + SlotMachine::TruthCheck.new(@condition.to_slotted(compiler) , false_label) end def each(&block) diff --git a/lib/sol/lambda_expression.rb b/lib/sol/lambda_expression.rb index 4bfef395..de57a9de 100644 --- a/lib/sol/lambda_expression.rb +++ b/lib/sol/lambda_expression.rb @@ -13,7 +13,7 @@ module Sol # # This means we do the compiler here (rather than to_slot, which is in # fact never called) - def to_slot_definition(compiler) + def to_slotted(compiler) compile(compiler) unless @parfait_block return SlotMachine::Slotted.for(SlotMachine::LambdaConstant.new(parfait_block(compiler)) , []) end diff --git a/lib/sol/macro_expression.rb b/lib/sol/macro_expression.rb index 1320f683..63968319 100644 --- a/lib/sol/macro_expression.rb +++ b/lib/sol/macro_expression.rb @@ -14,7 +14,7 @@ module Sol # When used as right hand side, this tells what data to move to get the result into # a varaible. It is (off course) the return value of the message - def to_slot_definition(_) + def to_slotted(_) SlotMachine::Slotted.for(:message ,[ :return_value]) end diff --git a/lib/sol/return_statement.rb b/lib/sol/return_statement.rb index af06e269..ac1dc5a8 100644 --- a/lib/sol/return_statement.rb +++ b/lib/sol/return_statement.rb @@ -32,7 +32,7 @@ module Sol def slot_load(compiler) SlotMachine::SlotLoad.new( self , [:message , :return_value] , - @return_value.to_slot_definition(compiler) ) + @return_value.to_slotted(compiler) ) end end end diff --git a/lib/sol/send_statement.rb b/lib/sol/send_statement.rb index 2630745f..a0cd9221 100644 --- a/lib/sol/send_statement.rb +++ b/lib/sol/send_statement.rb @@ -67,11 +67,11 @@ module Sol def message_setup(compiler,called_method) setup = SlotMachine::MessageSetup.new( called_method ) - slot_receive = @receiver.to_slot_definition(compiler) + slot_receive = @receiver.to_slotted(compiler) arg_target = [:message , :next_message ] args = [] @arguments.each_with_index do |arg , index| # +1 because of type - args << SlotMachine::SlotLoad.new(self, arg_target + ["arg#{index+1}".to_sym] , arg.to_slot_definition(compiler)) + args << SlotMachine::SlotLoad.new(self, arg_target + ["arg#{index+1}".to_sym] , arg.to_slotted(compiler)) end setup << SlotMachine::ArgumentTransfer.new(self, slot_receive , args ) end @@ -111,10 +111,11 @@ module Sol private def receiver_type_definition(compiler) - defi = @receiver.to_slot_definition(compiler) - defi.slots << :type + defi = @receiver.to_slotted(compiler) + defi.set_next( SlotMachine::Slot.new(:type) ) defi end + def build_condition(ok_label, compiler) cached_type = SlotMachine::Slotted.for(dynamic_call.cache_entry , [:cached_type]) current_type = receiver_type_definition(compiler) diff --git a/lib/sol/variables.rb b/lib/sol/variables.rb index f2d1efd5..351271a7 100644 --- a/lib/sol/variables.rb +++ b/lib/sol/variables.rb @@ -10,7 +10,7 @@ module Sol class LocalVariable < Expression include Named - def to_slot_definition(compiler) + def to_slotted(compiler) slot_def = compiler.slot_type_for(@name) SlotMachine::Slotted.for(:message , slot_def) end @@ -24,7 +24,7 @@ module Sol class InstanceVariable < Expression include Named - def to_slot_definition(_) + def to_slotted(_) SlotMachine::Slotted.for(:message , [ :receiver , @name] ) end # used to collect type information @@ -51,7 +51,7 @@ module Sol def ct_type get_named_class.single_class.instance_type end - def to_slot_definition(_) + def to_slotted(_) return SlotMachine::Slotted.for( get_named_class, []) end def get_named_class diff --git a/lib/sol/while_statement.rb b/lib/sol/while_statement.rb index dbd5123f..59063b21 100644 --- a/lib/sol/while_statement.rb +++ b/lib/sol/while_statement.rb @@ -15,7 +15,7 @@ module Sol codes = cond_label codes << @hoisted.to_slot(compiler) if @hoisted codes << @condition.to_slot(compiler) if @condition.is_a?(SendStatement) - codes << SlotMachine::TruthCheck.new(condition.to_slot_definition(compiler) , merge_label) + codes << SlotMachine::TruthCheck.new(condition.to_slotted(compiler) , merge_label) codes << @body.to_slot(compiler) codes << SlotMachine::Jump.new(cond_label) codes << merge_label diff --git a/lib/sol/yield_statement.rb b/lib/sol/yield_statement.rb index be67e0e0..23b6fae9 100644 --- a/lib/sol/yield_statement.rb +++ b/lib/sol/yield_statement.rb @@ -49,11 +49,11 @@ module Sol def yield_arg_block(compiler) arg_index = compiler.get_method.arguments_type.get_length - 1 setup = SlotMachine::MessageSetup.new( arg_index ) - slot_receive = @receiver.to_slot_definition(compiler) + slot_receive = @receiver.to_slotted(compiler) arg_target = [:message , :next_message ] args = [] @arguments.each_with_index do |arg , index| # +1 because of type - args << SlotMachine::SlotLoad.new(self, arg_target + ["arg#{index+1}".to_sym] , arg.to_slot_definition(compiler)) + args << SlotMachine::SlotLoad.new(self, arg_target + ["arg#{index+1}".to_sym] , arg.to_slotted(compiler)) end setup << SlotMachine::ArgumentTransfer.new( self , slot_receive , args ) setup << SlotMachine::BlockYield.new( self , arg_index )