private boolean trySimplifyUnusedResultInternal(Node tree, ArrayDeque<Node> sideEffectRoots) {
    // Special cases for conditional expressions that may be using results.
    switch (tree.getToken()) {
      case HOOK:
        // Try to remove one or more of the conditional children and transform the HOOK to an
        // equivalent operation. Remember that if either value branch still exists, the result of
        // the predicate expression is being used, and so cannot be removed.
        //    x() ? foo() : 1 --> x() && foo()
        //    x() ? 1 : foo() --> x() || foo()
        //    x() ? 1 : 1 --> x()
        //    x ? 1 : 1 --> null

        Node trueNode = trySimplifyUnusedResult(tree.getSecondChild());
        Node falseNode = trySimplifyUnusedResult(tree.getLastChild());
        if (trueNode == null && falseNode != null) {
          checkState(tree.hasTwoChildren(), tree);

          tree.setToken(Token.OR);
          sideEffectRoots.addLast(tree);
          return false; // The node type was changed.
        } else if (trueNode != null && falseNode == null) {
          checkState(tree.hasTwoChildren(), tree);

          tree.setToken(Token.AND);
          sideEffectRoots.addLast(tree);
          return false; // The node type was changed.
        } else if (trueNode == null && falseNode == null) {
          // Don't bother adding true and false branch children to make the AST valid; this HOOK is
          // going to be deleted. We just need to collect any side-effects from the predicate
          // expression.
          trySimplifyUnusedResultInternal(tree.getOnlyChild(), sideEffectRoots);
          return false; // This HOOK must be cleaned up.
        } else {
          sideEffectRoots.addLast(tree);
          return hasFixedPointParent(tree);
        }

      case AND:
      case OR:
        // Try to remove the second operand from a AND or OR operations. Remember that if the second
        // child still exists, the result of the first expression is being used, and so cannot be
        // removed.
        //    x() || f --> x()
        //    x() && f --> x()

        Node conditionalResultNode = trySimplifyUnusedResult(tree.getLastChild());
        if (conditionalResultNode == null) {
          // Don't bother adding a second child to make the AST valid; this op is going to be
          // deleted. We just need to collect any side-effects from the predicate first child.
          trySimplifyUnusedResultInternal(tree.getOnlyChild(), sideEffectRoots);
          return false; // This op must be cleaned up.
        } else {
          sideEffectRoots.addLast(tree);
          return hasFixedPointParent(tree);
        }

      case FUNCTION:
        // Functions that aren't being invoked are dead. If they were invoked we'd see the CALL
        // before arriving here. We don't want to look at any children since they'll never execute.
        return false;

      default:
        // This is the meat of this function. It covers the general case of nodes which are unused
        if (nodeTypeMayHaveSideEffects(tree)) {
          sideEffectRoots.addLast(tree);
          return hasFixedPointParent(tree);
        } else if (!tree.hasChildren()) {
          return false; // A node must have children or side-effects to be at fixed-point.
        }

        boolean atFixedPoint = hasFixedPointParent(tree);
        for (Node child = tree.getFirstChild(); child != null; child = child.getNext()) {
          atFixedPoint &= trySimplifyUnusedResultInternal(child, sideEffectRoots);
        }
        return atFixedPoint;
    }
  }
private boolean trySimplifyUnusedResultInternal ( Node tree , ArrayDeque < Node > sideEffectRoots ) { switch ( tree . getToken ( ) ) { case HOOK : Node trueNode = trySimplifyUnusedResult ( tree . getSecondChild ( ) ) ; Node falseNode = trySimplifyUnusedResult ( tree . getLastChild ( ) ) ; if ( trueNode == null && falseNode != null ) { checkState ( tree . hasTwoChildren ( ) , tree ) ; tree . setToken ( Token . OR ) ; sideEffectRoots . addLast ( tree ) ; return false ; } else if ( trueNode != null && falseNode == null ) { checkState ( tree . hasTwoChildren ( ) , tree ) ; tree . setToken ( Token . AND ) ; sideEffectRoots . addLast ( tree ) ; return false ; } else if ( trueNode == null && falseNode == null ) { trySimplifyUnusedResultInternal ( tree . getOnlyChild ( ) , sideEffectRoots ) ; return false ; } else { sideEffectRoots . addLast ( tree ) ; return hasFixedPointParent ( tree ) ; } case AND : case OR : Node conditionalResultNode = trySimplifyUnusedResult ( tree . getLastChild ( ) ) ; if ( conditionalResultNode == null ) { trySimplifyUnusedResultInternal ( tree . getOnlyChild ( ) , sideEffectRoots ) ; return false ; } else { sideEffectRoots . addLast ( tree ) ; return hasFixedPointParent ( tree ) ; } case FUNCTION : return false ; default : if ( nodeTypeMayHaveSideEffects ( tree ) ) { sideEffectRoots . addLast ( tree ) ; return hasFixedPointParent ( tree ) ; } else if ( ! tree . hasChildren ( ) ) { return false ; } boolean atFixedPoint = hasFixedPointParent ( tree ) ; for ( Node child = tree . getFirstChild ( ) ; child != null ; child = child . getNext ( ) ) { atFixedPoint &= trySimplifyUnusedResultInternal ( child , sideEffectRoots ) ; } return atFixedPoint ; } }
Collects any potentially side-effectful subtrees within {@code tree} into {@code
sideEffectRoots}.

<p>When a node is determined to have side-effects its descendants are not explored. This method
assumes the entire subtree of such a node must be preserved. As a corollary, the contents of
{@code sideEffectRoots} are a forest.

<p>This operation generally does not mutate {@code tree}; however, exceptions are made for
expressions that alter control-flow. Such expression will be pruned of their side-effectless
branches. Even in this case, {@code tree} is never detached.

@param sideEffectRoots The roots of subtrees determined to have side-effects, in execution
order.
@return {@code true} iff there is no code to be removed from within {@code tree}; it is already
at a fixed point for code removal.