diff options
author | Martin Odersky <odersky@gmail.com> | 2009-05-28 17:20:39 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2009-05-28 17:20:39 +0000 |
commit | 9b2430c7766882b55994fda01bc59130e256d022 (patch) | |
tree | 4310b80e1542e5a4577c8798c6ce8fb9cc5b55ee | |
parent | 7fc525184be32f405fc027675667c8e8bfa14679 (diff) | |
download | scala-9b2430c7766882b55994fda01bc59130e256d022.tar.gz scala-9b2430c7766882b55994fda01bc59130e256d022.tar.bz2 scala-9b2430c7766882b55994fda01bc59130e256d022.zip |
more work on the interactive mode.
8 files changed, 78 insertions, 54 deletions
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index ecf2bc521c..269c1f4e2d 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -319,6 +319,9 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable val global: Global.this.type = Global.this } with Analyzer + /** Switch to turn on detailed type logs */ + var printTypings = false + // phaseName = "superaccessors" object superAccessors extends { val global: Global.this.type = Global.this diff --git a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala index 9e9b801d25..b4b207b05e 100644 --- a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala +++ b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala @@ -336,15 +336,15 @@ abstract class TreePrinters { case Literal(x) => print(x.escapedStringValue) - case TypeTree() => - print( - if (tree.tpe eq null) - "<type ?>" - else if ((tree.tpe.typeSymbol ne null) && tree.tpe.typeSymbol.isAnonymousClass) - tree.tpe.typeSymbol.toString() - else - tree.tpe.toString() - ) + case tt: TypeTree => + if (tree.tpe eq null) { + if (tt.original != null) { print("<type: "); print(tt.original); print(">") } + else print("<type ?>") + } else if ((tree.tpe.typeSymbol ne null) && tree.tpe.typeSymbol.isAnonymousClass) { + print(tree.tpe.typeSymbol.toString()) + } else { + tree.tpe.toString() + } case Annotated(Annotation(Apply(Select(New(tpt), nme.CONSTRUCTOR), args), elements), tree) => def printAnnot() { diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala index ae6003a056..f57eed60b8 100644 --- a/src/compiler/scala/tools/nsc/ast/Trees.scala +++ b/src/compiler/scala/tools/nsc/ast/Trees.scala @@ -159,9 +159,12 @@ trait Trees { /** Is there part of this tree which satisfies predicate `p'? */ def exists(p: Tree => Boolean): Boolean = !find(p).isEmpty - /** The direct children of this tree */ + /** The direct child trees of this tree + * EmptyTrees are always omitted. Lists are collapsed. + */ def children(): List[Tree] = { def subtrees(x: Any): List[Tree] = x match { + case EmptyTree => List() case t: Tree => List(t) case xs: List[_] => xs flatMap subtrees case _ => List() diff --git a/src/compiler/scala/tools/nsc/interactive/Global.scala b/src/compiler/scala/tools/nsc/interactive/Global.scala index fb448aafc0..4d72f9ae07 100755 --- a/src/compiler/scala/tools/nsc/interactive/Global.scala +++ b/src/compiler/scala/tools/nsc/interactive/Global.scala @@ -145,6 +145,7 @@ self => */ private def backgroundCompile() { inform("Starting new presentation compiler type checking pass") + reporter.reset firsts = firsts filter (s => unitOfFile contains (s.file)) val prefix = firsts map unitOf val units = prefix ::: (unitOfFile.values.toList diff prefix) @@ -161,16 +162,23 @@ self => unit.toCheck.clear() unit.targetPos = NoPosition unit.contexts.clear() - ResetAttrs.traverse(unit.body) - currentTyperRun.enterNames(unit) - unit.status = JustParsed + unit.body = EmptyTree + unit.status = NotLoaded } + /** Parse unit and create a name index. */ + def parse(unit: RichCompilationUnit): Unit = { + currentTyperRun.compileLate(unit) + validatePositions(unit.body) + unit.status = JustParsed + } + /** Make sure symbol and type attributes are reset and recompile unit. */ def recompile(unit: RichCompilationUnit) { - assert(unit.status != NotLoaded) reset(unit) + inform("parsing: "+unit) + parse(unit) inform("type checking: "+unit) currentTyperRun.typeCheck(unit) unit.status = currentRunId @@ -190,9 +198,7 @@ self => for (source <- sources) { val unit = new RichCompilationUnit(source) unitOfFile(source.file) = unit - currentTyperRun.compileLate(unit) - validatePositions(unit.body) - unit.status = JustParsed + parse(unit) } moveToFront(sources) result set Left(()) @@ -208,10 +214,13 @@ self => /** Set sync var `result` to a fully attributed tree located at position `pos` */ def typedTreeAt(pos: Position, result: SyncVar[Either[Tree, Throwable]]) { try { + println("typed tree at "+pos.show) val unit = unitOf(pos) assert(unit.status != NotLoaded) moveToFront(List(unit.source)) - result set Left(currentTyperRun.typedTreeAt(pos)) + val typedTree = currentTyperRun.typedTreeAt(pos) + val located = new Locator(pos) locateIn typedTree + result set Left(located) } catch { case ex => result set Right(ex) @@ -233,15 +242,18 @@ self => } /** A traverser that resets all type and symbol attributes in a tree */ - object ResetAttrs extends Traverser { - override def traverse(t: Tree) { + object ResetAttrs extends Transformer { + override def transform(t: Tree): Tree = { if (t.hasSymbol) t.symbol = NoSymbol t match { case EmptyTree => - ; + t + case tt: TypeTree => + if (tt.original != null) tt.original + else t case _ => t.tpe = null - super.traverse(t) + super.transform(t) } } } @@ -252,13 +264,9 @@ self => // symSource, symData are ignored override def compiles(sym: Symbol) = false - def typeCheck(unit: CompilationUnit) { - applyPhase(typerPhase, unit) - } + def typeCheck(unit: CompilationUnit): Unit = applyPhase(typerPhase, unit) - def enterNames(unit: CompilationUnit) { - applyPhase(namerPhase, unit) - } + def enterNames(unit: CompilationUnit): Unit = applyPhase(namerPhase, unit) /** Return fully attributed tree at given position * (i.e. largest tree that's contained by position) @@ -280,7 +288,9 @@ self => } } - /** Apply a phase to a compilation unit */ + /** Apply a phase to a compilation unit + * @return true iff typechecked correctly + */ private def applyPhase(phase: Phase, unit: CompilationUnit) { val oldSource = reporter.getSource try { diff --git a/src/compiler/scala/tools/nsc/interactive/Positions.scala b/src/compiler/scala/tools/nsc/interactive/Positions.scala index ce4de1d311..f30fc83a2b 100755 --- a/src/compiler/scala/tools/nsc/interactive/Positions.scala +++ b/src/compiler/scala/tools/nsc/interactive/Positions.scala @@ -24,7 +24,7 @@ import scala.collection.mutable.ListBuffer trait Positions extends Trees { self: Global => - private case class Range(val pos: Position, val tree: Tree) { + case class Range(val pos: Position, val tree: Tree) { def isFree = tree == EmptyTree } @@ -83,22 +83,26 @@ self: Global => * @param ranges The current list of non-overlapping ranges, * both occupied and free, sorted from later to earlier. * No TransparentPositions allowed here! - * @param cts The list of trees to insert in ranges. + * @param trees The list of trees to insert in ranges. */ - def iterate(ranges: List[Range], cts: List[Tree]): Unit = cts match { + def iterate(ranges: List[Range], trees: List[Tree]): Unit = trees match { case List() => ; - case ct :: cts1 => - val conflicting = new ListBuffer[Tree] - val ranges1 = insert(ranges, ct, conflicting) - if (conflicting.isEmpty) { - iterate(ranges1, cts1) - } else { - val splitNode = - if (conflicting.size == 1 && (conflicting.head.pos includes ct.pos)) conflicting.head - else ct - splitNode setPos new TransparentPosition(splitNode.pos.source.get, splitNode.pos.start, splitNode.pos.point, splitNode.pos.end) - ensureNonOverlapping(replace(cts, splitNode, solidDescendants(splitNode))) + case ct :: trees1 => + if (isTransparent(ct.pos)) + iterate(ranges, solidDescendants(ct) ::: trees1) + else if (ct.pos.isDefined) { + val conflicting = new ListBuffer[Tree] + val ranges1 = insert(ranges, ct, conflicting) + if (conflicting.isEmpty) { + iterate(ranges1, trees1) + } else { + val splitNode = + if (conflicting.size == 1 && (conflicting.head.pos includes ct.pos)) conflicting.head + else ct + splitNode setPos new TransparentPosition(splitNode.pos.source.get, splitNode.pos.start, splitNode.pos.point, splitNode.pos.end) + ensureNonOverlapping(replace(cts, splitNode, solidDescendants(splitNode))) + } } } @@ -131,15 +135,18 @@ self: Global => private def setChildrenPos(pos: Position, trees: List[Tree]) { var currentPos = pos for (tree <- trees) { - val children = tree.children - if (children.isEmpty) - tree setPos OffsetPosition(pos.source.get, currentPos.start) - else { - setChildrenPos(currentPos, children) - tree setPos new RangePosition( - pos.source.get, (children map (_.pos.start)).min, pos.point, (children map (_.pos.end)).max) + if (tree != EmptyTree && tree.pos == NoPosition) { + val children = tree.children + if (children.isEmpty) + tree setPos OffsetPosition(pos.source.get, currentPos.start) + else { + setChildrenPos(currentPos, children) + tree setPos new RangePosition( + pos.source.get, (children map (_.pos.start)).min, pos.point, (children map (_.pos.end)).max) + } + currentPos = new RangePosition(pos.source.get, tree.pos.end, pos.point, pos.end) } - currentPos = new RangePosition(pos.source.get, tree.pos.end, pos.point, pos.end) +// println("set children pos "+pos+" of "+trees) } ensureNonOverlapping(trees) } diff --git a/src/compiler/scala/tools/nsc/interactive/REPL.scala b/src/compiler/scala/tools/nsc/interactive/REPL.scala index e773f9f281..f63789fc9b 100644 --- a/src/compiler/scala/tools/nsc/interactive/REPL.scala +++ b/src/compiler/scala/tools/nsc/interactive/REPL.scala @@ -32,7 +32,9 @@ object REPL { reporter.info(null, versionMsg, true) else { try { - object compiler extends Global(command.settings, reporter) + object compiler extends Global(command.settings, reporter) { +// printTypings = true + } if (reporter.hasErrors) { reporter.flush() return diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index c3f0365663..d43d09f79f 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -27,8 +27,6 @@ trait Typers { self: Analyzer => import global._ import definitions._ - private final val printTypings = false - var appcnt = 0 var idcnt = 0 var selcnt = 0 diff --git a/src/compiler/scala/tools/nsc/util/Position.scala b/src/compiler/scala/tools/nsc/util/Position.scala index 1063135b8b..6707bf6243 100644 --- a/src/compiler/scala/tools/nsc/util/Position.scala +++ b/src/compiler/scala/tools/nsc/util/Position.scala @@ -44,6 +44,7 @@ trait Position { precedes(pos) && start < pos.end def overlaps(pos: Position) = + isDefined && pos.isDefined && (pos.start <= start && start < pos.end) || (start <= pos.start && pos.start < end) def sameRange(pos: Position) = |