diff options
Diffstat (limited to 'src/dotty/tools/dotc/core')
-rw-r--r-- | src/dotty/tools/dotc/core/Contexts.scala | 11 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/DenotTransformers.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Denotations.scala | 13 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Periods.scala | 6 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Phases.scala | 76 |
5 files changed, 86 insertions, 22 deletions
diff --git a/src/dotty/tools/dotc/core/Contexts.scala b/src/dotty/tools/dotc/core/Contexts.scala index 38784ec0c..68daea440 100644 --- a/src/dotty/tools/dotc/core/Contexts.scala +++ b/src/dotty/tools/dotc/core/Contexts.scala @@ -25,7 +25,7 @@ import collection.immutable.BitSet import printing._ import config.{Settings, ScalaSettings, Platform, JavaPlatform} import language.implicitConversions - +import DenotTransformers.DenotTransformer object Contexts { /** A context is passed basically everywhere in dotc. @@ -387,7 +387,7 @@ object Contexts { def rootLoader(root: TermSymbol)(implicit ctx: Context): SymbolLoader = platform.rootLoader(root) // Set up some phases to get started */ - usePhases(SomePhase :: Nil) + usePhases(List(List(SomePhase))) /** The standard definitions */ val definitions = new Definitions @@ -460,8 +460,13 @@ object Contexts { /** Phases by id */ private[core] var phases: Array[Phase] = _ + /** Phases with consecutive Transforms groupped into a single phase */ + private [core] var squashedPhases: Array[Phase] = _ + /** Next denotation transformer id */ - private[core] var nextTransformerId: Array[Int] = _ + private[core] var nextDenotTransformerId: Array[Int] = _ + + private[core] var denotTransformers: Array[DenotTransformer] = _ // Printers state /** Number of recursive invocations of a show method on cuyrrent stack */ diff --git a/src/dotty/tools/dotc/core/DenotTransformers.scala b/src/dotty/tools/dotc/core/DenotTransformers.scala index be85b5877..e1ee355d8 100644 --- a/src/dotty/tools/dotc/core/DenotTransformers.scala +++ b/src/dotty/tools/dotc/core/DenotTransformers.scala @@ -21,7 +21,7 @@ object DenotTransformers { trait DenotTransformer extends Phase { /** The last phase during which the transformed denotations are valid */ - def lastPhaseId(implicit ctx: Context) = ctx.nextTransformerId(id + 1) + def lastPhaseId(implicit ctx: Context) = ctx.nextDenotTransformerId(id + 1) /** The validity period of the transformer in the given context */ def validFor(implicit ctx: Context): Period = diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala index b35647ead..e15c70637 100644 --- a/src/dotty/tools/dotc/core/Denotations.scala +++ b/src/dotty/tools/dotc/core/Denotations.scala @@ -501,6 +501,8 @@ object Denotations { def current(implicit ctx: Context): SingleDenotation = { val currentPeriod = ctx.period val valid = myValidFor + assert(valid.code > 0, s"negative period $valid: ${valid.code}") + if (valid.runId != currentPeriod.runId) bringForward.current else { var cur = this @@ -514,12 +516,15 @@ object Denotations { if (next.validFor.code > valid.code) { // in this case, next.validFor contains currentPeriod cur = next + cur } else { // not found, cur points to highest existing variant var startPid = cur.validFor.lastPhaseId + 1 - val transformer = ctx.phases(startPid - 1).asInstanceOf[DenotTransformer] + val nextTranformerId = ctx.nextDenotTransformerId(startPid) + val transformer = ctx.denotTransformers(nextTranformerId) //println(s"transforming with $transformer") - next = transformer.transform(cur).syncWithParents + if (currentPeriod.lastPhaseId > transformer.id) + next = transformer.transform(cur).syncWithParents if (next eq cur) startPid = cur.validFor.firstPhaseId else { @@ -534,6 +539,7 @@ object Denotations { cur.validFor = Period( currentPeriod.runId, startPid, transformer.lastPhaseId) //println(s"new denot: $cur, valid for ${cur.validFor}") + cur.current // multiple transformations could be required } } else { // currentPeriod < end of valid; in this case a version must exist @@ -545,8 +551,9 @@ object Denotations { cnt += 1 assert(cnt <= MaxPossiblePhaseId, s"seems to be a loop in Denotations for $this, currentPeriod = $currentPeriod") } + cur } - cur + } } diff --git a/src/dotty/tools/dotc/core/Periods.scala b/src/dotty/tools/dotc/core/Periods.scala index 1c9fbf0c6..61f395c7d 100644 --- a/src/dotty/tools/dotc/core/Periods.scala +++ b/src/dotty/tools/dotc/core/Periods.scala @@ -32,8 +32,8 @@ abstract class Periods extends DotClass { self: Context => */ def stablePeriod = { var first = phaseId - val nxTrans = ctx.base.nextTransformerId(first) - while (first - 1 > NoPhaseId && (ctx.base.nextTransformerId(first - 1) == nxTrans)) { + val nxTrans = ctx.base.nextDenotTransformerId(first) + while (first - 1 > NoPhaseId && (ctx.base.nextDenotTransformerId(first - 1) == nxTrans)) { first -= 1 } Period(runId, first, nxTrans) @@ -49,6 +49,8 @@ object Periods { * runid 21 bits * last phase id: 5 bits * #phases before last: 5 bits + * + * // Dmitry: sign == 0 isn't actually always true, in some cases phaseId == -1 is used for shifts, that easily creates code < 0 */ class Period(val code: Int) extends AnyVal { diff --git a/src/dotty/tools/dotc/core/Phases.scala b/src/dotty/tools/dotc/core/Phases.scala index 81ab7acbf..c49d314bc 100644 --- a/src/dotty/tools/dotc/core/Phases.scala +++ b/src/dotty/tools/dotc/core/Phases.scala @@ -7,8 +7,15 @@ import util.DotClass import DenotTransformers._ import Denotations._ import config.Printers._ +import scala.collection.mutable.{ListBuffer, ArrayBuffer} +import dotty.tools.dotc.transform.TreeTransforms.{TreeTransformer, TreeTransform} +import dotty.tools.dotc.transform.PostTyperTransformers.PostTyperTransformer +import dotty.tools.dotc.transform.TreeTransforms +import TreeTransforms.Separator + +trait Phases { + self: Context => -trait Phases { self: Context => import Phases._ def phase: Phase = base.phases(period.phaseId) @@ -32,9 +39,13 @@ trait Phases { self: Context => object Phases { - trait PhasesBase { this: ContextBase => + trait PhasesBase { + this: ContextBase => + + // drop NoPhase at beginning + def allPhases = squashedPhases.tail + - def allPhases = phases.tail // drop NoPhase at beginning object NoPhase extends Phase { override def exists = false @@ -62,10 +73,12 @@ object Phases { /** 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[Phase]) = { - this.phases = (NoPhase :: phases ::: new TerminalPhase :: Nil).toArray - this.nextTransformerId = new Array[Int](this.phases.length) + 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) var i = 0 while (i < this.phases.length) { this.phases(i)._id = i @@ -74,11 +87,48 @@ object Phases { var lastTransformerId = i while (i > 0) { i -= 1 - if (this.phases(i).isInstanceOf[DenotTransformer]) lastTransformerId = i - nextTransformerId(i) = lastTransformerId + this.phases(i) match { + case transformer: DenotTransformer => + lastTransformerId = i + denotTransformers(i) = transformer + case _ => + } + nextDenotTransformerId(i) = lastTransformerId } + + if (squash) { + 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") + + val transforms = phases(i).asInstanceOf[List[TreeTransform]] + val block = + if (!postTyperEmmited) { + postTyperEmmited = true + new PostTyperTransformer { + override def name: String = transformations.map(_.name).mkString("TreeTransform:{", ", ", "}") + override protected def transformations: Array[TreeTransform] = transforms.toArray + } + } else new TreeTransformer { + override def name: String = transformations.map(_.name).mkString("TreeTransform:{", ", ", "}") + override protected def transformations: Array[TreeTransform] = transforms.toArray + } + squashedPhases += block + block._id = phases(i).head.id + } else squashedPhases += phases(i).head + i += 1 + } + this.squashedPhases = (NoPhase::squashedPhases.toList :::new TerminalPhase :: Nil).toArray + } else { + this.squashedPhases = this.phases + } + config.println(s"Phases = ${this.phases.deep}") - config.println(s"nextTransformId = ${nextTransformerId.deep}") + config.println(s"squashedPhases = ${this.squashedPhases.deep}") + config.println(s"nextDenotTransformerId = ${nextDenotTransformerId.deep}") } final val typerName = "typer" @@ -110,12 +160,12 @@ object Phases { private[Phases] var _id = -1 /** 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. + * 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 - final def <= (that: Phase)(implicit ctx: Context) = + final def <=(that: Phase)(implicit ctx: Context) = exists && id <= that.id final def prev(implicit ctx: Context): Phase = @@ -131,7 +181,7 @@ object Phases { 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 + final def refChecked(implicit ctx: Context): Boolean = ctx.refchecksPhase <= this override def toString = name } |