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 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)
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 )
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)
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
raise "Type mismatch for #{type} access #{value.type}!=#{value_type}" unless value.type == value_type
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 )

View File

@ -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

View File

@ -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