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 index and the register, add a SlotToReg to the instruction
def resolve_and_add(slot , compiler)
index = resolve_index( slot )
index = resolve_index(slot)
new_left = get_new_left( slot , compiler )
compiler.add_code Risc::SlotToReg.new( "SlotLoad #{type}[#{slot}]" , self ,index, new_left)
new_left

View File

@ -25,7 +25,7 @@ module SlotMachine
def initialize( source , receiver,arguments )
super(source)
@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)}
end

View File

@ -33,8 +33,8 @@ module SlotMachine
@left , @right = left , right
@left = Slotted.for(@left.shift , @left) if @left.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 "left not SlotMachine, #{@left.to_s}" unless @left.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?( Slotted )
@original_source = original_source || self
end

View File

@ -11,7 +11,7 @@ module SlotMachine
def initialize(condition , false_jump)
super(false_jump)
@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
def to_s

View File

@ -1,5 +1,5 @@
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
# 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
# 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
# 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
#
class Slot
# get the right definition, depending on the object
def self.for(object , slots)
case object
when :message
SlottedMessage.new(slots)
when Constant
SlottedConstant.new(object , slots)
when Parfait::Object , Risc::Label
SlottedObject.new(object , slots)
attr_reader :name , :next_slot
def initialize( name )
raise "No name" unless name
@name = name
end
def set_next(slot)
if(@next_slot)
@next_slot.set_next(slot)
else
raise "not supported type #{object}"
@next_slot = slot
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
names = [known_name] + @slots
"[#{names.join(', ')}]"
names = name.to_s
names += ".#{@next_slot}" if @next_slot
names
end

View File

@ -15,21 +15,24 @@ module SlotMachine
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)
# The first in a possible chain of slots, that name instance variables in the
# previous object
attr_reader :slot
def initialize( slots )
raise "No slots #{object}" unless slots
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
def to_s
names = [known_name] + @slots
"[#{names.join(', ')}]"
names = known_name.to_s
names += ".#{@slot}" if @slot
names
end

View File

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

View File

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

View File

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

View File

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