Source file dumb.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
module P = Plebeia
open P.Result.Infix
type t =
| Null
| Leaf of P.Value.t
| Tree of t
| Node of t * t
type trail = Root | Treed of trail | Left of t * trail | Right of t * trail
type segment = P.Segment.t
type error = string
type value = P.Value.t
type context = unit
type cursor = t * trail
let get_node (t, _) = t
let rec of_plebeia_node : P.Context.t -> P.Node.node -> t = fun context -> function
| Hash _ -> assert false
| Disk (i, wit) ->
of_plebeia_node context (View (P.Node.read_node context i wit))
| View n ->
match n with
| Bud (None, _, _) -> Tree Null
| Bud (Some n, _, _) -> Tree (of_plebeia_node context n)
| Internal (l, r, _, _) -> Node (of_plebeia_node context l,
of_plebeia_node context r)
| Leaf (v, _, _) -> Leaf v
| Extender (seg, n, _, _) ->
let rec aux n seg =
match P.Segment.cut seg with
| None -> n
| Some (P.Segment.Left, seg) -> Node (aux n seg, Null)
| Some (P.Segment.Right, seg) -> Node (Null, aux n seg)
in
aux (of_plebeia_node context n) seg
let empty () = (Tree Null, Root)
let check_node (n, trail) =
match n with
| Tree n -> Ok (n, Treed trail)
| _ -> Error "Start node is not Tree"
let subtree ntrail seg =
let rec aux ((n, trail) as cur) = function
| [] ->
begin match n with
| Tree _ -> Ok cur
| _ -> Error "Reached to non Tree"
end
| P.Segment.Left :: seg' ->
begin match n with
| Null -> Error "Null"
| Leaf _ -> Error "Leaf"
| Tree _ -> Error "Tree in middle"
| Node (l, r) -> aux (l, Left (r, trail)) seg'
end
| P.Segment.Right :: seg' ->
begin match n with
| Null -> Error "Null"
| Leaf _ -> Error "Leaf"
| Tree _ -> Error "Tree in middle"
| Node (l, r) -> aux (r, Right (l, trail)) seg'
end
in
check_node ntrail >>= fun ntrail -> aux ntrail (P.Segment.to_sides seg)
let rec go_up_tree (n, trail) =
let trim_null = function
| Node (Null, Null) -> Null
| t -> t
in
match trail with
| Treed trail -> Ok (Tree n, trail)
| Root -> Error "Root"
| Left (r, trail) -> go_up_tree (trim_null (Node (n,r)), trail)
| Right (l, trail) -> go_up_tree (trim_null (Node (l, n)), trail)
let parent ((n, _) as ntrail) =
match n with
| Tree _ -> go_up_tree ntrail
| _ -> Error "not Tree"
let get_node_seg ntrail seg =
let rec aux ((n, trail) as ntrail) = function
| [] -> Ok ntrail
| P.Segment.Left :: seg' ->
begin match n with
| Null -> Error "Null"
| Leaf _ -> Error "Leaf"
| Tree _ -> Error "Tree in middle"
| Node (l, r) -> aux (l, Left (r, trail)) seg'
end
| P.Segment.Right :: seg' ->
begin match n with
| Null -> Error "Null"
| Leaf _ -> Error "Leaf"
| Tree _ -> Error "Tree in middle"
| Node (l, r) -> aux (r, Right (l, trail)) seg'
end
in
check_node ntrail >>= fun ntrail ->
aux ntrail seg
let get_value ntrail seg =
let seg = P.Segment.to_sides seg in
get_node_seg ntrail seg >>= function
| (Leaf v, _) -> Ok v
| _ -> Error "Not Leaf"
let alter ntrail seg f =
let seg = P.Segment.to_sides seg in
let rec aux (n, trail) = function
| [] -> f n >>= fun v -> Ok (v, trail)
| P.Segment.Left :: seg' ->
begin match n with
| Null -> aux (Null, Left (Null, trail)) seg'
| Leaf _ -> Error "Leaf"
| Tree _ -> Error "Tree in middle"
| Node (l, r) -> aux (l, Left (r, trail)) seg'
end
| P.Segment.Right :: seg' ->
begin match n with
| Null -> aux (Null, Right (Null, trail)) seg'
| Leaf _ -> Error "Leaf"
| Tree _ -> Error "Tree in middle"
| Node (l, r) -> aux (r, Right (l, trail)) seg'
end
in
check_node ntrail >>= fun ntrail ->
aux ntrail seg >>= go_up_tree
let insert ntrail seg v =
let f = function
| Null -> Ok (Leaf v)
| _ -> Error "not Null"
in
alter ntrail seg f
let upsert ntrail seg v =
let f = function
| Null | Leaf _ -> Ok (Leaf v)
| _ -> Error "not Null nor Leaf"
in
alter ntrail seg f
let create_subtree ntrail seg =
let f = function
| Null -> Ok (Tree Null)
| _ -> Error "not Null"
in
alter ntrail seg f
let delete ntrail seg =
let seg = P.Segment.to_sides seg in
get_node_seg ntrail seg >>= function
| ((Leaf _ | Tree _), trail) -> go_up_tree (Null, trail)
| _ -> Error "Not Leaf nor Tree"
let link ?label n1 n2 =
match label with
| None -> Printf.sprintf "%s -> %s;" n1 n2
| Some l -> Printf.sprintf "%s -> %s [label=\"%s\"];" n1 n2 l
let null n = Printf.sprintf "%s [shape=point];" n
let leaf n value = Printf.sprintf "%s [label=%S];" n (P.Value.to_string value)
let tree n = Printf.sprintf "%s [shape=diamond, label=\"\"];" n
let node n = Printf.sprintf "%s [shape=circle, label=\"\"];" n
let of_node_aux cntr root =
let rec aux : int -> t -> (string * string list * int) = fun cntr -> function
| Null ->
let n = Printf.sprintf "Null%d\n" cntr in
(n, [null n], cntr+1)
| Leaf value ->
let n = Printf.sprintf "Leaf%d\n" cntr in
(n, [leaf n value], cntr+1)
| Tree node ->
let n', s, cntr = aux cntr node in
let n = Printf.sprintf "Tree%d" cntr in
(n,
[tree n;
link n n'
] @ s,
cntr + 1)
| Node (left, right) ->
let ln, ls, cntr = aux cntr left in
let rn, rs, cntr = aux cntr right in
let n = Printf.sprintf "Node%d" cntr in
(n,
[ node n;
link n ln ~label:"L";
link n rn ~label:"R" ]
@ ls @ rs,
cntr + 1)
in
aux cntr root
let rec of_trail dst cntr = function
| Root -> ([], cntr)
| Left (r, trail) ->
let n = Printf.sprintf "Node%d" cntr in
let cntr = cntr + 1 in
let r, ss, cntr = of_node_aux cntr r in
let (ss', cntr) = of_trail n cntr trail in
([ node n;
link n dst ~label:"L";
link n r ~label:"R" ]
@ ss @ ss',
cntr)
| Right (l, trail) ->
let n = Printf.sprintf "Node%d" cntr in
let cntr = cntr + 1 in
let l, ss, cntr = of_node_aux cntr l in
let (ss', cntr) = of_trail n cntr trail in
([ node n;
link n l ~label:"L";
link n dst ~label:"R" ]
@ ss @ ss',
cntr)
| Treed trail ->
let n = Printf.sprintf "Tree%d" cntr in
let cntr = cntr + 1 in
let (ss, cntr) = of_trail n cntr trail in
([ tree n;
link n dst ]
@ ss,
cntr)
let make_digraph ss = "digraph G {\n" ^ String.concat "\n" ss ^ "\n}\n"
let dot_of_node root =
let (_name, ss, _cntr) = of_node_aux 0 root in
make_digraph ss
let dot_of_cursor (node, trail) =
let (n, ss, cntr) = of_node_aux 0 node in
let ss', _ = of_trail n cntr trail in
let s = Printf.sprintf "cursor [shape=point, label=\"\"]; cursor -> %s [style=bold];" n in
make_digraph (s :: ss @ ss')