summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/reflect/internal/Definitions.scala3
-rw-r--r--src/compiler/scala/reflect/internal/SymbolTable.scala14
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala64
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/Power.scala25
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/ReplVals.scala6
-rw-r--r--src/library/scala/collection/GenTraversableLike.scala2
-rw-r--r--src/library/scala/collection/immutable/List.scala10
7 files changed, 115 insertions, 9 deletions
diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala
index ce5bb3d1c4..7ed3e977db 100644
--- a/src/compiler/scala/reflect/internal/Definitions.scala
+++ b/src/compiler/scala/reflect/internal/Definitions.scala
@@ -814,6 +814,9 @@ trait Definitions extends reflect.api.StandardDefinitions {
try getModule(fullname.toTermName)
catch { case _: MissingRequirementError => NoSymbol }
+ def termMember(owner: Symbol, name: String): Symbol = owner.info.member(newTermName(name))
+ def typeMember(owner: Symbol, name: String): Symbol = owner.info.member(newTypeName(name))
+
def getMember(owner: Symbol, name: Name): Symbol = {
if (owner == NoSymbol) NoSymbol
else owner.info.nonPrivateMember(name) match {
diff --git a/src/compiler/scala/reflect/internal/SymbolTable.scala b/src/compiler/scala/reflect/internal/SymbolTable.scala
index b3c62bffbf..4bcf522a8f 100644
--- a/src/compiler/scala/reflect/internal/SymbolTable.scala
+++ b/src/compiler/scala/reflect/internal/SymbolTable.scala
@@ -78,16 +78,18 @@ abstract class SymbolTable extends api.Universe
type RunId = Int
final val NoRunId = 0
+ private var phStack: List[Phase] = Nil
private var ph: Phase = NoPhase
private var per = NoPeriod
+ final def atPhaseStack: List[Phase] = phStack
final def phase: Phase = ph
final def phase_=(p: Phase) {
//System.out.println("setting phase to " + p)
- assert((p ne null) && p != NoPhase)
+ assert((p ne null) && p != NoPhase, p)
ph = p
- per = (currentRunId << 8) + p.id
+ per = period(currentRunId, p.id)
}
/** The current compiler run identifier. */
@@ -112,14 +114,18 @@ abstract class SymbolTable extends api.Universe
final def phaseOf(period: Period): Phase = phaseWithId(phaseId(period))
final def period(rid: RunId, pid: Phase#Id): Period =
- (currentRunId << 8) + pid
+ (rid << 8) + pid
/** Perform given operation at given phase. */
@inline final def atPhase[T](ph: Phase)(op: => T): T = {
val current = phase
phase = ph
+ phStack ::= ph
try op
- finally phase = current
+ finally {
+ phase = current
+ phStack = phStack.tail
+ }
}
/** Since when it is to be "at" a phase is inherently ambiguous,
* a couple unambiguously named methods.
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index 4493188b31..ca5604c828 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -213,10 +213,23 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
def informTime(msg: String, start: Long) = informProgress(elapsedMessage(msg, start))
def logError(msg: String, t: Throwable): Unit = ()
+
+ private def atPhaseStackMessage = atPhaseStack match {
+ case Nil => ""
+ case ps => ps.reverseMap("->" + _).mkString("(", " ", ")")
+ }
+ private def shouldLogAtThisPhase = (
+ (settings.log.isSetByUser)
+ && ((settings.log containsPhase globalPhase) || (settings.log containsPhase phase))
+ )
+
+ def logAfterEveryPhase[T](msg: String)(op: => T) {
+ log("Running operation '%s' after every phase.\n" + describeAfterEveryPhase(op))
+ }
// Over 200 closure objects are eliminated by inlining this.
@inline final def log(msg: => AnyRef): Unit =
- if (settings.log containsPhase globalPhase)
- inform("[log " + phase + "] " + msg)
+ if (shouldLogAtThisPhase)
+ inform("[log %s%s] %s".format(globalPhase, atPhaseStackMessage, msg))
def logThrowable(t: Throwable): Unit = globalError(throwableAsString(t))
def throwableAsString(t: Throwable): String =
@@ -754,6 +767,51 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
line1 :: line2 :: descs mkString
}
+ /** Returns List of (phase, value) pairs, including only those
+ * where the value compares unequal to the previous phase's value.
+ */
+ def afterEachPhase[T](op: => T): List[(Phase, T)] = {
+ phaseDescriptors.map(_.ownPhase).foldLeft(List[(Phase, T)]()) { (res, ph) =>
+ val value = afterPhase(ph)(op)
+ if (res.nonEmpty && res.head._2 == value) res
+ else ((ph, value)) :: res
+ } reverse
+ }
+
+ /** Returns List of ChangeAfterPhase objects, encapsulating those
+ * phase transitions where the result of the operation gave a different
+ * list than it had when run during the previous phase.
+ */
+ def changesAfterEachPhase[T](op: => List[T]): List[ChangeAfterPhase[T]] = {
+ val ops = ((NoPhase, Nil)) :: afterEachPhase(op)
+
+ ops sliding 2 map {
+ case (_, before) :: (ph, after) :: Nil =>
+ val lost = before filterNot (after contains _)
+ val gained = after filterNot (before contains _)
+ ChangeAfterPhase(ph, lost, gained)
+ case _ => ???
+ } toList
+ }
+ private def numberedPhase(ph: Phase) = "%2d/%s".format(ph.id, ph.name)
+
+ case class ChangeAfterPhase[+T](ph: Phase, lost: List[T], gained: List[T]) {
+ private def mkStr(what: String, xs: List[_]) = (
+ if (xs.isEmpty) ""
+ else xs.mkString(what + " after " + numberedPhase(ph) + " {\n ", "\n ", "\n}\n")
+ )
+ override def toString = mkStr("Lost", lost) + mkStr("Gained", gained)
+ }
+
+ def describeAfterEachPhase[T](op: => T): List[String] =
+ afterEachPhase(op) map { case (ph, t) => "[after %-15s] %s".format(numberedPhase(ph), t) }
+
+ def describeAfterEveryPhase[T](op: => T): String =
+ describeAfterEachPhase(op) map (" " + _ + "\n") mkString
+
+ def printAfterEachPhase[T](op: => T): Unit =
+ describeAfterEachPhase(op) foreach (m => println(" " + m))
+
// ----------- Runs ---------------------------------------
private var curRun: Run = null
@@ -1027,9 +1085,11 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
val refchecksPhase = phaseNamed("refchecks")
val uncurryPhase = phaseNamed("uncurry")
// tailcalls, specialize
+ val specializePhase = phaseNamed("specialize")
val explicitouterPhase = phaseNamed("explicitouter")
val erasurePhase = phaseNamed("erasure")
// lazyvals, lambdalift, constructors
+ val lambdaLiftPhase = phaseNamed("lambdalift")
val flattenPhase = phaseNamed("flatten")
val mixinPhase = phaseNamed("mixin")
val cleanupPhase = phaseNamed("cleanup")
diff --git a/src/compiler/scala/tools/nsc/interpreter/Power.scala b/src/compiler/scala/tools/nsc/interpreter/Power.scala
index 835fbb5638..ef84876b94 100644
--- a/src/compiler/scala/tools/nsc/interpreter/Power.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/Power.scala
@@ -15,6 +15,31 @@ import scala.io.Codec
import java.net.{ URL, MalformedURLException }
import io.{ Path }
+/** Collecting some power mode examples.
+
+scala> trait F[@specialized(Int) T] { def f: T = ??? }
+defined trait F
+
+scala> trait G[@specialized(Long, Int) T] extends F[T] { override def f: T = super.f }
+defined trait G
+
+scala> changesAfterEachPhase(intp("G").info.members filter (_.name.toString contains "super")) >
+Gained after 1/parser {
+ method super$f
+}
+
+Gained after 12/specialize {
+ method super$f$mcJ$sp
+ method super$f$mcI$sp
+}
+
+Lost after 18/flatten {
+ method super$f$mcJ$sp
+ method super$f$mcI$sp
+ method super$f
+}
+*/
+
/** A class for methods to be injected into the intp in power mode.
*/
class Power[ReplValsImpl <: ReplVals : Manifest](val intp: IMain, replVals: ReplValsImpl) {
diff --git a/src/compiler/scala/tools/nsc/interpreter/ReplVals.scala b/src/compiler/scala/tools/nsc/interpreter/ReplVals.scala
index 6e5dec4205..b20017c1d3 100644
--- a/src/compiler/scala/tools/nsc/interpreter/ReplVals.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/ReplVals.scala
@@ -62,10 +62,12 @@ object ReplVals {
class AppliedTypeFromManifests(sym: Symbol) {
def apply[M](implicit m1: Manifest[M]): Type =
- appliedType(sym.typeConstructor, List(m1) map (x => manifestToType(x).asInstanceOf[Type]))
+ if (sym eq NoSymbol) NoType
+ else appliedType(sym.typeConstructor, List(m1) map (x => manifestToType(x).asInstanceOf[Type]))
def apply[M1, M2](implicit m1: Manifest[M1], m2: Manifest[M2]): Type =
- appliedType(sym.typeConstructor, List(m1, m2) map (x => manifestToType(x).asInstanceOf[Type]))
+ if (sym eq NoSymbol) NoType
+ else appliedType(sym.typeConstructor, List(m1, m2) map (x => manifestToType(x).asInstanceOf[Type]))
}
(sym: Symbol) => new AppliedTypeFromManifests(sym)
diff --git a/src/library/scala/collection/GenTraversableLike.scala b/src/library/scala/collection/GenTraversableLike.scala
index c837775cf9..1dcc0bdac7 100644
--- a/src/library/scala/collection/GenTraversableLike.scala
+++ b/src/library/scala/collection/GenTraversableLike.scala
@@ -318,7 +318,7 @@ trait GenTraversableLike[+A, +Repr] extends GenTraversableOnce[A] with Paralleli
* $orderDependent
*
* @param from the lowest index to include from this $coll.
- * @param until the highest index to EXCLUDE from this $coll.
+ * @param until the lowest index to EXCLUDE from this $coll.
* @return a $coll containing the elements greater than or equal to
* index `from` extending up to (but not including) index `until`
* of this $coll.
diff --git a/src/library/scala/collection/immutable/List.scala b/src/library/scala/collection/immutable/List.scala
index 5f3f9b717f..e2a4a09938 100644
--- a/src/library/scala/collection/immutable/List.scala
+++ b/src/library/scala/collection/immutable/List.scala
@@ -205,6 +205,16 @@ sealed abstract class List[+A] extends AbstractSeq[A]
these
}
+ /**
+ * @example {{{
+ * // Given a list
+ * val letters = List('a','b','c','d','e')
+ *
+ * // `slice` returns all elements beginning at index `from` and afterwards,
+ * // up until index `until` (excluding index `until`.)
+ * letters.slice(1,3) // Returns List('b','c')
+ * }}}
+ */
override def slice(from: Int, until: Int): List[A] = {
val lo = math.max(from, 0)
if (until <= lo || isEmpty) Nil