2009-06-26 03:26:06 +02:00
|
|
|
/* sbt -- Simple Build Tool
|
2010-07-15 01:24:50 +02:00
|
|
|
* Copyright 2008, 2009, 2010 David MacIver, Mark Harrah
|
2009-06-26 03:26:06 +02:00
|
|
|
*/
|
|
|
|
|
package sbt;
|
|
|
|
|
|
|
|
|
|
trait Dag[Node <: Dag[Node]]{
|
|
|
|
|
self : Node =>
|
|
|
|
|
|
|
|
|
|
def dependencies : Iterable[Node]
|
2009-08-09 04:03:24 +02:00
|
|
|
def topologicalSort = Dag.topologicalSort(self)(_.dependencies)
|
|
|
|
|
}
|
|
|
|
|
object Dag
|
|
|
|
|
{
|
2010-07-15 01:24:50 +02:00
|
|
|
import scala.collection.{mutable, JavaConversions};
|
|
|
|
|
import JavaConversions.{asIterable, asSet}
|
2009-06-26 03:26:06 +02:00
|
|
|
|
2010-12-13 03:33:32 +01:00
|
|
|
def topologicalSort[T](root: T)(dependencies: T => Iterable[T]): List[T] = topologicalSort(root :: Nil)(dependencies)
|
|
|
|
|
|
|
|
|
|
def topologicalSort[T](nodes: Iterable[T])(dependencies: T => Iterable[T]): List[T] =
|
|
|
|
|
{
|
2010-07-15 01:24:50 +02:00
|
|
|
val discovered = new mutable.HashSet[T]
|
|
|
|
|
val finished = asSet(new java.util.LinkedHashSet[T])
|
2009-06-26 03:26:06 +02:00
|
|
|
|
2010-12-13 03:33:32 +01:00
|
|
|
def visitAll(nodes: Iterable[T]) = nodes foreach visit
|
2009-08-09 04:03:24 +02:00
|
|
|
def visit(dag : T){
|
2009-06-26 03:26:06 +02:00
|
|
|
if (!discovered(dag)) {
|
|
|
|
|
discovered(dag) = true;
|
2010-12-13 03:33:32 +01:00
|
|
|
visitAll(dependencies(dag));
|
2009-06-26 03:26:06 +02:00
|
|
|
finished += dag;
|
|
|
|
|
}
|
2010-12-13 03:33:32 +01:00
|
|
|
else if(!finished(dag))
|
|
|
|
|
throw new Cyclic(dag)
|
2009-06-26 03:26:06 +02:00
|
|
|
}
|
|
|
|
|
|
2010-12-13 03:33:32 +01:00
|
|
|
visitAll(nodes);
|
2009-06-26 03:26:06 +02:00
|
|
|
|
|
|
|
|
finished.toList;
|
|
|
|
|
}
|
2010-12-13 03:33:32 +01:00
|
|
|
final class Cyclic(val value: Any) extends Exception("Cyclic reference involving " + value)
|
2009-06-26 03:26:06 +02:00
|
|
|
}
|
|
|
|
|
|