diff options
Diffstat (limited to 'src/reflect/scala/reflect/internal/util/Collections.scala')
-rw-r--r-- | src/reflect/scala/reflect/internal/util/Collections.scala | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/src/reflect/scala/reflect/internal/util/Collections.scala b/src/reflect/scala/reflect/internal/util/Collections.scala new file mode 100644 index 0000000000..1f8eb15c90 --- /dev/null +++ b/src/reflect/scala/reflect/internal/util/Collections.scala @@ -0,0 +1,213 @@ +/* NSC -- new Scala compiler + * Copyright 2005-2011 LAMP/EPFL + * @author Paul Phillips + */ + +package scala.reflect.internal.util + +import scala.collection.{ mutable, immutable } +import scala.annotation.tailrec +import mutable.ListBuffer + +/** Profiler driven changes. + * TODO - inlining doesn't work from here because of the bug that + * methods in traits aren't inlined. + */ +trait Collections { + /** True if all three arguments have the same number of elements and + * the function is true for all the triples. + */ + @tailrec final def corresponds3[A, B, C](xs1: List[A], xs2: List[B], xs3: List[C]) + (f: (A, B, C) => Boolean): Boolean = ( + if (xs1.isEmpty) xs2.isEmpty && xs3.isEmpty + else !xs2.isEmpty && !xs3.isEmpty && f(xs1.head, xs2.head, xs3.head) && corresponds3(xs1.tail, xs2.tail, xs3.tail)(f) + ) + + /** All these mm methods are "deep map" style methods for + * mapping etc. on a list of lists while avoiding unnecessary + * intermediate structures like those created via flatten. + */ + final def mexists[A](xss: List[List[A]])(p: A => Boolean) = + xss exists (_ exists p) + final def mforall[A](xss: List[List[A]])(p: A => Boolean) = + xss forall (_ forall p) + final def mmap[A, B](xss: List[List[A]])(f: A => B) = + xss map (_ map f) + final def mforeach[A](xss: List[List[A]])(f: A => Unit) = + xss foreach (_ foreach f) + final def mfind[A](xss: List[List[A]])(p: A => Boolean): Option[A] = { + var res: Option[A] = null + mforeach(xss)(x => if ((res eq null) && p(x)) res = Some(x)) + if (res eq null) None else res + } + final def mfilter[A](xss: List[List[A]])(p: A => Boolean) = + for (xs <- xss; x <- xs; if p(x)) yield x + + final def map2[A, B, C](xs1: List[A], xs2: List[B])(f: (A, B) => C): List[C] = { + val lb = new ListBuffer[C] + var ys1 = xs1 + var ys2 = xs2 + while (!ys1.isEmpty && !ys2.isEmpty) { + lb += f(ys1.head, ys2.head) + ys1 = ys1.tail + ys2 = ys2.tail + } + lb.toList + } + final def map3[A, B, C, D](xs1: List[A], xs2: List[B], xs3: List[C])(f: (A, B, C) => D): List[D] = { + if (xs1.isEmpty || xs2.isEmpty || xs3.isEmpty) Nil + else f(xs1.head, xs2.head, xs3.head) :: map3(xs1.tail, xs2.tail, xs3.tail)(f) + } + final def flatMap2[A, B, C](xs1: List[A], xs2: List[B])(f: (A, B) => List[C]): List[C] = { + val lb = new ListBuffer[C] + var ys1 = xs1 + var ys2 = xs2 + while (!ys1.isEmpty && !ys2.isEmpty) { + lb ++= f(ys1.head, ys2.head) + ys1 = ys1.tail + ys2 = ys2.tail + } + lb.toList + } + + final def flatCollect[A, B](elems: List[A])(pf: PartialFunction[A, Traversable[B]]): List[B] = { + val lb = new ListBuffer[B] + for (x <- elems ; if pf isDefinedAt x) + lb ++= pf(x) + + lb.toList + } + + final def distinctBy[A, B](xs: List[A])(f: A => B): List[A] = { + val buf = new ListBuffer[A] + val seen = mutable.Set[B]() + xs foreach { x => + val y = f(x) + if (!seen(y)) { + buf += x + seen += y + } + } + buf.toList + } + + @tailrec final def flattensToEmpty(xss: Seq[Seq[_]]): Boolean = { + xss.isEmpty || xss.head.isEmpty && flattensToEmpty(xss.tail) + } + + final def foreachWithIndex[A, B](xs: List[A])(f: (A, Int) => Unit) { + var index = 0 + var ys = xs + while (!ys.isEmpty) { + f(ys.head, index) + ys = ys.tail + index += 1 + } + } + + // @inline + final def findOrElse[A](xs: TraversableOnce[A])(p: A => Boolean)(orElse: => A): A = { + xs find p getOrElse orElse + } + + final def mapFrom[A, A1 >: A, B](xs: List[A])(f: A => B): Map[A1, B] = { + Map[A1, B](xs map (x => (x, f(x))): _*) + } + + final def mapWithIndex[A, B](xs: List[A])(f: (A, Int) => B): List[B] = { + val lb = new ListBuffer[B] + var index = 0 + var ys = xs + while (!ys.isEmpty) { + lb += f(ys.head, index) + ys = ys.tail + index += 1 + } + lb.toList + } + final def collectMap2[A, B, C](xs1: List[A], xs2: List[B])(p: (A, B) => Boolean): Map[A, B] = { + if (xs1.isEmpty || xs2.isEmpty) + return Map() + + val buf = immutable.Map.newBuilder[A, B] + var ys1 = xs1 + var ys2 = xs2 + while (!ys1.isEmpty && !ys2.isEmpty) { + val x1 = ys1.head + val x2 = ys2.head + if (p(x1, x2)) + buf += ((x1, x2)) + + ys1 = ys1.tail + ys2 = ys2.tail + } + buf.result + } + final def foreach2[A, B](xs1: List[A], xs2: List[B])(f: (A, B) => Unit): Unit = { + var ys1 = xs1 + var ys2 = xs2 + while (!ys1.isEmpty && !ys2.isEmpty) { + f(ys1.head, ys2.head) + ys1 = ys1.tail + ys2 = ys2.tail + } + } + final def foreach3[A, B, C](xs1: List[A], xs2: List[B], xs3: List[C])(f: (A, B, C) => Unit): Unit = { + var ys1 = xs1 + var ys2 = xs2 + var ys3 = xs3 + while (!ys1.isEmpty && !ys2.isEmpty && !ys3.isEmpty) { + f(ys1.head, ys2.head, ys3.head) + ys1 = ys1.tail + ys2 = ys2.tail + ys3 = ys3.tail + } + } + final def exists2[A, B](xs1: List[A], xs2: List[B])(f: (A, B) => Boolean): Boolean = { + var ys1 = xs1 + var ys2 = xs2 + while (!ys1.isEmpty && !ys2.isEmpty) { + if (f(ys1.head, ys2.head)) + return true + + ys1 = ys1.tail + ys2 = ys2.tail + } + false + } + final def forall2[A, B](xs1: List[A], xs2: List[B])(f: (A, B) => Boolean): Boolean = { + var ys1 = xs1 + var ys2 = xs2 + while (!ys1.isEmpty && !ys2.isEmpty) { + if (!f(ys1.head, ys2.head)) + return false + + ys1 = ys1.tail + ys2 = ys2.tail + } + true + } + final def forall3[A, B, C](xs1: List[A], xs2: List[B], xs3: List[C])(f: (A, B, C) => Boolean): Boolean = { + var ys1 = xs1 + var ys2 = xs2 + var ys3 = xs3 + while (!ys1.isEmpty && !ys2.isEmpty && !ys3.isEmpty) { + if (!f(ys1.head, ys2.head, ys3.head)) + return false + + ys1 = ys1.tail + ys2 = ys2.tail + ys3 = ys3.tail + } + true + } + + final def transposeSafe[A](ass: List[List[A]]): Option[List[List[A]]] = try { + Some(ass.transpose) + } catch { + case _: IllegalArgumentException => None + } +} + +object Collections extends Collections { } + |