From cf4c6c334a045b6da6ad9ea0249a6602e9558649 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 2 Jun 2009 21:32:36 +0000 Subject: fixed some problems with positions. --- src/compiler/scala/tools/nsc/ast/Trees.scala | 18 ++++--- .../scala/tools/nsc/interactive/ContextTrees.scala | 24 +++++---- .../scala/tools/nsc/interactive/Positions.scala | 63 +++++++++++++++------- src/compiler/scala/tools/nsc/symtab/Types.scala | 2 +- .../scala/tools/nsc/typechecker/Infer.scala | 1 + src/library/scala/Enumeration.scala | 13 +++-- 6 files changed, 76 insertions(+), 45 deletions(-) diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala index 53644c6bee..02768ddb5b 100644 --- a/src/compiler/scala/tools/nsc/ast/Trees.scala +++ b/src/compiler/scala/tools/nsc/ast/Trees.scala @@ -113,6 +113,10 @@ trait Trees { def tpe_=(t: Type) = rawtpe = t def setPos(pos: Position): this.type = { + pos match { + case SyntheticAliasPosition(orig) => assert(orig != this) + case _ => + } // !!! rawpos = pos; this } @@ -569,17 +573,19 @@ trait Trees { // create parameters for var vparamss1 = vparamss map (vps => vps.map { vd => - ValDef( - Modifiers(vd.mods.flags & (IMPLICIT | DEFAULTPARAM) | PARAM) withAnnotations vd.mods.annotations, - vd.name, vd.tpt.duplicate, vd.rhs.duplicate).setOriginal(vd) - }) + atPos(vd) { + ValDef( + Modifiers(vd.mods.flags & IMPLICIT | PARAM) withAnnotations vd.mods.annotations, + vd.name, atPos(vd.tpt) { vd.tpt.duplicate }, EmptyTree) + }}) val (edefs, rest) = body span treeInfo.isEarlyDef val (evdefs, etdefs) = edefs partition treeInfo.isEarlyValDef val (lvdefs, gvdefs) = List.unzip { evdefs map { case vdef @ ValDef(mods, name, tpt, rhs) => - (treeCopy.ValDef(vdef, Modifiers(PRESUPER), name, tpt, rhs), - treeCopy.ValDef(vdef, mods, name, TypeTree(), EmptyTree)) + val fld = atPos(vdef.pos) { treeCopy.ValDef(vdef, mods, name, TypeTree(), EmptyTree) } + val local = atPos(fld) { treeCopy.ValDef(vdef, Modifiers(PRESUPER), name, tpt, rhs) } + (local, fld) } } val constrs = diff --git a/src/compiler/scala/tools/nsc/interactive/ContextTrees.scala b/src/compiler/scala/tools/nsc/interactive/ContextTrees.scala index 5ed0581bdf..8d188cac62 100755 --- a/src/compiler/scala/tools/nsc/interactive/ContextTrees.scala +++ b/src/compiler/scala/tools/nsc/interactive/ContextTrees.scala @@ -23,7 +23,7 @@ trait ContextTrees { self: Global => override def toString = "ContextTree("+pos+", "+children+")" } - /** Optionally return the smallest context taht contains given `pos`, or None if none exists. + /** Optionally return the smallest context that contains given `pos`, or None if none exists. */ def locateContext(contexts: Contexts, pos: Position): Option[Context] = { if (contexts.isEmpty) None @@ -32,17 +32,17 @@ trait ContextTrees { self: Global => if ((contexts(hi).pos precedes pos) || (pos precedes contexts(0).pos)) None else { def loop(lo: Int, hi: Int): Option[Context] = { - assert(lo <= hi) val mid = (lo + hi) / 2 val midpos = contexts(mid).pos - if (pos precedes midpos) - loop(lo, mid - 1) - else if (midpos precedes pos) - loop(mid + 1, hi) + if ((pos precedes midpos) && (mid < hi)) + loop(lo, mid) + else if ((midpos precedes pos) && (lo < mid)) + loop(mid, hi) else if (midpos includes pos) - locateContext(contexts(mid).children, pos) orElse Some(contexts(mid).context) - else - None + Some(contexts(mid).context) + else if (contexts(mid+1).pos includes pos) + Some(contexts(mid+1).context) + else None } loop(0, hi) } @@ -74,7 +74,7 @@ trait ContextTrees { self: Global => if (contexts(hi).pos properlyPrecedes cpos) contexts += new ContextTree(cpos, context) else if (contexts(hi).pos properlyIncludes cpos) // fast path w/o search - addContext(contexts(hi).children, context) + addContext(contexts(hi).children, context, cpos) else if (cpos properlyPrecedes contexts(0).pos) new ContextTree(cpos, context) +: contexts else { @@ -84,7 +84,7 @@ trait ContextTrees { self: Global => contexts(idx) = new ContextTree(cpos, context, contexts(idx).children) true } else if (oldpos includes cpos) { - addContext(contexts(idx).children, context) + addContext(contexts(idx).children, context, cpos) true } else if (cpos includes oldpos) { val start = contexts.indexWhere(cpos includes _.pos) @@ -116,6 +116,8 @@ trait ContextTrees { self: Global => } } catch { case ex: Throwable => + println(ex) + ex.printStackTrace() println("failure inserting "+cpos+" into "+contexts+"/"+contexts(contexts.length - 1).pos+"/"+ (contexts(contexts.length - 1).pos includes cpos)) throw ex diff --git a/src/compiler/scala/tools/nsc/interactive/Positions.scala b/src/compiler/scala/tools/nsc/interactive/Positions.scala index 2eaf32f6db..e253f2f3d8 100755 --- a/src/compiler/scala/tools/nsc/interactive/Positions.scala +++ b/src/compiler/scala/tools/nsc/interactive/Positions.scala @@ -66,6 +66,7 @@ self: Global => case r :: rs1 => assert(!isTransparent(t.pos)) if (r.isFree && (r.pos includes t.pos)) { +// println("subdividing "+r+"/"+t.pos) maybeFree(t.pos.end, r.pos.end) ::: List(Range(t.pos, t)) ::: maybeFree(r.pos.start, t.pos.start) ::: rs1 } else { if (!r.isFree && (r.pos overlaps t.pos)) conflicting += r.tree @@ -97,21 +98,25 @@ self: Global => case ct :: trees1 => if (isTransparent(ct.pos)) iterate(ranges, solidDescendants(ct) ::: trees1) - else if (ct.pos.isDefined && !ct.pos.isSynthetic) { + else if (!ct.pos.isDefined || ct.pos.isSynthetic) + iterate(ranges, trees1) + else { val conflicting = new ListBuffer[Tree] val ranges1 = insert(ranges, ct, conflicting) +// println("inserted "+ct+"; ranges = "+ranges1) if (conflicting.isEmpty) { iterate(ranges1, trees1) } else { val splitNode = if (conflicting.size == 1 && (conflicting.head.pos includes ct.pos)) conflicting.head else ct + println("splitting "+splitNode) splitNode setPos new TransparentPosition(splitNode.pos.source.get, splitNode.pos.start, splitNode.pos.point, splitNode.pos.end) ensureNonOverlapping(replace(cts, splitNode, solidDescendants(splitNode))) } } } - +// println("ensure non overlap "+cts) iterate(List(maxFree), cts) } @@ -137,26 +142,28 @@ self: Global => * Uses the point of the position as the point of all positions it assigns. * Uses the start of this position as an Offset position for unpositioed trees * without children. - * @param trees The children to position + * @param trees The children to position. All children must be positionable. */ - private def setChildrenPos(pos: Position, trees: List[Tree]) { + private def setChildrenPos(pos: Position, trees: List[Tree]): Unit = try { var currentPos = pos for (tree <- trees) { - if (isPositionable(tree) && tree.pos == NoPosition) { - val children = tree.children + if (tree.pos == NoPosition) { + val children = tree.children filter isPositionable if (children.isEmpty) tree setPos OffsetPosition(pos.source.get, currentPos.start) else { setChildrenPos(currentPos, children) - val positionableChildren = children filter (isPositionable(_)) tree setPos new RangePosition( - pos.source.get, (positionableChildren map (_.pos.start)).min, pos.point, (positionableChildren map (_.pos.end)).max) + 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) } -// println("set children pos "+pos+" of "+trees) } ensureNonOverlapping(trees) + } catch { + case ex: Exception => + println("error while set children pos "+pos+" of "+trees) + throw ex } /** Position a tree. @@ -169,7 +176,13 @@ self: Global => val children = tree.children if (children.nonEmpty) { if (children.tail.isEmpty) atPos(pos)(children.head) - else setChildrenPos(pos, children) + else if (tree.isInstanceOf[Template]) { + println("setting children "+children) + setChildrenPos(pos, children filter isPositionable) + println("set children "+children) + } else { + setChildrenPos(pos, children filter isPositionable) + } } } tree @@ -186,20 +199,30 @@ self: Global => inform("================= in =================") inform(tree.toString) } - def validate(tree: Tree, encltree: Tree) { - if (isPositionable(tree) && !tree.pos.isDefined) - error("tree without position: "+tree) - if (encltree.pos.isSynthetic && !tree.pos.isDefined && tree.pos.isSynthetic) - error("synthetic "+encltree+" contains nonsynthetic" + tree) - if (tree.pos.isDefined && !(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) + def validate(tree: Tree, encltree: Tree): Unit = try { + if (isPositionable(tree)) { + if (!tree.pos.isDefined) { + error("tree without position: "+tree) + throw new ValidateError + } + if (encltree.pos.isSynthetic && !tree.pos.isDefined && tree.pos.isSynthetic) + error("synthetic "+encltree+" contains nonsynthetic" + tree) + if (tree.pos.isDefined && !(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) + } + } catch { + case ex: ValidateError => + println("error while validating "+tree) + throw ex } validate(tree, tree) } + class ValidateError extends Exception + // ---------------- Locating trees ---------------------------------- /** A locator for trees with given positions. diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala index ec00d7fd96..75ecd9dfca 100644 --- a/src/compiler/scala/tools/nsc/symtab/Types.scala +++ b/src/compiler/scala/tools/nsc/symtab/Types.scala @@ -3899,7 +3899,7 @@ A type's typeSymbol should never be inspected directly. val up = if (variance != CONTRAVARIANT) upper else !upper tvar.constr.inst = null val bound: Type = if (up) tparam.info.bounds.hi else tparam.info.bounds.lo - // Console.println("solveOne0 "+tvar+" "+config+" "+bound);//DEBUG + //Console.println("solveOne0 "+tvar+" "+config+" "+bound);//DEBUG var cyclic = bound contains tparam for ((tvar2, (tparam2, variance2)) <- config) { if (tparam2 != tparam && diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala index 7a340176d9..e57e8bcc71 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala @@ -595,6 +595,7 @@ trait Infer { } () } +// println("solve "+tvars+" "+(tvars map (_.constr))) val targs = solvedTypes(tvars, tparams, tparams map varianceInTypes(formals), false, lubDepth(formals) max lubDepth(argtpes)) // val res = diff --git a/src/library/scala/Enumeration.scala b/src/library/scala/Enumeration.scala index f3a6b2f68c..7edd390c02 100644 --- a/src/library/scala/Enumeration.scala +++ b/src/library/scala/Enumeration.scala @@ -64,13 +64,12 @@ abstract class Enumeration(initial: Int, names: String*) { /** The name of this enumeration. */ override def toString = { - val cname = this.getClass().getName() - if (cname endsWith "$") - cname.substring(0, cname.length() - 1) - else if (cname endsWith "$class") - cname.substring(0, cname.length() - 6) - else - cname + var string = getClass.getName + val idx1 = string.lastIndexOf('.' : Int) + if (idx1 != -1) string = string.substring(idx1 + 1) + val idx2 = string.indexOf('$') + if (idx2 != -1) string = string.substring(0, idx2) + string } /** The mapping from the integer used to identifying values to the actual -- cgit v1.2.3