sbt/util/collection/Dag.scala

42 lines
1.0 KiB
Scala
Raw Normal View History

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