mirror of https://github.com/sbt/sbt.git
minor updates to utilities
This commit is contained in:
parent
f8439d2d64
commit
0846ffd02b
|
|
@ -3,12 +3,40 @@
|
|||
*/
|
||||
package sbt
|
||||
|
||||
import Relation._
|
||||
|
||||
object Relation
|
||||
{
|
||||
/** Constructs a new immutable, finite relation that is initially empty. */
|
||||
def empty[A,B]: Relation[A,B] = make(Map.empty, Map.empty)
|
||||
def make[A,B](forward: Map[A,Set[B]], reverse: Map[B, Set[A]]): Relation[A,B] = new MRelation(forward, reverse)
|
||||
def reconstruct[A,B](forward: Map[A, Set[B]]): Relation[A,B] =
|
||||
{
|
||||
val reversePairs = for( (a,bs) <- forward.view; b <- bs.view) yield (b, a)
|
||||
val reverse = (Map.empty[B,Set[A]] /: reversePairs) { case (m, (b, a)) => add(m, b, a :: Nil) }
|
||||
make(forward, reverse)
|
||||
}
|
||||
|
||||
|
||||
private[sbt] def remove[X,Y](map: M[X,Y], from: X, to: Y): M[X,Y] =
|
||||
map.get(from) match {
|
||||
case Some(tos) =>
|
||||
val newSet = tos - to
|
||||
if(newSet.isEmpty) map - from else map.updated(from, newSet)
|
||||
case None => map
|
||||
}
|
||||
|
||||
private[sbt] def combine[X,Y](a: M[X,Y], b: M[X,Y]): M[X,Y] =
|
||||
(a /: b) { (map, mapping) => add(map, mapping._1, mapping._2) }
|
||||
|
||||
private[sbt] def add[X,Y](map: M[X,Y], from: X, to: Iterable[Y]): M[X,Y] =
|
||||
map.updated(from, get(map, from) ++ to)
|
||||
|
||||
private[sbt] def get[X,Y](map: M[X,Y], t: X): Set[Y] = map.getOrElse(t, Set.empty[Y])
|
||||
|
||||
private[sbt] type M[X,Y] = Map[X, Set[Y]]
|
||||
}
|
||||
|
||||
/** Binary relation between A and B. It is a set of pairs (_1, _2) for _1 in A, _2 in B. */
|
||||
trait Relation[A,B]
|
||||
{
|
||||
|
|
@ -49,8 +77,6 @@ trait Relation[A,B]
|
|||
}
|
||||
private final class MRelation[A,B](fwd: Map[A, Set[B]], rev: Map[B, Set[A]]) extends Relation[A,B]
|
||||
{
|
||||
type M[X,Y] = Map[X, Set[Y]]
|
||||
|
||||
def forwardMap = fwd
|
||||
def reverseMap = rev
|
||||
|
||||
|
|
@ -65,9 +91,9 @@ private final class MRelation[A,B](fwd: Map[A, Set[B]], rev: Map[B, Set[A]]) ext
|
|||
def all: Traversable[(A,B)] = fwd.iterator.flatMap { case (a, bs) => bs.iterator.map( b => (a,b) ) }.toTraversable
|
||||
|
||||
def +(pair: (A,B)) = this + (pair._1, Set(pair._2))
|
||||
def +(from: A, to: B) = this + (from, Set(to))
|
||||
def +(from: A, to: B) = this + (from, to :: Nil)
|
||||
def +(from: A, to: Iterable[B]) =
|
||||
new MRelation( add(fwd, from, to), (rev /: to) { (map, t) => add(map, t, Seq(from)) })
|
||||
new MRelation( add(fwd, from, to), (rev /: to) { (map, t) => add(map, t, from :: Nil) })
|
||||
|
||||
def ++(rs: Iterable[(A,B)]) = ((this: Relation[A,B]) /: rs) { _ + _ }
|
||||
def ++(other: Relation[A,B]) = new MRelation[A,B]( combine(fwd, other.forwardMap), combine(rev, other.reverseMap) )
|
||||
|
|
@ -84,21 +110,5 @@ private final class MRelation[A,B](fwd: Map[A, Set[B]], rev: Map[B, Set[A]]) ext
|
|||
case None => this
|
||||
}
|
||||
|
||||
private def remove[X,Y](map: M[X,Y], from: X, to: Y): M[X,Y] =
|
||||
map.get(from) match {
|
||||
case Some(tos) =>
|
||||
val newSet = tos - to
|
||||
if(newSet.isEmpty) map - from else map.updated(from, newSet)
|
||||
case None => map
|
||||
}
|
||||
|
||||
private def combine[X,Y](a: M[X,Y], b: M[X,Y]): M[X,Y] =
|
||||
(a /: b) { (map, mapping) => add(map, mapping._1, mapping._2) }
|
||||
|
||||
private[this] def add[X,Y](map: M[X,Y], from: X, to: Iterable[Y]): M[X,Y] =
|
||||
map.updated(from, get(map, from) ++ to)
|
||||
|
||||
private[this] def get[X,Y](map: M[X,Y], t: X): Set[Y] = map.getOrElse(t, Set.empty[Y])
|
||||
|
||||
override def toString = all.map { case (a,b) => a + " -> " + b }.mkString("Relation [", ", ", "]")
|
||||
}
|
||||
|
|
@ -6,9 +6,9 @@ package sbt
|
|||
trait TypeFunctions
|
||||
{
|
||||
type Id[X] = X
|
||||
trait Const[A] { type Apply[B] = A }
|
||||
trait Compose[A[_], B[_]] { type Apply[T] = A[B[T]] }
|
||||
trait P1of2[M[_,_], A] { type Apply[B] = M[A,B]; type Flip[B] = M[B, A] }
|
||||
sealed trait Const[A] { type Apply[B] = A }
|
||||
sealed trait Compose[A[_], B[_]] { type Apply[T] = A[B[T]] }
|
||||
sealed trait P1of2[M[_,_], A] { type Apply[B] = M[A,B]; type Flip[B] = M[B, A] }
|
||||
|
||||
final val left = new (Id ~> P1of2[Left, Nothing]#Flip) { def apply[T](t: T) = Left(t) }
|
||||
final val right = new (Id ~> P1of2[Right, Nothing]#Apply) { def apply[T](t: T) = Right(t) }
|
||||
|
|
|
|||
|
|
@ -74,6 +74,8 @@ object Using
|
|||
}
|
||||
private def closeCloseable[T <: Closeable]: T => Unit = _.close()
|
||||
|
||||
def bufferedOutputStream = wrap( (out: OutputStream) => new BufferedOutputStream(out) )
|
||||
def bufferedInputStream = wrap( (in: InputStream) => new BufferedInputStream(in) )
|
||||
def fileOutputStream(append: Boolean = false) = file(f => new BufferedOutputStream(new FileOutputStream(f, append)))
|
||||
def fileInputStream = file(f => new BufferedInputStream(new FileInputStream(f)))
|
||||
def urlInputStream = resource( (u: URL) => translate("Error opening " + u + ": ")(u.openStream))
|
||||
|
|
@ -85,9 +87,10 @@ object Using
|
|||
def jarFile(verify: Boolean) = file(f => new JarFile(f, verify), (_: JarFile).close())
|
||||
def zipFile = file(f => new ZipFile(f), (_: ZipFile).close())
|
||||
def streamReader = wrap{ (_: (InputStream, Charset)) match { case (in, charset) => new InputStreamReader(in, charset) } }
|
||||
def gzipInputStream = wrap( (in: InputStream) => new GZIPInputStream(in) )
|
||||
def gzipInputStream = wrap( (in: InputStream) => new GZIPInputStream(in, 8192) )
|
||||
def zipInputStream = wrap( (in: InputStream) => new ZipInputStream(in))
|
||||
def gzipOutputStream = wrap((out: OutputStream) => new GZIPOutputStream(out), (_: GZIPOutputStream).finish())
|
||||
def zipOutputStream = wrap( (out: OutputStream) => new ZipOutputStream(out))
|
||||
def gzipOutputStream = wrap((out: OutputStream) => new GZIPOutputStream(out, 8192), (_: GZIPOutputStream).finish())
|
||||
def jarOutputStream = wrap( (out: OutputStream) => new JarOutputStream(out))
|
||||
def jarInputStream = wrap( (in: InputStream) => new JarInputStream(in))
|
||||
def zipEntry(zip: ZipFile) = resource( (entry: ZipEntry) =>
|
||||
|
|
|
|||
Loading…
Reference in New Issue