seperate args from message (just like frame)

This commit is contained in:
Torsten Ruger 2016-12-21 22:35:36 +02:00
parent ed12108425
commit c3c52d36b8
12 changed files with 46 additions and 70 deletions

View File

@ -117,7 +117,7 @@ module Register
:List => {:indexed_length => :Integer} ,
:Message => { :next_message => :Message, :receiver => :Object, :locals => :NamedList ,
:return_address => :Integer, :return_value => :Integer,
:caller => :Message , :name => :Word , :indexed_length => :Integer },
:caller => :Message , :name => :Word , :arguments => :NamedList },
:MetaClass => {:object => :Object},
:Integer => {},
:Object => {},

View File

@ -3,12 +3,12 @@ module Register
module Builtin
module CompileHelper
def self_and_arg(compiler , source)
def self_and_int_arg(compiler , source)
#Load self by "calling" on_name
me = compiler.process( Typed::Tree::NameExpression.new( :self) )
# Load the argument
index = compiler.use_reg :Integer
compiler.add_code Register.get_slot(source , :message , Parfait::Message.get_indexed(1), index )
compiler.add_code Register.get_slot(source , :message , 1 , index )
return me , index
end
@ -18,9 +18,9 @@ module Register
end
# Load the value
def do_load(compiler, source)
def load_arg_at(compiler, source , at)
value = compiler.use_reg :Integer
compiler.add_code Register.get_slot(source , :message , Parfait::Message.get_indexed(2), value )
compiler.add_code Register.get_slot(source , :message , at , value )
value
end

View File

@ -12,7 +12,7 @@ module Register
def get_internal_word context
compiler = compiler_for(:Object , :get_internal_word )
source = "get_internal_word"
me , index = self_and_arg(compiler,source)
me , index = self_and_int_arg(compiler,source)
# reduce me to me[index]
compiler.add_code GetSlot.new( source , me , index , me)
# and put it back into the return value
@ -25,8 +25,8 @@ module Register
def set_internal_word context
compiler = compiler_for(:Object , :set_internal_word , {:value => :Object} )
source = "set_internal_word"
me , index = self_and_arg(compiler,source)
value = do_load(compiler,source)
me , index = self_and_int_arg(compiler,source)
value = load_arg_at(compiler,source , 2)
# do the set
compiler.add_code SetSlot.new( source , value , me , index)

View File

@ -21,7 +21,7 @@ module Register
def get_internal_byte context
compiler = compiler_for(:Word , :get_internal_byte)
source = "get_internal_byte"
me , index = self_and_arg(compiler,source)
me , index = self_and_int_arg(compiler,source)
# reduce me to me[index]
compiler.add_code GetByte.new( source , me , index , me)
# and put it back into the return value
@ -35,8 +35,8 @@ module Register
def set_internal_byte context
compiler = compiler_for(:Word, :set_internal_byte , {:value => :Integer} )
source = "set_internal_byte"
me , index = self_and_arg(compiler,source)
value = do_load(compiler,source)
me , index = self_and_int_arg(compiler,source)
value = load_arg_at(compiler , source , 2 )
# do the set
compiler.add_code SetByte.new( source , value , me , index)
return compiler.method

View File

@ -15,16 +15,18 @@ module Typed
def get_code( statement , value)
name = no_space(statement.name).name
named_list = use_reg(:NamedList)
if( index = @method.has_arg(name))
# TODO, check type @method.arguments[index].type
return Register.set_slot(statement , value , :message , Parfait::Message.get_indexed(index) )
type = :arguments
else
# or a local so it is in the frame
index = @method.has_local( name )
type = :locals
return nil unless index
end
# or a local so it is in the named_list
index = @method.has_local( name )
return nil unless index
# TODO, check type @method.locals[index].type
named_list = use_reg(:NamedList)
add_code Register.get_slot(statement , :message , :locals , named_list )
add_code Register.get_slot(statement , :message , type , named_list )
return Register.set_slot(statement , value , named_list , index )
end
end

View File

@ -15,7 +15,7 @@ module Typed
set_message_details(statement , statement.arguments)
set_arguments(statement.arguments)
ret = use_reg( :Integer ) #TODO real return type
ret = use_reg( :Integer ) #FIXME real return type
do_call(type , statement)
# the effect of the method is that the NewMessage Return slot will be filled, return it
# but move it into a register too
@ -35,10 +35,7 @@ module Typed
me
end
def get_my_type( me )
if(me.type == :MetaClass)
raise "Remove this test #{me.class}"
end
# now we have to resolve the method name (+ receiver) into a callable method
# now we have to resolve the method name (+ receiver) into a callable method
case me.type
when Parfait::Type
type = me.type
@ -50,6 +47,7 @@ module Typed
raise "Not type #{type}" unless type.is_a? Parfait::Type
type
end
def do_call( type , statement )
name = statement.name
#puts "type #{type.inspect}"
@ -58,16 +56,24 @@ module Typed
raise "Method not implemented #{type.inspect}.#{name}" unless method
Register.issue_call( self , method )
end
# load method name and set to new message (for exceptions/debug)
def set_message_details name_s , arguments
name = name_s.name
# load method name and set to new message (for exceptions/debug)
name_tmp = use_reg(:Word)
add_code Register::LoadConstant.new(name_s, name , name_tmp)
add_code Register.set_slot( name_s , name_tmp , :new_message , :name)
# next arguments. first length then args
len_tmp = use_reg(:Integer , arguments.to_a.length )
add_code Register::LoadConstant.new(name_s, arguments.to_a.length , len_tmp)
add_code Register.set_slot( name_s , len_tmp , :new_message , :indexed_length)
# next arg and local types
args_reg = use_reg(:Type , @method.arguments )
list_reg = use_reg(:NamedList , arguments )
add_code Register::LoadConstant.new(name_s, @method , args_reg)
add_code Register.get_slot( name_s , :message , :arguments , list_reg )
add_code Register.set_slot( name_s , args_reg , list_reg , 1 )
#FIXME need to set type of locals too. sama sama
# len_tmp = use_reg(:Integer , arguments.to_a.length )
# add_code Register::LoadConstant.new(name_s, arguments.to_a.length , len_tmp)
# add_code Register.set_slot( name_s , len_tmp , :new_message , :indexed_length)
end
def set_arguments arguments
# reset tmp regs for each and load result into new_message
@ -76,8 +82,10 @@ module Typed
# processing should return the register with the value
val = process( arg)
raise "Not register #{val}" unless val.is_a?(Register::RegisterValue)
list_reg = use_reg(:NamedList , arguments )
add_code Register.get_slot( "Set arg #{i}#{arg}" , :message , :arguments , list_reg )
# which we load int the new_message at the argument's index (the one comes from c index)
set = Register.set_slot( arg , val , :new_message , Parfait::Message.get_indexed(i+1))
set = Register.set_slot( arg , val , list_reg , i + 1 )
add_code set
end
end

View File

@ -14,7 +14,7 @@ module Typed
if( index = @method.has_arg(name))
ret = use_reg @method.argument_type(index)
#puts "For #{name} at #{index} got #{@method.arguments.inspect}"
add_code Register.get_slot(statement , :message , Parfait::Message.get_indexed(index), ret )
add_code Register.get_slot(statement , :message , index, ret )
return ret
end
# or a local so it is in the named_list

View File

@ -10,14 +10,12 @@
module Parfait
class Message < Object
attributes [:next_message , :receiver , :locals , :return_address ]
attributes [:return_value, :caller , :name ]
include Indexed
self.offset(8) # 8 == the seven attributes above + type. (indexed_length gets added)
attributes [:return_value, :caller , :name , :arguments]
def initialize next_m
self.next_message = next_m
self.locals = NamedList.new()
self.arguments = NamedList.new()
self.caller = nil
super()
end

View File

@ -16,7 +16,7 @@ module Ticker
# must be after boot, but before main compile, to define method
def do_clean_compile
end
def check_chain should
should.each_with_index do |name , index|
got = ticks(1)
@ -51,6 +51,7 @@ module Ticker
rescue => e
puts "Error at tick #{tick}"
puts e
puts e.backtrace
end
classes = classes.collect {|c| '"' + c.name.sub("Register::","") + '",' }
classes << "length = #{classes.length}"

View File

@ -32,7 +32,7 @@ HERE
s(:false_statements, s(:call, s(:name, :putstring), s(:arguments), s(:receiver, s(:string, "else"))))))
end
def test_if
#show_ticks # get output of what is
show_ticks # get output of what is
check_chain ["Branch","Label","LoadConstant","GetSlot","SetSlot",
"LoadConstant","SetSlot","FunctionCall","Label","GetSlot",
"GetSlot","SetSlot","LoadConstant","SetSlot","LoadConstant",

View File

@ -8,7 +8,6 @@ class TestMessage < MiniTest::Test
def test_length
assert_equal 9 , @mess.get_type.instance_length , @mess.get_type.inspect
assert_equal 9 , Parfait::Message.get_length_index
end
def test_attribute_set
@ -17,39 +16,7 @@ class TestMessage < MiniTest::Test
end
def test_indexed
assert_equal 9 , @mess.get_type.variable_index(:indexed_length)
end
def test_push1
@mess.push :name
assert_equal 1 , @mess.get_length
end
def test_push2
@mess.push :name
assert_equal 1 , @mess.indexed_length
end
def test_push3
@mess.push :name
assert_equal 1 , @mess.get_internal_word(9)
end
def test_get_internal_word
@mess.push :name
assert_equal :name , @mess.get_internal_word(10)
end
def test_get
index = @mess.push :name
assert_equal 1 , index
assert_equal :name , @mess.get(1)
end
def test_each
three = [:one,:two,:three]
three.each {|i| @mess.push(i)}
assert_equal 3 , @mess.get_length
@mess.each do |u|
assert_equal u , three.delete(u)
end
assert_equal 0 , three.length
assert_equal 9 , @mess.get_type.variable_index(:arguments)
end
end

View File

@ -79,7 +79,7 @@ class TestAssignStatement < MiniTest::Test
was = check
get = was.next(1)
assert_equal GetSlot , get.class
assert_equal 10, get.index , "Get to named_list index must be offset, not #{get.index}"
assert_equal 1, get.index , "Get to args index must be offset, not #{get.index}"
end
end
end