redoing the ifs with new (old) block structure

This commit is contained in:
Torsten Ruger 2014-08-13 20:05:32 +03:00
parent 90cbeddc0a
commit 7e60827dd3
7 changed files with 37 additions and 29 deletions

View File

@ -48,7 +48,7 @@ module Ast
call.do_call into call.do_call into
after = into.new_block("#{name}#{@@counter+=1}") after = into.new_block("#{name}#{@@counter+=1}")
into.insert_at after into.current after
into.pop([]) unless current_function.nil? into.pop([]) unless current_function.nil?
function.return_type function.return_type
end end

View File

@ -1,28 +1,40 @@
module Ast module Ast
class IfExpression < Expression class IfExpression < Expression
# attr_reader :cond, :if_true, :if_false # attr_reader :cond, :if_true, :if_false
def compile method , message 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 = cond.compile(method,message)
# is.is_false(frame,method)
# TODO should/will use different branches for different conditions. # TODO should/will use different branches for different conditions.
branch = Virtual::ImplicitBranch.new "if_merge" # just a scetch : cond_val = cond_val.is_true?(method) unless cond_val.is_a? Virtual::BranchCondition
method.add_code branch 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 last = is
if_true.each do |part| if_true.each do |part|
last = part.compile(method,message ) last = part.compile(method,message )
raise part.inspect if last.nil? raise part.inspect if last.nil?
end end
merge = Virtual::Label.new(branch.name)
method.add_code merge # compile the false block
branch.swap method.current false_block
method.current = branch
if_false.each do |part| 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? raise part.inspect if last.nil?
end end
method.add_code merge method.add_code Virtual::UnconditionalBranch.new( merge_block )
branch.swap
method.current = merge puts "compiled if: end"
method.current merge_block
#TODO should return the union of the true and false types #TODO should return the union of the true and false types
last last
end end

View File

@ -34,7 +34,7 @@ module Boot
index = get_function.call( index_function ) index = get_function.call( index_function )
after_body = get_function.new_block("after_index") after_body = get_function.new_block("after_index")
get_function.insert_at after_body get_function.current after_body
get_function.pop([me]) get_function.pop([me])
return_to.at_index( get_function , me , return_to ) return_to.at_index( get_function , me , return_to )
@ -55,7 +55,7 @@ module Boot
set_function.call( index_function ) set_function.call( index_function )
after_body = set_function.new_block("after_index") after_body = set_function.new_block("after_index")
set_function.insert_at after_body set_function.current after_body
set_function.pop([me]) set_function.pop([me])
return_to.at_index( set_function , me , return_to ) return_to.at_index( set_function , me , return_to )
set_function.set_return return_to set_function.set_return return_to

View File

@ -5,3 +5,4 @@ require 'salama-reader'
require 'parser/transform' require 'parser/transform'
require "virtual/machine" require "virtual/machine"
require "ast/all" require "ast/all"
require "sof/all"

View File

@ -53,22 +53,14 @@ module Virtual
class MethodReturn < Instruction class MethodReturn < Instruction
end end
# the next instruction represents the "true" branch and the other is the .... other # a branch must branch to a block. This is an abstract class, names indicate the actual test
# 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
class Branch < Instruction class Branch < Instruction
def initialize name , other = nil def initialize to
unless(name.to_s.split("_").last.to_i > 0) @to = to
name = "#{name}_#{name.to_i(36) % 65536}".to_sym
end
@name = name
@other = other
end end
attr_reader :name attr_reader :to
attr_accessor :other
def attributes def attributes
[:name , :other] [:to]
end end
end end
@ -77,6 +69,9 @@ module Virtual
class ImplicitBranch < Branch class ImplicitBranch < Branch
end end
class UnconditionalBranch < Branch
end
class MessageGet < Instruction class MessageGet < Instruction
include Named include Named
end end

View File

@ -40,7 +40,7 @@ def foo()
2 + 5 2 + 5
end end
HERE 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 check
end end

View File

@ -11,7 +11,7 @@ module VirtualHelper
machine = Virtual::Machine.boot machine = Virtual::Machine.boot
expressions = machine.compile_main @string_input expressions = machine.compile_main @string_input
should = YAML.load(@output.gsub("RETURN_MARKER" , "\n")) 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
end end