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