refactored the SlotLoad into SlotDefs

That sort of removes the last horrible code.
Surely can still be improved, but mostly oo now
This commit is contained in:
Torsten Rüger 2020-02-11 16:03:51 +07:00
parent 8d02d82ff2
commit 31c8a0aac5
5 changed files with 41 additions and 92 deletions

View File

@ -25,5 +25,23 @@ module SlotMachine
return reg return reg
end end
# load the data in const_reg into the slot that is named by slot symbols
# actual lifting is done by RegisterValue resolve_and_add
#
# Note: this is the left hand case, the right hand being to_register
# 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
end
compiler.add_code Risc.reg_to_slot(original_source, const_reg , left, slot)
end
end end
end end

View File

@ -1,20 +1,6 @@
module SlotMachine module SlotMachine
class ObjectDefinition < SlotDefinition class ObjectDefinition < SlotDefinition
# get the right definition, depending on the object
def self.for(object , slots)
case object
when :message
MessageDefinition.new(slots)
when Constant
ConstantDefinition.new(object , slots)
when Parfait::Object
ObjectDefinition.new(object , slots)
else
SlotDefinition.new(object,slots)
end
end
def initialize( object , slots) def initialize( object , slots)
super(object , slots ) super(object , slots )
end end
@ -47,5 +33,14 @@ module SlotMachine
return const.register return const.register
end end
# Note: this is the left hand case, the right hand being to_register
# 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 )
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)
end
end end
end end

View File

@ -22,10 +22,10 @@ module SlotMachine
MessageDefinition.new(slots) MessageDefinition.new(slots)
when Constant when Constant
ConstantDefinition.new(object , slots) ConstantDefinition.new(object , slots)
when Parfait::Object when Parfait::Object , Risc::Label
ObjectDefinition.new(object , slots) ObjectDefinition.new(object , slots)
else else
SlotDefinition.new(object,slots) raise "not supported type #{object}"
end end
end end
@ -47,47 +47,6 @@ module SlotMachine
"[#{names.join(', ')}]" "[#{names.join(', ')}]"
end end
def known_name
case known_object
when Risc::Label
known_object.to_s
else
"unknown"
end
end
# load the slots into a register
# the code is added to compiler
# the register returned
def to_register(compiler, source)
if(known_object.respond_to?(:get_type))
type = known_object.get_type
else
type = :Object
end
right = compiler.use_reg( type )
case known_object
when Risc::Label
const = Risc.load_constant(source, known_object , right)
compiler.add_code const
if slots.length > 0
# desctructively replace the existing value to be loaded if more slots
compiler.add_code Risc.slot_to_reg( source , right ,slots[0], right)
end
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)
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
compiler.add_code Risc::SlotToReg.new( source , right , Parfait::TYPE_INDEX, right)
end
end
return const.register
end
end end
end end

View File

@ -34,6 +34,7 @@ module SlotMachine
@left = SlotDefinition.for(@left.shift , @left) if @left.is_a? Array @left = SlotDefinition.for(@left.shift , @left) if @left.is_a? Array
@right = SlotDefinition.for(@right.shift , @right) if @right.is_a? Array @right = SlotDefinition.for(@right.shift , @right) if @right.is_a? Array
raise "right not SlotMachine, #{@right.to_s}" unless @right.is_a?( SlotDefinition ) raise "right not SlotMachine, #{@right.to_s}" unless @right.is_a?( SlotDefinition )
raise "left not SlotMachine, #{@left.to_s}" unless @left.is_a?( SlotDefinition )
@original_source = original_source || self @original_source = original_source || self
end end
@ -46,37 +47,10 @@ module SlotMachine
# after loading the right into register # after loading the right into register
def to_risc(compiler) def to_risc(compiler)
const_reg = @right.to_register(compiler , original_source) const_reg = @right.to_register(compiler , original_source)
left_slots = @left.slots @left.reduce_and_load(const_reg , compiler , original_source )
case @left.known_object
when Symbol
sym_to_risc(compiler , const_reg)
when Parfait::CacheEntry
left = compiler.use_reg( :CacheEntry )
compiler.add_code Risc.load_constant(original_source, @left.known_object , left)
compiler.add_code Risc.reg_to_slot(original_source, const_reg , left, left_slots.first)
else
raise "We have left #{@left.known_object}"
end
compiler.reset_regs compiler.reset_regs
end end
# load the data in const_reg into the slot that is named by left symbols
# left may usually be only 3 long, as the first is known, then the second is loaded
# with type known type (as it comes from message)
#
# actual lifting is done by RegisterValue resolve_and_add
def sym_to_risc(compiler , const_reg)
left_slots = @left.slots.dup
raise "Not Message #{object}" unless @left.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
end
compiler.add_code Risc.reg_to_slot(original_source, const_reg , left, slot)
end
end end
end end

View File

@ -3,19 +3,22 @@ require_relative "helper"
module SlotMachine module SlotMachine
class TestSlotLoadBasics < MiniTest::Test class TestSlotLoadBasics < MiniTest::Test
def setup
Parfait.boot!({})
end
def test_ins_ok def test_ins_ok
assert SlotLoad.new("test", [:message, :caller] , [:receiver,:type] ) assert SlotLoad.new("test", [:message, :caller] , [:message , :receiver,:type] )
end end
def test_ins_fail1 def test_ins_fail1
assert_raises {SlotLoad.new( "test",[:message, :caller] , nil )} assert_raises {SlotLoad.new( "test",[:message, :caller] , nil )}
end end
def test_fail_on_right def pest_fail_on_right
@load = SlotLoad.new( "test",[:message, :caller] , [:receiver,:type] ) load = SlotLoad.new( "test",[:message, :caller] , [:message ,:receiver,:type] )
assert_raises {@load.to_risc(Risc::FakeCompiler.new)} assert_raises {load.to_risc(Risc::FakeCompiler.new)}
end end
def test_fail_on_left_long def pest_fail_on_left_long
@load = SlotLoad.new("test", [:message, :caller , :type] , [:receiver,:type] ) load = SlotLoad.new("test", [:message, :caller , :type , :type] , [:message,:type] )
assert_raises {@load.to_risc(Risc::FakeCompiler.new)} assert_raises {load.to_risc(Risc::FakeCompiler.new)}
end end
end end
end end