summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/Global.scala
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2012-02-25 20:43:37 -0800
committerPaul Phillips <paulp@improving.org>2012-02-25 21:41:19 -0800
commitda12146b8f3a5215e9685cd978d898131f67f1eb (patch)
treed00f643dcfb3b08fbe2842f46a4ed54b520cf236 /src/compiler/scala/tools/nsc/Global.scala
parent7970e0d949bd8b3a5e8069e377d007351327ce80 (diff)
downloadscala-da12146b8f3a5215e9685cd978d898131f67f1eb.tar.gz
scala-da12146b8f3a5215e9685cd978d898131f67f1eb.tar.bz2
scala-da12146b8f3a5215e9685cd978d898131f67f1eb.zip
Toward a higher level abstraction than atPhase.
I guess these are self-explanatory. @inline final def afterErasure[T](op: => T): T = afterPhase(currentRun.erasurePhase)(op) @inline final def afterExplicitOuter[T](op: => T): T = afterPhase(currentRun.explicitouterPhase)(op) ... @inline final def beforeTyper[T](op: => T): T = beforePhase(currentRun.typerPhase)(op) @inline final def beforeUncurry[T](op: => T): T = beforePhase(currentRun.uncurryPhase)(op) This commit is basically pure substitution. To get anywhere interesting with all the phase-related bugs we have to determine why we use atPhase and capture that reasoning directly. With the exception of erasure, most phases don't have much meaning outside of the compiler. How can anyone know why a block of code which says atPhase(explicitouter.prev) { ... } needs to run there? Too much cargo cult, and it should stop. Every usage of atPhase should be commented as to intention. It's easy to find bugs like atPhase(uncurryPhase.prev) which was probably intended to run before uncurry, but actually runs before whatever happens to be before uncurry - which, luckily enough, is non-deterministic because the continuations plugin inserts phases between refchecks and uncurry. % scalac -Xplugin-disable:continuations -Xshow-phases refchecks 7 reference/override checking, translate nested objects uncurry 8 uncurry, translate function values to anonymous classes % scalac -Xshow-phases selectivecps 9 uncurry 10 uncurry, translate function values to anonymous classes Expressions like atPhase(somePhase.prev) are never right or are at best highly suboptimal, because most of the time you have no guarantees about what phase precedes you. Anyway, I think most or all atPhases expressed that way only wanted to run before somePhase, and because one can never be too sure without searching for documentation whether "atPhase" means before or after, people err on the side of caution and overshoot by a phase. Unfortunately, this usually works. (I prefer bugs which never work.)
Diffstat (limited to 'src/compiler/scala/tools/nsc/Global.scala')
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala22
1 files changed, 20 insertions, 2 deletions
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index ca5604c828..1a6507936c 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -224,7 +224,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
)
def logAfterEveryPhase[T](msg: String)(op: => T) {
- log("Running operation '%s' after every phase.\n" + describeAfterEveryPhase(op))
+ log("Running operation '%s' after every phase.\n".format(msg) + describeAfterEveryPhase(op))
}
// Over 200 closure objects are eliminated by inlining this.
@inline final def log(msg: => AnyRef): Unit =
@@ -866,9 +866,27 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
def currentUnit: CompilationUnit = if (currentRun eq null) NoCompilationUnit else currentRun.currentUnit
def currentSource: SourceFile = if (currentUnit.exists) currentUnit.source else lastSeenSourceFile
+ // TODO - trim these to the absolute minimum.
+ @inline final def afterErasure[T](op: => T): T = afterPhase(currentRun.erasurePhase)(op)
+ @inline final def afterExplicitOuter[T](op: => T): T = afterPhase(currentRun.explicitouterPhase)(op)
+ @inline final def afterFlatten[T](op: => T): T = afterPhase(currentRun.flattenPhase)(op)
+ @inline final def afterIcode[T](op: => T): T = afterPhase(currentRun.icodePhase)(op)
+ @inline final def afterMixin[T](op: => T): T = afterPhase(currentRun.mixinPhase)(op)
+ @inline final def afterPickler[T](op: => T): T = afterPhase(currentRun.picklerPhase)(op)
+ @inline final def afterRefchecks[T](op: => T): T = afterPhase(currentRun.refchecksPhase)(op)
+ @inline final def afterSpecialize[T](op: => T): T = afterPhase(currentRun.specializePhase)(op)
@inline final def afterTyper[T](op: => T): T = afterPhase(currentRun.typerPhase)(op)
+ @inline final def afterUncurry[T](op: => T): T = afterPhase(currentRun.uncurryPhase)(op)
@inline final def beforeErasure[T](op: => T): T = beforePhase(currentRun.erasurePhase)(op)
- @inline final def afterErasure[T](op: => T): T = afterPhase(currentRun.erasurePhase)(op)
+ @inline final def beforeExplicitOuter[T](op: => T): T = beforePhase(currentRun.explicitouterPhase)(op)
+ @inline final def beforeFlatten[T](op: => T): T = beforePhase(currentRun.flattenPhase)(op)
+ @inline final def beforeIcode[T](op: => T): T = beforePhase(currentRun.icodePhase)(op)
+ @inline final def beforeMixin[T](op: => T): T = beforePhase(currentRun.mixinPhase)(op)
+ @inline final def beforePickler[T](op: => T): T = beforePhase(currentRun.picklerPhase)(op)
+ @inline final def beforeRefchecks[T](op: => T): T = beforePhase(currentRun.refchecksPhase)(op)
+ @inline final def beforeSpecialize[T](op: => T): T = beforePhase(currentRun.specializePhase)(op)
+ @inline final def beforeTyper[T](op: => T): T = beforePhase(currentRun.typerPhase)(op)
+ @inline final def beforeUncurry[T](op: => T): T = beforePhase(currentRun.uncurryPhase)(op)
/** Don't want to introduce new errors trying to report errors,
* so swallow exceptions.