class Opal::Nodes::IfNode

def compile

def compile
  if should_compile_as_simple_expression?
    if true_body == s(:true)
      compile_with_binary_or
    elsif false_body == s(:false)
      compile_with_binary_and
    else
      compile_with_ternary
    end
  else
    compile_with_if
  end
end

def compile_with_binary_and

def compile_with_binary_and
  if sexp.meta[:do_js_truthy_on_true_body]
    truthy = js_truthy(true_body || s(:nil))
  else
    truthy = expr(true_body || s(:nil))
  end
  push '('
  push js_truthy(test), ' && '
  push '(', truthy, ')'
  push ')'
end

def compile_with_binary_or

def compile_with_binary_or
  if sexp.meta[:do_js_truthy_on_false_body]
    falsy = js_truthy(false_body || s(:nil))
  else
    falsy = expr(false_body || s(:nil))
  end
  push '('
  push js_truthy(test), ' || '
  push '(', falsy, ')'
  push ')'
end

def compile_with_if

def compile_with_if
  truthy = self.truthy
  falsy = self.falsy
  if falsy && !truthy
    # Let's optimize a little bit `unless` calls.
    push 'if (!', js_truthy(test), ') {'
    falsy, truthy = truthy, falsy
  else
    push 'if (', js_truthy(test), ') {'
  end
  # skip if-body if no truthy sexp
  indent { line stmt(truthy) } if truthy
  if falsy
    if falsy.type == :if
      line '} else ', stmt(falsy)
    else
      line '} else {'
      indent do
        line stmt(falsy)
      end
      line '}'
    end
  else
    line '}'
    # This resolution isn't finite. Let's ensure this block
    # always return something if we expect a return
    line 'return nil;' if expects_expression?
  end
  if expects_expression?
    if scope.await_encountered
      wrap '(await (async function() {', '})())'
    else
      wrap '(function() {', '})()'
    end
  end
end

def compile_with_ternary

def compile_with_ternary
  truthy = true_body
  falsy = false_body
  push '('
  push js_truthy(test), ' ? '
  push '(', expr(truthy || s(:nil)), ') : '
  if !falsy || falsy.type == :if
    push expr(falsy || s(:nil))
  else
    push '(', expr(falsy || s(:nil)), ')'
  end
  push ')'
end

def expects_expression?

def expects_expression?
  expr? || recv?
end

def falsy

def falsy
  returnify(false_body)
end

def returnify(body)

def returnify(body)
  if expects_expression? && body
    compiler.returns(body)
  else
    body
  end
end

def should_compile_as_simple_expression?

even?
a ternary operator instead and possibly a binary operator
This addition tries to make a few cases compiled with
it. This produced an ugly code that was hard to minify.
expected an expression from if, we always had to closure
There was a particular case in the past, that when we
def should_compile_as_simple_expression?
  expects_expression? && simple?(true_body) && simple?(false_body)
end

def simple?(body)

Let's ensure there are no control flow statements inside.
def simple?(body)
  case body
  when AST::Node
    case body.type
    when :return, :js_return, :break, :next, :redo, :retry
      false
    when :xstr
      XStringNode.single_line?(
        XStringNode.strip_empty_children(body.children)
      )
    else
      body.children.all? { |i| simple?(i) }
    end
  else
    true
  end
end

def truthy

def truthy
  returnify(true_body)
end