begin implementing clojure-style vector first as a rope implementation of radix-relaxed balanced trees

This commit is contained in:
2025-10-23 05:11:57 +01:00
parent ec62efb40c
commit 7c9d47346e

105
src/rrb_rope.sml Normal file
View File

@@ -0,0 +1,105 @@
structure RrbRope =
struct
val bits: Word.word = 0w5
val width: Word.word = 0w32
val mask: Word.word = 0w31
datatype tree = BRANCH of tree vector | LEAF of int vector
type t = {root: tree, shift: word, count: int}
val empty: t = {root = LEAF (Vector.fromList []), shift = 0w0, count = 0}
fun tailoff count =
if count < 32 then
0w0
else
let
val w = Word.fromInt (count - 1)
val w = Word.>> (w, bits)
in
Word.<< (w, bits)
end
fun getLast tree =
case tree of
BRANCH n => getLast (Vector.sub (n, Vector.length n - 1))
| LEAF i => Vector.sub (i, Vector.length i - 1)
fun helpGet (key: Word.word, level, tree) =
case tree of
BRANCH nodes =>
let
val w = Word.>> (key, level)
val w = Word.andb (w, mask)
val node = Vector.sub (nodes, Word.toInt w)
in
helpGet (key, level - bits, node)
end
| LEAF items =>
let val idx = Word.andb (key, mask)
in Vector.sub (items, Word.toInt idx)
end
fun get (key, {shift, root, count}: t) =
let val key = Word.fromInt key
in if key >= tailoff count then getLast root else helpGet (key, shift, root)
end
datatype append_result = UPDATE | APPEND
fun helpAppend (item, tree) =
case tree of
BRANCH n =>
let
val lastNode = Vector.sub (n, Vector.length n - 1)
in
case helpAppend (item, lastNode) of
(UPDATE, newLast, newDepth) =>
let val n = Vector.update (n, Vector.length n - 1, newLast)
in (UPDATE, BRANCH n, newDepth + 1)
end
| (APPEND, newNode, newDepth) =>
if Vector.length n = 32 then
let val hewNode = BRANCH (Vector.fromList [newNode])
in (APPEND, newNode, newDepth + 1)
end
else
let val n = Vector.concat [n, Vector.fromList [newNode]]
in (UPDATE, BRANCH n, newDepth + 1)
end
end
| LEAF items =>
if Vector.length items = 32 then
let val appendLeaf = LEAF (Vector.fromList [item])
in (APPEND, appendLeaf, 0)
end
else
let val newLeaf = Vector.concat [items, Vector.fromList [item]]
in (UPDATE, LEAF newLeaf, 0)
end
fun append (item, {shift, root, count}: t) =
case helpAppend (item, root) of
(UPDATE, updatedTree, newDepth) =>
{ count = count + 1
, root = updatedTree
, shift = let val w = Word.fromInt newDepth in w * bits end
}
| (APPEND, newLast, newDepth) =>
let
val root = BRANCH (Vector.fromList [root, newLast])
val w = Word.fromInt newDepth
val shift = w * bits
in
{count = count + 1, root = root, shift = shift}
end
fun mk (count, acc) =
if count = 97 then acc
else let val acc = append (count, acc) in mk (count + 1, acc) end
val root = mk (0, empty)
val result = get (99, root)
end