begin reimplementing persistent-vector.sml's 'helpInsert' function so that it uses rope-like metadata
This commit is contained in:
@@ -359,6 +359,87 @@ struct
|
||||
LEAF (_, sizes) => Vector.sub (sizes, Vector.length sizes - 1)
|
||||
| BRANCH (_, sizes) => Vector.sub (sizes, Vector.length sizes - 1)
|
||||
|
||||
fun helpInsert (start, finish, tree) =
|
||||
case tree of
|
||||
BRANCH (nodes, sizes) =>
|
||||
if finish >= Vector.sub (sizes, Vector.length sizes - 1) then
|
||||
(* we want to append *)
|
||||
let
|
||||
val prevSize =
|
||||
if Vector.length sizes > 1 then
|
||||
Vector.sub (sizes, Vector.length sizes - 1)
|
||||
else
|
||||
0
|
||||
val descendStart = start - prevSize
|
||||
val descendFinish = finish - prevSize
|
||||
val descendNode = Vector.sub (nodes, Vector.length nodes - 1)
|
||||
in
|
||||
case helpAppend (descendStart, descendFinish, descendNode) of
|
||||
UPDATE newLast =>
|
||||
let
|
||||
val sizes = Vector.update (sizes, Vector.length sizes - 1, finish)
|
||||
val nodes = Vector.update (nodes, Vector.length nodes - 1, newLast)
|
||||
in
|
||||
INSERT_UPDATE (BRANCH (nodes, sizes))
|
||||
end
|
||||
| APPEND newLast =>
|
||||
if Vector.length nodes > maxSize then
|
||||
(* we have to split *)
|
||||
let
|
||||
val leftLen = SOME halfSize
|
||||
val rightLen = SOME (Vector.length nodes - halfSize)
|
||||
|
||||
val leftNodeSlice = VectorSlice.slice (nodes, 0, leftLen)
|
||||
val leftSizeSlice = VectorSlice.slice (sizes, 0, leftLen)
|
||||
val leftNodes = VectorSlice.vector leftNodeSlice
|
||||
val leftSizes = VectorSlice.vector leftSizeSlice
|
||||
|
||||
val rightNodeSlice =
|
||||
VectorSlice.slice (nodes, halfSize, rightLen)
|
||||
val rightSizeSlice =
|
||||
VectorSlice.slice (sizes, halfSize, rightLen)
|
||||
|
||||
val rightNodes =
|
||||
VectorSlice.concat [rightNodeSlice, VectorSlice.full #[newLast]]
|
||||
val rightSizes =
|
||||
let
|
||||
(* we want to maintain relative indexing metadata
|
||||
* so that each vector only considers the metadata of its
|
||||
* own nodes.
|
||||
* So, we need to subtract the maximum sizes of the leftSizes
|
||||
* from every size on the right node, to maintain relative
|
||||
* indexing metadata *)
|
||||
val maxLeftSize = Vector.sub (leftSizes, Vector.length leftSizes - 1)
|
||||
val maxRightSize = Vector.sub (sizes, Vector.length sizes - 1)
|
||||
val finish = finish + maxRightSize
|
||||
in
|
||||
Vector.tabulate (VectorSlice.length rightSizeSlice + 1,
|
||||
fn i =>
|
||||
if i < VectorSlice.length rightSizeSlice then
|
||||
Vector.sub (rightSizeSlice, i) - maxLeftSize
|
||||
else
|
||||
finish)
|
||||
end
|
||||
|
||||
val left = BRANCH (leftNodes, leftSizes)
|
||||
val right = BRANCH (rightNodes, rightSizes)
|
||||
in
|
||||
INSERT_SPLIT (left, right)
|
||||
end
|
||||
else
|
||||
(* append newLast to current node *)
|
||||
let
|
||||
val newLast = #[newLast]
|
||||
val finish =
|
||||
#[Vector.sub (sizes, Vector.length sizes - 1) + finish]
|
||||
|
||||
val nodes = Vector.concat [nodes, newLast]
|
||||
val sizes = Vector.concat [sizes, finish]
|
||||
in
|
||||
INSERT_UPDATE (BRANCH (nodes, sizes))
|
||||
end
|
||||
end
|
||||
|
||||
fun helpInsert (start, finish, tree) =
|
||||
case tree of
|
||||
BRANCH (nodes, sizes) =>
|
||||
@@ -626,7 +707,8 @@ struct
|
||||
INSERT_UPDATE tree => tree
|
||||
| INSERT_SPLIT (left, right) =>
|
||||
let
|
||||
val sizes = #[getMaxSize left, getMaxSize right]
|
||||
val leftSize = getMaxSize left
|
||||
val sizes = #[leftSize, leftSize + getMaxSize right]
|
||||
val nodes = #[left, right]
|
||||
in
|
||||
BRANCH (nodes, sizes)
|
||||
|
||||
Reference in New Issue
Block a user