Skip to content

Commit 09d02bd

Browse files
committed
Allow MiniPhase to be DenotTransformer
All MiniPhases now as are full-fledged phases, and are given their own periods and can register DenotTransformers. MiniPhases belonging to same group(list) will be squashed to single phase.
1 parent 5cbd2fb commit 09d02bd

14 files changed

+278
-129
lines changed

src/dotty/tools/dotc/Compiler.scala

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,20 @@ import Symbols._
88
import typer.{FrontEnd, Typer, Mode, ImportInfo}
99
import reporting.ConsoleReporter
1010
import dotty.tools.dotc.core.Phases.Phase
11-
import dotty.tools.dotc.transform.{LazyValsCreateCompanionObjects, LazyValTranformContext}
11+
import dotty.tools.dotc.transform.{UncurryTreeTransform, LazyValsCreateCompanionObjects, LazyValTranformContext}
1212
import dotty.tools.dotc.transform.TreeTransforms.{TreeTransform, TreeTransformer}
1313
import dotty.tools.dotc.transform.PostTyperTransformers.PostTyperTransformer
14+
import dotty.tools.dotc.core.DenotTransformers.DenotTransformer
15+
import dotty.tools.dotc.core.Denotations.SingleDenotation
16+
import dotty.tools.dotc.transform.TreeTransforms.Separator
1417

1518
class Compiler {
1619

17-
18-
def phases: List[Phase] = List(new FrontEnd, new transform.SamplePhase)
20+
def phases: List[List[Phase]] = List(
21+
List(new FrontEnd), List(new LazyValsCreateCompanionObjects),
22+
//force separataion between lazyVals and LVCreateCO
23+
List(new LazyValTranformContext().transformer, new UncurryTreeTransform)
24+
)
1925

2026
var runId = 1
2127
def nextRunId = {

src/dotty/tools/dotc/core/Contexts.scala

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import collection.immutable.BitSet
2525
import printing._
2626
import config.{Settings, ScalaSettings, Platform, JavaPlatform}
2727
import language.implicitConversions
28-
28+
import DenotTransformers.DenotTransformer
2929
object Contexts {
3030

3131
/** A context is passed basically everywhere in dotc.
@@ -387,7 +387,7 @@ object Contexts {
387387
def rootLoader(root: TermSymbol)(implicit ctx: Context): SymbolLoader = platform.rootLoader(root)
388388

389389
// Set up some phases to get started */
390-
usePhases(SomePhase :: Nil)
390+
usePhases(List(List(SomePhase)))
391391

392392
/** The standard definitions */
393393
val definitions = new Definitions
@@ -460,8 +460,13 @@ object Contexts {
460460
/** Phases by id */
461461
private[core] var phases: Array[Phase] = _
462462

463+
/** Phases with consecutive Transforms groupped into a single phase */
464+
private [core] var squashedPhases: Array[Phase] = _
465+
463466
/** Next denotation transformer id */
464-
private[core] var nextTransformerId: Array[Int] = _
467+
private[core] var nextDenotTransformerId: Array[Int] = _
468+
469+
private[core] var denotTransformers: Array[DenotTransformer] = _
465470

466471
// Printers state
467472
/** Number of recursive invocations of a show method on cuyrrent stack */

src/dotty/tools/dotc/core/DenotTransformers.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ object DenotTransformers {
2121
trait DenotTransformer extends Phase {
2222

2323
/** The last phase during which the transformed denotations are valid */
24-
def lastPhaseId(implicit ctx: Context) = ctx.nextTransformerId(id + 1)
24+
def lastPhaseId(implicit ctx: Context) = ctx.nextDenotTransformerId(id + 1)
2525

2626
/** The validity period of the transformer in the given context */
2727
def validFor(implicit ctx: Context): Period =

src/dotty/tools/dotc/core/Denotations.scala

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,8 @@ object Denotations {
501501
def current(implicit ctx: Context): SingleDenotation = {
502502
val currentPeriod = ctx.period
503503
val valid = myValidFor
504+
assert(valid.code > 0, s"negative period $valid: ${valid.code}")
505+
504506
if (valid.runId != currentPeriod.runId) bringForward.current
505507
else {
506508
var cur = this
@@ -514,12 +516,15 @@ object Denotations {
514516
if (next.validFor.code > valid.code) {
515517
// in this case, next.validFor contains currentPeriod
516518
cur = next
519+
cur
517520
} else {
518521
// not found, cur points to highest existing variant
519522
var startPid = cur.validFor.lastPhaseId + 1
520-
val transformer = ctx.phases(startPid - 1).asInstanceOf[DenotTransformer]
523+
val nextTranformerId = ctx.nextDenotTransformerId(startPid)
524+
val transformer = ctx.denotTransformers(nextTranformerId)
521525
//println(s"transforming with $transformer")
522-
next = transformer.transform(cur).syncWithParents
526+
if (currentPeriod.lastPhaseId > transformer.id)
527+
next = transformer.transform(cur).syncWithParents
523528
if (next eq cur)
524529
startPid = cur.validFor.firstPhaseId
525530
else {
@@ -534,6 +539,7 @@ object Denotations {
534539
cur.validFor = Period(
535540
currentPeriod.runId, startPid, transformer.lastPhaseId)
536541
//println(s"new denot: $cur, valid for ${cur.validFor}")
542+
cur.current // multiple transformations could be required
537543
}
538544
} else {
539545
// currentPeriod < end of valid; in this case a version must exist
@@ -545,8 +551,9 @@ object Denotations {
545551
cnt += 1
546552
assert(cnt <= MaxPossiblePhaseId, s"seems to be a loop in Denotations for $this, currentPeriod = $currentPeriod")
547553
}
554+
cur
548555
}
549-
cur
556+
550557
}
551558
}
552559

src/dotty/tools/dotc/core/Periods.scala

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ abstract class Periods extends DotClass { self: Context =>
3232
*/
3333
def stablePeriod = {
3434
var first = phaseId
35-
val nxTrans = ctx.base.nextTransformerId(first)
36-
while (first - 1 > NoPhaseId && (ctx.base.nextTransformerId(first - 1) == nxTrans)) {
35+
val nxTrans = ctx.base.nextDenotTransformerId(first)
36+
while (first - 1 > NoPhaseId && (ctx.base.nextDenotTransformerId(first - 1) == nxTrans)) {
3737
first -= 1
3838
}
3939
Period(runId, first, nxTrans)
@@ -49,6 +49,8 @@ object Periods {
4949
* runid 21 bits
5050
* last phase id: 5 bits
5151
* #phases before last: 5 bits
52+
*
53+
* // Dmitry: sign == 0 isn't actually always true, in some cases phaseId == -1 is used for shifts, that easily creates code < 0
5254
*/
5355
class Period(val code: Int) extends AnyVal {
5456

src/dotty/tools/dotc/core/Phases.scala

Lines changed: 63 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,15 @@ import util.DotClass
77
import DenotTransformers._
88
import Denotations._
99
import config.Printers._
10+
import scala.collection.mutable.{ListBuffer, ArrayBuffer}
11+
import dotty.tools.dotc.transform.TreeTransforms.{TreeTransformer, TreeTransform}
12+
import dotty.tools.dotc.transform.PostTyperTransformers.PostTyperTransformer
13+
import dotty.tools.dotc.transform.TreeTransforms
14+
import TreeTransforms.Separator
15+
16+
trait Phases {
17+
self: Context =>
1018

11-
trait Phases { self: Context =>
1219
import Phases._
1320

1421
def phase: Phase = base.phases(period.phaseId)
@@ -32,9 +39,13 @@ trait Phases { self: Context =>
3239

3340
object Phases {
3441

35-
trait PhasesBase { this: ContextBase =>
42+
trait PhasesBase {
43+
this: ContextBase =>
44+
45+
// drop NoPhase at beginning
46+
def allPhases = squashedPhases.tail
47+
3648

37-
def allPhases = phases.tail // drop NoPhase at beginning
3849

3950
object NoPhase extends Phase {
4051
override def exists = false
@@ -62,10 +73,12 @@ object Phases {
6273

6374
/** Use the following phases in the order they are given.
6475
* The list should never contain NoPhase.
76+
* if squashing is enabled, phases in same subgroup will be squashed to single phase.
6577
*/
66-
def usePhases(phases: List[Phase]) = {
67-
this.phases = (NoPhase :: phases ::: new TerminalPhase :: Nil).toArray
68-
this.nextTransformerId = new Array[Int](this.phases.length)
78+
def usePhases(phases: List[List[Phase]], squash: Boolean = true) = {
79+
this.phases = (NoPhase :: phases.flatten ::: new TerminalPhase :: Nil).toArray
80+
this.nextDenotTransformerId = new Array[Int](this.phases.length)
81+
this.denotTransformers = new Array[DenotTransformer](this.phases.length)
6982
var i = 0
7083
while (i < this.phases.length) {
7184
this.phases(i)._id = i
@@ -74,11 +87,48 @@ object Phases {
7487
var lastTransformerId = i
7588
while (i > 0) {
7689
i -= 1
77-
if (this.phases(i).isInstanceOf[DenotTransformer]) lastTransformerId = i
78-
nextTransformerId(i) = lastTransformerId
90+
this.phases(i) match {
91+
case transformer: DenotTransformer =>
92+
lastTransformerId = i
93+
denotTransformers(i) = transformer
94+
case _ =>
95+
}
96+
nextDenotTransformerId(i) = lastTransformerId
7997
}
98+
99+
if (squash) {
100+
val squashedPhases = ListBuffer[Phase]()
101+
var postTyperEmmited = false
102+
var i = 0
103+
while (i < phases.length) {
104+
if (phases(i).length > 1) {
105+
assert(phases(i).forall(x => x.isInstanceOf[TreeTransform]), "Only tree transforms can be squashed")
106+
107+
val transforms = phases(i).asInstanceOf[List[TreeTransform]]
108+
val block =
109+
if (!postTyperEmmited) {
110+
postTyperEmmited = true
111+
new PostTyperTransformer {
112+
override def name: String = transformations.map(_.name).mkString("TreeTransform:{", ", ", "}")
113+
override protected def transformations: Array[TreeTransform] = transforms.toArray
114+
}
115+
} else new TreeTransformer {
116+
override def name: String = transformations.map(_.name).mkString("TreeTransform:{", ", ", "}")
117+
override protected def transformations: Array[TreeTransform] = transforms.toArray
118+
}
119+
squashedPhases += block
120+
block._id = phases(i).head.id
121+
} else squashedPhases += phases(i).head
122+
i += 1
123+
}
124+
this.squashedPhases = (NoPhase::squashedPhases.toList :::new TerminalPhase :: Nil).toArray
125+
} else {
126+
this.squashedPhases = this.phases
127+
}
128+
80129
config.println(s"Phases = ${this.phases.deep}")
81-
config.println(s"nextTransformId = ${nextTransformerId.deep}")
130+
config.println(s"squashedPhases = ${this.squashedPhases.deep}")
131+
config.println(s"nextDenotTransformerId = ${nextDenotTransformerId.deep}")
82132
}
83133

84134
final val typerName = "typer"
@@ -110,12 +160,12 @@ object Phases {
110160
private[Phases] var _id = -1
111161

112162
/** The sequence position of this phase in the given context where 0
113-
* is reserved for NoPhase and the first real phase is at position 1.
114-
* -1 if the phase is not installed in the context.
163+
* is reserved for NoPhase and the first real phase is at position 1.
164+
* -1 if the phase is not installed in the context.
115165
*/
116166
def id = _id
117167

118-
final def <= (that: Phase)(implicit ctx: Context) =
168+
final def <=(that: Phase)(implicit ctx: Context) =
119169
exists && id <= that.id
120170

121171
final def prev(implicit ctx: Context): Phase =
@@ -131,7 +181,7 @@ object Phases {
131181

132182
final def erasedTypes(implicit ctx: Context): Boolean = ctx.erasurePhase <= this
133183
final def flatClasses(implicit ctx: Context): Boolean = ctx.flattenPhase <= this
134-
final def refChecked (implicit ctx: Context): Boolean = ctx.refchecksPhase <= this
184+
final def refChecked(implicit ctx: Context): Boolean = ctx.refchecksPhase <= this
135185

136186
override def toString = name
137187
}

src/dotty/tools/dotc/transform/CreateCompanionObjects.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,13 @@ import NameOps._
1919

2020
/** A transformer that provides a convenient way to create companion objects
2121
*/
22-
abstract class CreateCompanionObjects(group: TreeTransformer, idx: Int) extends TreeTransform(group, idx) {
22+
abstract class CreateCompanionObjects extends TreeTransform {
2323

2424
import tpd._
2525

2626
/** Given class definition should return true if companion object creation should be enforced
2727
*/
28-
def predicate(cls: TypeDef)(implicit ctx:Context): Boolean
28+
def predicate(cls: TypeDef)(implicit ctx: Context): Boolean
2929

3030
override def transformStats(trees: List[Tree])(implicit ctx: Context, info: TransformerInfo): List[tpd.Tree] = {
3131
@tailrec

0 commit comments

Comments
 (0)