diff options
author | Martin Odersky <odersky@gmail.com> | 2014-03-15 17:10:24 +0100 |
---|---|---|
committer | Dmitry Petrashko <dmitry.petrashko@gmail.com> | 2014-03-18 16:06:33 +0100 |
commit | 1dbf020c43639b0c37e9005f2692871d39676ac7 (patch) | |
tree | b1855130096b99917845a715344ba6a768ede1fc /src/dotty/tools/dotc/core | |
parent | 76ea699ac1a76ee6048d7fe8239d0a1126581429 (diff) | |
download | dotty-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.scala | 5 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/DenotTransformers.scala | 44 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Denotations.scala | 11 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Periods.scala | 14 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Phases.scala | 53 |
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 |