aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-03-15 17:10:24 +0100
committerDmitry Petrashko <dmitry.petrashko@gmail.com>2014-03-18 16:06:33 +0100
commit1dbf020c43639b0c37e9005f2692871d39676ac7 (patch)
treeb1855130096b99917845a715344ba6a768ede1fc /src/dotty/tools/dotc/core
parent76ea699ac1a76ee6048d7fe8239d0a1126581429 (diff)
downloaddotty-1dbf020c43639b0c37e9005f2692871d39676ac7.tar.gz
dotty-1dbf020c43639b0c37e9005f2692871d39676ac7.tar.bz2
dotty-1dbf020c43639b0c37e9005f2692871d39676ac7.zip
Refactored denotation transformers
Many small and large changes. Added samplePhase to demonstrate functionality. To test functioning, run the compiler with args tests/pos/uncurry.scala -Ylog:sample,terminal
Diffstat (limited to 'src/dotty/tools/dotc/core')
-rw-r--r--src/dotty/tools/dotc/core/Contexts.scala5
-rw-r--r--src/dotty/tools/dotc/core/DenotTransformers.scala44
-rw-r--r--src/dotty/tools/dotc/core/Denotations.scala11
-rw-r--r--src/dotty/tools/dotc/core/Periods.scala14
-rw-r--r--src/dotty/tools/dotc/core/Phases.scala53
5 files changed, 57 insertions, 70 deletions
diff --git a/src/dotty/tools/dotc/core/Contexts.scala b/src/dotty/tools/dotc/core/Contexts.scala
index 0d6e341a6..38784ec0c 100644
--- a/src/dotty/tools/dotc/core/Contexts.scala
+++ b/src/dotty/tools/dotc/core/Contexts.scala
@@ -325,6 +325,7 @@ object Contexts {
def withProperty(prop: (String, Any)): this.type = withMoreProperties(moreProperties + prop)
def withPhase(pid: PhaseId): this.type = withPeriod(Period(runId, pid))
+ def withPhase(phase: Phase): this.type = withPhase(phase.id)
def withSetting[T](setting: Setting[T], value: T): this.type =
withSettings(setting.updateIn(sstate, value))
@@ -361,7 +362,6 @@ object Contexts {
* compiler run.
*/
class ContextBase extends ContextState
- with DenotTransformers.DenotTransformerBase
with Denotations.DenotationsBase
with Phases.PhasesBase {
@@ -460,6 +460,9 @@ object Contexts {
/** Phases by id */
private[core] var phases: Array[Phase] = _
+ /** Next denotation transformer id */
+ private[core] var nextTransformerId: Array[Int] = _
+
// Printers state
/** Number of recursive invocations of a show method on cuyrrent stack */
private[dotc] var toTextRecursions = 0
diff --git a/src/dotty/tools/dotc/core/DenotTransformers.scala b/src/dotty/tools/dotc/core/DenotTransformers.scala
index f41f1d171..be85b5877 100644
--- a/src/dotty/tools/dotc/core/DenotTransformers.scala
+++ b/src/dotty/tools/dotc/core/DenotTransformers.scala
@@ -6,62 +6,26 @@ import SymDenotations._
import Contexts._
import Types._
import Denotations._
+import Phases._
import java.lang.AssertionError
import dotty.tools.dotc.util.DotClass
object DenotTransformers {
- trait DenotTransformerBase { self: ContextBase =>
- val denotTransformers = new DenotTransformerGroup
- }
-
/** A transformer group contains a sequence of transformers,
* ordered by the phase where they apply. Transformers are added
* to a group via `install`.
- *
- * There are two transformerGroups in a context base:
- * symTransformers and refTransformers. symTransformers translate
- * full symbol denotations, refTransformers translate only symbol references
- * of type Unique/JointRefDenotation.
*/
- class DenotTransformerGroup {
-
- private val nxTransformer =
- Array.fill[DenotTransformer](MaxPossiblePhaseId + 1)(NoTransformer)
-
- def nextTransformer(pid: PhaseId) = nxTransformer(pid)
-
- def install(pid: PhaseId, transFn: DenotTransformerGroup => DenotTransformer): Unit =
- if ((pid > NoPhaseId) && (nxTransformer(pid).phaseId > pid)) {
- val trans = transFn(this)
- trans._phaseId = pid
- nxTransformer(pid) = transFn(this)
- install(pid - 1, transFn)
- }
-
- /** A sentinel transformer object */
- object NoTransformer extends DenotTransformer(this) {
- _phaseId = MaxPossiblePhaseId + 1
- override def lastPhaseId = phaseId - 1 // TODO JZ Probably off-by-N error here. MO: Don't think so: we want empty validity period.
- def transform(ref: SingleDenotation)(implicit ctx: Context): SingleDenotation =
- unsupported("transform")
- }
- }
/** A transformer transforms denotations at a given phase */
- abstract class DenotTransformer(group: DenotTransformerGroup) extends DotClass {
-
- private[DenotTransformers] var _phaseId: PhaseId = _
-
- /** The phase at the start of which the denotations are transformed */
- def phaseId: PhaseId = _phaseId
+ trait DenotTransformer extends Phase {
/** The last phase during which the transformed denotations are valid */
- def lastPhaseId = group.nextTransformer(phaseId).phaseId - 1
+ def lastPhaseId(implicit ctx: Context) = ctx.nextTransformerId(id + 1)
/** The validity period of the transformer in the given context */
def validFor(implicit ctx: Context): Period =
- Period(ctx.runId, phaseId, lastPhaseId)
+ Period(ctx.runId, id, lastPhaseId)
/** The transformation method */
def transform(ref: SingleDenotation)(implicit ctx: Context): SingleDenotation
diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala
index bd1aedd75..b35647ead 100644
--- a/src/dotty/tools/dotc/core/Denotations.scala
+++ b/src/dotty/tools/dotc/core/Denotations.scala
@@ -390,7 +390,6 @@ object Denotations {
if ((symbol eq this.symbol) && (info eq this.info)) this
else newLikeThis(symbol, info)
-
def orElse(that: => SingleDenotation) = if (this.exists) this else that
def altsWith(p: Symbol => Boolean): List[SingleDenotation] =
@@ -518,7 +517,8 @@ object Denotations {
} else {
// not found, cur points to highest existing variant
var startPid = cur.validFor.lastPhaseId + 1
- val transformer = ctx.denotTransformers.nextTransformer(startPid)
+ val transformer = ctx.phases(startPid - 1).asInstanceOf[DenotTransformer]
+ //println(s"transforming with $transformer")
next = transformer.transform(cur).syncWithParents
if (next eq cur)
startPid = cur.validFor.firstPhaseId
@@ -527,20 +527,23 @@ object Denotations {
case next: ClassDenotation => next.resetFlag(Frozen)
case _ =>
}
+ next.nextInRun = cur.nextInRun
cur.nextInRun = next
cur = next
}
cur.validFor = Period(
currentPeriod.runId, startPid, transformer.lastPhaseId)
+ //println(s"new denot: $cur, valid for ${cur.validFor}")
}
} else {
- // currentPeriod < valid; in this case a version must exist
+ // currentPeriod < end of valid; in this case a version must exist
// but to be defensive we check for infinite loop anyway
var cnt = 0
while (!(cur.validFor contains currentPeriod)) {
+ //println(s"searching: $cur at $currentPeriod, valid for ${cur.validFor}")
cur = cur.nextInRun
cnt += 1
- assert(cnt <= MaxPossiblePhaseId, "seems to be a loop in Denotations")
+ assert(cnt <= MaxPossiblePhaseId, s"seems to be a loop in Denotations for $this, currentPeriod = $currentPeriod")
}
}
cur
diff --git a/src/dotty/tools/dotc/core/Periods.scala b/src/dotty/tools/dotc/core/Periods.scala
index 592516531..1c9fbf0c6 100644
--- a/src/dotty/tools/dotc/core/Periods.scala
+++ b/src/dotty/tools/dotc/core/Periods.scala
@@ -27,20 +27,16 @@ abstract class Periods extends DotClass { self: Context =>
/** The period containing the current period where denotations do not change.
* We compute this by taking as first phase the first phase less or equal to
- * the current phase that has the same "nextTransformer". As last phase
- * we take the phaseId of the nextTransformer - 1. This has the advantage that
- * it works even if no transformer is installed other than the sentinel
- * NoTransformer, which is always installed automatically.
+ * the current phase that has the same "nextTransformerId". As last phase
+ * we take the next transformer id following the current phase.
*/
def stablePeriod = {
var first = phaseId
- val transformers = base.denotTransformers
- val nxTrans = transformers.nextTransformer(first)
- while (first - 1 > NoPhaseId &&
- (transformers.nextTransformer(first - 1) eq nxTrans)) {
+ val nxTrans = ctx.base.nextTransformerId(first)
+ while (first - 1 > NoPhaseId && (ctx.base.nextTransformerId(first - 1) == nxTrans)) {
first -= 1
}
- Period(runId, first, nxTrans.phaseId - 1)
+ Period(runId, first, nxTrans)
}
}
diff --git a/src/dotty/tools/dotc/core/Phases.scala b/src/dotty/tools/dotc/core/Phases.scala
index 14cab9821..81ab7acbf 100644
--- a/src/dotty/tools/dotc/core/Phases.scala
+++ b/src/dotty/tools/dotc/core/Phases.scala
@@ -4,6 +4,9 @@ package core
import Periods._
import Contexts._
import util.DotClass
+import DenotTransformers._
+import Denotations._
+import config.Printers._
trait Phases { self: Context =>
import Phases._
@@ -18,6 +21,8 @@ trait Phases { self: Context =>
def atPhase[T](phase: Phase)(op: Context => T): T =
atPhase(phase.id)(op)
+ def atNextPhase[T](op: Context => T): T = atPhase(phase.next)(op)
+
def atPhaseNotLaterThan[T](limit: Phase)(op: Context => T): T =
if (!limit.exists || phase <= limit) op(this) else atPhase(limit)(op)
@@ -29,12 +34,13 @@ object Phases {
trait PhasesBase { this: ContextBase =>
- def allPhases = phases.tail
+ def allPhases = phases.tail // drop NoPhase at beginning
object NoPhase extends Phase {
override def exists = false
def name = "<no phase>"
def run(implicit ctx: Context): Unit = unsupported("run")
+ def transform(ref: SingleDenotation)(implicit ctx: Context): SingleDenotation = unsupported("transform")
}
object SomePhase extends Phase {
@@ -42,14 +48,38 @@ object Phases {
def run(implicit ctx: Context): Unit = unsupported("run")
}
+ /** A sentinel transformer object */
+ class TerminalPhase extends DenotTransformer {
+ def name = "terminal"
+ def run(implicit ctx: Context): Unit = unsupported("run")
+ def transform(ref: SingleDenotation)(implicit ctx: Context): SingleDenotation =
+ unsupported("transform")
+ 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.
*/
- def usePhases(phases: List[Phase]) =
- this.phases = (NoPhase :: phases).toArray
+ def usePhases(phases: List[Phase]) = {
+ this.phases = (NoPhase :: phases ::: new TerminalPhase :: Nil).toArray
+ this.nextTransformerId = new Array[Int](this.phases.length)
+ var i = 0
+ while (i < this.phases.length) {
+ this.phases(i)._id = i
+ i += 1
+ }
+ var lastTransformerId = i
+ while (i > 0) {
+ i -= 1
+ if (this.phases(i).isInstanceOf[DenotTransformer]) lastTransformerId = i
+ nextTransformerId(i) = lastTransformerId
+ }
+ config.println(s"Phases = ${this.phases.deep}")
+ config.println(s"nextTransformId = ${nextTransformerId.deep}")
+ }
final val typerName = "typer"
final val refchecksName = "refchecks"
@@ -69,7 +99,7 @@ object Phases {
def run(implicit ctx: Context): Unit
def runOn(units: List[CompilationUnit])(implicit ctx: Context): Unit =
- for (unit <- units) run(ctx.fresh.withCompilationUnit(unit))
+ for (unit <- units) run(ctx.fresh.withPhase(this).withCompilationUnit(unit))
def description: String = name
@@ -77,22 +107,13 @@ object Phases {
def exists: Boolean = true
- private[this] var idCache = -1
+ 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.
- * Returns -1 if the phase is not installed in the context.
+ * -1 if the phase is not installed in the context.
*/
- def id(implicit ctx: Context) = {
- val id = idCache
- val phases = ctx.phases
- if (idCache >= 0 && idCache < phases.length && (phases(idCache) eq this))
- id
- else {
- idCache = phases indexOf this
- idCache
- }
- }
+ def id = _id
final def <= (that: Phase)(implicit ctx: Context) =
exists && id <= that.id