aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/dotty/tools/dotc/core')
-rw-r--r--src/dotty/tools/dotc/core/Contexts.scala11
-rw-r--r--src/dotty/tools/dotc/core/DenotTransformers.scala2
-rw-r--r--src/dotty/tools/dotc/core/Denotations.scala13
-rw-r--r--src/dotty/tools/dotc/core/Periods.scala6
-rw-r--r--src/dotty/tools/dotc/core/Phases.scala76
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
}