summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2011-01-10 14:35:20 +0000
committerMartin Odersky <odersky@gmail.com>2011-01-10 14:35:20 +0000
commit0b78a0196af2525c4ba6978f2eb79d8abc6ec7e1 (patch)
treebfcc3c6909c82787b6da164ea048a163bd1139cf /src
parent09052a6a1a01986a2f8bd721ece11c43bf766ab5 (diff)
downloadscala-0b78a0196af2525c4ba6978f2eb79d8abc6ec7e1.tar.gz
scala-0b78a0196af2525c4ba6978f2eb79d8abc6ec7e1.tar.bz2
scala-0b78a0196af2525c4ba6978f2eb79d8abc6ec7e1.zip
Made presentation type checker idempotent and r...
Made presentation type checker idempotent and removed code in Global that was needed to work around non-idempotency.
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/interactive/Global.scala22
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala31
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala23
3 files changed, 45 insertions, 31 deletions
diff --git a/src/compiler/scala/tools/nsc/interactive/Global.scala b/src/compiler/scala/tools/nsc/interactive/Global.scala
index 99619e3a2f..7f8f3385bf 100644
--- a/src/compiler/scala/tools/nsc/interactive/Global.scala
+++ b/src/compiler/scala/tools/nsc/interactive/Global.scala
@@ -114,7 +114,7 @@ self =>
while(true)
try {
try {
- pollForWork()
+ pollForWork(old.pos)
} catch {
case ex : Throwable =>
if (context.unit != null) integrateNew()
@@ -176,7 +176,7 @@ self =>
* Then, poll for exceptions and execute them.
* Then, poll for work reload/typedTreeAt/doFirst commands during background checking.
*/
- def pollForWork() {
+ def pollForWork(pos: Position) {
scheduler.pollInterrupt() match {
case Some(ir) =>
try {
@@ -185,7 +185,7 @@ self =>
} finally {
activeLocks -= 1
}
- pollForWork()
+ pollForWork(pos)
case _ =>
}
@@ -219,7 +219,7 @@ self =>
logreplay("workitem", scheduler.nextWorkItem()) match {
case Some(action) =>
try {
- debugLog("picked up work item: "+action)
+ debugLog("picked up work item at "+pos+": "+action)
action()
debugLog("done with work item: "+action)
} finally {
@@ -282,7 +282,7 @@ self =>
try {
while (true) {
logreplay("wait for more work", { scheduler.waitForMoreWork(); true })
- pollForWork()
+ pollForWork(NoPosition)
debugLog("got more work")
while (outOfDate) {
try {
@@ -359,7 +359,7 @@ self =>
*/
def typeCheck(unit: RichCompilationUnit) {
debugLog("type checking: "+unit)
- if (currentlyChecked == Some(unit) || unit.status > JustParsed) reset(unit)
+ //if (currentlyChecked == Some(unit) || unit.status > JustParsed) reset(unit) // not deeded for idempotent type checker phase
if (unit.status == NotLoaded) parse(unit)
currentlyChecked = Some(unit)
currentTyperRun.typeCheck(unit)
@@ -412,9 +412,11 @@ self =>
} catch {
case CancelException =>
;
+/* Commented out. Typing should always cancel requests
case ex @ FreshRunReq =>
scheduler.postWorkItem(() => respondGradually(response)(op))
throw ex
+*/
case ex =>
response raise ex
throw ex
@@ -459,7 +461,7 @@ self =>
unit.targetPos = pos
try {
debugLog("starting targeted type check")
- newTyperRun()
+ //newTyperRun() // not deeded for idempotent type checker phase
typeCheck(unit)
println("tree not found at "+pos)
EmptyTree
@@ -477,7 +479,7 @@ self =>
val unit = unitOf(source)
if (forceReload) reset(unit)
if (unit.status <= JustParsed) {
- newTyperRun()
+ //newTyperRun() // not deeded for idempotent type checker phase
typeCheck(unit)
}
unit.body
@@ -678,10 +680,10 @@ self =>
class TyperRun extends Run {
// units is always empty
- /** canRedefine is used to detect double declarations in multiple source files.
+ /** canRedefine is used to detect double declarations of classes and objects
+ * in multiple source files.
* Since the IDE rechecks units several times in the same run, these tests
* are disabled by always returning true here.
- * (I think we don't need that anymore)
*/
override def canRedefine(sym: Symbol) = true
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 8111e2f5a1..775731df2b 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -173,10 +173,10 @@ trait Namers { self: Analyzer =>
if (!(sym.isSourceMethod && sym.owner.isClass && !sym.owner.isPackageClass)) {
var prev = scope.lookupEntry(sym.name)
if ((prev ne null) && prev.owner == scope && conflict(sym, prev.sym)) {
- doubleDefError(sym.pos, prev.sym)
- sym setInfo ErrorType
- scope unlink prev.sym // let them co-exist...
- scope enter sym
+ doubleDefError(sym.pos, prev.sym)
+ sym setInfo ErrorType
+ scope unlink prev.sym // let them co-exist...
+ scope enter sym
} else scope enter sym
} else scope enter sym
}
@@ -338,13 +338,32 @@ trait Namers { self: Analyzer =>
} else setInfo(sym)(ltype)
}
+ def enterIfNotThere(sym: Symbol) {
+ val scope = context.scope
+ var e = scope.lookupEntry(sym.name)
+ while ((e ne null) && (e.owner eq scope) && (e.sym ne sym)) e = e.tail
+ if (!((e ne null) && (e.owner eq scope))) context.scope.enter(sym)
+ }
+
def enterSym(tree: Tree): Context = {
def finishWith(tparams: List[TypeDef]) { enterSymFinishWith(tree, tparams) }
def finish = finishWith(Nil)
def sym = tree.symbol
- if (sym != NoSymbol)
+ if (sym != NoSymbol) {
+ if (forInteractive && sym != null && sym.owner.isTerm) {
+ // this logic is needed in case typer was interrupted half way through and then comes
+ // back to do the tree again. In that case the definitions that were already
+ // attributed as well as any default parameters of such methods need to be
+ // re-entered in the current scope.
+ enterIfNotThere(sym)
+ if (sym.isLazy) {
+ val acc = sym.lazyAccessor
+ if (acc != NoSymbol) enterIfNotThere(acc)
+ }
+ defaultParametersOfMethod(sym) foreach enterIfNotThere
+ }
return this.context
-
+ }
try {
val owner = context.owner
tree match {
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 28faf16541..522e39837a 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -1798,23 +1798,9 @@ trait Typers extends Modes {
*/
def typedBlock(block: Block, mode: Int, pt: Type): Block = {
val syntheticPrivates = new ListBuffer[Symbol]
- def enterIfNotThere(sym: Symbol) {
- var e = context.scope.lookupEntry(sym.name)
- while ((e ne null) && (e.sym ne sym)) e = e.tail
- if (e eq null) context.scope.enter(sym)
- }
try {
namer.enterSyms(block.stats)
- for (stat <- block.stats) {
- if (forInteractive && stat.isDef) {
- // this logic is needed in case typer was interrupted half way through a block and then comes
- // back to do the block again. In that case the definitions that were already attributed as well as any
- // default parameters of such methods need to be re-entered in the current scope.
- enterIfNotThere(stat.symbol)
- defaultParametersOfMethod(stat.symbol) foreach enterIfNotThere
- }
- enterLabelDef(stat)
- }
+ for (stat <- block.stats) enterLabelDef(stat)
if (phaseId(currentPeriod) <= currentRun.typerPhase.id) {
// This is very tricky stuff, because we are navigating
@@ -1888,6 +1874,13 @@ trait Typers extends Modes {
error(x.pos, "_* may only come last")
val pat1: Tree = typedPattern(cdef.pat, pattpe)
+
+ if (forInteractive) {
+ for (bind @ Bind(name, _) <- cdef.pat)
+ if (name.toTermName != nme.WILDCARD && bind.symbol != null && bind.symbol != NoSymbol)
+ namer.enterIfNotThere(bind.symbol)
+ }
+
val guard1: Tree = if (cdef.guard == EmptyTree) EmptyTree
else typed(cdef.guard, BooleanClass.tpe)
var body1: Tree = typed(cdef.body, pt)