/**
  * Add the given CFG node to the node map.
  *
  * @param nodeMap
  * @param cfgNode
  */
 private static <N> void registerCfgNode(Map<N, Set<ICFGNode<N>>> nodeMap, ICFGNode<N> cfgNode) {
   N astnode = cfgNode.getASTNode();
   if (astnode == null) return;
   Set<ICFGNode<N>> cfgnodes = nodeMap.get(astnode);
   if (cfgnodes == null) {
     cfgnodes = new HashSet<ICFGNode<N>>();
     nodeMap.put(astnode, cfgnodes);
   }
   cfgnodes.add(cfgNode);
 }
  /**
   * Builds a post-order comparator for the nodes in the given CFG, in which a node is bigger than
   * all of its successors (predecessors) if <code>isForward</code> is <code>true</code> (<code>
   * false</code>), and populates a map from AST nodes to all their corresponding nodes in the given
   * CFG.
   *
   * @param cfg
   * @param nodeMap Node map to be populated (will not be cleared).
   * @param isForward If <code>true</code> the CFG is traversed in the forward direction, meaning
   *     starting from the {@link IControlFlowGraph#getStartNode() start node} following {@link
   *     ICFGNode#getOutputs() outgoing edges}; if <code>false</code> the traversal direction is
   *     reversed, meaning traversal starts from the {@link IControlFlowGraph#getEndNode() end node}
   *     and follows {@link ICFGNode#getInputs() incoming edges}.
   * @return Post-order comparator for the nodes in the given CFG
   */
  public static <N> WorklistNodeOrderComparator createPostOrderAndPopulateNodeMap(
      final IControlFlowGraph<N> cfg,
      final Map<N, Set<ICFGNode<N>>> nodeMap,
      final boolean isForward) {
    Map<ICFGNode<?>, Integer> order = new HashMap<ICFGNode<?>, Integer>();

    // iterative post-order visit / depth-first search (DFS)
    // "visits" (numbers) nodes after all their children are
    // visited (ie., when nodes become "black")
    int cur = 0;
    LinkedList<Object> spine = new LinkedList<Object>();
    ICFGNode<N> node = isForward ? cfg.getStartNode() : cfg.getEndNode();
    order.put(node, null);
    spine.addFirst(node);
    spine.addFirst((isForward ? node.getOutputs() : node.getInputs()).iterator());

    newNode:
    while (spine.isEmpty() == false) {
      Iterator<ICFGEdge<N>> it = (Iterator<ICFGEdge<N>>) spine.peek();
      while (it.hasNext()) {
        node = isForward ? it.next().getSink() : it.next().getSource();
        if (order.containsKey(node) == false) {
          order.put(node, null);
          spine.addFirst(node);
          spine.addFirst((isForward ? node.getOutputs() : node.getInputs()).iterator());
          continue newNode;
        }
      }
      spine.removeFirst();
      node = (ICFGNode<N>) spine.removeFirst();
      // number nodes in increasing order
      if (order.put(node, cur++) != null)
        throw new IllegalStateException("Node already visited: " + node);
      // also register node so that we can find it given its AST node
      registerCfgNode(nodeMap, node);
    }

    //		visitPostOrder(cfg.getStartNode(), order, Integer.MAX_VALUE);
    return new WorklistNodeOrderComparator(order);
  }