/**
   * Translate a single linear path to code.
   *
   * @param pPath the path to translate
   * @param callback A callback that receives each <code>ARGState</code> along with their edges and
   *     can then determine what code to generate from it. The default behavior of a <code>
   *     ProcessEdgeFunction</code> is to call {@link #processEdge(ARGState, CFAEdge, Stack)}
   */
  protected void translateSinglePath0(ARGPath pPath, EdgeVisitor callback) {
    assert pPath.size() >= 1;

    PathIterator pathIt = pPath.fullPathIterator();
    ARGState firstElement = pathIt.getAbstractState();

    Stack<FunctionBody> functionStack = new Stack<>();

    // create the first function and put in into the stack
    startFunction(firstElement, functionStack, extractFunctionCallLocation(firstElement));

    while (pathIt.hasNext()) {
      pathIt.advance();

      CFAEdge currentCFAEdge = pathIt.getIncomingEdge();
      ARGState childElement;
      if (pathIt.isPositionWithState()) {
        childElement = pathIt.getAbstractState();
      } else {
        childElement = pathIt.getPreviousAbstractState();
      }

      callback.visit(childElement, currentCFAEdge, functionStack);
    }
  }
  /**
   * After a path was strengthened, we need to take care of the coverage relation. We also remove
   * the infeasible part from the ARG, and re-establish the coverage invariant (i.e., that states on
   * the path are either covered or cannot be covered).
   */
  @Override
  protected void finishRefinementOfPath(
      ARGState infeasiblePartOfART,
      List<ARGState> changedElements,
      ARGReachedSet pReached,
      boolean pRepeatedCounterexample)
      throws CPAException, InterruptedException {
    // only thing to do here is adding the false predicate for unreacheable states
    newPredicates.put(extractLocation(infeasiblePartOfART), predAbsMgr.makeFalsePredicate());
    changedElements.add(infeasiblePartOfART);

    if (restartAfterRefinement) {
      refinementRoot = (ARGState) reached.asReachedSet().getFirstState();

    } else if (refinementRoot == null) {
      refinementRoot = changedElements.get(0);

      // search parent of both refinement roots and use this as the new
      // refinement root
    } else {
      PathIterator firstPath = ARGUtils.getOnePathTo(refinementRoot).pathIterator();
      PathIterator secondPath = ARGUtils.getOnePathTo(changedElements.get(0)).pathIterator();

      // TODO should they be equal or identical?
      while (firstPath.getAbstractState().equals(secondPath.getAbstractState())) {
        refinementRoot = firstPath.getAbstractState();

        if (firstPath.hasNext() && secondPath.hasNext()) {
          firstPath.advance();
          secondPath.advance();
        } else {
          break;
        }
      }
    }
  }