Makes slots linked list

slots used to ba an array of symbols
Now we have an object for each slot, that holds the name and the next_slot
relatively easy change, though quite broad
This commit is contained in:
Torsten Rüger 2020-02-17 14:29:45 +07:00
parent 93103d551f
commit c1679bd6ff
16 changed files with 69 additions and 49 deletions

View File

@ -18,11 +18,13 @@ module SlotMachine
attr_reader :name , :next_slot attr_reader :name , :next_slot
# initialize with just the name of the slot. Add more to the chain with set_next
def initialize( name ) def initialize( name )
raise "No name" unless name raise "No name" unless name
@name = name @name = name
end end
#set the next_slot , but always at the end of the chain
def set_next(slot) def set_next(slot)
if(@next_slot) if(@next_slot)
@next_slot.set_next(slot) @next_slot.set_next(slot)
@ -31,12 +33,18 @@ module SlotMachine
end end
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 def to_s
names = name.to_s names = name.to_s
names += ".#{@next_slot}" if @next_slot names += ".#{@next_slot}" if @next_slot
names names
end end
end end
end end

View File

@ -11,27 +11,41 @@ module SlotMachine
when Parfait::Object , Risc::Label when Parfait::Object , Risc::Label
SlottedObject.new(object , slots) SlottedObject.new(object , slots)
else else
raise "not supported type #{object}" raise "not supported type #{object}:#{object.class}"
end end
end end
# The first in a possible chain of slots, that name instance variables in the # The first in a possible chain of slots, that name instance variables in the
# previous object # previous object
attr_reader :slot attr_reader :slots
def initialize( slots ) def initialize( slots )
raise "No slots #{object}" unless slots raise "No slots #{object}" unless slots
slots = [slots] unless slots.is_a?(Array) slots = [slots] unless slots.is_a?(Array)
first = slots.shift first = slots.shift
@slot = Slot.new(first) return unless first
@slots = Slot.new(first)
until(slots.empty?) 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
end end
def to_s def to_s
names = known_name.to_s names = known_name.to_s
names += ".#{@slot}" if @slot names += ".#{@slots}" if @slots
names names
end end

View File

@ -1,7 +1,6 @@
module SlotMachine module SlotMachine
class SlottedConstant < Slotted class SlottedConstant < Slotted
attr_reader :known_object attr_reader :known_object
def initialize( object , slots) def initialize( object , slots)
@ -27,11 +26,11 @@ module SlotMachine
parfait = known_object.to_parfait(compiler) parfait = known_object.to_parfait(compiler)
const = Risc.load_constant(source, parfait , right) const = Risc.load_constant(source, parfait , right)
compiler.add_code const compiler.add_code const
if slots.length == 1 if slots_length == 2
raise "only type allowed for constants, not #{slots[0]}" unless slots[0] == :type raise "only type allowed for constants, not #{slots}" unless slots.name == :type
compiler.add_code Risc::SlotToReg.new( source , right , Parfait::TYPE_INDEX, right) compiler.add_code Risc::SlotToReg.new( source , right , Parfait::TYPE_INDEX, right)
end 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 return const.register
end end

View File

@ -1,7 +1,6 @@
module SlotMachine module SlotMachine
class SlottedMessage < Slotted class SlottedMessage < Slotted
def known_name def known_name
:message :message
end end
@ -13,13 +12,13 @@ module SlotMachine
def to_register(compiler, source) def to_register(compiler, source)
type = :Message type = :Message
right = compiler.use_reg( type ) right = compiler.use_reg( type )
slots = @slot slots = @slots
left = Risc.message_reg left = Risc.message_reg
left = left.resolve_and_add( slots.name , compiler) left = left.resolve_and_add( slots.name , compiler)
reg = compiler.current.register reg = compiler.current.register
slots = slots.next_slot slots = slots.next_slot
while( slots ) while( slots )
left = left.resolve_and_add( slots , compiler) left = left.resolve_and_add( slots.name , compiler)
slots = slots.next_slot slots = slots.next_slot
end end
return reg return reg
@ -32,15 +31,14 @@ module SlotMachine
# They are very similar (apart from the final reg_to_slot here) and should # They are very similar (apart from the final reg_to_slot here) and should
# most likely be united # most likely be united
def reduce_and_load(const_reg , compiler , original_source ) def reduce_and_load(const_reg , compiler , original_source )
left_slots = slots.dup
raise "Not Message #{object}" unless known_object == :message raise "Not Message #{object}" unless known_object == :message
left = Risc.message_reg left = Risc.message_reg
slot = left_slots.shift slot = slots
while( !left_slots.empty? ) while( slot.next_slot )
left = left.resolve_and_add( slot , compiler) left = left.resolve_and_add( slot.name , compiler)
slot = left_slots.shift slot = slot.next_slot
end 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
end end

View File

@ -21,16 +21,16 @@ module SlotMachine
right = compiler.use_reg( type ) right = compiler.use_reg( type )
const = Risc.load_constant(source, known_object , right) const = Risc.load_constant(source, known_object , right)
compiler.add_code const compiler.add_code const
if slots.length > 0 if slots_length > 1
# desctructively replace the existing value to be loaded if more slots # 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 end
if slots.length > 1 if slots_length > 2
# desctructively replace the existing value to be loaded if more slots # 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) compiler.add_code Risc::SlotToReg.new( source , right ,index, right)
if slots.length > 2 if slots_length > 3
raise "3 slots only for type #{slots}" unless slots[2] == :type 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) compiler.add_code Risc::SlotToReg.new( source , right , Parfait::TYPE_INDEX, right)
end end
end end
@ -44,7 +44,7 @@ module SlotMachine
raise "only cache" unless known_object.is_a?( Parfait::CacheEntry) raise "only cache" unless known_object.is_a?( Parfait::CacheEntry)
left = compiler.use_reg( :CacheEntry ) left = compiler.use_reg( :CacheEntry )
compiler.add_code Risc.load_constant(original_source, known_object , left) 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 end
end end

View File

@ -33,7 +33,7 @@ module Sol
# Derived classes do not implement to_slot, only slot_position # Derived classes do not implement to_slot, only slot_position
def to_slot(compiler) def to_slot(compiler)
to = SlotMachine::Slotted.for(:message , self.slot_position(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) assign = SlotMachine::SlotLoad.new(self,to,from)
return assign unless @value.is_a?(CallStatement) return assign unless @value.is_a?(CallStatement)
@value.to_slot(compiler) << assign @value.to_slot(compiler) << assign

View File

@ -9,7 +9,7 @@ module Sol
def initialize(value) def initialize(value)
@value = value @value = value
end end
def to_slot_definition(_) def to_slotted(_)
return SlotMachine::Slotted.for(SlotMachine::IntegerConstant.new(@value) , []) return SlotMachine::Slotted.for(SlotMachine::IntegerConstant.new(@value) , [])
end end
def ct_type def ct_type
@ -37,7 +37,7 @@ module Sol
def ct_type def ct_type
Parfait.object_space.get_type_by_class_name(:True) Parfait.object_space.get_type_by_class_name(:True)
end end
def to_slot_definition(_) def to_slotted(_)
return SlotMachine::Slotted.for(Parfait.object_space.true_object , []) return SlotMachine::Slotted.for(Parfait.object_space.true_object , [])
end end
def to_s(depth = 0) def to_s(depth = 0)
@ -49,7 +49,7 @@ module Sol
def ct_type def ct_type
Parfait.object_space.get_type_by_class_name(:False) Parfait.object_space.get_type_by_class_name(:False)
end end
def to_slot_definition(_) def to_slotted(_)
return SlotMachine::Slotted.for(Parfait.object_space.false_object , []) return SlotMachine::Slotted.for(Parfait.object_space.false_object , [])
end end
def to_s(depth = 0) def to_s(depth = 0)
@ -61,7 +61,7 @@ module Sol
def ct_type def ct_type
Parfait.object_space.get_type_by_class_name(:Nil) Parfait.object_space.get_type_by_class_name(:Nil)
end end
def to_slot_definition(_) def to_slotted(_)
return SlotMachine::Slotted.for(Parfait.object_space.nil_object , []) return SlotMachine::Slotted.for(Parfait.object_space.nil_object , [])
end end
def to_s(depth = 0) def to_s(depth = 0)
@ -75,7 +75,7 @@ module Sol
def initialize(type = nil) def initialize(type = nil)
@my_type = type @my_type = type
end end
def to_slot_definition(compiler) def to_slotted(compiler)
@my_type = compiler.receiver_type @my_type = compiler.receiver_type
SlotMachine::Slotted.for(:message , [:receiver]) SlotMachine::Slotted.for(:message , [:receiver])
end end
@ -91,7 +91,7 @@ module Sol
def initialize(value) def initialize(value)
@value = value @value = value
end end
def to_slot_definition(_) def to_slotted(_)
return SlotMachine::Slotted.for(SlotMachine::StringConstant.new(@value),[]) return SlotMachine::Slotted.for(SlotMachine::StringConstant.new(@value),[])
end end
def ct_type def ct_type

View File

@ -10,7 +10,7 @@ module Sol
# When used as right hand side, this tells what data to move to get the result into # 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 # 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]) SlotMachine::Slotted.for(:message ,[ :return_value])
end end

View File

@ -32,7 +32,7 @@ module Sol
# create the slot lazily, so to_slot gets called first # create the slot lazily, so to_slot gets called first
def check_slot(compiler , false_label) 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 end
def each(&block) def each(&block)

View File

@ -13,7 +13,7 @@ module Sol
# #
# This means we do the compiler here (rather than to_slot, which is in # This means we do the compiler here (rather than to_slot, which is in
# fact never called) # fact never called)
def to_slot_definition(compiler) def to_slotted(compiler)
compile(compiler) unless @parfait_block compile(compiler) unless @parfait_block
return SlotMachine::Slotted.for(SlotMachine::LambdaConstant.new(parfait_block(compiler)) , []) return SlotMachine::Slotted.for(SlotMachine::LambdaConstant.new(parfait_block(compiler)) , [])
end end

View File

@ -14,7 +14,7 @@ module Sol
# When used as right hand side, this tells what data to move to get the result into # 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 # 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]) SlotMachine::Slotted.for(:message ,[ :return_value])
end end

View File

@ -32,7 +32,7 @@ module Sol
def slot_load(compiler) def slot_load(compiler)
SlotMachine::SlotLoad.new( self , [:message , :return_value] , SlotMachine::SlotLoad.new( self , [:message , :return_value] ,
@return_value.to_slot_definition(compiler) ) @return_value.to_slotted(compiler) )
end end
end end
end end

View File

@ -67,11 +67,11 @@ module Sol
def message_setup(compiler,called_method) def message_setup(compiler,called_method)
setup = SlotMachine::MessageSetup.new( 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 ] arg_target = [:message , :next_message ]
args = [] args = []
@arguments.each_with_index do |arg , index| # +1 because of type @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 end
setup << SlotMachine::ArgumentTransfer.new(self, slot_receive , args ) setup << SlotMachine::ArgumentTransfer.new(self, slot_receive , args )
end end
@ -111,10 +111,11 @@ module Sol
private private
def receiver_type_definition(compiler) def receiver_type_definition(compiler)
defi = @receiver.to_slot_definition(compiler) defi = @receiver.to_slotted(compiler)
defi.slots << :type defi.set_next( SlotMachine::Slot.new(:type) )
defi defi
end end
def build_condition(ok_label, compiler) def build_condition(ok_label, compiler)
cached_type = SlotMachine::Slotted.for(dynamic_call.cache_entry , [:cached_type]) cached_type = SlotMachine::Slotted.for(dynamic_call.cache_entry , [:cached_type])
current_type = receiver_type_definition(compiler) current_type = receiver_type_definition(compiler)

View File

@ -10,7 +10,7 @@ module Sol
class LocalVariable < Expression class LocalVariable < Expression
include Named include Named
def to_slot_definition(compiler) def to_slotted(compiler)
slot_def = compiler.slot_type_for(@name) slot_def = compiler.slot_type_for(@name)
SlotMachine::Slotted.for(:message , slot_def) SlotMachine::Slotted.for(:message , slot_def)
end end
@ -24,7 +24,7 @@ module Sol
class InstanceVariable < Expression class InstanceVariable < Expression
include Named include Named
def to_slot_definition(_) def to_slotted(_)
SlotMachine::Slotted.for(:message , [ :receiver , @name] ) SlotMachine::Slotted.for(:message , [ :receiver , @name] )
end end
# used to collect type information # used to collect type information
@ -51,7 +51,7 @@ module Sol
def ct_type def ct_type
get_named_class.single_class.instance_type get_named_class.single_class.instance_type
end end
def to_slot_definition(_) def to_slotted(_)
return SlotMachine::Slotted.for( get_named_class, []) return SlotMachine::Slotted.for( get_named_class, [])
end end
def get_named_class def get_named_class

View File

@ -15,7 +15,7 @@ module Sol
codes = cond_label codes = cond_label
codes << @hoisted.to_slot(compiler) if @hoisted codes << @hoisted.to_slot(compiler) if @hoisted
codes << @condition.to_slot(compiler) if @condition.is_a?(SendStatement) 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 << @body.to_slot(compiler)
codes << SlotMachine::Jump.new(cond_label) codes << SlotMachine::Jump.new(cond_label)
codes << merge_label codes << merge_label

View File

@ -49,11 +49,11 @@ module Sol
def yield_arg_block(compiler) def yield_arg_block(compiler)
arg_index = compiler.get_method.arguments_type.get_length - 1 arg_index = compiler.get_method.arguments_type.get_length - 1
setup = SlotMachine::MessageSetup.new( arg_index ) setup = SlotMachine::MessageSetup.new( arg_index )
slot_receive = @receiver.to_slot_definition(compiler) slot_receive = @receiver.to_slotted(compiler)
arg_target = [:message , :next_message ] arg_target = [:message , :next_message ]
args = [] args = []
@arguments.each_with_index do |arg , index| # +1 because of type @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 end
setup << SlotMachine::ArgumentTransfer.new( self , slot_receive , args ) setup << SlotMachine::ArgumentTransfer.new( self , slot_receive , args )
setup << SlotMachine::BlockYield.new( self , arg_index ) setup << SlotMachine::BlockYield.new( self , arg_index )