@@ -29,9 +29,10 @@ trait PhaseAssembly {
29
29
*/
30
30
def computePhaseAssembly (): List [SubComponent ] = {
31
31
require(phasesSet.exists(phase => phase.initial || phase.phaseName == DependencyGraph .Parser ), " Missing initial phase" )
32
- if (! phasesSet.exists(phase => phase.terminal || phase.phaseName == DependencyGraph .Terminal ))
33
- if (phasesSet.add(terminal))
34
- reporter.warning(NoPosition , " Added default terminal phase" )
32
+ if (! phasesSet.exists(phase => phase.terminal || phase.phaseName == DependencyGraph .Terminal )) {
33
+ phasesSet.add(terminal)
34
+ reporter.warning(NoPosition , " Added default terminal phase" )
35
+ }
35
36
val graph = DependencyGraph (phasesSet)
36
37
for (n <- settings.genPhaseGraph.valueSetByUser; d <- settings.outputDirs.getSingleOutput if ! d.isVirtual)
37
38
DependencyGraph .graphToDotFile(graph, Path (d.file) / File (s " $n.dot " ))
@@ -60,8 +61,8 @@ class DependencyGraph(order: Int, start: String, val components: Map[String, Sub
60
61
61
62
// phase names and their vertex index
62
63
private val nodeCount = new AtomicInteger
63
- private val nodes = mutable.HashMap .empty[String , Int ]
64
- private val names = Array .ofDim[String ](order)
64
+ private val nodes = mutable.HashMap .empty[String , Int ] // name to index
65
+ private val names = Array .ofDim[String ](order) // index to name
65
66
66
67
/** Add the edge between named phases, where `to` follows `from`.
67
68
*/
@@ -74,11 +75,11 @@ class DependencyGraph(order: Int, start: String, val components: Map[String, Sub
74
75
}
75
76
val v = getNode(from)
76
77
val w = getNode(to)
77
- adjacency(v).find(e => e.from == v && e .to == w) match {
78
+ adjacency(v).find(_ .to == w) match {
78
79
case None =>
79
80
adjacency(v) ::= Edge (from = v, to = w, weight)
80
- case Some (e ) if weight == FollowsNow => // retain runsRightAfter if there is a competing constraint
81
- adjacency(v) = Edge (from = v, to = w, weight) :: adjacency(v).filterNot(e => e.from == v && e .to == w)
81
+ case Some (_ ) if weight == FollowsNow => // retain runsRightAfter if there is a competing constraint
82
+ adjacency(v) = Edge (from = v, to = w, weight) :: adjacency(v).filterNot(_ .to == w)
82
83
case _ =>
83
84
}
84
85
}
@@ -157,9 +158,11 @@ class DependencyGraph(order: Int, start: String, val components: Map[String, Sub
157
158
// if (debugging) println(s"deq ${names(v)}")
158
159
for (e <- adjacency(v)) {
159
160
val w = e.to
161
+ /* cannot happen as `runsRightAfter: Option[String]` is the only way to introduce a `FollowsNow`
160
162
val e2 = edgeTo(w)
161
163
if (e.weight == FollowsNow && e2 != null && e2.weight == FollowsNow && e.from != e2.from)
162
164
throw new FatalError(s"${names(w)} cannot follow right after both ${names(e.from)} and ${names(e2.from)}")
165
+ */
163
166
if (distance(w) < distance(v) + e.weight) {
164
167
distance(w) = distance(v) + e.weight
165
168
edgeTo(w) = e
@@ -172,36 +175,38 @@ class DependencyGraph(order: Int, start: String, val components: Map[String, Sub
172
175
}
173
176
/** Put the vertices in a linear order.
174
177
*
178
+ * `Follows` edges increase the level, `FollowsNow` don't.
175
179
* Partition by "level" or distance from start.
176
- * Partition the level into "anchors" that follow a node in the previous level, and "followers".
177
- * Starting with the "ends", which are followers without a follower in the level,
178
- * construct paths back to the anchors. The anchors are sorted by name only.
180
+ * Partition the level into "anchors" that follow a node in the previous level, and "followers" (nodes
181
+ * with a `FollowsNow` edge).
182
+ * Starting at the "ends", build the chains of `FollowsNow` nodes within the level. Each chain leads to an anchor.
183
+ * The anchors are sorted by name, then the chains are flattened.
179
184
*/
180
185
def traverse (): List [SubComponent ] = {
181
186
def componentOf (i : Int ) = components(names(i))
182
187
def sortComponents (c : SubComponent , d : SubComponent ): Boolean =
188
+ // sort by name only, like the old implementation (pre scala/scala#10687)
183
189
/* c.internal && !d.internal ||*/ c.phaseName.compareTo(d.phaseName) < 0
184
190
def sortVertex (i : Int , j : Int ): Boolean = sortComponents(componentOf(i), componentOf(j))
185
191
186
192
distance.zipWithIndex.groupBy(_._1).toList.sortBy(_._1)
187
193
.flatMap { case (d, dis) =>
188
194
val vs = dis.map { case (_, i) => i }
189
- val (anchors, followers) = vs.partition(v => edgeTo(v) == null || distance( edgeTo(v).from) != d )
195
+ val (anchors, followers) = vs.partition(v => edgeTo(v) == null || edgeTo(v).weight != FollowsNow )
190
196
// if (debugging) println(s"d=$d, anchors=${anchors.toList.map(n => names(n))}, followers=${followers.toList.map(n => names(n))}")
191
197
if (followers.isEmpty)
192
198
anchors.toList.map(componentOf).sortWith(sortComponents)
193
199
else {
194
- // find phases which are not the source of an edgeTo, then construct paths at this level distance
195
200
val froms = followers.map(v => edgeTo(v).from).toSet
196
201
val ends = followers.iterator.filterNot(froms).toList
197
- val followed : Array [ArrayDeque [Int ]] = anchors.map(ArrayDeque (_))
202
+ val chains : Array [ArrayDeque [Int ]] = anchors.map(ArrayDeque (_))
198
203
def drill (v : Int , path : List [Int ]): Unit =
199
204
edgeTo(v) match {
200
- case e if e != null && distance(e.from) == d => drill(e.from, v :: path)
201
- case _ => followed .find(_.apply(0 ) == v).foreach(deque => path.foreach(deque.append))
205
+ case e if e != null && e.weight == FollowsNow => drill(e.from, v :: path)
206
+ case _ => chains .find(_.apply(0 ) == v).foreach(deque => path.foreach(deque.append))
202
207
}
203
208
ends.foreach(drill(_, Nil ))
204
- followed .sortWith((p, q) => sortVertex(p(0 ), q(0 ))).toList.flatten.map(componentOf)
209
+ chains .sortWith((p, q) => sortVertex(p(0 ), q(0 ))).toList.flatten.map(componentOf)
205
210
}
206
211
}
207
212
}
@@ -237,18 +242,18 @@ object DependencyGraph {
237
242
for (p <- phases) {
238
243
require(p.phaseName.nonEmpty, " Phase name must be non-empty." )
239
244
def checkConstraint (name : String , constraint : String ): Boolean =
240
- phases.exists(_.phaseName == name).tap(ok => if (! ok) graph.warning(s " No phase ` $name` for ${p.phaseName}. $constraint" ))
245
+ graph.components.contains( name).tap(ok => if (! ok) graph.warning(s " No phase ` $name` for ${p.phaseName}. $constraint" ))
241
246
for (after <- p.runsRightAfter if after.nonEmpty && checkConstraint(after, " runsRightAfter" ))
242
247
graph.addEdge(after, p.phaseName, FollowsNow )
243
248
for (after <- p.runsAfter if after.nonEmpty && ! p.runsRightAfter.contains(after) && checkConstraint(after, " runsAfter" ))
244
249
graph.addEdge(after, p.phaseName, Follows )
245
250
for (before <- p.runsBefore if before.nonEmpty && checkConstraint(before, " runsBefore" ))
246
251
graph.addEdge(p.phaseName, before, Follows )
247
252
if (p != start && p != end)
248
- if (p.runsRightAfter.find( ! _.isEmpty).isEmpty && p.runsAfter.find( ! _.isEmpty).isEmpty )
253
+ if (p.runsRightAfter.forall( _.isEmpty) && p.runsAfter.forall( _.isEmpty))
249
254
graph.addEdge(start.phaseName, p.phaseName, Follows )
250
255
if (p != end || p == end && p == start)
251
- if (! p.runsBefore.contains(end.phaseName ))
256
+ if (p.runsBefore.forall(_.isEmpty ))
252
257
graph.addEdge(p.phaseName, end.phaseName, Follows )
253
258
}
254
259
}
0 commit comments