From f9824079d6b1beca891a6694222429c6ede8d45c Mon Sep 17 00:00:00 2001 From: Torsten Ruger Date: Sun, 15 Jan 2017 13:01:28 +0200 Subject: [PATCH] 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) --- lib/vm/method_compiler/assignment.rb | 40 ++++++++++++++++++---------- lib/vm/tree/assignment.rb | 21 +++++++++++++-- lib/vm/tree/to_code.rb | 21 +++++++++++---- 3 files changed, 61 insertions(+), 21 deletions(-) diff --git a/lib/vm/method_compiler/assignment.rb b/lib/vm/method_compiler/assignment.rb index 701ba0b9..c3dbef91 100644 --- a/lib/vm/method_compiler/assignment.rb +++ b/lib/vm/method_compiler/assignment.rb @@ -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 ) diff --git a/lib/vm/tree/assignment.rb b/lib/vm/tree/assignment.rb index 32264b6e..bbb22843 100644 --- a/lib/vm/tree/assignment.rb +++ b/lib/vm/tree/assignment.rb @@ -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 diff --git a/lib/vm/tree/to_code.rb b/lib/vm/tree/to_code.rb index 3a9ba69f..17453a26 100644 --- a/lib/vm/tree/to_code.rb +++ b/lib/vm/tree/to_code.rb @@ -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