From 02827fb0819f36d5cebd52ff2c1f5688f7fc2575 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 29 May 2009 14:30:07 +0000 Subject: minor twiddling with position. --- src/compiler/scala/tools/nsc/ast/Trees.scala | 38 ++++++++++---- .../scala/tools/nsc/interactive/Positions.scala | 14 +++-- .../scala/tools/nsc/interactive/REPL.scala | 2 +- .../scala/tools/nsc/typechecker/Typers.scala | 24 +++++---- src/compiler/scala/tools/nsc/util/Position.scala | 59 +++++++++++++++++++++- 5 files changed, 109 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala index f57eed60b8..3de4df932f 100644 --- a/src/compiler/scala/tools/nsc/ast/Trees.scala +++ b/src/compiler/scala/tools/nsc/ast/Trees.scala @@ -116,6 +116,10 @@ trait Trees { this } + def setOriginal(tree: Tree): this.type = { + setPos(SyntheticAliasPosition(tree)) + } + def setType(tp: Type): this.type = { /*assert(kindingIrrelevant(tp) || !kindStar || !tp.isHigherKinded, tp+" should not be higher-kinded");*/ @@ -424,6 +428,7 @@ trait Trees { object emptyValDef extends ValDef(Modifiers(PRIVATE), nme.WILDCARD, TypeTree(NoType), EmptyTree) { override def isEmpty = true + setPos(NoPosition) } /** Method definition @@ -585,7 +590,7 @@ trait Trees { vparamss map (vps => vps.map { vd => ValDef( Modifiers(vd.mods.flags & IMPLICIT | PARAM) withAnnotations vd.mods.annotations, - vd.name, vd.tpt.duplicate, EmptyTree).setPos(vd.pos) + vd.name, vd.tpt.duplicate, EmptyTree).setOriginal(vd) }) val (edefs, rest) = body span treeInfo.isEarlyDef val (evdefs, etdefs) = edefs partition treeInfo.isEarlyValDef @@ -607,7 +612,7 @@ trait Trees { !vparamss1.head.isEmpty && (vparamss1.head.head.mods.flags & IMPLICIT) != 0) vparamss1 = List() :: vparamss1; val superRef: Tree = Select(Super(nme.EMPTY.toTypeName, nme.EMPTY.toTypeName), nme.CONSTRUCTOR) - val superCall = atPos(parents.head.pos) { (superRef /: argss) (Apply) } + val superCall = atPos(parents.head) { (superRef /: argss) (Apply) } List( DefDef(constrMods, nme.CONSTRUCTOR, List(), vparamss1, TypeTree(), Block(lvdefs ::: List(superCall), Literal(())))) } @@ -824,12 +829,8 @@ trait Trees { case class TypeTree() extends TypTree { override def symbol = if (tpe == null) null else tpe.typeSymbol - def setOriginal(tree: Tree): this.type = { - setPos(SyntheticPosition(tree)) - } - def original: Tree = pos match { - case SyntheticPosition(orig) => orig + case SyntheticAliasPosition(orig) => orig case _ => null } @@ -1705,12 +1706,29 @@ trait Trees { } } + object syntheticMaker extends Traverser { + override def traverse(t: Tree) { + if (!t.pos.isSynthetic) { + t setPos t.pos.toSynthetic + super.traverse(t) + } + } + } + def atPos[T <: Tree](pos: Position)(tree: T): T = { posAssigner.pos = pos posAssigner.traverse(tree) tree } + def atPos[T <: Tree](original: Tree)(tree: T): T = + atPos(SyntheticAliasPosition(original))(tree) + + def makeSynthetic[T <: Tree](tree: T): T = { + syntheticMaker.traverse(tree) + tree + } + class ForeachTreeTraverser(f: Tree => Unit) extends Traverser { override def traverse(t: Tree) { f(t) @@ -1789,7 +1807,7 @@ trait Trees { /** A position to be used for synthetic trees that correspond to some original tree * @note Trees with synthetic positions may not contain trees with real positions inside them! */ - case class SyntheticPosition(original: Tree) extends Position { + case class SyntheticAliasPosition(original: Tree) extends Position { override def isDefined: Boolean = true override def isSynthetic: Boolean = true override def offset: Option[Int] = original.pos.offset @@ -1798,7 +1816,9 @@ trait Trees { override def point: Int = original.pos.point override def end: Int = original.pos.end override def underlying = original.pos.underlying - override def focus = original.pos.focus + override def focusStart = original.pos.focusStart + override def focusPoint = original.pos.focusPoint + override def focusEnd = original.pos.focusEnd override def show = "["+ underlying.show +"]" } } diff --git a/src/compiler/scala/tools/nsc/interactive/Positions.scala b/src/compiler/scala/tools/nsc/interactive/Positions.scala index f30fc83a2b..36c60e7a2c 100755 --- a/src/compiler/scala/tools/nsc/interactive/Positions.scala +++ b/src/compiler/scala/tools/nsc/interactive/Positions.scala @@ -91,7 +91,7 @@ self: Global => case ct :: trees1 => if (isTransparent(ct.pos)) iterate(ranges, solidDescendants(ct) ::: trees1) - else if (ct.pos.isDefined) { + else if (ct.pos.isDefined && !ct.pos.isSynthetic) { val conflicting = new ListBuffer[Tree] val ranges1 = insert(ranges, ct, conflicting) if (conflicting.isEmpty) { @@ -113,9 +113,11 @@ self: Global => def findOverlapping(cts: List[Tree]): List[(Tree, Tree)] = { var ranges = List(maxFree) for (ct <- cts) { - val conflicting = new ListBuffer[Tree] - ranges = insert(ranges, ct, conflicting) - if (conflicting.nonEmpty) return conflicting.toList map (t => (t, ct)) + if (ct.pos.isDefined && !ct.pos.isSynthetic) { + val conflicting = new ListBuffer[Tree] + ranges = insert(ranges, ct, conflicting) + if (conflicting.nonEmpty) return conflicting.toList map (t => (t, ct)) + } } List() } @@ -124,7 +126,6 @@ self: Global => /** The sorted list of descendant nodes, a long positions */ - /** Set position of all children of a node * @param pos A target position. * Uses the point of the position as the point of all positions it assigns. @@ -179,12 +180,15 @@ self: Global => inform(tree.toString) } def validate(tree: Tree, encltree: Tree) { + if (tree != EmptyTree && !tree.pos.isDefined) + error("tree without position: "+tree) if (encltree.pos.isSynthetic && !tree.pos.isSynthetic) error("synthetic "+encltree+" contains nonsynthetic" + tree) if (!(encltree.pos includes tree.pos)) error(encltree+" does not include "+tree) for ((t1, t2) <- findOverlapping(tree.children flatMap solidDescendants)) error("overlapping trees: "+t1+" === and === "+t2) + for (ct <- tree.children flatMap solidDescendants) validate(ct, tree) } validate(tree, tree) } diff --git a/src/compiler/scala/tools/nsc/interactive/REPL.scala b/src/compiler/scala/tools/nsc/interactive/REPL.scala index f63789fc9b..331cdd597a 100644 --- a/src/compiler/scala/tools/nsc/interactive/REPL.scala +++ b/src/compiler/scala/tools/nsc/interactive/REPL.scala @@ -33,7 +33,7 @@ object REPL { else { try { object compiler extends Global(command.settings, reporter) { -// printTypings = true + printTypings = true } if (reporter.hasErrors) { reporter.flush() diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 915786597c..002830bd0c 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -576,13 +576,13 @@ trait Typers { self: Analyzer => case _ => } } - val qual = typedQualifier { + val qual = typedQualifier { atPos(tree.pos.focusStart) { tree match { case Ident(_) => Ident(nme.PACKAGEkw) case Select(qual, _) => Select(qual, nme.PACKAGEkw) case SelectFromTypeTree(qual, _) => Select(qual, nme.PACKAGEkw) } - } + }} val tree1 = atPos(tree.pos) { tree match { case Ident(name) => Select(qual, name) @@ -1226,12 +1226,12 @@ trait Typers { self: Analyzer => assert(getter != NoSymbol, stat) if (getter hasFlag OVERLOADED) error(getter.pos, getter+" is defined twice") - val getterDef: DefDef = { + val getterDef: DefDef = atPos(vdef) { getter.attributes = value.initialize.attributes val result = DefDef(getter, vparamss => if (mods hasFlag DEFERRED) EmptyTree else typed( - atPos(vdef.pos) { gen.mkCheckInit(Select(This(value.owner), value)) }, + atPos(vdef) { gen.mkCheckInit(Select(This(value.owner), value)) }, EXPRmode, value.tpe)) result.tpt.asInstanceOf[TypeTree] setOriginal tpt /* setPos tpt.pos */ checkNoEscaping.privates(getter, result.tpt) @@ -1242,7 +1242,7 @@ trait Typers { self: Analyzer => def setterDef: DefDef = { val setr = getter.setter(value.owner) setr.attributes = value.attributes - val result = atPos(vdef.pos)( + val result = atPos(vdef)( DefDef(setr, vparamss => if ((mods hasFlag DEFERRED) || (setr hasFlag OVERLOADED)) EmptyTree @@ -3071,7 +3071,7 @@ trait Typers { self: Analyzer => else if (!defSym.owner.isClass || defSym.owner.isPackageClass || defSym.isTypeParameterOrSkolem) pre = NoPrefix else - qual = atPos(tree.pos)(gen.mkAttributedQualifier(pre)) + qual = atPos(tree.pos.focusStart)(gen.mkAttributedQualifier(pre)) } else { if (impSym.exists) { var impSym1 = NoSymbol @@ -3097,7 +3097,7 @@ trait Typers { self: Analyzer => imports1 = imports1.tail } defSym = impSym - qual = atPos(tree.pos)(resetPos(imports.head.qual.duplicate)) + qual = atPos(tree.pos.focusStart)(resetPos(imports.head.qual.duplicate)) pre = qual.tpe } else { if (settings.debug.value) { @@ -3267,10 +3267,12 @@ trait Typers { self: Analyzer => if (selector == EmptyTree) { val arity = if (isFunctionType(pt)) pt.normalize.typeArgs.length - 1 else 1 val params = for (i <- List.range(0, arity)) yield - ValDef(Modifiers(PARAM | SYNTHETIC), - unit.fresh.newName(tree.pos, "x" + i + "$"), TypeTree(), EmptyTree) + atPos(tree.pos.focusStart) { + ValDef(Modifiers(PARAM | SYNTHETIC), + unit.fresh.newName(tree.pos, "x" + i + "$"), TypeTree(), EmptyTree) + } val ids = for (p <- params) yield Ident(p.name) - val selector1 = atPos(tree.pos) { if (arity == 1) ids.head else gen.mkTuple(ids) } + val selector1 = atPos(tree.pos.focusStart) { if (arity == 1) ids.head else gen.mkTuple(ids) } val body = copy.Match(tree, selector1, cases) typed1(atPos(tree.pos) { Function(params, body) }, mode, pt) } else { @@ -3426,7 +3428,7 @@ trait Typers { self: Analyzer => case TypeTree() => tree.pos match { - case SyntheticPosition(original) => + case SyntheticAliasPosition(original) => tree setType typedType(original, mode).tpe case _ => // we should get here only when something before failed diff --git a/src/compiler/scala/tools/nsc/util/Position.scala b/src/compiler/scala/tools/nsc/util/Position.scala index 6707bf6243..07b0a785d5 100644 --- a/src/compiler/scala/tools/nsc/util/Position.scala +++ b/src/compiler/scala/tools/nsc/util/Position.scala @@ -17,6 +17,7 @@ trait Position { def source: Option[SourceFile] = None def isDefined: Boolean = false def isSynthetic: Boolean = false + def toSynthetic: Position = this def start: Int = point def point: Int = offset.get @@ -26,8 +27,31 @@ trait Position { def pointOrElse(d: Int) = offset.getOrElse(d) def endOrElse(d: Int) = offset.getOrElse(d) + def withStart(off: Int) = this + def withEnd(off: Int) = this + def withPoint(off: Int) = this + + /** If this is a range, the union with the other range, with the point of this position. + * Otherwise, this position + */ + def union(pos: Position) = this + def underlying = this - def focus = this + + /** If this is a range position, the offset position of its start. + * Otherwise the position itself + */ + def focusStart = this + + /** If this is a range position, the offset position of its point. + * Otherwise the position itself + */ + def focusPoint = this + + /** If this is a range position, the offset position of its end. + * Otherwise the position itself + */ + def focusEnd = this def includes(pos: Position) = isDefined && pos.isDefined && start <= pos.start && pos.end <= end @@ -113,7 +137,9 @@ case class FakePos(msg: String) extends Position { case class OffsetPosition(source0: SourceFile, offset0: Int) extends Position { override def source = Some(source0) override def offset = Some(offset0) + override def withPoint(off: Int) = new OffsetPosition(source0, off) override def isDefined = true + override def toSynthetic: Position = new SyntheticOffsetPosition(source0, offset0) override def equals(that : Any) = that match { case that : OffsetPosition => offset0 == that.offset0 && source0.file == that.source0.file case that => false @@ -122,17 +148,46 @@ case class OffsetPosition(source0: SourceFile, offset0: Int) extends Position { override def show = "["+point+"]" } +class SyntheticOffsetPosition(source0: SourceFile, offset0: Int) extends OffsetPosition(source0, offset0) { + override def isSynthetic = true + override def toSynthetic = this + override def withPoint(off: Int) = new SyntheticOffsetPosition(source0, off) +} + /** new for position ranges */ class RangePosition(source0: SourceFile, override val start: Int, override val point: Int, override val end: Int) extends OffsetPosition(source0, point) { override def isDefined = true override def startOrElse(d: Int) = start override def pointOrElse(d: Int) = point + override def withStart(off: Int) = new RangePosition(source0, off, point, end) + override def withEnd(off: Int) = new RangePosition(source0, start, off, end) + override def withPoint(off: Int) = new RangePosition(source0, start, point, off) + override def union(pos: Position) = new RangePosition(source0, start min pos.start, point, end max pos.end) override def endOrElse(d: Int) = end - override def focus = OffsetPosition(source0, point) + override def focusStart = OffsetPosition(source0, start) + override def focusPoint = OffsetPosition(source0, point) + override def focusEnd = OffsetPosition(source0, end) + override def toSynthetic = new SyntheticRangePosition(source0, start, point, end) override def toString = "RangePosition("+source0+", "+start+", "+point+", "+end+")" override def show = "["+start+":"+end+"]" } +/** A position to be used for synthetic trees that do not correspond to some original tree + * @note Trees with synthetic positions may not contain trees with real positions inside them! + */ +class SyntheticRangePosition(source0: SourceFile, start: Int, point: Int, end: Int) extends RangePosition(source0, start, point, end) { + override def isSynthetic = true + override def toSynthetic = this + override def withStart(off: Int) = new SyntheticRangePosition(source0, off, point, end) + override def withEnd(off: Int) = new SyntheticRangePosition(source0, start, off, end) + override def withPoint(off: Int) = new SyntheticRangePosition(source0, start, point, off) + override def union(pos: Position) = new SyntheticRangePosition(source0, start min pos.start, point, end max pos.end) + override def focusStart = new SyntheticOffsetPosition(source0, start) + override def focusPoint = new SyntheticOffsetPosition(source0, point) + override def focusEnd = new SyntheticOffsetPosition(source0, end) +} + + -- cgit v1.2.3