splitting assignment into three, for args, locals and ivars
The decision on which is moving up to the ruby compiler, so it can at the same time emit the correct assignment form. Just another example of moving away from a language and to an intermediate form (that has no language equivalent)
This commit is contained in:
parent
a0cf5bffc0
commit
f9824079d6
@ -1,26 +1,38 @@
|
||||
module Vm
|
||||
module Assignment
|
||||
|
||||
def on_Assignment( 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)
|
||||
name = check_name(statement.name.name)
|
||||
named_list = use_reg(:NamedList)
|
||||
if( index = @method.has_arg(name))
|
||||
type = :arguments
|
||||
value_type = @method.argument_type( index )
|
||||
else
|
||||
index = @method.has_local( name )
|
||||
type = :locals
|
||||
raise "must define variable #{statement.name.name} before using it in #{@method.inspect}" unless index
|
||||
value_type = @method.locals_type( index )
|
||||
def on_LocalAssignment( statement )
|
||||
do_assignment_for( statement , :local )
|
||||
end
|
||||
raise "Type mismatch for #{type} access #{value.type}!=#{value_type}" unless value.type == value_type
|
||||
|
||||
def on_ArgAssignment( statement )
|
||||
do_assignment_for( statement , :argument )
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def do_assignment_for( statement , type )
|
||||
value = assignemnt_value(statement)
|
||||
name = check_name(statement.name.name)
|
||||
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)
|
||||
named_list = use_reg(:NamedList)
|
||||
add_slot_to_reg(statement , :message , type , named_list )
|
||||
add_reg_to_slot(statement , value , named_list , index + 1 ) # one for type
|
||||
end
|
||||
|
||||
def assignemnt_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)
|
||||
value
|
||||
end
|
||||
# ensure the name given is not space and raise exception otherwise
|
||||
# return the name
|
||||
def check_name( name )
|
||||
|
@ -1,13 +1,30 @@
|
||||
module Vm
|
||||
module Tree
|
||||
|
||||
class Assignment < Statement
|
||||
attr_accessor :name , :value
|
||||
def initialize(n = nil , v = nil )
|
||||
@name , @value = n , v
|
||||
|
||||
def initialize(name , value = nil )
|
||||
@name , @value = name , value
|
||||
end
|
||||
|
||||
def to_s
|
||||
"#{name} = #{value}\n"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class IvarAssignment < Assignment
|
||||
def to_s
|
||||
"@#{name} = #{value}\n"
|
||||
end
|
||||
end
|
||||
|
||||
class ArgAssignment < Assignment
|
||||
end
|
||||
|
||||
class LocalAssignment < Assignment
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
@ -120,12 +120,23 @@ module Vm
|
||||
Tree::ClassExpression.new(expression.children.first)
|
||||
end
|
||||
|
||||
def on_assignment statement
|
||||
def on_i_assignment statement
|
||||
assignment_for( statement, Vm::Tree::IvarAssignment)
|
||||
end
|
||||
|
||||
def on_a_assignment statement
|
||||
assignment_for( statement, Vm::Tree::ArgAssignment)
|
||||
end
|
||||
|
||||
def on_l_assignment( statement )
|
||||
assignment_for( statement, Vm::Tree::LocalAssignment)
|
||||
end
|
||||
|
||||
def assignment_for( statement , clazz)
|
||||
name , value = *statement
|
||||
w = Vm::Tree::Assignment.new()
|
||||
w.name = process name
|
||||
w.value = process(value)
|
||||
w
|
||||
p_name = process name
|
||||
p_value = process(value)
|
||||
clazz.new(p_name , p_value)
|
||||
end
|
||||
|
||||
end
|
||||
|
Loading…
x
Reference in New Issue
Block a user