diff options
author | Martin Odersky <odersky@gmail.com> | 2011-01-10 14:35:20 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2011-01-10 14:35:20 +0000 |
commit | 0b78a0196af2525c4ba6978f2eb79d8abc6ec7e1 (patch) | |
tree | bfcc3c6909c82787b6da164ea048a163bd1139cf | |
parent | 09052a6a1a01986a2f8bd721ece11c43bf766ab5 (diff) | |
download | scala-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.
-rw-r--r-- | src/compiler/scala/tools/nsc/interactive/Global.scala | 22 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Namers.scala | 31 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 23 |
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) |