aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dotty/tools/dotc/core/Phases.scala108
1 files changed, 68 insertions, 40 deletions
diff --git a/src/dotty/tools/dotc/core/Phases.scala b/src/dotty/tools/dotc/core/Phases.scala
index c49d314bc..7ae7b6ad3 100644
--- a/src/dotty/tools/dotc/core/Phases.scala
+++ b/src/dotty/tools/dotc/core/Phases.scala
@@ -45,8 +45,6 @@ object Phases {
// drop NoPhase at beginning
def allPhases = squashedPhases.tail
-
-
object NoPhase extends Phase {
override def exists = false
def name = "<no phase>"
@@ -68,26 +66,23 @@ object Phases {
override def lastPhaseId(implicit ctx: Context) = id
}
- def phaseNamed(name: String) =
- phases.find(_.name == name).getOrElse(NoPhase)
-
/** Use the following phases in the order they are given.
* The list should never contain NoPhase.
* if squashing is enabled, phases in same subgroup will be squashed to single phase.
*/
- def usePhases(phases: List[List[Phase]], squash: Boolean = true) = {
- this.phases = (NoPhase :: phases.flatten ::: new TerminalPhase :: Nil).toArray
- this.nextDenotTransformerId = new Array[Int](this.phases.length)
- this.denotTransformers = new Array[DenotTransformer](this.phases.length)
+ def usePhases(phasess: List[List[Phase]], squash: Boolean = false) = {
+ phases = (NoPhase :: phasess.flatten ::: new TerminalPhase :: Nil).toArray
+ nextDenotTransformerId = new Array[Int](phases.length)
+ denotTransformers = new Array[DenotTransformer](phases.length)
var i = 0
- while (i < this.phases.length) {
- this.phases(i)._id = i
+ while (i < phases.length) {
+ phases(i).init(this, i)
i += 1
}
var lastTransformerId = i
while (i > 0) {
i -= 1
- this.phases(i) match {
+ phases(i) match {
case transformer: DenotTransformer =>
lastTransformerId = i
denotTransformers(i) = transformer
@@ -100,11 +95,11 @@ object Phases {
val squashedPhases = ListBuffer[Phase]()
var postTyperEmmited = false
var i = 0
- while (i < phases.length) {
- if (phases(i).length > 1) {
- assert(phases(i).forall(x => x.isInstanceOf[TreeTransform]), "Only tree transforms can be squashed")
+ while (i < phasess.length) {
+ if (phasess(i).length > 1) {
+ assert(phasess(i).forall(x => x.isInstanceOf[TreeTransform]), "Only tree transforms can be squashed")
- val transforms = phases(i).asInstanceOf[List[TreeTransform]]
+ val transforms = phasess(i).asInstanceOf[List[TreeTransform]]
val block =
if (!postTyperEmmited) {
postTyperEmmited = true
@@ -117,8 +112,8 @@ object Phases {
override protected def transformations: Array[TreeTransform] = transforms.toArray
}
squashedPhases += block
- block._id = phases(i).head.id
- } else squashedPhases += phases(i).head
+ block.init(this, phasess(i).head.id)
+ } else squashedPhases += phasess(i).head
i += 1
}
this.squashedPhases = (NoPhase::squashedPhases.toList :::new TerminalPhase :: Nil).toArray
@@ -126,22 +121,41 @@ object Phases {
this.squashedPhases = this.phases
}
- config.println(s"Phases = ${this.phases.deep}")
- config.println(s"squashedPhases = ${this.squashedPhases.deep}")
+ config.println(s"Phases = ${phases.deep}")
+ config.println(s"squashedPhases = ${squashedPhases.deep}")
config.println(s"nextDenotTransformerId = ${nextDenotTransformerId.deep}")
}
- final val typerName = "typer"
- final val refchecksName = "refchecks"
- final val erasureName = "erasure"
- final val flattenName = "flatten"
+ def phaseNamed(name: String) = phases.find(_.name == name).getOrElse(NoPhase)
- lazy val typerPhase = phaseNamed(typerName)
- lazy val refchecksPhase = phaseNamed(refchecksName)
- lazy val erasurePhase = phaseNamed(erasureName)
- lazy val flattenPhase = phaseNamed(flattenName)
+ /** A cache to compute the phase with given name, which
+ * stores the phase as soon as phaseNamed returns something
+ * different from NoPhase.
+ */
+ private class PhaseCache(name: String) {
+ private var myPhase: Phase = NoPhase
+ def phase = {
+ if (myPhase eq NoPhase) myPhase = phaseNamed(name)
+ myPhase
+ }
+ }
+
+ private val typerCache = new PhaseCache(typerName)
+ private val refChecksCache = new PhaseCache(refChecksName)
+ private val erasureCache = new PhaseCache(erasureName)
+ private val flattenCache = new PhaseCache(flattenName)
+
+ def typerPhase = typerCache.phase
+ def refchecksPhase = refChecksCache.phase
+ def erasurePhase = erasureCache.phase
+ def flattenPhase = flattenCache.phase
}
+ final val typerName = "typer"
+ final val refChecksName = "refchecks"
+ final val erasureName = "erasure"
+ final val flattenName = "flatten"
+
abstract class Phase extends DotClass {
def name: String
@@ -157,32 +171,46 @@ object Phases {
def exists: Boolean = true
- private[Phases] var _id = -1
+ private var myId: PhaseId = -1
+ private var myBase: ContextBase = null
+ private var myErasedTypes = false
+ private var myFlatClasses = false
+ private var myRefChecked = false
/** The sequence position of this phase in the given context where 0
* is reserved for NoPhase and the first real phase is at position 1.
* -1 if the phase is not installed in the context.
*/
- def id = _id
+ def id = myId
+
+ final def erasedTypes = myErasedTypes
+ final def flatClasses = myFlatClasses
+ final def refChecked = myRefChecked
+
+ protected[Phases] def init(base: ContextBase, id: Int): Unit = {
+ if (id >= FirstPhaseId)
+ assert(myId == -1, s"phase $this has already been used once; cannot be reused")
+ myBase = base
+ myId = id
+ myErasedTypes = prev.name == erasureName || prev.erasedTypes
+ myFlatClasses = prev.name == flattenName || prev.flatClasses
+ myRefChecked = prev.name == refChecksName || prev.refChecked
+ }
final def <=(that: Phase)(implicit ctx: Context) =
exists && id <= that.id
- final def prev(implicit ctx: Context): Phase =
- if (id > FirstPhaseId) ctx.phases(id - 1) else ctx.NoPhase
+ final def prev: Phase =
+ if (id > FirstPhaseId) myBase.phases(id - 1) else myBase.NoPhase
- final def next(implicit ctx: Context): Phase =
- if (hasNext) ctx.phases(id + 1) else ctx.NoPhase
+ final def next: Phase =
+ if (hasNext) myBase.phases(id + 1) else myBase.NoPhase
- final def hasNext(implicit ctx: Context) = id + 1 < ctx.phases.length
+ final def hasNext = id >= FirstPhaseId && id + 1 < myBase.phases.length
- final def iterator(implicit ctx: Context) =
+ final def iterator =
Iterator.iterate(this)(_.next) takeWhile (_.hasNext)
- final def erasedTypes(implicit ctx: Context): Boolean = ctx.erasurePhase <= this
- final def flatClasses(implicit ctx: Context): Boolean = ctx.flattenPhase <= this
- final def refChecked(implicit ctx: Context): Boolean = ctx.refchecksPhase <= this
-
override def toString = name
}
} \ No newline at end of file