From e6c30d98fb5eccdc7a07a021dcff81d70fc5d3c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torsten=20R=C3=BCger?= Date: Fri, 16 Aug 2019 18:42:57 +0300 Subject: [PATCH] Fix if statements hoisting, now that send is working Same same, just have to remembe to actually execute the condition if it is a send Having send a possible expression, removes one tmp variable and associated move, for a little extra work. Next return and assign (rest) --- lib/ruby/if_statement.rb | 8 ++--- lib/vool/if_statement.rb | 9 +++-- lib/vool/return_statement.rb | 8 ++++- lib/vool/statement.rb | 4 +++ lib/vool/variables.rb | 4 +-- test/ruby/test_assignment.rb | 10 ++++-- test/ruby/test_assignment1.rb | 23 ++++--------- test/ruby/test_if_statement2.rb | 6 ++-- test/ruby/test_send_statement1.rb | 33 +++++++++++++++++++ .../{test_assign.rb => test_assignment.rb} | 0 test/vool/test_if_statement.rb | 12 +++---- 11 files changed, 80 insertions(+), 37 deletions(-) rename test/vool/{test_assign.rb => test_assignment.rb} (100%) diff --git a/lib/ruby/if_statement.rb b/lib/ruby/if_statement.rb index 4f866d06..b8ef7d77 100644 --- a/lib/ruby/if_statement.rb +++ b/lib/ruby/if_statement.rb @@ -22,10 +22,10 @@ module Ruby end def to_vool - cond , rest = *normalize_name(@condition) - me = Vool::IfStatement.new(cond.to_vool , @if_true&.to_vool, @if_false&.to_vool) - return me unless rest - Vool::Statements.new([ rest.to_vool , me]) + cond , hoisted = *normalized_vool(@condition) + me = Vool::IfStatement.new(cond , @if_true&.to_vool, @if_false&.to_vool) + return me unless hoisted + Vool::Statements.new( hoisted ) << me end def has_false? diff --git a/lib/vool/if_statement.rb b/lib/vool/if_statement.rb index 59e1970a..069224f5 100644 --- a/lib/vool/if_statement.rb +++ b/lib/vool/if_statement.rb @@ -15,8 +15,13 @@ module Vool false_label = Mom::Label.new( self , "false_label_#{object_id.to_s(16)}") merge_label = Mom::Label.new( self , "merge_label_#{object_id.to_s(16)}") - head = @condition.to_mom(compiler) if @condition.is_a?(SendStatement) - head << Mom::TruthCheck.new(condition.slot_definition(compiler) , false_label) + check = Mom::TruthCheck.new(condition.slot_definition(compiler) , false_label) + if @condition.is_a?(SendStatement) + head = @condition.to_mom(compiler) + head << check + else + head = check + end head << true_label head << if_true.to_mom(compiler) if @if_true head << Mom::Jump.new(merge_label) if @if_false diff --git a/lib/vool/return_statement.rb b/lib/vool/return_statement.rb index ae4d5928..4e028252 100644 --- a/lib/vool/return_statement.rb +++ b/lib/vool/return_statement.rb @@ -16,8 +16,14 @@ module Vool # - store the given return value, this is a SlotMove # - activate return sequence (reinstantiate old message and jump to return address) def to_mom( compiler ) - ret = Mom::SlotLoad.new( self , [:message , :return_value] , + load = Mom::SlotLoad.new( self , [:message , :return_value] , @return_value.slot_definition(compiler) ) + if @return_value.is_a?(SendStatement) + ret = @return_value.to_mom(compiler) + ret << load + else + ret = load + end ret << Mom::ReturnJump.new(self , compiler.return_label ) end diff --git a/lib/vool/statement.rb b/lib/vool/statement.rb index 38d2b4ec..8aea9849 100644 --- a/lib/vool/statement.rb +++ b/lib/vool/statement.rb @@ -56,6 +56,10 @@ module Vool raise "not iplemented in #{self}" end + def at_depth(depth , *strings) + prefix = " " * 2 * depth + strings.collect{|str| prefix + str}.join("\n") + end end end diff --git a/lib/vool/variables.rb b/lib/vool/variables.rb index 3a8e5ceb..a0977bbd 100644 --- a/lib/vool/variables.rb +++ b/lib/vool/variables.rb @@ -28,8 +28,8 @@ module Vool def add_ivar( array ) array << @name end - def to_s - "@#{name}" + def to_s(depth = 0) + at_depth(depth , "@#{name}") end end diff --git a/test/ruby/test_assignment.rb b/test/ruby/test_assignment.rb index d9bdf4e6..ed463ff2 100644 --- a/test/ruby/test_assignment.rb +++ b/test/ruby/test_assignment.rb @@ -1,7 +1,7 @@ require_relative "helper" module Ruby - class TestAssignment < MiniTest::Test + class TestAssignmentRuby < MiniTest::Test include RubyTests def test_local @@ -25,11 +25,14 @@ module Ruby assert_equal IvarAssignment , lst.class end end - class TestAssignmentVoolBar < MiniTest::Test + class TestAssignmentVoolLocal < MiniTest::Test include RubyTests def setup @lst = compile( "foo = bar").to_vool end + def test_tos + assert_equal "foo = self.bar()" , @lst.to_s + end def test_local assert_equal Vool::LocalAssignment , @lst.class end @@ -45,6 +48,9 @@ module Ruby def setup @lst = compile( "@foo = bar").to_vool end + def test_tos + assert_equal "@foo = self.bar()" , @lst.to_s + end def test_instance assert_equal Vool::IvarAssignment , @lst.class end diff --git a/test/ruby/test_assignment1.rb b/test/ruby/test_assignment1.rb index 88e2e3de..5443a5c8 100644 --- a/test/ruby/test_assignment1.rb +++ b/test/ruby/test_assignment1.rb @@ -1,26 +1,15 @@ require_relative "helper" module Ruby - class TestLocalAssignment < MiniTest::Test + class TestVoolCallMulti2 < MiniTest::Test include RubyTests - def test_local - lst = compile( "foo = bar") - assert_equal LocalAssignment , lst.class + include RubyTests + def setup + @lst = compile( "@foo = a.call(b)").to_vool end - def test_local_name - lst = compile( "foo = bar") - assert_equal :foo , lst.name + def test_s + assert_equal "" , @lst.to_s end - def test_local_const - lst = compile( "foo = 5") - assert_equal LocalAssignment , lst.class - end - def test_local_ivar - lst = compile( "foo = @iv") - assert_equal LocalAssignment , lst.class - assert_equal InstanceVariable , lst.value.class - end - end end diff --git a/test/ruby/test_if_statement2.rb b/test/ruby/test_if_statement2.rb index a2ad2682..89723c5c 100644 --- a/test/ruby/test_if_statement2.rb +++ b/test/ruby/test_if_statement2.rb @@ -24,7 +24,7 @@ module Ruby include RubyTests def setup - @lst = compile("if(a == 1) ; a = 1 end").to_vool + @lst = compile("if(foo() == 1) ; a = 1 ; end").to_vool end def test_class @@ -40,8 +40,8 @@ module Ruby assert_equal Vool::LocalAssignment , @lst.last.if_true.class end def test_condition - assert_equal Vool::LocalVariable , @lst.last.condition.class - assert_equal @lst.first.name , @lst.last.condition.name + assert_equal Vool::SendStatement , @lst.last.condition.class + assert_equal :== , @lst.last.condition.name end end diff --git a/test/ruby/test_send_statement1.rb b/test/ruby/test_send_statement1.rb index 9e72b714..8cb65c44 100644 --- a/test/ruby/test_send_statement1.rb +++ b/test/ruby/test_send_statement1.rb @@ -81,4 +81,37 @@ module Ruby assert_equal "Word_Type" , sent.receiver.ct_type.name end end + class TestSendReceiver < MiniTest::Test + include RubyTests + def setup + @lst = compile( "call.once.more").to_vool + end + def test_class + assert_equal Vool::Statements , @lst.class + end + def test_one + assert_equal Vool::LocalAssignment , @lst.first.class + end + def test_one_name + assert @lst[0].name.to_s.start_with?("tmp_") + end + def test_one_value + assert_equal :call , @lst[0].value.name + end + def test_two_name + assert @lst[1].name.to_s.start_with?("tmp_") + end + def test_two_value + assert_equal :once , @lst[1].value.name + end + def test_three_class + assert_equal Vool::SendStatement, @lst[2].class + end + def test_three_name + assert_equal :more , @lst[2].name + end + def test_three_self + assert @lst[2].receiver.name.to_s.start_with?("tmp_") + end + end end diff --git a/test/vool/test_assign.rb b/test/vool/test_assignment.rb similarity index 100% rename from test/vool/test_assign.rb rename to test/vool/test_assignment.rb diff --git a/test/vool/test_if_statement.rb b/test/vool/test_if_statement.rb index d4b659ff..5a237a14 100644 --- a/test/vool/test_if_statement.rb +++ b/test/vool/test_if_statement.rb @@ -11,19 +11,19 @@ module Vool end def test_condition - assert_equal TruthCheck , @ins.next(4).class + assert_equal TruthCheck , @ins.next(3).class end def test_condition_is_slot - assert_equal SlotDefinition , @ins.next(4).condition.class , @ins + assert_equal SlotDefinition , @ins.next(3).condition.class , @ins end - def test_hoisted_dynamic_call + def test_hoisted_call assert_equal SimpleCall , @ins.next(2).class assert_equal :div4 , @ins.next(2).method.name end def test_array - check_array [MessageSetup, ArgumentTransfer, SimpleCall, SlotLoad, TruthCheck, - Label ,SlotLoad, Jump, Label, SlotLoad, Label, - Label, ReturnSequence, Label ] , @ins + check_array [MessageSetup, ArgumentTransfer, SimpleCall, TruthCheck, Label , + SlotLoad, Jump, Label, SlotLoad, Label , + Label, ReturnSequence, Label] , @ins end end