Permalink
Browse files

Issue #13 - Introduced the notion of Zipper#hasValidContext to avoid …

…some of these issues
  • Loading branch information...
djspiewak committed May 11, 2011
1 parent e95566e commit 85ca4e3e44a37e09f41d793cc2d90caf6c2aa339
@@ -165,6 +165,7 @@ class Group[+A <: Node] private[antixml] (private[antixml] val nodes: VectorCase
new Group(nodes) with Zipper[A] {
val map = Vector()
def parent = error("Attempted to move up at root of the tree")
override val hasValidContext = false
}
}
@@ -239,6 +240,8 @@ object Group {
case group: Group[Node] => group.toZipper
case _ => error("No zipper context available")
}
override val hasValidContext = from.isInstanceOf[Group[Node]]
}
}
}
@@ -248,6 +251,7 @@ object Group {
new Group(vec) with Zipper[A] {
lazy val map = baseMap
def parent = error("No zipper context available")
override val hasValidContext = false
}
}
}
@@ -38,6 +38,7 @@ trait Zipper[+A <: Node] extends Group[A] with ScalaCompat { self =>
protected def map: Vector[Option[ZContext]]
protected def parent: Zipper[Node]
protected val hasValidContext = true
// TODO this *may* be a poor choice of words...
def stripZipper = new Group(toVectorCase)
@@ -67,52 +68,56 @@ trait Zipper[+A <: Node] extends Group[A] with ScalaCompat { self =>
override def flatMap[B, That](f: A => CompatTraversable[B])(implicit cbf: CanBuildFrom[Group[A], B, That]): That = cbf match {
case cbf: CanBuildFromWithZipper[Group[A], B, That] => {
val result = toVectorCase.toVector map f
val intermedMap = map map {
case Some((from, to, rebuild, childMap)) => {
// get the mapping from *our* indexes to source indexes
val inverseMap = {
val maps = for ((source, targets) <- childMap)
yield (Map[Int, Int]() /: targets) { (acc, t) => acc + (t -> source) }
(Map[Int, Int]() /: maps) { _ ++ _ }
}
val (_, aggregate, childMap2) = result.slice(from, to).zipWithIndex.foldLeft((0, Vector[B](), Map[Int, Set[Int]]())) {
case ((start, acc, childMap2), (chunk, i)) => {
val size = chunk.size
val source = inverseMap(i)
val contrib = Set(start until (start + size): _*)
val set2 = childMap2.getOrElse(source, contrib) ++ contrib
if (!hasValidContext) {
super.flatMap(f)(cbf) // don't try to preserve
} else {
val result = toVectorCase.toVector map f
(start + size, acc ++ chunk, childMap2.updated(source, set2))
val intermedMap = map map {
case Some((from, to, rebuild, childMap)) => {
// get the mapping from *our* indexes to source indexes
val inverseMap = {
val maps = for ((source, targets) <- childMap)
yield (Map[Int, Int]() /: targets) { (acc, t) => acc + (t -> source) }
(Map[Int, Int]() /: maps) { _ ++ _ }
}
val (_, aggregate, childMap2) = result.slice(from, to).zipWithIndex.foldLeft((0, Vector[B](), Map[Int, Set[Int]]())) {
case ((start, acc, childMap2), (chunk, i)) => {
val size = chunk.size
val source = inverseMap(i)
val contrib = Set(start until (start + size): _*)
val set2 = childMap2.getOrElse(source, contrib) ++ contrib
(start + size, acc ++ chunk, childMap2.updated(source, set2))
}
}
val length = aggregate.length
val delta = length - (to - from)
Some((from, to + delta, rebuild, childMap2, aggregate, delta))
}
val length = aggregate.length
val delta = length - (to - from)
Some((from, to + delta, rebuild, childMap2, aggregate, delta))
case None => None
}
case None => None
}
val (_, map2, chunks) = intermedMap.foldLeft((0, Vector[Option[ZContext]](), Vector[Vector[B]]())) {
case ((offset, map2, acc), Some((from, to, rebuild, childMap, aggregate, delta))) => {
val from2 = from + offset
val to2 = to + offset
val offset2 = offset + delta
(offset2, map2 :+ Some((from2, to2, rebuild, childMap)), acc :+ aggregate)
val (_, map2, chunks) = intermedMap.foldLeft((0, Vector[Option[ZContext]](), Vector[Vector[B]]())) {
case ((offset, map2, acc), Some((from, to, rebuild, childMap, aggregate, delta))) => {
val from2 = from + offset
val to2 = to + offset
val offset2 = offset + delta
(offset2, map2 :+ Some((from2, to2, rebuild, childMap)), acc :+ aggregate)
}
case ((offset, map2, acc), None) => (offset, map2 :+ None, acc)
}
case ((offset, map2, acc), None) => (offset, map2 :+ None, acc)
val builder = cbf(parent.asInstanceOf[Group[A]], map2)
chunks foreach (builder ++=)
builder.result
}
val builder = cbf(parent.asInstanceOf[Group[A]], map2)
chunks foreach (builder ++=)
builder.result
}
case _ => super.flatMap(f)(cbf)

0 comments on commit 85ca4e3

Please sign in to comment.