5 Formalized Verification of Snapshotable Trees: Separation and Sharing
6 Hannes Mehnert, Filip Sieczkowski, Lars Birkedal, and Peter Sestoft
10 (* Purely applicative binary trees with elements at the nodes *)
16 use export list.Length
17 use export list.Append
25 function tree_elements (t: tree) : list elt = match t with
27 | Node l x r -> tree_elements l ++ Cons x (tree_elements r)
30 predicate mem (x: elt) (t: tree) = match t with
32 | Node l y r -> mem x l || x = y || mem x r
37 (* Purely applicative iterators over binary trees *)
47 function enum_elements (e: enum) : list elt = match e with
49 | Next x r e -> Cons x (tree_elements r ++ enum_elements e)
52 let rec enum t e variant {t}
53 ensures { enum_elements result = tree_elements t ++ enum_elements e }
56 | Node l x r -> enum l (Next x r e)
61 (* Mutable iterators with a Java-like API *)
68 type iterator = { mutable it: enum }
70 function elements (i: iterator) : list elt = enum_elements i.it
72 let create_iterator (t: tree)
73 ensures { elements result = tree_elements t }
74 = { it = enum t Done }
76 predicate hasNext (i: iterator) = i.it <> Done
78 let hasNext (i: iterator)
79 ensures { result = True <-> hasNext i }
80 = match i.it with Done -> False | _ -> True end
82 let next (i: iterator)
83 requires { hasNext i }
84 ensures { old (elements i) = Cons result (elements i) }
87 | Next x r e -> i.it <- enum r e; x
92 (* Binary search trees *)
98 predicate lt_tree (x: elt) (t: tree) =
99 forall y: elt. mem y t -> y < x
101 predicate gt_tree (x: elt) (t: tree) =
102 forall y: elt. mem y t -> x < y
104 predicate bst (t: tree) =
107 | Node l x r -> bst l /\ bst r /\ lt_tree x l /\ gt_tree x r
110 let rec bst_mem (x: elt) (t: tree)
111 requires { bst t } ensures { result=True <-> mem x t } variant { t }
116 if x < y then bst_mem x l else x = y || bst_mem x r
120 (* bst_add raises exception Already when the element is already present *)
122 let rec bst_add (x: elt) (t: tree)
124 ensures { bst result /\ not (mem x t) /\
125 forall y: elt. mem y result <-> y=x || mem y t }
126 raises { Already -> mem x t }
132 if x = y then raise Already;
133 if x < y then Node (bst_add x l) y r else Node l y (bst_add x r)
138 (* Imperative trees with add/contains/snapshot/iterator API *)
145 type itree = { mutable tree: tree } invariant { bst tree }
147 let create () = { tree = Empty }
149 let contains (t: itree) (x: elt)
150 ensures { result=True <-> mem x t.tree }
153 let add (t: itree) (x: elt)
154 ensures { (result=False <-> mem x (old t.tree)) /\
155 forall y: elt. mem y t.tree <-> y=x || mem y (old t.tree) }
156 = try t.tree <- bst_add x t.tree; True with Already -> False end
158 let snapshot (t: itree) = { tree = t.tree }
160 let iterator (t: itree)
161 ensures { elements result = tree_elements t.tree }
162 = create_iterator t.tree
175 assert { mem 2 t.tree };
176 let s = snapshot t in
177 let it = iterator s in
179 invariant { bst t.tree }
180 variant { length (elements it) }
182 let _ = add t (x * 3) in