diff --git a/lib/register/boot.rb b/lib/register/boot.rb index 8462b68a..1a4ab303 100644 --- a/lib/register/boot.rb +++ b/lib/register/boot.rb @@ -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 => {}, diff --git a/lib/register/builtin/compile_helper.rb b/lib/register/builtin/compile_helper.rb index 79819415..63a1ef08 100644 --- a/lib/register/builtin/compile_helper.rb +++ b/lib/register/builtin/compile_helper.rb @@ -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 diff --git a/lib/register/builtin/object.rb b/lib/register/builtin/object.rb index 9133f9f8..b0b20201 100644 --- a/lib/register/builtin/object.rb +++ b/lib/register/builtin/object.rb @@ -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) diff --git a/lib/register/builtin/word.rb b/lib/register/builtin/word.rb index 544243e5..7a1005b3 100644 --- a/lib/register/builtin/word.rb +++ b/lib/register/builtin/word.rb @@ -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 diff --git a/lib/typed/method_compiler/assignment.rb b/lib/typed/method_compiler/assignment.rb index 30fe04f2..88756bcc 100644 --- a/lib/typed/method_compiler/assignment.rb +++ b/lib/typed/method_compiler/assignment.rb @@ -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 diff --git a/lib/typed/method_compiler/call_site.rb b/lib/typed/method_compiler/call_site.rb index 464d6ae3..c4db118a 100644 --- a/lib/typed/method_compiler/call_site.rb +++ b/lib/typed/method_compiler/call_site.rb @@ -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 diff --git a/lib/typed/method_compiler/name_expression.rb b/lib/typed/method_compiler/name_expression.rb index f8fcb7d5..cdf5b60e 100644 --- a/lib/typed/method_compiler/name_expression.rb +++ b/lib/typed/method_compiler/name_expression.rb @@ -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 diff --git a/lib/typed/parfait/message.rb b/lib/typed/parfait/message.rb index ab722077..c2ec8943 100644 --- a/lib/typed/parfait/message.rb +++ b/lib/typed/parfait/message.rb @@ -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 diff --git a/test/register/interpreter/helper.rb b/test/register/interpreter/helper.rb index e3e6dbf7..7a6fc697 100644 --- a/test/register/interpreter/helper.rb +++ b/test/register/interpreter/helper.rb @@ -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}" diff --git a/test/register/interpreter/test_if.rb b/test/register/interpreter/test_if.rb index 9fabbfcb..6eb1ccf2 100644 --- a/test/register/interpreter/test_if.rb +++ b/test/register/interpreter/test_if.rb @@ -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", diff --git a/test/typed/parfait/test_message.rb b/test/typed/parfait/test_message.rb index db936b9e..908c30cf 100644 --- a/test/typed/parfait/test_message.rb +++ b/test/typed/parfait/test_message.rb @@ -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 diff --git a/test/typed/statements/test_assign.rb b/test/typed/statements/test_assign.rb index 4d786a89..ff48248b 100644 --- a/test/typed/statements/test_assign.rb +++ b/test/typed/statements/test_assign.rb @@ -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