diff options
author | Martin Odersky <odersky@gmail.com> | 2009-05-28 14:12:26 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2009-05-28 14:12:26 +0000 |
commit | 578d4c671696ec6db3c44dec82bf11d90c65d819 (patch) | |
tree | 320874513badd5a748e20c2d67f23ab4f6444377 /src/compiler/scala/tools/nsc/interactive/ContextTrees.scala | |
parent | b7eac378dadaac07aa77a9acfc8a64b212c09e83 (diff) | |
download | scala-578d4c671696ec6db3c44dec82bf11d90c65d819.tar.gz scala-578d4c671696ec6db3c44dec82bf11d90c65d819.tar.bz2 scala-578d4c671696ec6db3c44dec82bf11d90c65d819.zip |
more work on rangepositions.
Diffstat (limited to 'src/compiler/scala/tools/nsc/interactive/ContextTrees.scala')
-rwxr-xr-x | src/compiler/scala/tools/nsc/interactive/ContextTrees.scala | 129 |
1 files changed, 78 insertions, 51 deletions
diff --git a/src/compiler/scala/tools/nsc/interactive/ContextTrees.scala b/src/compiler/scala/tools/nsc/interactive/ContextTrees.scala index b3a290964e..5ed0581bdf 100755 --- a/src/compiler/scala/tools/nsc/interactive/ContextTrees.scala +++ b/src/compiler/scala/tools/nsc/interactive/ContextTrees.scala @@ -8,12 +8,23 @@ trait ContextTrees { self: Global => type Context = analyzer.Context type Contexts = ArrayBuffer[ContextTree] - class ContextTree(val context: Context, val children: ArrayBuffer[ContextTree]) { - def this(context: Context) = this(context, new ArrayBuffer[ContextTree]) - def pos: Position = context.tree.pos + /** A context tree contains contexts that are indexed by positions. + * It satisfies the following properties: + * 1. All context come from compiling the same unit. + * 2. Child contexts have parent contexts in their outer chain. + * 3. The `pos` field of a context is the same as `context.tree.pos`, unless that + * position is transparent. In that case, `pos` equals the position of + * one of the solid descendants of `context.tree`. + * 4. Children of a context have non-overlapping increasining positions. + * 5. No context in the tree has a transparent position. + */ + class ContextTree(val pos: Position, val context: Context, val children: ArrayBuffer[ContextTree]) { + def this(pos: Position, context: Context) = this(pos, context, new ArrayBuffer[ContextTree]) override def toString = "ContextTree("+pos+", "+children+")" } + /** Optionally return the smallest context taht contains given `pos`, or None if none exists. + */ def locateContext(contexts: Contexts, pos: Position): Option[Context] = { if (contexts.isEmpty) None else { @@ -38,61 +49,77 @@ trait ContextTrees { self: Global => } } + /** Insert a context at correct position into a buffer of context trees. + * If the `context` has a transparent position, add it multiple times + * at the positions of all its solid descendant trees. + */ def addContext(contexts: Contexts, context: Context) { val cpos = context.tree.pos + if (isTransparent(cpos)) + for (t <- context.tree.children flatMap solidDescendants) + addContext(contexts, context, t.pos) + else + addContext(contexts, context, cpos) + } + + /** Insert a context with non-transparent position `cpos` + * at correct position into a buffer of context trees. + */ + def addContext(contexts: Contexts, context: Context, cpos: Position) { try { - if (!cpos.isDefined || cpos.isSynthetic) {} - else if (contexts.isEmpty) contexts += new ContextTree(context) - else { - val hi = contexts.length - 1 - if (contexts(hi).pos properlyPrecedes cpos) - contexts += new ContextTree(context) - else if (contexts(hi).pos properlyIncludes cpos) // fast path w/o search - addContext(contexts(hi).children, context) - else if (cpos properlyPrecedes contexts(0).pos) - new ContextTree(context) +: contexts + if (!cpos.isDefined || cpos.isSynthetic) {} + else if (contexts.isEmpty) contexts += new ContextTree(cpos, context) else { - def insertAt(idx: Int): Boolean = { - val oldpos = contexts(idx).pos - if (oldpos sameRange cpos) { - contexts(idx) = new ContextTree(context, contexts(idx).children) - true - } else if (oldpos includes cpos) { - addContext(contexts(idx).children, context) - true - } else if (cpos includes oldpos) { - val start = contexts.indexWhere(cpos includes _.pos) - val last = contexts.lastIndexWhere(cpos includes _.pos) - contexts(start) = new ContextTree(context, contexts.slice(start, last + 1)) - contexts.remove(start + 1, last - start) - true - } else false - } - def loop(lo: Int, hi: Int) { - if (hi - lo > 1) { - val mid = (lo + hi) / 2 - val midpos = contexts(mid).pos - if (cpos precedes midpos) - loop(lo, mid) - else if (midpos precedes cpos) - loop(mid, hi) - } else if (!insertAt(lo) && !insertAt(hi)) { - val lopos = contexts(lo).pos - val hipos = contexts(hi).pos - if ((lopos precedes cpos) && (cpos precedes hipos)) - contexts.insert(hi, new ContextTree(context)) - else - inform("internal error? skewed positions: "+lopos+" !< "+cpos+" !< "+hipos) + val hi = contexts.length - 1 + 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) + else if (cpos properlyPrecedes contexts(0).pos) + new ContextTree(cpos, context) +: contexts + else { + def insertAt(idx: Int): Boolean = { + val oldpos = contexts(idx).pos + if (oldpos sameRange cpos) { + contexts(idx) = new ContextTree(cpos, context, contexts(idx).children) + true + } else if (oldpos includes cpos) { + addContext(contexts(idx).children, context) + true + } else if (cpos includes oldpos) { + val start = contexts.indexWhere(cpos includes _.pos) + val last = contexts.lastIndexWhere(cpos includes _.pos) + contexts(start) = new ContextTree(cpos, context, contexts.slice(start, last + 1)) + contexts.remove(start + 1, last - start) + true + } else false + } + def loop(lo: Int, hi: Int) { + if (hi - lo > 1) { + val mid = (lo + hi) / 2 + val midpos = contexts(mid).pos + if (cpos precedes midpos) + loop(lo, mid) + else if (midpos precedes cpos) + loop(mid, hi) + } else if (!insertAt(lo) && !insertAt(hi)) { + val lopos = contexts(lo).pos + val hipos = contexts(hi).pos + if ((lopos precedes cpos) && (cpos precedes hipos)) + contexts.insert(hi, new ContextTree(cpos, context)) + else + inform("internal error? skewed positions: "+lopos+" !< "+cpos+" !< "+hipos) + } } + loop(0, hi) } - loop(0, hi) } + } catch { + case ex: Throwable => + println("failure inserting "+cpos+" into "+contexts+"/"+contexts(contexts.length - 1).pos+"/"+ + (contexts(contexts.length - 1).pos includes cpos)) + throw ex } - } catch { - case ex: Throwable => - println("failure inserting "+context.tree.pos+" into "+contexts+"/"+contexts(contexts.length - 1).pos+"/"+ - (contexts(contexts.length - 1).pos includes cpos)) - throw ex - }} + } } |