Start to make slots recursive
This commit is contained in:
parent
b7df6f66f9
commit
21817b182e
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
module SlotMachine
|
||||
class SlottedConstant < Slot
|
||||
class SlottedConstant < Slotted
|
||||
|
||||
|
||||
attr_reader :known_object
|
||||
|
@ -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
|
||||
|
@ -1,5 +1,5 @@
|
||||
module SlotMachine
|
||||
class SlottedObject < Slot
|
||||
class SlottedObject < Slotted
|
||||
|
||||
attr_reader :known_object
|
||||
|
||||
|
@ -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
|
Loading…
Reference in New Issue
Block a user