From 3d83f203ca55b82b100c06b04ea013350253c115 Mon Sep 17 00:00:00 2001 From: Torsten Ruger Date: Thu, 15 Oct 2015 09:32:47 +0300 Subject: [PATCH] fixing and testing operators --- lib/interpreter/interpreter.rb | 4 +- lib/parfait/variable.rb | 2 +- lib/phisol/compiler/field_access.rb | 2 +- lib/phisol/compiler/operator_value.rb | 26 ++++------- lib/register/builtin/kernel.rb | 6 ++- lib/register/instruction.rb | 6 --- .../instructions/register_transfer.rb | 6 ++- lib/register/register_value.rb | 5 ++- test/compiler/expressions/test_ops.rb | 45 +++++++++++++++++++ 9 files changed, 69 insertions(+), 33 deletions(-) create mode 100644 test/compiler/expressions/test_ops.rb diff --git a/lib/interpreter/interpreter.rb b/lib/interpreter/interpreter.rb index 1289c5b1..7a0c2185 100644 --- a/lib/interpreter/interpreter.rb +++ b/lib/interpreter/interpreter.rb @@ -184,7 +184,7 @@ module Interpreter rr = @instruction.right right = get_register(rr) case @instruction.operator.to_s - when "add" + when "+" result = left + right when "/" result = left / right @@ -198,7 +198,7 @@ module Interpreter raise "unimplemented '#{@instruction.operator}' #{@instruction}" end puts "#{@instruction} == #{result}" - right = set_register(rr , result) + right = set_register(@instruction.left , result) true end end diff --git a/lib/parfait/variable.rb b/lib/parfait/variable.rb index 9903370f..da847b5e 100644 --- a/lib/parfait/variable.rb +++ b/lib/parfait/variable.rb @@ -4,7 +4,7 @@ module Parfait def initialize type , name , value = nil raise "not type #{type}" unless Virtual.machine.space.get_class_by_name(type) self.type , self.name , self.value = type , name , value - self.value = 0 if self.type == :int and value == nil + self.value = 0 if self.type == :Integer and value == nil raise "must give name for variable" unless name end attributes [:type , :name, :value] diff --git a/lib/phisol/compiler/field_access.rb b/lib/phisol/compiler/field_access.rb index 7d132b64..7b9f1b02 100644 --- a/lib/phisol/compiler/field_access.rb +++ b/lib/phisol/compiler/field_access.rb @@ -11,7 +11,7 @@ module Phisol when :self index = @clazz.object_layout.variable_index(field_name) raise "field access, but no such field:#{field_name} for class #{@clazz.name}" unless index - value = use_reg(:int) #TODO, need types in layout + value = use_reg(:Integer) #TODO, need types in layout move = Register.get_slot(statement, :self , index , value ) @method.source.add_code move return value diff --git a/lib/phisol/compiler/operator_value.rb b/lib/phisol/compiler/operator_value.rb index d3895c7b..1f7e047b 100644 --- a/lib/phisol/compiler/operator_value.rb +++ b/lib/phisol/compiler/operator_value.rb @@ -4,23 +4,15 @@ module Phisol def on_operator_value statement puts "operator #{statement.inspect}" operator , left_e , right_e = *statement - left_slot = process(left_e) - right_slot = process(right_e) - puts "left #{left_slot}" - puts "right #{right_slot}" - tmp1 = use_reg :int - tmp2 = use_reg :int - get = Register.get_slot_to(statement , left_slot , tmp1 ) - get2 = Register.get_slot_to(statement , right_slot , tmp2 ) - puts "GET #{get}" - puts "GET2 #{get2}" - @method.source.add_code get - @method.source.add_code get2 - - @method.source.add_code Register::OperatorInstruction.new(statement,operator, tmp1,tmp2) - release_reg tmp2 - release_reg tmp1 - Virtual::Return.new(:int ) + # left and right must be expressions. Expressions return a register when compiled + left_reg = process(left_e) + right_reg = process(right_e) + raise "Not register #{left_reg}" unless left_reg.is_a?(Register::RegisterValue) + raise "Not register #{right_reg}" unless right_reg.is_a?(Register::RegisterValue) + puts "left #{left_reg}" + puts "right #{right_reg}" + @method.source.add_code Register::OperatorInstruction.new(statement,operator,left_reg,right_reg) + return left_reg # though this has wrong value attached end def on_assignment statement diff --git a/lib/register/builtin/kernel.rb b/lib/register/builtin/kernel.rb index 457352c1..c3e73d0e 100644 --- a/lib/register/builtin/kernel.rb +++ b/lib/register/builtin/kernel.rb @@ -49,15 +49,17 @@ module Register # This relies on linux to save and restore all registers # def save_message(function) - function.source.add_code RegisterTransfer.new(function, Register.message_reg , :r8 ) + r8 = RegisterValue.new( :r8 , :Message) + function.source.add_code RegisterTransfer.new(function, Register.message_reg , r8 ) end def restore_message(function) + r8 = RegisterValue.new( :r8 , :Message) return_tmp = Register.tmp_reg function.source.return_type # get the sys return out of the way function.source.add_code RegisterTransfer.new(function, Register.message_reg , return_tmp ) # load the stored message into the base RegisterMachine - function.source.add_code RegisterTransfer.new(function, :r8 , Register.message_reg ) + function.source.add_code RegisterTransfer.new(function, r8 , Register.message_reg ) # save the return value into the message function.source.add_code Register.set_slot( function, return_tmp , :message , :return_value ) # and "unroll" self and frame diff --git a/lib/register/instruction.rb b/lib/register/instruction.rb index c8581078..d888827f 100644 --- a/lib/register/instruction.rb +++ b/lib/register/instruction.rb @@ -30,12 +30,6 @@ module Register def assigns raise "abstract called for #{self.class}" end - - # wrap symbols into regsiter reference if needed - def wrap_register reg , type - return reg if reg.is_a? RegisterValue - RegisterValue.new(reg , type) - end end end diff --git a/lib/register/instructions/register_transfer.rb b/lib/register/instructions/register_transfer.rb index f54f87f9..a26e0f33 100644 --- a/lib/register/instructions/register_transfer.rb +++ b/lib/register/instructions/register_transfer.rb @@ -18,8 +18,10 @@ module Register # Note: this may be reversed from some assembler notations (also arm) def initialize source , from , to super(source) - @from = wrap_register(from,:int) - @to = wrap_register(to,:int) + @from = from + @to = to + raise "Fix me #{from}" unless from.is_a? RegisterValue + raise "Fix me #{to}" unless to.is_a? RegisterValue end attr_reader :from, :to diff --git a/lib/register/register_value.rb b/lib/register/register_value.rb index db266c9f..10d6e3b7 100644 --- a/lib/register/register_value.rb +++ b/lib/register/register_value.rb @@ -10,6 +10,7 @@ module Register raise "wrong type for register init #{r}" unless r.is_a? Symbol raise "double r #{r}" if r.to_s[0,1] == "rr" raise "not reg #{r}" unless self.class.look_like_reg r + raise "Legacy type error, should be class" if (type == :int) or (type == :ref) @type = type @symbol = r @value = value @@ -39,10 +40,10 @@ module Register end #helper method to calculate with register symbols - def next_reg_use type + def next_reg_use type , value = nil int = @symbol[1,3].to_i sym = "r#{int + 1}".to_sym - RegisterValue.new( sym , type) + RegisterValue.new( sym , type, value) end def sof_reference_name diff --git a/test/compiler/expressions/test_ops.rb b/test/compiler/expressions/test_ops.rb new file mode 100644 index 00000000..af68b0e0 --- /dev/null +++ b/test/compiler/expressions/test_ops.rb @@ -0,0 +1,45 @@ +require_relative "compiler_helper" + +module Virtual + class TestOps < MiniTest::Test + include CompilerHelper + + def setup + Virtual.machine.boot + @root = :operator_value + @output = Register::RegisterValue + end + + def operators + ["+" , "-" , "*" , "/" , "=="] + end + def test_ints + operators.each do |op| + @string_input = '2 + 3'.sub("+" , op) + check + end + end + def test_local_int + Virtual.machine.space.get_main.ensure_local(:bar , :Integer) + @string_input = 'bar + 3' + check + end + def test_int_local + Virtual.machine.space.get_main.ensure_local(:bar , :Integer) + @string_input = '3 + bar' + check + end + + def test_field_int + Virtual.machine.space.get_class_by_name(:Object).object_layout.add_instance_variable(:bro) + @string_input = "self.bro + 3" + check + end + + def test_int_field + Virtual.machine.space.get_class_by_name(:Object).object_layout.add_instance_variable(:bro) + @string_input = "3 + self.bro" + check + end + end +end