From 7e60827dd30881acaa143c78dcccff35264506e6 Mon Sep 17 00:00:00 2001 From: Torsten Ruger Date: Wed, 13 Aug 2014 20:05:32 +0300 Subject: [PATCH] redoing the ifs with new (old) block structure --- lib/ast/call_site_expression.rb | 2 +- lib/ast/if_expression.rb | 34 ++++++++++++++++++++++----------- lib/boot/object.rb | 4 ++-- lib/salama.rb | 1 + lib/virtual/instruction.rb | 21 ++++++++------------ test/virtual/test_methods.rb | 2 +- test/virtual/virtual_helper.rb | 2 +- 7 files changed, 37 insertions(+), 29 deletions(-) diff --git a/lib/ast/call_site_expression.rb b/lib/ast/call_site_expression.rb index 42aaec35..1c84789a 100644 --- a/lib/ast/call_site_expression.rb +++ b/lib/ast/call_site_expression.rb @@ -48,7 +48,7 @@ module Ast call.do_call into after = into.new_block("#{name}#{@@counter+=1}") - into.insert_at after + into.current after into.pop([]) unless current_function.nil? function.return_type end diff --git a/lib/ast/if_expression.rb b/lib/ast/if_expression.rb index 98bf0d4e..9f1b1127 100644 --- a/lib/ast/if_expression.rb +++ b/lib/ast/if_expression.rb @@ -1,28 +1,40 @@ module Ast class IfExpression < Expression # attr_reader :cond, :if_true, :if_false + def compile method , message + # to execute the logic as the if states it, the blocks are the other way around + # so we can the jump over the else if true ,and the else joins unconditionally after the true_block + merge_block = method.new_block "if_merge" # last one, created first + true_block = method.new_block "if_true" # second, linked in after current, before merge + false_block = method.new_block "if_false" # directly next in order, ie if we don't jump we land here + + is = cond.compile(method,message) - # is.is_false(frame,method) # TODO should/will use different branches for different conditions. - branch = Virtual::ImplicitBranch.new "if_merge" - method.add_code branch + # just a scetch : cond_val = cond_val.is_true?(method) unless cond_val.is_a? Virtual::BranchCondition + method.add_code Virtual::ImplicitBranch.new( true_block ) + + # compile the true block (as we think of it first, even it is second in sequential order) + method.current true_block last = is if_true.each do |part| last = part.compile(method,message ) raise part.inspect if last.nil? end - merge = Virtual::Label.new(branch.name) - method.add_code merge - branch.swap - method.current = branch + + # compile the false block + method.current false_block if_false.each do |part| - last = part.compile(method,message ) + puts "compiling in if false #{part}" + last = part.compile(method,message) raise part.inspect if last.nil? end - method.add_code merge - branch.swap - method.current = merge + method.add_code Virtual::UnconditionalBranch.new( merge_block ) + + puts "compiled if: end" + method.current merge_block + #TODO should return the union of the true and false types last end diff --git a/lib/boot/object.rb b/lib/boot/object.rb index 5e334a58..3c3513cb 100644 --- a/lib/boot/object.rb +++ b/lib/boot/object.rb @@ -34,7 +34,7 @@ module Boot index = get_function.call( index_function ) after_body = get_function.new_block("after_index") - get_function.insert_at after_body + get_function.current after_body get_function.pop([me]) return_to.at_index( get_function , me , return_to ) @@ -55,7 +55,7 @@ module Boot set_function.call( index_function ) after_body = set_function.new_block("after_index") - set_function.insert_at after_body + set_function.current after_body set_function.pop([me]) return_to.at_index( set_function , me , return_to ) set_function.set_return return_to diff --git a/lib/salama.rb b/lib/salama.rb index 65f51577..f957989e 100644 --- a/lib/salama.rb +++ b/lib/salama.rb @@ -5,3 +5,4 @@ require 'salama-reader' require 'parser/transform' require "virtual/machine" require "ast/all" +require "sof/all" \ No newline at end of file diff --git a/lib/virtual/instruction.rb b/lib/virtual/instruction.rb index e792a89f..a4049ca4 100644 --- a/lib/virtual/instruction.rb +++ b/lib/virtual/instruction.rb @@ -53,22 +53,14 @@ module Virtual class MethodReturn < Instruction end - # the next instruction represents the "true" branch and the other is the .... other - # could have been the false, but false is a keyword and is asymetric to next anyway - # this is an abstract base class (though no measures are taken to prevent instantiation) and derived - # class names indicate the actual test + # a branch must branch to a block. This is an abstract class, names indicate the actual test class Branch < Instruction - def initialize name , other = nil - unless(name.to_s.split("_").last.to_i > 0) - name = "#{name}_#{name.to_i(36) % 65536}".to_sym - end - @name = name - @other = other + def initialize to + @to = to end - attr_reader :name - attr_accessor :other + attr_reader :to def attributes - [:name , :other] + [:to] end end @@ -77,6 +69,9 @@ module Virtual class ImplicitBranch < Branch end + class UnconditionalBranch < Branch + end + class MessageGet < Instruction include Named end diff --git a/test/virtual/test_methods.rb b/test/virtual/test_methods.rb index 7fa0d781..efe4a714 100644 --- a/test/virtual/test_methods.rb +++ b/test/virtual/test_methods.rb @@ -40,7 +40,7 @@ def foo() 2 + 5 end HERE - @output = "" + @output = "---RETURN_MARKER- &1 !ruby/object:Virtual::MethodDefinitionRETURN_MARKER name: :fooRETURN_MARKER args: []RETURN_MARKER locals: []RETURN_MARKER tmps: []RETURN_MARKER receiver: !ruby/object:Virtual::SelfReferenceRETURN_MARKER clazz: RETURN_MARKER return_type: !ruby/object:Virtual::ReturnRETURN_MARKER name: :returnRETURN_MARKER type: !ruby/class 'Virtual::Mystery'RETURN_MARKER blocks:RETURN_MARKER - &2 !ruby/object:Virtual::BlockRETURN_MARKER method: *1RETURN_MARKER name: :fooRETURN_MARKER branch: RETURN_MARKER codes:RETURN_MARKER - !ruby/object:Virtual::MethodEnter {}RETURN_MARKER - !ruby/object:Virtual::LoadSelfRETURN_MARKER value: !ruby/object:Virtual::IntegerConstantRETURN_MARKER integer: 2RETURN_MARKER - !ruby/object:Virtual::MessageSendRETURN_MARKER name: :+RETURN_MARKER args:RETURN_MARKER - !ruby/object:Virtual::IntegerConstantRETURN_MARKER integer: 5RETURN_MARKER - !ruby/object:Virtual::BlockRETURN_MARKER method: *1RETURN_MARKER name: :foo_returnRETURN_MARKER branch: RETURN_MARKER codes:RETURN_MARKER - !ruby/object:Virtual::MethodReturn {}RETURN_MARKER current: *2RETURN_MARKER" check end diff --git a/test/virtual/virtual_helper.rb b/test/virtual/virtual_helper.rb index 7f44ff1e..08a31487 100644 --- a/test/virtual/virtual_helper.rb +++ b/test/virtual/virtual_helper.rb @@ -11,7 +11,7 @@ module VirtualHelper machine = Virtual::Machine.boot expressions = machine.compile_main @string_input should = YAML.load(@output.gsub("RETURN_MARKER" , "\n")) - assert_equal should , expressions , expressions.to_yaml.gsub("\n" , "RETURN_MARKER") + "\n" + expressions.to_yaml.gsub("!ruby/object:","") + assert_equal should , expressions , expressions.to_yaml.gsub("\n" , "RETURN_MARKER") + "\n" + Sof::Members.write(expressions) end end