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} ,
|
:List => {:indexed_length => :Integer} ,
|
||||||
:Message => { :next_message => :Message, :receiver => :Object, :locals => :NamedList ,
|
:Message => { :next_message => :Message, :receiver => :Object, :locals => :NamedList ,
|
||||||
:return_address => :Integer, :return_value => :Integer,
|
:return_address => :Integer, :return_value => :Integer,
|
||||||
:caller => :Message , :name => :Word , :indexed_length => :Integer },
|
:caller => :Message , :name => :Word , :arguments => :NamedList },
|
||||||
:MetaClass => {:object => :Object},
|
:MetaClass => {:object => :Object},
|
||||||
:Integer => {},
|
:Integer => {},
|
||||||
:Object => {},
|
:Object => {},
|
||||||
|
@ -3,12 +3,12 @@ module Register
|
|||||||
module Builtin
|
module Builtin
|
||||||
module CompileHelper
|
module CompileHelper
|
||||||
|
|
||||||
def self_and_arg(compiler , source)
|
def self_and_int_arg(compiler , source)
|
||||||
#Load self by "calling" on_name
|
#Load self by "calling" on_name
|
||||||
me = compiler.process( Typed::Tree::NameExpression.new( :self) )
|
me = compiler.process( Typed::Tree::NameExpression.new( :self) )
|
||||||
# Load the argument
|
# Load the argument
|
||||||
index = compiler.use_reg :Integer
|
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
|
return me , index
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -18,9 +18,9 @@ module Register
|
|||||||
end
|
end
|
||||||
|
|
||||||
# Load the value
|
# Load the value
|
||||||
def do_load(compiler, source)
|
def load_arg_at(compiler, source , at)
|
||||||
value = compiler.use_reg :Integer
|
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
|
value
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ module Register
|
|||||||
def get_internal_word context
|
def get_internal_word context
|
||||||
compiler = compiler_for(:Object , :get_internal_word )
|
compiler = compiler_for(:Object , :get_internal_word )
|
||||||
source = "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]
|
# reduce me to me[index]
|
||||||
compiler.add_code GetSlot.new( source , me , index , me)
|
compiler.add_code GetSlot.new( source , me , index , me)
|
||||||
# and put it back into the return value
|
# and put it back into the return value
|
||||||
@ -25,8 +25,8 @@ module Register
|
|||||||
def set_internal_word context
|
def set_internal_word context
|
||||||
compiler = compiler_for(:Object , :set_internal_word , {:value => :Object} )
|
compiler = compiler_for(:Object , :set_internal_word , {:value => :Object} )
|
||||||
source = "set_internal_word"
|
source = "set_internal_word"
|
||||||
me , index = self_and_arg(compiler,source)
|
me , index = self_and_int_arg(compiler,source)
|
||||||
value = do_load(compiler,source)
|
value = load_arg_at(compiler,source , 2)
|
||||||
|
|
||||||
# do the set
|
# do the set
|
||||||
compiler.add_code SetSlot.new( source , value , me , index)
|
compiler.add_code SetSlot.new( source , value , me , index)
|
||||||
|
@ -21,7 +21,7 @@ module Register
|
|||||||
def get_internal_byte context
|
def get_internal_byte context
|
||||||
compiler = compiler_for(:Word , :get_internal_byte)
|
compiler = compiler_for(:Word , :get_internal_byte)
|
||||||
source = "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]
|
# reduce me to me[index]
|
||||||
compiler.add_code GetByte.new( source , me , index , me)
|
compiler.add_code GetByte.new( source , me , index , me)
|
||||||
# and put it back into the return value
|
# and put it back into the return value
|
||||||
@ -35,8 +35,8 @@ module Register
|
|||||||
def set_internal_byte context
|
def set_internal_byte context
|
||||||
compiler = compiler_for(:Word, :set_internal_byte , {:value => :Integer} )
|
compiler = compiler_for(:Word, :set_internal_byte , {:value => :Integer} )
|
||||||
source = "set_internal_byte"
|
source = "set_internal_byte"
|
||||||
me , index = self_and_arg(compiler,source)
|
me , index = self_and_int_arg(compiler,source)
|
||||||
value = do_load(compiler,source)
|
value = load_arg_at(compiler , source , 2 )
|
||||||
# do the set
|
# do the set
|
||||||
compiler.add_code SetByte.new( source , value , me , index)
|
compiler.add_code SetByte.new( source , value , me , index)
|
||||||
return compiler.method
|
return compiler.method
|
||||||
|
@ -15,16 +15,18 @@ module Typed
|
|||||||
|
|
||||||
def get_code( statement , value)
|
def get_code( statement , value)
|
||||||
name = no_space(statement.name).name
|
name = no_space(statement.name).name
|
||||||
|
named_list = use_reg(:NamedList)
|
||||||
if( index = @method.has_arg(name))
|
if( index = @method.has_arg(name))
|
||||||
# TODO, check type @method.arguments[index].type
|
# TODO, check type @method.arguments[index].type
|
||||||
return Register.set_slot(statement , value , :message , Parfait::Message.get_indexed(index) )
|
type = :arguments
|
||||||
end
|
else
|
||||||
# or a local so it is in the named_list
|
# or a local so it is in the frame
|
||||||
index = @method.has_local( name )
|
index = @method.has_local( name )
|
||||||
|
type = :locals
|
||||||
return nil unless index
|
return nil unless index
|
||||||
|
end
|
||||||
# TODO, check type @method.locals[index].type
|
# TODO, check type @method.locals[index].type
|
||||||
named_list = use_reg(:NamedList)
|
add_code Register.get_slot(statement , :message , type , named_list )
|
||||||
add_code Register.get_slot(statement , :message , :locals , named_list )
|
|
||||||
return Register.set_slot(statement , value , named_list , index )
|
return Register.set_slot(statement , value , named_list , index )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -15,7 +15,7 @@ module Typed
|
|||||||
|
|
||||||
set_message_details(statement , statement.arguments)
|
set_message_details(statement , statement.arguments)
|
||||||
set_arguments(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)
|
do_call(type , statement)
|
||||||
# the effect of the method is that the NewMessage Return slot will be filled, return it
|
# the effect of the method is that the NewMessage Return slot will be filled, return it
|
||||||
# but move it into a register too
|
# but move it into a register too
|
||||||
@ -35,9 +35,6 @@ module Typed
|
|||||||
me
|
me
|
||||||
end
|
end
|
||||||
def get_my_type( me )
|
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
|
case me.type
|
||||||
when Parfait::Type
|
when Parfait::Type
|
||||||
@ -50,6 +47,7 @@ module Typed
|
|||||||
raise "Not type #{type}" unless type.is_a? Parfait::Type
|
raise "Not type #{type}" unless type.is_a? Parfait::Type
|
||||||
type
|
type
|
||||||
end
|
end
|
||||||
|
|
||||||
def do_call( type , statement )
|
def do_call( type , statement )
|
||||||
name = statement.name
|
name = statement.name
|
||||||
#puts "type #{type.inspect}"
|
#puts "type #{type.inspect}"
|
||||||
@ -58,16 +56,24 @@ module Typed
|
|||||||
raise "Method not implemented #{type.inspect}.#{name}" unless method
|
raise "Method not implemented #{type.inspect}.#{name}" unless method
|
||||||
Register.issue_call( self , method )
|
Register.issue_call( self , method )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# load method name and set to new message (for exceptions/debug)
|
||||||
def set_message_details name_s , arguments
|
def set_message_details name_s , arguments
|
||||||
name = name_s.name
|
name = name_s.name
|
||||||
# load method name and set to new message (for exceptions/debug)
|
|
||||||
name_tmp = use_reg(:Word)
|
name_tmp = use_reg(:Word)
|
||||||
add_code Register::LoadConstant.new(name_s, name , name_tmp)
|
add_code Register::LoadConstant.new(name_s, name , name_tmp)
|
||||||
add_code Register.set_slot( name_s , name_tmp , :new_message , :name)
|
add_code Register.set_slot( name_s , name_tmp , :new_message , :name)
|
||||||
# next arguments. first length then args
|
# next arg and local types
|
||||||
len_tmp = use_reg(:Integer , arguments.to_a.length )
|
args_reg = use_reg(:Type , @method.arguments )
|
||||||
add_code Register::LoadConstant.new(name_s, arguments.to_a.length , len_tmp)
|
list_reg = use_reg(:NamedList , arguments )
|
||||||
add_code Register.set_slot( name_s , len_tmp , :new_message , :indexed_length)
|
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
|
end
|
||||||
def set_arguments arguments
|
def set_arguments arguments
|
||||||
# reset tmp regs for each and load result into new_message
|
# 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
|
# processing should return the register with the value
|
||||||
val = process( arg)
|
val = process( arg)
|
||||||
raise "Not register #{val}" unless val.is_a?(Register::RegisterValue)
|
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)
|
# 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
|
add_code set
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -14,7 +14,7 @@ module Typed
|
|||||||
if( index = @method.has_arg(name))
|
if( index = @method.has_arg(name))
|
||||||
ret = use_reg @method.argument_type(index)
|
ret = use_reg @method.argument_type(index)
|
||||||
#puts "For #{name} at #{index} got #{@method.arguments.inspect}"
|
#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
|
return ret
|
||||||
end
|
end
|
||||||
# or a local so it is in the named_list
|
# or a local so it is in the named_list
|
||||||
|
@ -10,14 +10,12 @@
|
|||||||
module Parfait
|
module Parfait
|
||||||
class Message < Object
|
class Message < Object
|
||||||
attributes [:next_message , :receiver , :locals , :return_address ]
|
attributes [:next_message , :receiver , :locals , :return_address ]
|
||||||
attributes [:return_value, :caller , :name ]
|
attributes [:return_value, :caller , :name , :arguments]
|
||||||
|
|
||||||
include Indexed
|
|
||||||
self.offset(8) # 8 == the seven attributes above + type. (indexed_length gets added)
|
|
||||||
|
|
||||||
def initialize next_m
|
def initialize next_m
|
||||||
self.next_message = next_m
|
self.next_message = next_m
|
||||||
self.locals = NamedList.new()
|
self.locals = NamedList.new()
|
||||||
|
self.arguments = NamedList.new()
|
||||||
self.caller = nil
|
self.caller = nil
|
||||||
super()
|
super()
|
||||||
end
|
end
|
||||||
|
@ -51,6 +51,7 @@ module Ticker
|
|||||||
rescue => e
|
rescue => e
|
||||||
puts "Error at tick #{tick}"
|
puts "Error at tick #{tick}"
|
||||||
puts e
|
puts e
|
||||||
|
puts e.backtrace
|
||||||
end
|
end
|
||||||
classes = classes.collect {|c| '"' + c.name.sub("Register::","") + '",' }
|
classes = classes.collect {|c| '"' + c.name.sub("Register::","") + '",' }
|
||||||
classes << "length = #{classes.length}"
|
classes << "length = #{classes.length}"
|
||||||
|
@ -32,7 +32,7 @@ HERE
|
|||||||
s(:false_statements, s(:call, s(:name, :putstring), s(:arguments), s(:receiver, s(:string, "else"))))))
|
s(:false_statements, s(:call, s(:name, :putstring), s(:arguments), s(:receiver, s(:string, "else"))))))
|
||||||
end
|
end
|
||||||
def test_if
|
def test_if
|
||||||
#show_ticks # get output of what is
|
show_ticks # get output of what is
|
||||||
check_chain ["Branch","Label","LoadConstant","GetSlot","SetSlot",
|
check_chain ["Branch","Label","LoadConstant","GetSlot","SetSlot",
|
||||||
"LoadConstant","SetSlot","FunctionCall","Label","GetSlot",
|
"LoadConstant","SetSlot","FunctionCall","Label","GetSlot",
|
||||||
"GetSlot","SetSlot","LoadConstant","SetSlot","LoadConstant",
|
"GetSlot","SetSlot","LoadConstant","SetSlot","LoadConstant",
|
||||||
|
@ -8,7 +8,6 @@ class TestMessage < MiniTest::Test
|
|||||||
|
|
||||||
def test_length
|
def test_length
|
||||||
assert_equal 9 , @mess.get_type.instance_length , @mess.get_type.inspect
|
assert_equal 9 , @mess.get_type.instance_length , @mess.get_type.inspect
|
||||||
assert_equal 9 , Parfait::Message.get_length_index
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_attribute_set
|
def test_attribute_set
|
||||||
@ -17,39 +16,7 @@ class TestMessage < MiniTest::Test
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_indexed
|
def test_indexed
|
||||||
assert_equal 9 , @mess.get_type.variable_index(:indexed_length)
|
assert_equal 9 , @mess.get_type.variable_index(:arguments)
|
||||||
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
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -79,7 +79,7 @@ class TestAssignStatement < MiniTest::Test
|
|||||||
was = check
|
was = check
|
||||||
get = was.next(1)
|
get = was.next(1)
|
||||||
assert_equal GetSlot , get.class
|
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
|
end
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user