diff --git a/lib/vm/method_compiler/assignment.rb b/lib/vm/method_compiler/assignment.rb index c3dbef91..06e12398 100644 --- a/lib/vm/method_compiler/assignment.rb +++ b/lib/vm/method_compiler/assignment.rb @@ -1,6 +1,18 @@ module Vm module Assignment + def on_IvarAssignment( statement ) + value = assignment_value(statement) + name = check_name(statement.name.name) + index = @method.for_type.variable_index( name) + raise "No such ivar #{name} #{@method.for_type}" unless index + value_type = @method.for_type.type_at( index ) + raise "Argument Type mismatch #{value.type}!=#{value_type}" unless value.type == value_type + value_reg = use_reg(:value_type) + add_slot_to_reg(statement , :message , :receiver , value_reg ) + add_reg_to_slot(statement , value , value_reg , index + 1 ) # one for type + end + def on_LocalAssignment( statement ) do_assignment_for( statement , :local ) end @@ -12,7 +24,7 @@ module Vm private def do_assignment_for( statement , type ) - value = assignemnt_value(statement) + value = assignment_value(statement) name = check_name(statement.name.name) index = @method.send( "has_#{type}" , name) raise "No such #{type} #{name} #{@method.inspect}" unless index @@ -27,7 +39,7 @@ module Vm add_reg_to_slot(statement , value , named_list , index + 1 ) # one for type end - def assignemnt_value(statement) + def assignment_value(statement) reset_regs # statements reset registers, ie have all at their disposal value = process(statement.value) raise "Not register #{v}" unless value.is_a?(Register::RegisterValue) diff --git a/test/vm/method_compiler/helper.rb b/test/vm/method_compiler/helper.rb index c95ed867..251e8db6 100644 --- a/test/vm/method_compiler/helper.rb +++ b/test/vm/method_compiler/helper.rb @@ -1,7 +1,15 @@ require_relative '../helper' module Register + module SpaceHack + # test hack to in place change object type + def add_space_field(name,type) + class_type = Parfait.object_space.get_class_by_name(:Space).instance_type + class_type.send(:private_add_instance_variable, name , type) + end + end module ExpressionHelper + include SpaceHack def check Register.machine.boot unless Register.machine.booted @@ -14,17 +22,13 @@ module Register produced end - # test hack to in place change object type - def add_space_field(name,type) - class_type = Parfait.object_space.get_class_by_name(:Space).instance_type - class_type.send(:private_add_instance_variable, name , type) - end end module Statements include AST::Sexp include Compiling - + include SpaceHack + def setup Register.machine.boot # force boot to reset main end diff --git a/test/vm/method_compiler/test_assignment.rb b/test/vm/method_compiler/test_assignment.rb index fb20df8a..08262e6d 100644 --- a/test/vm/method_compiler/test_assignment.rb +++ b/test/vm/method_compiler/test_assignment.rb @@ -14,9 +14,16 @@ module Register assert_nil msg = check_nil , msg end - def test_assign_local - Parfait.object_space.get_main.add_local(:r , :Integer) - @input =s(:statements, s(:l_assignment, s(:name, :r), s(:int, 5))) + def test_assign_ivar_notpresent + @input =s(:statements, s(:i_assignment, s(:name, :r), s(:int, 5))) + @expect = [] + assert_raises{ check_nil } + end + + def test_assign_ivar + add_space_field(:r , :Integer) + + @input =s(:statements, s(:i_assignment, s(:name, :r), s(:int, 5))) @expect = [Label, LoadConstant, SlotToReg, RegToSlot, LoadConstant, SlotToReg , RegToSlot, Label, FunctionReturn]