get block resolution to use the extra

block_compiler puts in the extra, that we get out when resolving the type
Thus block args work, though only by assuming direct call
This commit is contained in:
Torsten Ruger 2018-07-17 10:37:33 +03:00
parent 280ea8a8c4
commit ff8b95f21a
7 changed files with 36 additions and 11 deletions

View File

@ -16,6 +16,20 @@ module Risc
"#{@method.self_type.name}.init" "#{@method.self_type.name}.init"
end end
# resolve the type of the slot, by inferring from it's name, using the type
# scope related slots are resolved by the compiler by method/block
#
# This mainly calls super, and only for :caller adds extra info
# Using the info, means assuming that the block is not passed around (FIXME in 2020)
def slot_type( slot , type)
new_type = super
if slot == :caller
extra_info = { type_frame: @method.frame_type ,
type_arguments: @method.arguments_type ,
type_self: @method.self_type}
end
return new_type , extra_info
end
# determine how given name need to be accsessed. # determine how given name need to be accsessed.
# For blocks the options are args or frame # For blocks the options are args or frame
# or then the methods arg or frame # or then the methods arg or frame

View File

@ -66,7 +66,7 @@ module Risc
end end
# resolve the type of the slot, by inferring from it's name, using the type # resolve the type of the slot, by inferring from it's name, using the type
# scope related slots are resolved by the compiler by methood/block # scope related slots are resolved by the compiler by method/block
def slot_type( slot , type) def slot_type( slot , type)
case slot case slot
when :frame when :frame

View File

@ -9,7 +9,7 @@ module Risc
# results of dsl operations (like <<) back to the builder # results of dsl operations (like <<) back to the builder
class RegisterValue class RegisterValue
attr_reader :symbol , :type , :value attr_reader :symbol , :type , :extra
attr_accessor :builder attr_accessor :builder
@ -20,13 +20,14 @@ module Risc
# be :value, or :value_XX or :type_XX to indicate value or type information # be :value, or :value_XX or :type_XX to indicate value or type information
# for an XX instance # for an XX instance
def initialize( reg , type , extra = {}) def initialize( reg , type , extra = {})
extra = {} unless extra
raise "Not Hash #{extra}" unless extra.is_a?(Hash) raise "Not Hash #{extra}" unless extra.is_a?(Hash)
raise "not reg #{reg}" unless self.class.look_like_reg( reg ) raise "not reg #{reg}" unless self.class.look_like_reg( reg )
raise "No type " unless type raise "No type " unless type
type = Parfait.object_space.get_type_by_class_name(type) if type.is_a?(Symbol) type = Parfait.object_space.get_type_by_class_name(type) if type.is_a?(Symbol)
@type = type @type = type
@symbol = reg @symbol = reg
@value = extra @extra = extra
end end
# using the registers type, resolve the slot to an index # using the registers type, resolve the slot to an index
@ -54,18 +55,19 @@ module Risc
# overwrite the message) # overwrite the message)
# We get the type with resolve_new_type # We get the type with resolve_new_type
def get_new_left(slot, compiler) def get_new_left(slot, compiler)
new_type = compiler.slot_type(slot , type) new_type = extra["type_#{slot}".to_sym]
new_type , extra = compiler.slot_type(slot , type) unless new_type
if( @symbol == :r0 ) if( @symbol == :r0 )
new_left = compiler.use_reg( new_type ) new_left = compiler.use_reg( new_type , extra)
else else
new_left = RegisterValue.new( @symbol , new_type) new_left = RegisterValue.new( @symbol , new_type , extra)
end end
new_left new_left
end end
def to_s def to_s
s = "#{symbol}:#{type}" s = "#{symbol}:#{type}"
s += ":#{value}" if value s += ":#{extra}" unless extra.empty?
s s
end end
@ -93,11 +95,11 @@ module Risc
end end
#helper method to calculate with register symbols #helper method to calculate with register symbols
def next_reg_use( type , value = nil ) def next_reg_use( type , extra = {} )
int = @symbol[1,3].to_i int = @symbol[1,3].to_i
raise "No more registers #{self}" if int > 11 raise "No more registers #{self}" if int > 11
sym = "r#{int + 1}".to_sym sym = "r#{int + 1}".to_sym
RegisterValue.new( sym , type, value) RegisterValue.new( sym , type, extra)
end end
def rxf_reference_name def rxf_reference_name

View File

@ -15,6 +15,7 @@ module Arm
end end
module ArmHelper module ArmHelper
def setup def setup
Parfait.boot!
@machine = Arm::ArmMachine @machine = Arm::ArmMachine
@binary = FakeBin.new @binary = FakeBin.new
Risc::Position.clear_positions Risc::Position.clear_positions

View File

@ -39,7 +39,7 @@ module Vool
assert_equal 1, @block.frame_type.variable_index(:local) assert_equal 1, @block.frame_type.variable_index(:local)
end end
end end
class TestBlockMethod #< MiniTest::Test class TestBlockMethod < MiniTest::Test
include MomCompile include MomCompile
def setup def setup
Parfait.boot! Parfait.boot!

View File

@ -19,6 +19,9 @@ module Risc
def test_get_new_left_0 def test_get_new_left_0
assert_equal RegisterValue , @r0.get_new_left(:caller , @compiler).class assert_equal RegisterValue , @r0.get_new_left(:caller , @compiler).class
end end
def test_get_new_left_no_extra
assert @r0.get_new_left(:caller , @compiler).extra.empty?
end
def test_get_new_left_0_reg def test_get_new_left_0_reg
assert_equal :r1 , @r0.get_new_left(:caller , @compiler).symbol assert_equal :r1 , @r0.get_new_left(:caller , @compiler).symbol
end end
@ -28,5 +31,10 @@ module Risc
def test_get_new_left_1_reg def test_get_new_left_1_reg
assert_equal :r1 , @r0.get_new_left(:caller , @compiler).symbol assert_equal :r1 , @r0.get_new_left(:caller , @compiler).symbol
end end
def test_get_left_uses_extra
@r1 = RegisterValue.new(:r1 , :Space , type_arguments: @r0.type)
# works with nil as compiler, because extra is used
assert_equal :Message , @r1.get_new_left(:arguments , nil).type.class_name
end
end end
end end

View File

@ -6,7 +6,7 @@ module Risc
def resolve_type(name) def resolve_type(name)
Parfait.object_space.types.values.first Parfait.object_space.types.values.first
end end
def use_reg(type) def use_reg(type , extra = {})
RegisterValue.new(:r1 , type) RegisterValue.new(:r1 , type)
end end
def reset_regs def reset_regs