unsigned UnwrappedLineFormatter::analyzeSolutionSpace(LineState &InitialState,
                                                      bool DryRun) {
  std::set<LineState *, CompareLineStatePointers> Seen;

  // Increasing count of \c StateNode items we have created. This is used to
  // create a deterministic order independent of the container.
  unsigned Count = 0;
  QueueType Queue;

  // Insert start element into queue.
  StateNode *Node =
      new (Allocator.Allocate()) StateNode(InitialState, false, nullptr);
  Queue.push(QueueItem(OrderedPenalty(0, Count), Node));
  ++Count;

  unsigned Penalty = 0;

  // While not empty, take first element and follow edges.
  while (!Queue.empty()) {
    Penalty = Queue.top().first.first;
    StateNode *Node = Queue.top().second;
    if (!Node->State.NextToken) {
      DEBUG(llvm::dbgs() << "\n---\nPenalty for line: " << Penalty << "\n");
      break;
    }
    Queue.pop();

    // Cut off the analysis of certain solutions if the analysis gets too
    // complex. See description of IgnoreStackForComparison.
    if (Count > 10000)
      Node->State.IgnoreStackForComparison = true;

    if (!Seen.insert(&Node->State).second)
      // State already examined with lower penalty.
      continue;

    FormatDecision LastFormat = Node->State.NextToken->Decision;
    if (LastFormat == FD_Unformatted || LastFormat == FD_Continue)
      addNextStateToQueue(Penalty, Node, /*NewLine=*/false, &Count, &Queue);
    if (LastFormat == FD_Unformatted || LastFormat == FD_Break)
      addNextStateToQueue(Penalty, Node, /*NewLine=*/true, &Count, &Queue);
  }

  if (Queue.empty()) {
    // We were unable to find a solution, do nothing.
    // FIXME: Add diagnostic?
    DEBUG(llvm::dbgs() << "Could not find a solution.\n");
    return 0;
  }

  // Reconstruct the solution.
  if (!DryRun)
    reconstructPath(InitialState, Queue.top().second);

  DEBUG(llvm::dbgs() << "Total number of analyzed states: " << Count << "\n");
  DEBUG(llvm::dbgs() << "---\n");

  return Penalty;
}
Beispiel #2
0
  /// \brief Analyze the entire solution space starting from \p InitialState.
  ///
  /// This implements a variant of Dijkstra's algorithm on the graph that spans
  /// the solution space (\c LineStates are the nodes). The algorithm tries to
  /// find the shortest path (the one with lowest penalty) from \p InitialState
  /// to a state where all tokens are placed.
  void analyzeSolutionSpace(LineState &InitialState) {
    std::set<LineState> Seen;

    // Insert start element into queue.
    StateNode *Node =
        new (Allocator.Allocate()) StateNode(InitialState, false, NULL);
    Queue.push(QueueItem(OrderedPenalty(0, Count), Node));
    ++Count;

    // While not empty, take first element and follow edges.
    while (!Queue.empty()) {
      unsigned Penalty = Queue.top().first.first;
      StateNode *Node = Queue.top().second;
      if (Node->State.NextToken == NULL) {
        DEBUG(llvm::dbgs() << "\n---\nPenalty for line: " << Penalty << "\n");
        break;
      }
      Queue.pop();

      // Cut off the analysis of certain solutions if the analysis gets too
      // complex. See description of IgnoreStackForComparison.
      if (Count > 10000)
        Node->State.IgnoreStackForComparison = true;

      if (!Seen.insert(Node->State).second)
        // State already examined with lower penalty.
        continue;

      addNextStateToQueue(Penalty, Node, /*NewLine=*/false);
      addNextStateToQueue(Penalty, Node, /*NewLine=*/true);
    }

    if (Queue.empty())
      // We were unable to find a solution, do nothing.
      // FIXME: Add diagnostic?
      return;

    // Reconstruct the solution.
    reconstructPath(InitialState, Queue.top().second);
    DEBUG(llvm::dbgs() << "Total number of analyzed states: " << Count << "\n");
    DEBUG(llvm::dbgs() << "---\n");
  }