private void computeGenKill(Node n, BitSet gen, BitSet kill, boolean conditional) {

    switch (n.getToken()) {
      case SCRIPT:
      case ROOT:
      case FUNCTION:
      case BLOCK:
        return;

      case WHILE:
      case DO:
      case IF:
      case FOR:
        computeGenKill(NodeUtil.getConditionExpression(n), gen, kill, conditional);
        return;

      case FOR_OF:
      case FOR_AWAIT_OF:
      case FOR_IN:
        {
          // for (x in y) {...}
          Node lhs = n.getFirstChild();
          if (NodeUtil.isNameDeclaration(lhs)) {
            // for (var x in y) {...}
            lhs = lhs.getLastChild();
          }

          // Note that the LHS may never be assigned to or evaluated, like in:
          //   for (x in []) {}
          // so should not be killed.
          computeGenKill(lhs, gen, kill, conditional);

          // rhs is executed only once so we don't go into it every loop.
          return;
        }

      case LET:
      case CONST:
      case VAR:
        for (Node c = n.getFirstChild(); c != null; c = c.getNext()) {
          if (c.isName()) {
            if (c.hasChildren()) {
              computeGenKill(c.getFirstChild(), gen, kill, conditional);
              if (!conditional) {
                addToSetIfLocal(c, kill);
              }
            }
          } else {
            checkState(c.isDestructuringLhs(), c);
            if (!conditional) {
              Iterable<Node> allVars = NodeUtil.findLhsNodesInNode(c);
              for (Node lhsNode : allVars) {
                addToSetIfLocal(lhsNode, kill);
              }
            }
            computeGenKill(c.getFirstChild(), gen, kill, conditional);
            computeGenKill(c.getSecondChild(), gen, kill, conditional);
          }
        }
        return;

      case AND:
      case OR:
        computeGenKill(n.getFirstChild(), gen, kill, conditional);
        // May short circuit.
        computeGenKill(n.getLastChild(), gen, kill, true);
        return;

      case HOOK:
        computeGenKill(n.getFirstChild(), gen, kill, conditional);
        // Assume both sides are conditional.
        computeGenKill(n.getSecondChild(), gen, kill, true);
        computeGenKill(n.getLastChild(), gen, kill, true);
        return;

      case NAME:
        if (isArgumentsName(n)) {
          markAllParametersEscaped();
        } else if (!NodeUtil.isLhsByDestructuring(n)) {
          // Only add names in destructuring patterns if they're not lvalues.
          // e.g. "x" in "const {foo = x} = obj;"
          addToSetIfLocal(n, gen);
        }
        return;

      default:
        if (NodeUtil.isAssignmentOp(n) && n.getFirstChild().isName()) {
          Node lhs = n.getFirstChild();
          if (!conditional) {
            addToSetIfLocal(lhs, kill);
          }
          if (!n.isAssign()) {
            // assignments such as a += 1 reads a.
            addToSetIfLocal(lhs, gen);
          }
          computeGenKill(lhs.getNext(), gen, kill, conditional);
        } else if (n.isAssign() && n.getFirstChild().isDestructuringPattern()) {
          if (!conditional) {
            Iterable<Node> allVars = NodeUtil.findLhsNodesInNode(n);
            for (Node child : allVars) {
              if (child.isName()) {
                addToSetIfLocal(child, kill);
              }
            }
          }
          computeGenKill(n.getFirstChild(), gen, kill, conditional);
          computeGenKill(n.getSecondChild(), gen, kill, conditional);
        } else {
          for (Node c = n.getFirstChild(); c != null; c = c.getNext()) {
            computeGenKill(c, gen, kill, conditional);
          }
        }
        return;
    }
  }
private void computeGenKill ( Node n , BitSet gen , BitSet kill , boolean conditional ) { switch ( n . getToken ( ) ) { case SCRIPT : case ROOT : case FUNCTION : case BLOCK : return ; case WHILE : case DO : case IF : case FOR : computeGenKill ( NodeUtil . getConditionExpression ( n ) , gen , kill , conditional ) ; return ; case FOR_OF : case FOR_AWAIT_OF : case FOR_IN : { Node lhs = n . getFirstChild ( ) ; if ( NodeUtil . isNameDeclaration ( lhs ) ) { lhs = lhs . getLastChild ( ) ; } computeGenKill ( lhs , gen , kill , conditional ) ; return ; } case LET : case CONST : case VAR : for ( Node c = n . getFirstChild ( ) ; c != null ; c = c . getNext ( ) ) { if ( c . isName ( ) ) { if ( c . hasChildren ( ) ) { computeGenKill ( c . getFirstChild ( ) , gen , kill , conditional ) ; if ( ! conditional ) { addToSetIfLocal ( c , kill ) ; } } } else { checkState ( c . isDestructuringLhs ( ) , c ) ; if ( ! conditional ) { Iterable < Node > allVars = NodeUtil . findLhsNodesInNode ( c ) ; for ( Node lhsNode : allVars ) { addToSetIfLocal ( lhsNode , kill ) ; } } computeGenKill ( c . getFirstChild ( ) , gen , kill , conditional ) ; computeGenKill ( c . getSecondChild ( ) , gen , kill , conditional ) ; } } return ; case AND : case OR : computeGenKill ( n . getFirstChild ( ) , gen , kill , conditional ) ; computeGenKill ( n . getLastChild ( ) , gen , kill , true ) ; return ; case HOOK : computeGenKill ( n . getFirstChild ( ) , gen , kill , conditional ) ; computeGenKill ( n . getSecondChild ( ) , gen , kill , true ) ; computeGenKill ( n . getLastChild ( ) , gen , kill , true ) ; return ; case NAME : if ( isArgumentsName ( n ) ) { markAllParametersEscaped ( ) ; } else if ( ! NodeUtil . isLhsByDestructuring ( n ) ) { addToSetIfLocal ( n , gen ) ; } return ; default : if ( NodeUtil . isAssignmentOp ( n ) && n . getFirstChild ( ) . isName ( ) ) { Node lhs = n . getFirstChild ( ) ; if ( ! conditional ) { addToSetIfLocal ( lhs , kill ) ; } if ( ! n . isAssign ( ) ) { addToSetIfLocal ( lhs , gen ) ; } computeGenKill ( lhs . getNext ( ) , gen , kill , conditional ) ; } else if ( n . isAssign ( ) && n . getFirstChild ( ) . isDestructuringPattern ( ) ) { if ( ! conditional ) { Iterable < Node > allVars = NodeUtil . findLhsNodesInNode ( n ) ; for ( Node child : allVars ) { if ( child . isName ( ) ) { addToSetIfLocal ( child , kill ) ; } } } computeGenKill ( n . getFirstChild ( ) , gen , kill , conditional ) ; computeGenKill ( n . getSecondChild ( ) , gen , kill , conditional ) ; } else { for ( Node c = n . getFirstChild ( ) ; c != null ; c = c . getNext ( ) ) { computeGenKill ( c , gen , kill , conditional ) ; } } return ; } }
Computes the GEN and KILL set.

@param n Root node.
@param gen Local variables that are live because of the instruction at {@code n} will be added
to this set.
@param kill Local variables that are killed because of the instruction at {@code n} will be
added to this set.
@param conditional {@code true} if any assignments encountered are conditionally executed.
These assignments might not kill a variable.