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:
Torsten Ruger 2017-01-15 13:01:28 +02:00
parent a0cf5bffc0
commit f9824079d6
3 changed files with 61 additions and 21 deletions

View File

@ -1,26 +1,38 @@
module Vm module Vm
module Assignment module Assignment
def on_Assignment( statement ) def on_LocalAssignment( statement )
reset_regs # statements reset registers, ie have all at their disposal do_assignment_for( statement , :local )
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 )
end 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_slot_to_reg(statement , :message , type , named_list )
add_reg_to_slot(statement , value , named_list , index + 1 ) # one for type add_reg_to_slot(statement , value , named_list , index + 1 ) # one for type
end 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 # ensure the name given is not space and raise exception otherwise
# return the name # return the name
def check_name( name ) def check_name( name )

View File

@ -1,13 +1,30 @@
module Vm module Vm
module Tree module Tree
class Assignment < Statement class Assignment < Statement
attr_accessor :name , :value attr_accessor :name , :value
def initialize(n = nil , v = nil )
@name , @value = n , v def initialize(name , value = nil )
@name , @value = name , value
end end
def to_s def to_s
"#{name} = #{value}\n" "#{name} = #{value}\n"
end end
end
class IvarAssignment < Assignment
def to_s
"@#{name} = #{value}\n"
end end
end end
class ArgAssignment < Assignment
end
class LocalAssignment < Assignment
end
end
end end

View File

@ -120,12 +120,23 @@ module Vm
Tree::ClassExpression.new(expression.children.first) Tree::ClassExpression.new(expression.children.first)
end 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 name , value = *statement
w = Vm::Tree::Assignment.new() p_name = process name
w.name = process name p_value = process(value)
w.value = process(value) clazz.new(p_name , p_value)
w
end end
end end