seperate args from message (just like frame)
This commit is contained in:
parent
ed12108425
commit
c3c52d36b8
@ -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 => {},
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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}"
|
||||
|
@ -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",
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user