diff options
Diffstat (limited to 'src')
5 files changed, 104 insertions, 8 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) |