Start to make slots recursive

This commit is contained in:
Torsten Rüger 2020-02-17 14:26:50 +07:00
parent b7df6f66f9
commit 21817b182e
11 changed files with 48 additions and 55 deletions

View File

@ -46,7 +46,7 @@ module Risc
# using the registers type, resolve the slot to an index # using the registers type, resolve the slot to an index
# Using the index and the register, add a SlotToReg to the instruction # Using the index and the register, add a SlotToReg to the instruction
def resolve_and_add(slot , compiler) def resolve_and_add(slot , compiler)
index = resolve_index( slot ) index = resolve_index(slot)
new_left = get_new_left( slot , compiler ) new_left = get_new_left( slot , compiler )
compiler.add_code Risc::SlotToReg.new( "SlotLoad #{type}[#{slot}]" , self ,index, new_left) compiler.add_code Risc::SlotToReg.new( "SlotLoad #{type}[#{slot}]" , self ,index, new_left)
new_left new_left

View File

@ -25,7 +25,7 @@ module SlotMachine
def initialize( source , receiver,arguments ) def initialize( source , receiver,arguments )
super(source) super(source)
@receiver , @arguments = receiver , arguments @receiver , @arguments = receiver , arguments
raise "Receiver not Slot #{@receiver}" unless @receiver.is_a?(Slot) raise "Receiver not Slot #{@receiver}" unless @receiver.is_a?(Slotted)
@arguments.each{|a| raise "args not SlotLoad #{a}" unless a.is_a?(SlotLoad)} @arguments.each{|a| raise "args not SlotLoad #{a}" unless a.is_a?(SlotLoad)}
end end

View File

@ -33,8 +33,8 @@ module SlotMachine
@left , @right = left , right @left , @right = left , right
@left = Slotted.for(@left.shift , @left) if @left.is_a? Array @left = Slotted.for(@left.shift , @left) if @left.is_a? Array
@right = Slotted.for(@right.shift , @right) if @right.is_a? Array @right = Slotted.for(@right.shift , @right) if @right.is_a? Array
raise "right not SlotMachine, #{@right.to_s}" unless @right.is_a?( Slot ) raise "right not SlotMachine, #{@right.to_s}" unless @right.is_a?( Slotted )
raise "left not SlotMachine, #{@left.to_s}" unless @left.is_a?( Slot ) raise "left not SlotMachine, #{@left.to_s}" unless @left.is_a?( Slotted )
@original_source = original_source || self @original_source = original_source || self
end end

View File

@ -11,7 +11,7 @@ module SlotMachine
def initialize(condition , false_jump) def initialize(condition , false_jump)
super(false_jump) super(false_jump)
@condition = condition @condition = condition
raise "condition must be slot_definition #{condition}" unless condition.is_a?(Slot) raise "condition must be slot_definition #{condition}" unless condition.is_a?(Slotted)
end end
def to_s def to_s

View File

@ -1,5 +1,5 @@
module SlotMachine module SlotMachine
# A Slot defines a slot. A bit like a variable name but for objects. # A Slot defines a slot in a slotted. A bit like a variable name but for objects.
# #
# PS: for the interested: A "development" of Smalltalk was the # PS: for the interested: A "development" of Smalltalk was the
# prototype based language (read: JavaScript equivalent) # prototype based language (read: JavaScript equivalent)
@ -7,7 +7,7 @@ module SlotMachine
# #
# Slots are the instance names of objects. But since the language is dynamic # Slots are the instance names of objects. But since the language is dynamic
# what is it that we can say about instance names at runtime? # 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 # Start with a Slotted, 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 # 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. # too. And off course for _all_ objects we know where the type is.
# #
@ -15,35 +15,26 @@ module SlotMachine
# Instructions. Or in the case of constants to ConstantLoad # Instructions. Or in the case of constants to ConstantLoad
# #
class Slot class Slot
# get the right definition, depending on the object
def self.for(object , slots) attr_reader :name , :next_slot
case object
when :message def initialize( name )
SlottedMessage.new(slots) raise "No name" unless name
when Constant @name = name
SlottedConstant.new(object , slots) end
when Parfait::Object , Risc::Label
SlottedObject.new(object , slots) def set_next(slot)
if(@next_slot)
@next_slot.set_next(slot)
else else
raise "not supported type #{object}" @next_slot = slot
end end
end end
attr_reader :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( slots)
raise "No slots #{object}" unless slots
slots = [slots] unless slots.is_a?(Array)
@slots = slots
end
def to_s def to_s
names = [known_name] + @slots names = name.to_s
"[#{names.join(', ')}]" names += ".#{@next_slot}" if @next_slot
names
end end

View File

@ -15,21 +15,24 @@ module SlotMachine
end end
end end
attr_reader :slots # The first in a possible chain of slots, that name instance variables in the
# is an array of symbols, that specifies the first the object, and then the Slot. # previous object
# The first element is either a known type name (Capitalized symbol of the class name) , attr_reader :slot
# or the symbol :message
# And subsequent symbols must be instance variables on the previous type. def initialize( slots )
# Examples: [:message , :receiver] or [:Space , :next_message]
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)
@slots = slots first = slots.shift
@slot = Slot.new(first)
until(slots.empty?)
@slot.set_next( Slot.new( slots.shift ))
end
end end
def to_s def to_s
names = [known_name] + @slots names = known_name.to_s
"[#{names.join(', ')}]" names += ".#{@slot}" if @slot
names
end end

View File

@ -1,5 +1,5 @@
module SlotMachine module SlotMachine
class SlottedConstant < Slot class SlottedConstant < Slotted
attr_reader :known_object attr_reader :known_object

View File

@ -1,9 +1,6 @@
module SlotMachine module SlotMachine
class SlottedMessage < Slot class SlottedMessage < Slotted
def initialize(slots)
super(slots)
end
def known_name def known_name
:message :message
@ -16,12 +13,14 @@ 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 = @slots.dup slots = @slot
left = Risc.message_reg left = Risc.message_reg
left = left.resolve_and_add( slots.shift , compiler) left = left.resolve_and_add( slots.name , compiler)
reg = compiler.current.register reg = compiler.current.register
while( !slots.empty? ) slots = slots.next_slot
left = left.resolve_and_add( slots.shift , compiler) while( slots )
left = left.resolve_and_add( slots , compiler)
slots = slots.next_slot
end end
return reg return reg
end end

View File

@ -1,5 +1,5 @@
module SlotMachine module SlotMachine
class SlottedObject < Slot class SlottedObject < Slotted
attr_reader :known_object attr_reader :known_object

View File

@ -4,10 +4,10 @@ module SlotMachine
class TestSlotKnown1 < MiniTest::Test class TestSlotKnown1 < MiniTest::Test
def setup def setup
Parfait.boot!(Parfait.default_test_options) Parfait.boot!(Parfait.default_test_options)
@compiler = Risc::FakeCompiler.new compiler = Risc::FakeCompiler.new
@definition = SlottedMessage.new( :caller) slotted = SlottedMessage.new(:caller)
@register = @definition.to_register(@compiler , "fake source") @register = slotted.to_register(compiler , "fake source")
@instruction = @compiler.instructions.first @instruction = compiler.instructions.first
end end
def test_def_class def test_def_class
assert_equal Risc::SlotToReg , @instruction.class assert_equal Risc::SlotToReg , @instruction.class