diff --git a/lib/typed/compiler/field_def.rb b/lib/typed/compiler/field_def.rb index 750536d1..098a6ab3 100644 --- a/lib/typed/compiler/field_def.rb +++ b/lib/typed/compiler/field_def.rb @@ -7,7 +7,7 @@ module Typed reset_regs # field_def is a statement, no return and all regs name_s = no_space( statement.name.value ) - @method.ensure_local( name_s, statement.type ) unless( @method.has_arg(name_s)) + @method.add_local( name_s, statement.type ) unless( @method.has_arg(name_s)) # if there is a value assigned, process it as am assignemnt statement (kind of call on_assign) process( Tree::Assignment.new(statement.name , statement.value ) ) if statement.value return nil diff --git a/lib/typed/compiler/name_expression.rb b/lib/typed/compiler/name_expression.rb index 5168e49f..80eaa234 100644 --- a/lib/typed/compiler/name_expression.rb +++ b/lib/typed/compiler/name_expression.rb @@ -28,7 +28,7 @@ module Typed raise "must define variable '#{statement.name}' before using it" unless index frame = use_reg :Frame add_code Register.get_slot(statement , :message , :frame , frame ) - ret = use_reg @method.locals[index].value_type + ret = use_reg @method.locals_type( index ) add_code Register.get_slot(statement , frame , Parfait::Frame.get_indexed(index), ret ) return ret end diff --git a/lib/typed/parfait/typed_method.rb b/lib/typed/parfait/typed_method.rb index 261b1d1d..4b399f10 100644 --- a/lib/typed/parfait/typed_method.rb +++ b/lib/typed/parfait/typed_method.rb @@ -14,7 +14,7 @@ # Instructions derive from class Instruction and form a linked list # - binary: The binary (jumpable) code that the instructions get assembled into # - arguments: A type object describing the arguments (name+types) to be passed -# - locals: A List of Variables that the method has +# - locals: A type object describing the local variables that the method has # - for_class: The class the Method is for (TODO, should be Type) @@ -34,7 +34,8 @@ module Parfait self.name = name self.binary = BinaryCode.new 0 self.arguments = arguments - self.locals = List.new + self.locals = Type.new Space.object_space.get_class_by_name( :Object ) + end # determine whether this method has an argument by the name @@ -52,33 +53,35 @@ module Parfait arguments.instance_length - 1 end - def argument_name(index) + def argument_name( index ) arguments.get(index * 2 + 1) end - def argument_type(index) + def argument_type( index ) arguments.get(index * 2 + 2) end # determine if method has a local variable or tmp (anonymous local) by given name - def has_local name + def has_local( name ) raise "has_local #{name}.#{name.class}" unless name.is_a? Symbol - max = self.locals.get_length - counter = 1 - while( counter <= max ) - if( self.locals.get(counter).name == name) - return counter - end - counter = counter + 1 - end - return nil + index = locals.variable_index( name ) + index ? (index - 1) : index end - def ensure_local name , type + def add_local( name , type ) index = has_local name return index if index - var = Variable.new( type , name) - self.locals.push var - self.locals.get_length + self.locals = self.locals.add_instance_variable(name,type) + end + + def locals_length + locals.instance_length - 1 + end + + def locals_name( index ) + locals.get(index * 2 + 1) + end + def locals_type( index ) + locals.get(index * 2 + 2) end def sof_reference_name diff --git a/test/typed/expressions/test_call.rb b/test/typed/expressions/test_call.rb index 8012e99f..cadb608d 100644 --- a/test/typed/expressions/test_call.rb +++ b/test/typed/expressions/test_call.rb @@ -26,7 +26,7 @@ module Register end def test_call_main_op - Register.machine.space.get_main.ensure_local(:bar , :Integer) + Register.machine.space.get_main.add_local(:bar , :Integer) @input =s(:call,s(:name, :main),s(:arguments , s(:name, :bar) )) check end diff --git a/test/typed/expressions/test_ops.rb b/test/typed/expressions/test_ops.rb index 02483a85..1492aaa7 100644 --- a/test/typed/expressions/test_ops.rb +++ b/test/typed/expressions/test_ops.rb @@ -21,12 +21,12 @@ module Register end end def test_local_int - Register.machine.space.get_main.ensure_local(:bar , :Integer) + Register.machine.space.get_main.add_local(:bar , :Integer) @input = s(:operator_value, :+, s(:name, :bar), s(:int, 3)) check end def test_int_local - Register.machine.space.get_main.ensure_local(:bar , :Integer) + Register.machine.space.get_main.add_local(:bar , :Integer) @input = s(:operator_value, :+, s(:int, 3), s(:name, :bar)) check end diff --git a/test/typed/expressions/test_vars.rb b/test/typed/expressions/test_vars.rb index a77d9832..0c77aaaf 100644 --- a/test/typed/expressions/test_vars.rb +++ b/test/typed/expressions/test_vars.rb @@ -10,7 +10,7 @@ module Register end def test_local - Register.machine.space.get_main.ensure_local(:bar , :Integer) + Register.machine.space.get_main.add_local(:bar , :Integer) @input = s(:name, :bar) @output = Register::RegisterValue check diff --git a/test/typed/parfait/test_method.rb b/test/typed/parfait/test_method.rb index dfe4e3d2..039f8a07 100644 --- a/test/typed/parfait/test_method.rb +++ b/test/typed/parfait/test_method.rb @@ -6,6 +6,8 @@ class TestMethod < MiniTest::Test obj = Register.machine.space.get_class_by_name(:Object) args = Parfait::Type.new_for_hash( obj , { bar: :Integer , foo: :Type}) @method = ::Parfait::TypedMethod.new obj , :meth , args + @method.add_local :local_bar , :Integer + @method.add_local :local_foo , :Type end def test_method_name @@ -39,7 +41,7 @@ class TestMethod < MiniTest::Test assert_equal 1 , index assert_equal :bar , @method.argument_name(index) end - def test_get_arg_name1 + def test_get_arg_type1 index = @method.has_arg(:bar) assert_equal :Integer , @method.argument_type(index) end @@ -48,8 +50,46 @@ class TestMethod < MiniTest::Test assert_equal 2 , index assert_equal :foo , @method.argument_name(index) end - def test_get_arg_name2 + def test_get_arg_type2 index = @method.has_arg(:foo) assert_equal :Type , @method.argument_type(index) end + + def test_local1 + assert_equal 2 , @method.locals_length , @method.locals.inspect + assert_equal Symbol , @method.locals.first.class + assert_equal :local_bar , @method.locals_name(1) + end + + def test_has_local + assert_equal 1 , @method.has_local(:local_bar) + assert_equal 2 , @method.has_local(:local_foo) + end + + def test_add_local + @method.add_local(:foo2 , :Object) + assert_equal 3 , @method.locals_length + assert_equal :foo2 , @method.locals_name(3) + assert_equal :Object , @method.locals_type(3) + end + + def test_get_locals_name1 + index = @method.has_local(:local_bar) + assert_equal 1 , index + assert_equal :local_bar , @method.locals_name(index) + end + def test_get_locals_type1 + index = @method.has_local(:local_bar) + assert_equal :Integer , @method.locals_type(index) + end + def test_get_locals_name2 + index = @method.has_local(:local_foo) + assert_equal 2 , index + assert_equal :local_foo , @method.locals_name(index) + end + def test_get_locals_type2 + index = @method.has_local(:local_bar) + assert_equal :Integer , @method.locals_type(index) + end + end