done implementing functionality to get PersistentVector.prevMatch working. We use the call stack to try the node at the previous index if we receive an invalid state from the recursive call.
This commit is contained in:
@@ -105,6 +105,7 @@ struct
|
|||||||
BRANCH (#[tree, newNode], #[maxSize, finish])
|
BRANCH (#[tree, newNode], #[maxSize, finish])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
fun getStart tree =
|
fun getStart tree =
|
||||||
case tree of
|
case tree of
|
||||||
LEAF (values, _) => Vector.sub (values, 0)
|
LEAF (values, _) => Vector.sub (values, 0)
|
||||||
@@ -181,57 +182,78 @@ struct
|
|||||||
|
|
||||||
fun getLast tree =
|
fun getLast tree =
|
||||||
case tree of
|
case tree of
|
||||||
LEAF (values, _) =>
|
LEAF (values, _) => Vector.sub (values, Vector.length values - 1)
|
||||||
Vector.sub (values, Vector.length values - 1)
|
| BRANCH (nodes, _) => getLast (Vector.sub (nodes, Vector.length nodes - 1))
|
||||||
| BRANCH (nodes, _) =>
|
|
||||||
getLast (Vector.sub (nodes, Vector.length nodes - 1))
|
|
||||||
|
|
||||||
|
(* slightly tricky.
|
||||||
|
* The `sizes` vector contains the last/finish position of the item
|
||||||
|
* at the corresponding index in the `nodes` or `values` vector
|
||||||
|
* However, what we when searching for the previous match
|
||||||
|
* is different: we want the node that has a start prior
|
||||||
|
* to the cursorIdx.
|
||||||
|
* This information cannot be retrieved with 100% accuracy
|
||||||
|
* using the `sizes` vector.
|
||||||
|
* To get what we want, we recurse downwards using the `sizes` vector.
|
||||||
|
* If we found the node we want, we return it.
|
||||||
|
* Otherwise, we return a state meaning "no node at this position"
|
||||||
|
* and we use the call stack to descend down the node at the previous index.
|
||||||
|
* 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) =
|
||||||
case tree of
|
case tree of
|
||||||
LEAF (values, sizes) =>
|
LEAF (values, sizes) =>
|
||||||
let
|
let
|
||||||
val idx = BinSearch.equalOrMore (cursorIdx, sizes)
|
val idx = BinSearch.equalOrMore (cursorIdx, sizes)
|
||||||
in
|
in
|
||||||
if idx < 0 then {start = ~1, finish = ~1}
|
if idx < 0 then
|
||||||
else if idx = 0 then Vector.sub (values, 0)
|
{start = ~1, finish = ~1}
|
||||||
|
else if idx = 0 then
|
||||||
|
let
|
||||||
|
val result = Vector.sub (values, 0)
|
||||||
|
in
|
||||||
|
if #start result < cursorIdx then result
|
||||||
|
else {start = ~1, finish = ~1}
|
||||||
|
end
|
||||||
else
|
else
|
||||||
let
|
let
|
||||||
val current = Vector.sub (values, idx)
|
val current = Vector.sub (values, idx)
|
||||||
val prev = Vector.sub (values, idx - 1)
|
|
||||||
in
|
in
|
||||||
if cursorIdx > #start current then
|
if cursorIdx > #start current then current
|
||||||
current
|
else Vector.sub (values, idx - 1)
|
||||||
else
|
|
||||||
prev
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
| BRANCH (nodes, sizes) =>
|
| BRANCH (nodes, sizes) =>
|
||||||
let
|
let
|
||||||
val idx = BinSearch.equalOrMore (cursorIdx, sizes)
|
val idx = BinSearch.equalOrMore (cursorIdx, sizes)
|
||||||
in
|
in
|
||||||
if idx < 0 then {start = ~1, finish = ~1}
|
if idx < 0 then
|
||||||
|
{start = ~1, finish = ~1}
|
||||||
|
else if idx = 0 then
|
||||||
|
helpPrevMatch (cursorIdx, Vector.sub (nodes, idx))
|
||||||
else
|
else
|
||||||
let
|
let
|
||||||
val node = Vector.sub (nodes, idx)
|
val node = Vector.sub (nodes, idx)
|
||||||
val result = helpPrevMatch (cursorIdx, node)
|
val result = helpPrevMatch (cursorIdx, node)
|
||||||
in
|
in
|
||||||
result
|
if #start result = ~1 then getLast (Vector.sub (nodes, idx - 1))
|
||||||
|
else result
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
fun loopPrevMatch (prevStart, tree, count) =
|
fun loopPrevMatch (prevStart, prevFinish, tree, count) =
|
||||||
if count = 0 then
|
if count = 0 then
|
||||||
prevStart
|
prevStart
|
||||||
else
|
else
|
||||||
let
|
let
|
||||||
val {start, finish} = helpPrevMatch (prevStart - 1, tree)
|
val {start, finish} = helpPrevMatch (prevFinish - 1, tree)
|
||||||
in
|
in
|
||||||
if start = ~1 then
|
if start = ~1 then
|
||||||
let val {start, finish} = getLast tree
|
let val {start, finish} = getLast tree
|
||||||
in loopPrevMatch (start, tree, count - 1)
|
in loopPrevMatch (start, finish, tree, count - 1)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
loopPrevMatch (start, tree, count - 1)
|
loopPrevMatch (start, finish, tree, count - 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
fun prevMatch (cursorIdx, tree, count) =
|
fun prevMatch (cursorIdx, tree, count) =
|
||||||
@@ -243,11 +265,11 @@ struct
|
|||||||
in
|
in
|
||||||
if start = ~1 then
|
if start = ~1 then
|
||||||
let val {start, finish} = getLast tree
|
let val {start, finish} = getLast tree
|
||||||
in loopPrevMatch (start, tree, count - 1)
|
in loopPrevMatch (start, finish, tree, count - 1)
|
||||||
end
|
end
|
||||||
else if cursorIdx >= start andalso cursorIdx <= finish then
|
else if cursorIdx >= start andalso cursorIdx <= finish then
|
||||||
loopPrevMatch (start, tree, count)
|
loopPrevMatch (start, finish, tree, count)
|
||||||
else
|
else
|
||||||
loopPrevMatch (start, tree, count - 1)
|
loopPrevMatch (start, finish, tree, count - 1)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user