@Override
 protected final Optional<Expression> visitConditionalOpNode(ConditionalOpNode node) {
   if (allowsDetaches()) {
     Optional<Expression> trueBranch = visit(node.getChild(1));
     Optional<Expression> falseBranch = visit(node.getChild(2));
     // We only compile as an SVP if both branches are able to be compiled as such.  Technically,
     // we could also support cases where only one branch is compilable to an SVP, but i doubt
     // that would be that important.
     if (!trueBranch.isPresent() || !falseBranch.isPresent()) {
       return Optional.absent();
     }
     Expression condition =
         detachingExprCompiler.compile(node.getChild(0)).convert(boolean.class);
     return Optional.of(BytecodeUtils.ternary(condition, trueBranch.get(), falseBranch.get()));
   }
   return visitExprNode(node);
 }
 @Override
 protected Optional<Expression> visitNullCoalescingOpNode(NullCoalescingOpNode node) {
   // All non-trivial ?: will require detaches for the left hand side.
   if (allowsDetaches()) {
     // for '$foo ?: $bar' we always have to eagerly evaluate $foo but $bar could be lazy.
     // of course if $foo is not null, then we will need to box it, however the current support
     // for ?: in ExpressionCompiler also always boxes everything so we aren't really losing
     // anything here.
     Optional<Expression> right = visit(node.getRightChild());
     if (!right.isPresent()) {
       return Optional.absent();
     }
     Expression left =
         detachingExprCompiler.compile(node.getLeftChild()).box().cast(SoyValueProvider.class);
     return Optional.of(BytecodeUtils.firstNonNull(left, right.get()));
   }
   return visitExprNode(node);
 }