2017-01-14 18:28:44 +01:00
|
|
|
module Vm
|
2016-12-09 12:20:48 +01:00
|
|
|
module Assignment
|
2015-10-15 12:08:53 +02:00
|
|
|
|
2017-01-15 13:44:23 +01:00
|
|
|
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
|
|
|
|
|
2017-01-15 12:01:28 +01:00
|
|
|
def on_LocalAssignment( statement )
|
|
|
|
do_assignment_for( statement , :local )
|
|
|
|
end
|
|
|
|
|
|
|
|
def on_ArgAssignment( statement )
|
|
|
|
do_assignment_for( statement , :argument )
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
def do_assignment_for( statement , type )
|
2017-01-15 13:44:23 +01:00
|
|
|
value = assignment_value(statement)
|
2016-12-28 18:20:16 +01:00
|
|
|
name = check_name(statement.name.name)
|
2017-01-15 12:01:28 +01:00
|
|
|
index = @method.send( "has_#{type}" , name)
|
|
|
|
raise "No such #{type} #{name} #{@method.inspect}" unless index
|
|
|
|
value_type = @method.send("#{type}s_type" , index )
|
|
|
|
raise "Argument Type mismatch #{value.type}!=#{value_type}" unless value.type == value_type
|
|
|
|
move_reg(statement , "#{type}s".to_sym , value , index)
|
|
|
|
end
|
|
|
|
|
|
|
|
def move_reg(statement , type , value , index)
|
2016-12-21 21:35:36 +01:00
|
|
|
named_list = use_reg(:NamedList)
|
2016-12-28 19:37:54 +01:00
|
|
|
add_slot_to_reg(statement , :message , type , named_list )
|
|
|
|
add_reg_to_slot(statement , value , named_list , index + 1 ) # one for type
|
2015-10-15 12:08:53 +02:00
|
|
|
end
|
2016-12-28 18:20:16 +01:00
|
|
|
|
2017-01-15 13:44:23 +01:00
|
|
|
def assignment_value(statement)
|
2017-01-15 12:01:28 +01:00
|
|
|
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)
|
|
|
|
value
|
|
|
|
end
|
2016-12-28 18:20:16 +01:00
|
|
|
# ensure the name given is not space and raise exception otherwise
|
|
|
|
# return the name
|
|
|
|
def check_name( name )
|
|
|
|
raise "space is a reserved name" if name == :space
|
|
|
|
name
|
|
|
|
end
|
|
|
|
|
2015-10-15 12:08:53 +02:00
|
|
|
end
|
|
|
|
end
|