blob: 7979d3c58d2ef30cb7838f78c07e0507ec0adfe9 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
package dotty.tools.dotc
package core
import Periods._, Contexts._
trait Phases { self: Context =>
import Phases._
def phase: Phase = base.phases(period.phaseId)
def phasesStack: List[Phase] =
if ((this eq NoContext) || !phase.exists) Nil
else phase :: outersIterator.dropWhile(_.phase == phase).next.phasesStack
/** Execute `op` at given phase id */
def atPhase[T](phase: Phase)(op: Context => T): T =
atPhase(phase.id)(op)
def atPhaseNotLaterThan[T](limit: Phase)(op: Context => T): T =
if (!limit.exists || phase <= limit) op(this) else atPhase(limit)(op)
def atPhaseNotLaterThanTyper[T](op: Context => T): T =
atPhaseNotLaterThan(base.typerPhase)(op)
}
object Phases {
trait PhasesBase { this: ContextBase =>
def allPhases = phases.tail
object NoPhase extends Phase {
override def exists = false
def name = "<no phase>"
def run(implicit ctx: Context): Unit = unsupported("run")
}
object SomePhase extends Phase {
def name = "<some phase>"
def run(implicit ctx: Context): Unit = unsupported("run")
}
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
final val typerName = "typer"
final val refchecksName = "refchecks"
final val erasureName = "erasure"
final val flattenName = "flatten"
lazy val typerPhase = phaseNamed(typerName)
lazy val refchecksPhase = phaseNamed(refchecksName)
lazy val erasurePhase = phaseNamed(erasureName)
lazy val flattenPhase = phaseNamed(flattenName)
}
abstract class Phase extends DotClass {
def name: String
def run(implicit ctx: Context): Unit
def runOn(units: List[CompilationUnit])(implicit ctx: Context): Unit =
for (unit <- units) run(ctx.fresh.withCompilationUnit(unit))
def description: String = name
def checkable: Boolean = true
def exists: Boolean = true
private[this] var idCache = -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.
*/
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
}
}
final def <= (that: Phase)(implicit ctx: Context) =
exists && id <= that.id
final def prev(implicit ctx: Context): Phase =
if (id > FirstPhaseId) ctx.phases(id - 1) else ctx.NoPhase
final def next(implicit ctx: Context): Phase =
if (hasNext) ctx.phases(id + 1) else ctx.NoPhase
final def hasNext(implicit ctx: Context) = id + 1 < ctx.phases.length
final def iterator(implicit ctx: Context) =
Iterator.iterate(this)(_.next) takeWhile (_.hasNext)
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
override def toString = name
}
}
|