From d52c350a9093a853e699d517514e94aa4b4673a9 Mon Sep 17 00:00:00 2001 From: Humza Shahid Date: Mon, 8 Dec 2025 22:40:38 +0000 Subject: [PATCH] formatting for persistent-vector.sml (absolutely no changes other than formatting) --- fcore/persistent-vector.sml | 726 +++++++++++++++++------------------- 1 file changed, 343 insertions(+), 383 deletions(-) diff --git a/fcore/persistent-vector.sml b/fcore/persistent-vector.sml index 65c7e01..b16c751 100644 --- a/fcore/persistent-vector.sml +++ b/fcore/persistent-vector.sml @@ -104,10 +104,7 @@ struct val prevFinish = Vector.sub (sizes, Vector.length sizes - 1) val start = start - prevFinish val finish = finish - prevFinish - val newNode = LEAF - ( #[{start = start, finish = finish}] - , #[finish] - ) + val newNode = LEAF (#[{start = start, finish = finish}], #[finish]) in APPEND newNode end @@ -125,11 +122,8 @@ struct case helpAppend (start, finish, tree) of UPDATE t => t | APPEND newNode => - let - val maxSize = getFinishIdx tree - in - BRANCH - (#[tree, newNode], #[maxSize, finish]) + let val maxSize = getFinishIdx tree + in BRANCH (#[tree, newNode], #[maxSize, finish]) end fun getStart tree = @@ -350,10 +344,8 @@ struct case tree of BRANCH (nodes, _) => getFirstItem (Vector.sub (nodes, 0)) | LEAF (items, _) => - if Vector.length items = 0 then - {start = ~1, finish = ~1} - else - Vector.sub (items, 0) + if Vector.length items = 0 then {start = ~1, finish = ~1} + else Vector.sub (items, 0) fun getMaxSize tree = case tree of @@ -366,15 +358,14 @@ struct if offset <= Vector.sub (sizes, 0) then splitLeft (offset, Vector.sub (nodes, 0)) else if offset >= Vector.sub (sizes, Vector.length sizes - 1) then - let + let val prevSize = if Vector.length sizes > 1 then Vector.sub (sizes, Vector.length sizes - 1) else 0 - val result = - splitLeft - (offset - prevSize, Vector.sub (nodes, Vector.length nodes - 1)) + val result = splitLeft (offset - prevSize, Vector.sub + (nodes, Vector.length nodes - 1)) in if isEmpty result then let @@ -389,8 +380,10 @@ struct else let val newChildSize = getMaxSize result + prevSize - val sizes = Vector.update (sizes, Vector.length sizes - 1, newChildSize) - val nodes = Vector.update (nodes, Vector.length nodes - 1, result) + val sizes = Vector.update + (sizes, Vector.length sizes - 1, newChildSize) + val nodes = Vector.update + (nodes, Vector.length nodes - 1, result) in BRANCH (nodes, sizes) end @@ -398,11 +391,7 @@ struct else let val idx = BinSearch.equalOrMore (offset, sizes) - val prevSize = - if idx > 1 then - Vector.sub (sizes, idx - 1) - else - 0 + val prevSize = if idx > 1 then Vector.sub (sizes, idx - 1) else 0 val result = splitLeft (offset - prevSize, Vector.sub (nodes, idx)) in if isEmpty result then @@ -418,20 +407,11 @@ struct else let val len = idx + 1 - val sizes = Vector.tabulate (len, - fn i => - if i = idx then - getMaxSize result + prevSize - else - Vector.sub (sizes, i) - ) - val nodes = Vector.tabulate (len, - fn i => - if i = idx then - result - else - Vector.sub (nodes, i) - ) + val sizes = Vector.tabulate (len, fn i => + if i = idx then getMaxSize result + prevSize + else Vector.sub (sizes, i)) + val nodes = Vector.tabulate (len, fn i => + if i = idx then result else Vector.sub (nodes, i)) in BRANCH (nodes, sizes) end @@ -442,27 +422,27 @@ struct tree else if offset <= Vector.sub (sizes, 0) then LEAF (#[], #[]) - else - let - val len = BinSearch.equalOrMore (offset, sizes) - val sizes = VectorSlice.slice (sizes, 0, SOME len) - val sizes = VectorSlice.vector sizes - val items = VectorSlice.slice (items, 0, SOME len) - val items = VectorSlice.vector items - in - LEAF (items, sizes) - end + else + let + val len = BinSearch.equalOrMore (offset, sizes) + val sizes = VectorSlice.slice (sizes, 0, SOME len) + val sizes = VectorSlice.vector sizes + val items = VectorSlice.slice (items, 0, SOME len) + val items = VectorSlice.vector items + in + LEAF (items, sizes) + end else tree - (* Unlike 'splitLeft' which leaves the size metadata alone - * (except for splitting it), - * we want splitRight to decrement the size metadata - * by the largest entry in the size table that was split. - * This is so that we can maintain relative indexing metadata. *) - fun splitRight (offset, tree) = - case tree of - BRANCH (nodes, sizes) => + (* Unlike 'splitLeft' which leaves the size metadata alone + * (except for splitting it), + * we want splitRight to decrement the size metadata + * by the largest entry in the size table that was split. + * This is so that we can maintain relative indexing metadata. *) + fun splitRight (offset, tree) = + case tree of + BRANCH (nodes, sizes) => if offset <= Vector.sub (sizes, 0) then (* we want to split first node *) let @@ -474,7 +454,8 @@ struct val len = Vector.length sizes - 1 val sizeSlice = VectorSlice.slice (sizes, 1, SOME len) - val sizes = VectorSlice.map (fn el => el - firstSizeBefore) sizeSlice + val sizes = + VectorSlice.map (fn el => el - firstSizeBefore) sizeSlice val nodeSlice = VectorSlice.slice (nodes, 1, SOME len) val nodes = VectorSlice.vector nodeSlice @@ -486,12 +467,10 @@ struct val firstSizeAfter = getMaxSize result val sizeDiff = firstSizeBefore - firstSizeAfter - val sizes = Vector.mapi (fn (idx, el) => - if idx = 0 then - firstSizeAfter - else - el - sizeDiff - ) sizes + val sizes = + Vector.mapi + (fn (idx, el) => + if idx = 0 then firstSizeAfter else el - sizeDiff) sizes val nodes = Vector.update (nodes, 0, result) in @@ -536,351 +515,332 @@ struct BRANCH (nodes, sizes) end end - | LEAF (items, sizes) => - if offset > Vector.sub (sizes, Vector.length sizes - 1) then - LEAF (#[], #[]) - else if offset <= Vector.sub (sizes, 0) then - tree - else - let - val idx = BinSearch.equalOrMore (offset, sizes) - val len = Vector.length sizes - idx - val len = SOME len - - val prevSize = - if idx < 1 then - 0 - else - Vector.sub (sizes, idx - 1) - val sizes = VectorSlice.slice (sizes, idx, len) - val sizes = VectorSlice.map (fn i => i - prevSize) sizes - - val items = VectorSlice.slice (items, idx, len) - val items = - VectorSlice.map - (fn {start, finish} => - {start = start - prevSize, finish = finish - prevSize}) - items - in - LEAF (items, sizes) - end - - fun getDepth (tree, acc) = - case tree of - BRANCH (nodes, _) => getDepth (Vector.sub (nodes, 0), acc + 1) - | LEAF (_, _) => acc - - fun getRootVecLength tree = - case tree of - BRANCH (_, sizes) => Vector.length sizes - | LEAF (_, sizes) => Vector.length sizes - - fun joinSameDepth (left, right) = - case (left, right) of - (BRANCH (leftNodes, leftSizes), BRANCH (rightNodes, rightSizes)) => + | LEAF (items, sizes) => + if offset > Vector.sub (sizes, Vector.length sizes - 1) then + LEAF (#[], #[]) + else if offset <= Vector.sub (sizes, 0) then + tree + else let - val nodes = Vector.concat [leftNodes, rightNodes] - val maxLeftSize = Vector.sub (leftSizes, Vector.length leftSizes - 1) - val sizes = Vector.tabulate - (Vector.length leftSizes + Vector.length rightSizes, - fn i => - if i < Vector.length leftSizes then - Vector.sub (leftSizes, i) - else - Vector.sub (rightSizes, i - Vector.length leftSizes) - + maxLeftSize - ) - in - BRANCH (nodes, sizes) - end - | (LEAF (leftItems, leftSizes), LEAF (rightItems, rightSizes)) => - let - val maxLeftSize = Vector.sub (leftSizes, Vector.length leftSizes - 1) - val len = Vector.length leftItems + Vector.length rightItems + val idx = BinSearch.equalOrMore (offset, sizes) + val len = Vector.length sizes - idx + val len = SOME len + + val prevSize = if idx < 1 then 0 else Vector.sub (sizes, idx - 1) + val sizes = VectorSlice.slice (sizes, idx, len) + val sizes = VectorSlice.map (fn i => i - prevSize) sizes + + val items = VectorSlice.slice (items, idx, len) val items = - Vector.tabulate (len, - fn i => - if i < Vector.length leftItems then - Vector.sub (leftItems, i) - else - let - val {start, finish} = Vector.sub (rightItems, i - Vector.length leftItems) - in - {start = start + maxLeftSize, finish = finish + maxLeftSize} - end - ) - val sizes = - Vector.tabulate (len, - fn i => - if i < Vector.length leftSizes then - Vector.sub (leftSizes, i) - else - Vector.sub (rightSizes, i - Vector.length leftSizes) - + maxLeftSize - ) + VectorSlice.map + (fn {start, finish} => + {start = start - prevSize, finish = finish - prevSize}) items in LEAF (items, sizes) end - | _ => raise Fail "PersistentVector.joinSameDepth: one is BRANCH and other is LEAF" - datatype append_join_result = - APPEND_JOIN_APPEND of t - | APPEND_JOIN_UPDATE of t + fun getDepth (tree, acc) = + case tree of + BRANCH (nodes, _) => getDepth (Vector.sub (nodes, 0), acc + 1) + | LEAF (_, _) => acc - fun appendJoin (left, right, joinDepth, rightLength) = - case left of - BRANCH (nodes, sizes) => - if joinDepth = 0 then - (* base case: should join at this depth *) - if Vector.length nodes + rightLength > maxSize then - APPEND_JOIN_APPEND right - else - (case right of - BRANCH (rightNodes, rightSizes) => - let - val nodes = Vector.concat [nodes, rightNodes] + fun getRootVecLength tree = + case tree of + BRANCH (_, sizes) => Vector.length sizes + | LEAF (_, sizes) => Vector.length sizes - val lastLeftSize = Vector.sub (sizes, Vector.length sizes - 1) - val sizes = Vector.tabulate (Vector.length nodes, - fn i => - if i < Vector.length sizes then - Vector.sub (sizes, i) - else - Vector.sub (rightSizes, i - Vector.length sizes) - + lastLeftSize - ) - in - APPEND_JOIN_UPDATE (BRANCH (nodes, sizes)) - end - | LEAF _ => - raise Fail - "persistent-vector.sml appendJoin: \ - \expected to join when left and right are both BRANCH \ - \but left is BRANCH and right is LEAF" - ) - else - (* recursion case: join below *) - let - val lastIdx = Vector.length nodes - 1 - val lastNode = Vector.sub (nodes, lastIdx) - in - case appendJoin (lastNode, right, joinDepth - 1, rightLength) of - APPEND_JOIN_UPDATE newLast => - let - val prevSize = - if lastIdx > 0 then Vector.sub (sizes, lastIdx - 1) - else 0 - val newLastSize = getMaxSize newLast + prevSize - val sizes = Vector.update (sizes, lastIdx, newLastSize) - val nodes = Vector.update (nodes, lastIdx, newLast) - in - APPEND_JOIN_UPDATE (BRANCH (nodes, sizes)) - end - | APPEND_JOIN_APPEND newNode => - if Vector.length nodes = maxSize then - (* parent has to append insead as this node - * would exceed capacity if appended here *) - APPEND_JOIN_APPEND (BRANCH (#[newNode], #[getMaxSize newNode])) + fun joinSameDepth (left, right) = + case (left, right) of + (BRANCH (leftNodes, leftSizes), BRANCH (rightNodes, rightSizes)) => + let + val nodes = Vector.concat [leftNodes, rightNodes] + val maxLeftSize = Vector.sub (leftSizes, Vector.length leftSizes - 1) + val sizes = + Vector.tabulate + ( Vector.length leftSizes + Vector.length rightSizes + , fn i => + if i < Vector.length leftSizes then + Vector.sub (leftSizes, i) else - let - val prevSize = - Vector.sub (sizes, Vector.length sizes - 1) - val newNodeSize = #[getMaxSize newNode + prevSize] - val sizes = Vector.concat [sizes, newNodeSize] + Vector.sub (rightSizes, i - Vector.length leftSizes) + + maxLeftSize + ) + in + BRANCH (nodes, sizes) + end + | (LEAF (leftItems, leftSizes), LEAF (rightItems, rightSizes)) => + let + val maxLeftSize = Vector.sub (leftSizes, Vector.length leftSizes - 1) + val len = Vector.length leftItems + Vector.length rightItems + val items = Vector.tabulate (len, fn i => + if i < Vector.length leftItems then + Vector.sub (leftItems, i) + else + let + val {start, finish} = Vector.sub + (rightItems, i - Vector.length leftItems) + in + {start = start + maxLeftSize, finish = finish + maxLeftSize} + end) + val sizes = Vector.tabulate (len, fn i => + if i < Vector.length leftSizes then + Vector.sub (leftSizes, i) + else + Vector.sub (rightSizes, i - Vector.length leftSizes) + maxLeftSize) + in + LEAF (items, sizes) + end + | _ => + raise Fail + "PersistentVector.joinSameDepth: one is BRANCH and other is LEAF" - val newNode = #[newNode] - val nodes = Vector.concat [nodes, newNode] - in - APPEND_JOIN_UPDATE (BRANCH (nodes, sizes)) - end - end - | LEAF (items, sizes) => - (* joinDepth should = 0, and we assume it is *) - if Vector.length items + rightLength > maxSize then + datatype append_join_result = + APPEND_JOIN_APPEND of t + | APPEND_JOIN_UPDATE of t + + fun appendJoin (left, right, joinDepth, rightLength) = + case left of + BRANCH (nodes, sizes) => + if joinDepth = 0 then + (* base case: should join at this depth *) + if Vector.length nodes + rightLength > maxSize then APPEND_JOIN_APPEND right else (case right of - LEAF (rightItems, rightSizes) => + BRANCH (rightNodes, rightSizes) => + let + val nodes = Vector.concat [nodes, rightNodes] + + val lastLeftSize = Vector.sub + (sizes, Vector.length sizes - 1) + val sizes = Vector.tabulate (Vector.length nodes, fn i => + if i < Vector.length sizes then + Vector.sub (sizes, i) + else + Vector.sub (rightSizes, i - Vector.length sizes) + + lastLeftSize) + in + APPEND_JOIN_UPDATE (BRANCH (nodes, sizes)) + end + | LEAF _ => + raise Fail + "persistent-vector.sml appendJoin: \ + \expected to join when left and right are both BRANCH \ + \but left is BRANCH and right is LEAF") + else + (* recursion case: join below *) + let + val lastIdx = Vector.length nodes - 1 + val lastNode = Vector.sub (nodes, lastIdx) + in + case appendJoin (lastNode, right, joinDepth - 1, rightLength) of + APPEND_JOIN_UPDATE newLast => let - val leftMaxSize = Vector.sub (sizes, Vector.length sizes - 1) - - val newLen = Vector.length items + Vector.length rightItems - val items = Vector.tabulate (newLen, - fn i => - if i < Vector.length items then - Vector.sub (items, i) - else - let - val {start, finish} = Vector.sub (rightItems, i - Vector.length items) - in - {start = start + leftMaxSize, finish = finish + leftMaxSize} - end - ) - val sizes = Vector.tabulate (newLen, - fn i => - if i < Vector.length sizes then - Vector.sub (sizes, i) - else - Vector.sub (rightSizes, i - Vector.length sizes) - + leftMaxSize - ) + val prevSize = + if lastIdx > 0 then Vector.sub (sizes, lastIdx - 1) else 0 + val newLastSize = getMaxSize newLast + prevSize + val sizes = Vector.update (sizes, lastIdx, newLastSize) + val nodes = Vector.update (nodes, lastIdx, newLast) in - APPEND_JOIN_UPDATE (LEAF (items, sizes)) + APPEND_JOIN_UPDATE (BRANCH (nodes, sizes)) end - | BRANCH _ => - raise Fail - "persistent-vector.sml appendJoin: \ - \left is LEAF and expected right to also be LEAF \ - \but right is BRANCH" - ) - - datatype prepend_join_result = - PREPEND_JOIN_PREPEND of t - | PREPEND_JOIN_UPDATE of t - - fun prependJoin (left, right, joinDepth, leftLength) = - case right of - BRANCH (rightNodes, rightSizes) => - if joinDepth = 0 then - (* base case: join *) - if Vector.length rightNodes + leftLength > maxSize then - PREPEND_JOIN_PREPEND left - else - (case left of - BRANCH (leftNodes, leftSizes) => + | APPEND_JOIN_APPEND newNode => + if Vector.length nodes = maxSize then + (* parent has to append insead as this node + * would exceed capacity if appended here *) + APPEND_JOIN_APPEND (BRANCH + (#[newNode], #[getMaxSize newNode])) + else let - val nodes = Vector.concat [leftNodes, rightNodes] - val maxLeftSize = - Vector.sub (leftSizes, Vector.length leftSizes - 1) - val sizes = Vector.tabulate (Vector.length nodes, - fn i => - if i < Vector.length leftSizes then - Vector.sub (leftSizes, i) - else - Vector.sub (rightSizes, i - Vector.length leftSizes) - + maxLeftSize - ) - in - PREPEND_JOIN_UPDATE (BRANCH (nodes, sizes)) - end - | LEAF _ => - raise Fail - "persistent-vector.sml prependJoin: \ - \expected left and right to be BRANCH \ - \but right is BRANCH while left is LEAF" - ) - else - (* recursive case *) - let - val firstRightNode = Vector.sub (rightNodes, 0) - val firstRightSize = getMaxSize firstRightNode - in - (case prependJoin (left, firstRightNode, joinDepth - 1, leftLength) of - PREPEND_JOIN_UPDATE newFirst => - let - val newFirstSize = getMaxSize newFirst - val sizeDiff = newFirstSize - firstRightSize - val sizes = Vector.map (fn el => el + sizeDiff) rightSizes - val nodes = Vector.update (rightNodes, 0, newFirst) - in - PREPEND_JOIN_UPDATE (BRANCH (nodes, sizes)) - end - | PREPEND_JOIN_PREPEND newFirst => - if Vector.length rightSizes = maxSize then - PREPEND_JOIN_PREPEND (BRANCH (#[newFirst], #[getMaxSize newFirst])) - else - let - val nodes = Vector.concat [#[newFirst], rightNodes] - val newFirstSize = getMaxSize newFirst + val prevSize = Vector.sub (sizes, Vector.length sizes - 1) + val newNodeSize = #[getMaxSize newNode + prevSize] + val sizes = Vector.concat [sizes, newNodeSize] - val sizes = Vector.tabulate (Vector.length nodes, - fn i => - if i = 0 then - newFirstSize - else - Vector.sub (rightSizes, i - 1) + newFirstSize - ) - in - PREPEND_JOIN_UPDATE (BRANCH (nodes, sizes)) - end) - end - | LEAF (rightItems, rightSizes) => - (* joinDepth should = 0, and we assume it is *) - if Vector.length rightItems + leftLength > maxSize then + val newNode = #[newNode] + val nodes = Vector.concat [nodes, newNode] + in + APPEND_JOIN_UPDATE (BRANCH (nodes, sizes)) + end + end + | LEAF (items, sizes) => + (* joinDepth should = 0, and we assume it is *) + if Vector.length items + rightLength > maxSize then + APPEND_JOIN_APPEND right + else + (case right of + LEAF (rightItems, rightSizes) => + let + val leftMaxSize = Vector.sub (sizes, Vector.length sizes - 1) + + val newLen = Vector.length items + Vector.length rightItems + val items = Vector.tabulate (newLen, fn i => + if i < Vector.length items then + Vector.sub (items, i) + else + let + val {start, finish} = Vector.sub + (rightItems, i - Vector.length items) + in + { start = start + leftMaxSize + , finish = finish + leftMaxSize + } + end) + val sizes = Vector.tabulate (newLen, fn i => + if i < Vector.length sizes then + Vector.sub (sizes, i) + else + Vector.sub (rightSizes, i - Vector.length sizes) + + leftMaxSize) + in + APPEND_JOIN_UPDATE (LEAF (items, sizes)) + end + | BRANCH _ => + raise Fail + "persistent-vector.sml appendJoin: \ + \left is LEAF and expected right to also be LEAF \ + \but right is BRANCH") + + datatype prepend_join_result = + PREPEND_JOIN_PREPEND of t + | PREPEND_JOIN_UPDATE of t + + fun prependJoin (left, right, joinDepth, leftLength) = + case right of + BRANCH (rightNodes, rightSizes) => + if joinDepth = 0 then + (* base case: join *) + if Vector.length rightNodes + leftLength > maxSize then PREPEND_JOIN_PREPEND left else (case left of - LEAF (leftItems, leftSizes) => - let - val maxLeftSize = Vector.sub (leftSizes, Vector.length leftSizes - 1) - val len = Vector.length leftSizes + Vector.length rightItems - val sizes = Vector.tabulate (len, - fn i => - if i < Vector.length leftSizes then - Vector.sub (leftSizes, i) - else - Vector.sub (rightSizes, i - Vector.length leftSizes) - + maxLeftSize) - val items = Vector.tabulate (len, - fn i => - if i < Vector.length leftItems then - Vector.sub (leftItems, i) - else - let - val {start, finish} = - Vector.sub (rightItems, i - Vector.length leftItems) - in - {start = start + maxLeftSize, finish = finish + maxLeftSize} - end - ) - in - PREPEND_JOIN_UPDATE (LEAF (items, sizes)) - end - | BRANCH _ => - raise Fail - "persistent-vector.sml prependJoin: \ - \expected left and right to be LEAF \ - \but right is LEAF while left is BRANCH") + BRANCH (leftNodes, leftSizes) => + let + val nodes = Vector.concat [leftNodes, rightNodes] + val maxLeftSize = Vector.sub + (leftSizes, Vector.length leftSizes - 1) + val sizes = Vector.tabulate (Vector.length nodes, fn i => + if i < Vector.length leftSizes then + Vector.sub (leftSizes, i) + else + Vector.sub (rightSizes, i - Vector.length leftSizes) + + maxLeftSize) + in + PREPEND_JOIN_UPDATE (BRANCH (nodes, sizes)) + end + | LEAF _ => + raise Fail + "persistent-vector.sml prependJoin: \ + \expected left and right to be BRANCH \ + \but right is BRANCH while left is LEAF") + else + (* recursive case *) + let + val firstRightNode = Vector.sub (rightNodes, 0) + val firstRightSize = getMaxSize firstRightNode + in + (case prependJoin (left, firstRightNode, joinDepth - 1, leftLength) of + PREPEND_JOIN_UPDATE newFirst => + let + val newFirstSize = getMaxSize newFirst + val sizeDiff = newFirstSize - firstRightSize + val sizes = Vector.map (fn el => el + sizeDiff) rightSizes + val nodes = Vector.update (rightNodes, 0, newFirst) + in + PREPEND_JOIN_UPDATE (BRANCH (nodes, sizes)) + end + | PREPEND_JOIN_PREPEND newFirst => + if Vector.length rightSizes = maxSize then + PREPEND_JOIN_PREPEND (BRANCH + (#[newFirst], #[getMaxSize newFirst])) + else + let + val nodes = Vector.concat [#[newFirst], rightNodes] + val newFirstSize = getMaxSize newFirst - fun join (left, right) = - if isEmpty left then - right - else if isEmpty right then - left - else - let - val leftDepth = getDepth (left, 0) - val rightDepth = getDepth (right, 0) - in - if leftDepth = rightDepth then - if getRootVecLength left + getRootVecLength right <= maxSize then - joinSameDepth (left, right) - else - let - val ls = getMaxSize left - val rs = getMaxSize right + ls - val sizes = #[ls, rs] - val nodes = #[left, right] - in - BRANCH (nodes, sizes) - end - else if leftDepth > rightDepth then + val sizes = Vector.tabulate (Vector.length nodes, fn i => + if i = 0 then newFirstSize + else Vector.sub (rightSizes, i - 1) + newFirstSize) + in + PREPEND_JOIN_UPDATE (BRANCH (nodes, sizes)) + end) + end + | LEAF (rightItems, rightSizes) => + (* joinDepth should = 0, and we assume it is *) + if Vector.length rightItems + leftLength > maxSize then + PREPEND_JOIN_PREPEND left + else + (case left of + LEAF (leftItems, leftSizes) => + let + val maxLeftSize = Vector.sub + (leftSizes, Vector.length leftSizes - 1) + val len = Vector.length leftSizes + Vector.length rightItems + val sizes = Vector.tabulate (len, fn i => + if i < Vector.length leftSizes then + Vector.sub (leftSizes, i) + else + Vector.sub (rightSizes, i - Vector.length leftSizes) + + maxLeftSize) + val items = Vector.tabulate (len, fn i => + if i < Vector.length leftItems then + Vector.sub (leftItems, i) + else + let + val {start, finish} = Vector.sub + (rightItems, i - Vector.length leftItems) + in + { start = start + maxLeftSize + , finish = finish + maxLeftSize + } + end) + in + PREPEND_JOIN_UPDATE (LEAF (items, sizes)) + end + | BRANCH _ => + raise Fail + "persistent-vector.sml prependJoin: \ + \expected left and right to be LEAF \ + \but right is LEAF while left is BRANCH") + + fun join (left, right) = + if isEmpty left then + right + else if isEmpty right then + left + else + let + val leftDepth = getDepth (left, 0) + val rightDepth = getDepth (right, 0) + in + if leftDepth = rightDepth then + if getRootVecLength left + getRootVecLength right <= maxSize then + joinSameDepth (left, right) + else let - val joinDepth = leftDepth - rightDepth - val rightLength = getRootVecLength right + val ls = getMaxSize left + val rs = getMaxSize right + ls + val sizes = #[ls, rs] + val nodes = #[left, right] in - case appendJoin (left, right, joinDepth, rightLength) of - APPEND_JOIN_UPDATE t => t - | APPEND_JOIN_APPEND newRight => - let - val ls = getMaxSize left - val rs = getMaxSize right + ls - val sizes = #[ls, rs] - val nodes = #[left, newRight] - in - BRANCH (nodes, sizes) - end + BRANCH (nodes, sizes) end + else if leftDepth > rightDepth then + let + val joinDepth = leftDepth - rightDepth + val rightLength = getRootVecLength right + in + case appendJoin (left, right, joinDepth, rightLength) of + APPEND_JOIN_UPDATE t => t + | APPEND_JOIN_APPEND newRight => + let + val ls = getMaxSize left + val rs = getMaxSize right + ls + val sizes = #[ls, rs] + val nodes = #[left, newRight] + in + BRANCH (nodes, sizes) + end + end else let val joinDepth = rightDepth - leftDepth