module Sol
  class IfStatement < Statement

    attr_reader :condition , :if_true , :if_false

    def initialize( cond , if_true , if_false = nil)
      @condition = cond
      @if_true = if_true
      @if_false = if_false
    end

    def to_slot( compiler )
      true_label  = SlotMachine::Label.new( self , "true_label_#{object_id.to_s(16)}")
      false_label = SlotMachine::Label.new( self , "false_label_#{object_id.to_s(16)}")
      merge_label = SlotMachine::Label.new( self , "merge_label_#{object_id.to_s(16)}")

      if @condition.is_a?(CallStatement)
        head = @condition.to_slot(compiler)
        head << check_slot(compiler , false_label)
      else
        head = check_slot(compiler , false_label)
      end
      head << true_label
      head << if_true.to_slot(compiler)   if @if_true
      head << SlotMachine::Jump.new(merge_label) if @if_false
      head << false_label
      head << if_false.to_slot(compiler)  if @if_false
      head << merge_label                if @if_false
      head
    end

    # create the slot lazily, so to_slot gets called first
    def check_slot(compiler , false_label)
      SlotMachine::TruthCheck.new(@condition.to_slotted(compiler) , false_label)
    end

    def each(&block)
      block.call(condition)
      @if_true.each(&block) if @if_true
      @if_false.each(&block) if @if_false
    end

    def has_false?
      @if_false != nil
    end

    def has_true?
      @if_true != nil
    end

    def to_s(depth = 0)
      parts =  "if (#{@condition.to_s(0)})\n"
      parts += "  #{@if_true}\n" if @if_true
      parts += "else\n" if(@if_false)
      parts += "  #{@if_false}\n" if(@if_false)
      parts += "end\n"
      at_depth(depth , parts )
    end
  end
end