summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/interactive/ContextTrees.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2009-05-28 14:12:26 +0000
committerMartin Odersky <odersky@gmail.com>2009-05-28 14:12:26 +0000
commit578d4c671696ec6db3c44dec82bf11d90c65d819 (patch)
tree320874513badd5a748e20c2d67f23ab4f6444377 /src/compiler/scala/tools/nsc/interactive/ContextTrees.scala
parentb7eac378dadaac07aa77a9acfc8a64b212c09e83 (diff)
downloadscala-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-xsrc/compiler/scala/tools/nsc/interactive/ContextTrees.scala129
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
- }}
+ }
}