change method locals to type object too (same as args)
This commit is contained in:
parent
16b3a77350
commit
012b5d683c
@ -7,7 +7,7 @@ module Typed
|
|||||||
|
|
||||||
reset_regs # field_def is a statement, no return and all regs
|
reset_regs # field_def is a statement, no return and all regs
|
||||||
name_s = no_space( statement.name.value )
|
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)
|
# 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
|
process( Tree::Assignment.new(statement.name , statement.value ) ) if statement.value
|
||||||
return nil
|
return nil
|
||||||
|
@ -28,7 +28,7 @@ module Typed
|
|||||||
raise "must define variable '#{statement.name}' before using it" unless index
|
raise "must define variable '#{statement.name}' before using it" unless index
|
||||||
frame = use_reg :Frame
|
frame = use_reg :Frame
|
||||||
add_code Register.get_slot(statement , :message , :frame , 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 )
|
add_code Register.get_slot(statement , frame , Parfait::Frame.get_indexed(index), ret )
|
||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
# Instructions derive from class Instruction and form a linked list
|
# Instructions derive from class Instruction and form a linked list
|
||||||
# - binary: The binary (jumpable) code that the instructions get assembled into
|
# - binary: The binary (jumpable) code that the instructions get assembled into
|
||||||
# - arguments: A type object describing the arguments (name+types) to be passed
|
# - 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)
|
# - for_class: The class the Method is for (TODO, should be Type)
|
||||||
|
|
||||||
|
|
||||||
@ -34,7 +34,8 @@ module Parfait
|
|||||||
self.name = name
|
self.name = name
|
||||||
self.binary = BinaryCode.new 0
|
self.binary = BinaryCode.new 0
|
||||||
self.arguments = arguments
|
self.arguments = arguments
|
||||||
self.locals = List.new
|
self.locals = Type.new Space.object_space.get_class_by_name( :Object )
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# determine whether this method has an argument by the name
|
# determine whether this method has an argument by the name
|
||||||
@ -52,33 +53,35 @@ module Parfait
|
|||||||
arguments.instance_length - 1
|
arguments.instance_length - 1
|
||||||
end
|
end
|
||||||
|
|
||||||
def argument_name(index)
|
def argument_name( index )
|
||||||
arguments.get(index * 2 + 1)
|
arguments.get(index * 2 + 1)
|
||||||
end
|
end
|
||||||
def argument_type(index)
|
def argument_type( index )
|
||||||
arguments.get(index * 2 + 2)
|
arguments.get(index * 2 + 2)
|
||||||
end
|
end
|
||||||
|
|
||||||
# determine if method has a local variable or tmp (anonymous local) by given name
|
# 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
|
raise "has_local #{name}.#{name.class}" unless name.is_a? Symbol
|
||||||
max = self.locals.get_length
|
index = locals.variable_index( name )
|
||||||
counter = 1
|
index ? (index - 1) : index
|
||||||
while( counter <= max )
|
|
||||||
if( self.locals.get(counter).name == name)
|
|
||||||
return counter
|
|
||||||
end
|
|
||||||
counter = counter + 1
|
|
||||||
end
|
|
||||||
return nil
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def ensure_local name , type
|
def add_local( name , type )
|
||||||
index = has_local name
|
index = has_local name
|
||||||
return index if index
|
return index if index
|
||||||
var = Variable.new( type , name)
|
self.locals = self.locals.add_instance_variable(name,type)
|
||||||
self.locals.push var
|
end
|
||||||
self.locals.get_length
|
|
||||||
|
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
|
end
|
||||||
|
|
||||||
def sof_reference_name
|
def sof_reference_name
|
||||||
|
@ -26,7 +26,7 @@ module Register
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_call_main_op
|
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) ))
|
@input =s(:call,s(:name, :main),s(:arguments , s(:name, :bar) ))
|
||||||
check
|
check
|
||||||
end
|
end
|
||||||
|
@ -21,12 +21,12 @@ module Register
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
def test_local_int
|
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))
|
@input = s(:operator_value, :+, s(:name, :bar), s(:int, 3))
|
||||||
check
|
check
|
||||||
end
|
end
|
||||||
def test_int_local
|
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))
|
@input = s(:operator_value, :+, s(:int, 3), s(:name, :bar))
|
||||||
check
|
check
|
||||||
end
|
end
|
||||||
|
@ -10,7 +10,7 @@ module Register
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_local
|
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)
|
@input = s(:name, :bar)
|
||||||
@output = Register::RegisterValue
|
@output = Register::RegisterValue
|
||||||
check
|
check
|
||||||
|
@ -6,6 +6,8 @@ class TestMethod < MiniTest::Test
|
|||||||
obj = Register.machine.space.get_class_by_name(:Object)
|
obj = Register.machine.space.get_class_by_name(:Object)
|
||||||
args = Parfait::Type.new_for_hash( obj , { bar: :Integer , foo: :Type})
|
args = Parfait::Type.new_for_hash( obj , { bar: :Integer , foo: :Type})
|
||||||
@method = ::Parfait::TypedMethod.new obj , :meth , args
|
@method = ::Parfait::TypedMethod.new obj , :meth , args
|
||||||
|
@method.add_local :local_bar , :Integer
|
||||||
|
@method.add_local :local_foo , :Type
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_method_name
|
def test_method_name
|
||||||
@ -39,7 +41,7 @@ class TestMethod < MiniTest::Test
|
|||||||
assert_equal 1 , index
|
assert_equal 1 , index
|
||||||
assert_equal :bar , @method.argument_name(index)
|
assert_equal :bar , @method.argument_name(index)
|
||||||
end
|
end
|
||||||
def test_get_arg_name1
|
def test_get_arg_type1
|
||||||
index = @method.has_arg(:bar)
|
index = @method.has_arg(:bar)
|
||||||
assert_equal :Integer , @method.argument_type(index)
|
assert_equal :Integer , @method.argument_type(index)
|
||||||
end
|
end
|
||||||
@ -48,8 +50,46 @@ class TestMethod < MiniTest::Test
|
|||||||
assert_equal 2 , index
|
assert_equal 2 , index
|
||||||
assert_equal :foo , @method.argument_name(index)
|
assert_equal :foo , @method.argument_name(index)
|
||||||
end
|
end
|
||||||
def test_get_arg_name2
|
def test_get_arg_type2
|
||||||
index = @method.has_arg(:foo)
|
index = @method.has_arg(:foo)
|
||||||
assert_equal :Type , @method.argument_type(index)
|
assert_equal :Type , @method.argument_type(index)
|
||||||
end
|
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
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user