From 267c0c5d969c3238657997eb999d6fa6df91d126 Mon Sep 17 00:00:00 2001 From: Humza Shahid Date: Thu, 15 Jan 2026 05:39:55 +0000 Subject: [PATCH] change persistent-vector.sml's 'prevMatch' function to use rope-like metadata, and remove dead code --- fcore/persistent-vector.sml | 344 ++++++------------------------------ 1 file changed, 52 insertions(+), 292 deletions(-) diff --git a/fcore/persistent-vector.sml b/fcore/persistent-vector.sml index ea77d5c..ef7bc1d 100644 --- a/fcore/persistent-vector.sml +++ b/fcore/persistent-vector.sml @@ -200,13 +200,25 @@ struct loopNextMatch (start, finish, tree, count - 1) end - (* todo: modify below functions so that they also - * use rope-like metadata *) - - fun getLast tree = + fun getLast (tree, absOffset) = case tree of - LEAF (values, _) => Vector.sub (values, Vector.length values - 1) - | BRANCH (nodes, _) => getLast (Vector.sub (nodes, Vector.length nodes - 1)) + LEAF (values, _) => + let + val {start, finish} = Vector.sub (values, Vector.length values - 1) + in + {start = start + absOffset, finish = finish + absOffset} + end + | BRANCH (nodes, sizes) => + let + val prevSize = + if Vector.length sizes - 2 >= 0 then + Vector.sub (sizes, Vector.length sizes - 2) + else + 0 + val absOffset = absOffset + prevSize + in + getLast (Vector.sub (nodes, Vector.length nodes - 1), absOffset) + end (* slightly tricky. * The `sizes` vector contains the last/finish position of the item @@ -223,7 +235,7 @@ struct * There might not be a previous index because the current index is 0. * In this case, either the call stack will handle it, * or the caller to `helpPrevMatch` will. *) - fun helpPrevMatch (cursorIdx, tree) = + fun helpPrevMatch (cursorIdx, tree, absOffset) = case tree of LEAF (values, sizes) => let @@ -233,17 +245,25 @@ struct {start = ~1, finish = ~1} else if idx = 0 then let - val result = Vector.sub (values, 0) + val {start, finish} = Vector.sub (values, 0) in - if #start result < cursorIdx then result - else {start = ~1, finish = ~1} + if start < cursorIdx then + {start = start + absOffset, finish = finish + absOffset} + else + {start = ~1, finish = ~1} end else let - val current = Vector.sub (values, idx) + val {start, finish} = Vector.sub (values, idx) in - if cursorIdx > #start current then current - else Vector.sub (values, idx - 1) + if cursorIdx > start then + {start = start + absOffset, finish = finish + absOffset} + else + let + val {start, finish} = Vector.sub (values, idx - 1) + in + {start = start + absOffset, finish = finish + absOffset} + end end end | BRANCH (nodes, sizes) => @@ -253,13 +273,25 @@ struct if idx < 0 then {start = ~1, finish = ~1} else if idx = 0 then - helpPrevMatch (cursorIdx, Vector.sub (nodes, idx)) + helpPrevMatch (cursorIdx, Vector.sub (nodes, idx), absOffset) else let + val prevSize = Vector.sub (sizes, idx - 1) val node = Vector.sub (nodes, idx) - val result = helpPrevMatch (cursorIdx, node) + val result = + helpPrevMatch (cursorIdx - prevSize, node, absOffset + prevSize) in - if #start result = ~1 then getLast (Vector.sub (nodes, idx - 1)) + if #start result = ~1 then + let + val prevSize = + if idx - 2 >= 0 then + Vector.sub (sizes, idx - 2) + else + 0 + val absOffset = absOffset + prevSize + in + getLast (Vector.sub (nodes, idx - 1), absOffset) + end else result end end @@ -269,10 +301,10 @@ struct prevStart else let - val {start, finish} = helpPrevMatch (prevFinish - 1, tree) + val {start, finish} = helpPrevMatch (prevFinish - 1, tree, 0) in if start = ~1 then - let val {start, finish} = getLast tree + let val {start, finish} = getLast (tree, 0) in loopPrevMatch (start, finish, tree, count - 1) end else @@ -284,10 +316,10 @@ struct ~1 else let - val {start, finish} = helpPrevMatch (cursorIdx, tree) + val {start, finish} = helpPrevMatch (cursorIdx, tree, 0) in if start = ~1 then - let val {start, finish} = getLast tree + let val {start, finish} = getLast (tree, 0) in loopPrevMatch (start, finish, tree, count - 1) end else if cursorIdx >= start andalso cursorIdx <= finish then @@ -295,276 +327,4 @@ struct else loopPrevMatch (start, finish, tree, count - 1) end - - datatype insert_result = INSERT_UPDATE of t | INSERT_SPLIT of t * t - - fun getMaxSize tree = - case tree of - 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 - (* if we want to append *) - case - helpAppend (start, finish, Vector.sub - (nodes, Vector.length sizes - 1)) - 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 - (* have to split *) - let - val leftLen = SOME halfSize - val rightLen = SOME (Vector.length nodes - halfSize) - - val leftNodeSlice = VectorSlice.slice (nodes, 0, leftLen) - val rightNodeSlice = - VectorSlice.slice (nodes, halfSize, rightLen) - - val leftSizeSlice = VectorSlice.slice(sizes, 0, leftLen) - val rightSizeSlice = - VectorSlice.slice (sizes, halfSize, rightLen) - - val leftNodes = VectorSlice.vector leftNodeSlice - val leftSizes = VectorSlice.vector leftSizeSlice - - val newLast = VectorSlice.full (#[newLast]) - val finish = VectorSlice.full (#[finish]) - val rightNodes = VectorSlice.concat [rightNodeSlice, newLast] - val rightSizes = VectorSlice.concat [rightSizeSlice, finish] - - 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 = #[finish] - - val nodes = Vector.concat [nodes, newLast] - val sizes = Vector.concat [sizes, finish] - in - INSERT_UPDATE (BRANCH (nodes, sizes)) - end - else - let - val idx = BinSearch.equalOrMore (finish, sizes) - val idx = if idx = ~1 then 0 else idx - in - case helpInsert (start, finish, tree) of - INSERT_UPDATE newNode => - let - val sizes = - if finish > Vector.sub (sizes, idx) then - Vector.update (sizes, idx, finish) - else - sizes - val nodes = Vector.update (nodes, idx, newNode) - in - INSERT_UPDATE (BRANCH (nodes, sizes)) - end - | INSERT_SPLIT (left, right) => - if Vector.length nodes = maxSize then - (* have to split this node too *) - let - (* slice sizes *) - val leftSize = VectorSlice.full #[getMaxSize left] - val rightSize = VectorSlice.full #[getMaxSize right] - - val leftLen = SOME idx - val rightLen = SOME (Vector.length nodes - idx - 1) - - val leftSizeSlice = VectorSlice.slice (sizes, 0, leftLen) - val rightSizeSlice = VectorSlice.slice (sizes, idx + 1, rightLen) - - val leftSizes = VectorSlice.concat [leftSizeSlice, leftSize] - val rightSizes = VectorSlice.concat [rightSizeSlice, rightSize] - - (* slice nodes *) - val left = VectorSlice.full #[left] - val right = VectorSlice.full #[right] - - val leftNodesSlice = VectorSlice.slice (nodes, 0, leftLen) - val rightNodesSlice = VectorSlice.slice (nodes, idx + 1, rightLen) - - val leftNodes = VectorSlice.concat [leftNodesSlice, left] - val rightNodes = VectorSlice.concat [right, rightNodesSlice] - - (* join sizes and nodes *) - val left = BRANCH (leftNodes, leftSizes) - val right = BRANCH (rightNodes, rightSizes) - in - INSERT_SPLIT (left, right) - end - else - (* can join children into parent *) - let - val midSizes = #[getMaxSize left, getMaxSize right] - val midSizes = VectorSlice.full midSizes - val midNodes = #[left, right] - val midNodes = VectorSlice.full midNodes - - val leftLen = SOME idx - val rightLen = SOME (Vector.length sizes - idx) - - val leftSizes = VectorSlice.slice (sizes, 0, leftLen) - val rightSizes = VectorSlice.slice (sizes, idx, rightLen) - - val leftNodes = VectorSlice.slice (nodes, 0, leftLen) - val rightNodes = VectorSlice.slice (nodes, idx, rightLen) - - val sizes = - VectorSlice.concat [leftSizes, midSizes, rightSizes] - val nodes = - VectorSlice.concat [leftNodes, midNodes, rightNodes] - in - INSERT_UPDATE (BRANCH (nodes, sizes)) - end - end - | LEAF (items, sizes) => - if Vector.length items = 0 then - (* leaf is empty, so return leaf containing one item *) - let - val item = #[{start = start, finish = finish}] - val size = #[finish] - in - INSERT_UPDATE (LEAF (item, size)) - end - else - if finish > Vector.sub (sizes, Vector.length sizes - 1) then - if Vector.length sizes = maxSize then - (* have to split *) - let - val startLen = SOME halfSize - val midLen = SOME (Vector.length items - halfSize) - - val leftSizes = VectorSlice.slice (sizes, 0, startLen) - val leftItems = VectorSlice.slice (items, 0, startLen) - - val midSizes = VectorSlice.slice (sizes, halfSize, midLen) - val midItems = VectorSlice.slice (items, halfSize, midLen) - - val rightSizes = VectorSlice.full #[finish] - val rightItems = VectorSlice.full #[{start = start, finish = finish}] - - val rightItems = VectorSlice.concat [midItems, rightItems] - val leftItems = VectorSlice.vector leftItems - - val rightSizes = VectorSlice.concat [midSizes, rightSizes] - val leftSizes = VectorSlice.vector leftSizes - - val left = LEAF (leftItems, leftSizes) - val right = LEAF (rightItems, rightSizes) - in - INSERT_SPLIT (left, right) - end - else - (* can just append *) - let - val sizes = Vector.concat [sizes, #[finish]] - val item = #[{start = start, finish = finish}] - val items = Vector.concat [items, item] - in - INSERT_UPDATE (LEAF (items, sizes)) - end - else if finish < #start (Vector.sub (items, 0)) then - (* prepend *) - if Vector.length sizes = maxSize then - (* have to split *) - let - val leftSizes = VectorSlice.full #[finish] - val leftItems = VectorSlice.full #[{start = start, finish = finish}] - - val midLen = SOME halfSize - val rightLen = SOME (Vector.length items - halfSize) - - val midSizes = VectorSlice.slice (sizes, 0, midLen) - val midItems = VectorSlice.slice (items, 0, midLen) - - val rightSizes = VectorSlice.slice (sizes, halfSize, rightLen) - val rightItems = VectorSlice.slice (items, halfSize, rightLen) - - val leftSizes = VectorSlice.concat [leftSizes, midSizes] - val rightSizes = VectorSlice.vector rightSizes - - val leftItems = VectorSlice.concat [leftItems, midItems] - val rightItems = VectorSlice.vector rightItems - - val left = LEAF (leftItems, leftSizes) - val right = LEAF (rightItems, rightSizes) - in - INSERT_SPLIT (left, right) - end - else - (* just prepend *) - let - val sizes = Vector.concat [#[finish], sizes] - val item = {start = start, finish = finish} - val items = Vector.concat [#[item], items] - in - INSERT_UPDATE (LEAF (items, sizes)) - end - else - (* insert into middle *) - let - val idx = BinSearch.equalOrMore (finish, sizes) - val leftLen = SOME idx - val rightLen = SOME (Vector.length sizes - idx) - - val leftSizes = VectorSlice.slice (sizes, 0, leftLen) - val rightSizes = VectorSlice.slice (sizes, idx, rightLen) - - val leftItems = VectorSlice.slice (items, 0, leftLen) - val rightItems = VectorSlice.slice (items, idx, rightLen) - val midSize = VectorSlice.full #[finish] - val midItem = VectorSlice.full #[{start = start, finish = finish}] - in - if Vector.length items = maxSize then - (* have to return split *) - let - val leftSizes = VectorSlice.concat [leftSizes, midSize] - val rightSizes = VectorSlice.vector rightSizes - - val leftItems = VectorSlice.concat [leftItems, midItem] - val rightItems = VectorSlice.vector rightItems - - val left = LEAF (leftItems, leftSizes) - val right = LEAF (rightItems, rightSizes) - in - INSERT_SPLIT (left, right) - end - else - (* have to return update *) - let - val sizes = VectorSlice.concat [leftSizes, midSize, rightSizes] - val items = VectorSlice.concat [leftItems, midItem, rightItems] - in - INSERT_UPDATE (LEAF (items, sizes)) - end - end - - fun insert (start, finish, tree) = - case helpInsert (start, finish, tree) of - INSERT_UPDATE tree => tree - | INSERT_SPLIT (left, right) => - let - val sizes = #[getMaxSize left, getMaxSize right] - val nodes = #[left, right] - in - BRANCH (nodes, sizes) - end end