4 Some implementations and clients of module `cursor.Cursor`
5 from the standard library.
7 Author: Mário Pereira (Université Paris Sud) *)
18 (** sums all the remaining elements in the cursor *)
19 let sum (c: cursor int) : int
20 requires { permitted c }
21 requires { c.visited = empty }
22 ensures { result = sum (get c.visited) 0 (length c.visited) }
26 invariant { permitted c }
27 invariant { !s = sum (get c.visited) 0 (length c.visited) }
35 (** {2 Iteration over an immuable collection}
37 here we choose a list *)
39 module ListCursorImpl : cursor.ListCursor
47 mutable ghost visited : seq 'a;
48 ghost collection : list 'a;
49 mutable to_visit : list 'a;
50 } invariant { visited ++ to_visit = collection }
51 by { visited = empty; collection = Nil; to_visit = Nil }
53 predicate permitted (c: cursor 'a) =
54 length c.visited <= length c.collection /\
55 forall i. 0 <= i < length c.visited -> c.visited[i] = c.collection[i]
57 predicate complete (c: cursor 'a) =
58 length c.visited = length c.collection
60 let lemma snoc_Cons (s: seq 'a) (l: list 'a) (x: 'a)
61 ensures { snoc s x ++ l == s ++ Cons x l }
66 let next (c: cursor 'a) : 'a
67 requires { not (complete c) }
69 ensures { c.visited = snoc (old c).visited result }
70 ensures { match (old c).to_visit with
72 | Cons x r -> c.to_visit = r /\ x = result
74 = match c.to_visit with
77 let ghost v0 = c.visited in
78 c.visited <- snoc c.visited x; c.to_visit <- r;
80 assert { c.to_visit == c.collection [length c.visited ..] };
84 let has_next (c: cursor 'a) : bool
85 ensures { result <-> not (complete c) }
86 = match c.to_visit with (* could define a [val eq (l1 l2: list 'a) : bool] *)
93 let create (t: list 'a) : cursor 'a
94 ensures { result.visited = empty }
95 ensures { result.collection = t }
96 ensures { result.to_visit = t }
97 = { visited = empty; collection = t; to_visit = t }
101 module TestListCursor
114 lemma sum_of_list: forall l: list int.
115 sum l = S.sum (get (of_list l)) 0 (length l)
117 let list_sum (l: list int) : int
118 ensures { result = sum l }
121 while C.has_next c do
122 invariant { !s = S.sum (get c.visited) 0 (length c.visited) }
123 invariant { permitted c }
124 variant { length l - length c.visited }
132 (** {2 Iteration over a mutable collection}
134 here we choose an array of integers *)
136 module ArrayCursorImpl : cursor.ArrayCursor
147 mutable ghost visited : seq 'a;
148 collection : seq 'a; (* FIXME : extraction of seq *)
149 mutable index : int; (** index of next element *)
150 } invariant { 0 <= index <= length collection /\
151 index = length visited /\
152 forall i. 0 <= i < index -> collection[i] = visited[i] }
153 by { visited = empty; collection = empty; index = 0 }
155 predicate permitted (c: cursor 'a) =
156 length c.visited <= length c.collection /\
157 forall i. 0 <= i < length c.visited -> c.visited[i] = c.collection[i]
159 predicate complete (c: cursor 'a) =
160 length c.visited = length c.collection
162 let create (a: array 'a) : cursor 'a
163 ensures { result.visited = empty }
164 ensures { result.index = 0 }
165 ensures { result.collection = to_seq a }
166 = { visited = empty; collection = to_seq a; index = 0; }
170 let has_next (c: cursor 'a) : bool
171 ensures { result <-> not (complete c) }
172 = c.index < length c.collection
174 let next (c: cursor 'a) : 'a
175 requires { not (complete c) }
177 ensures { c.visited = snoc (old c).visited result }
178 ensures { c.index = (old c).index + 1 }
179 = if c.index >= length c.collection then absurd
180 else begin let x = c.collection[c.index] in
181 c.visited <- snoc c.visited x;
182 c.index <- c.index + 1;
189 module TestArrayCursor
200 let array_sum (a: array int) : int
201 ensures { result = sum (Array.([]) a) 0 (length a) }
204 while C.has_next c do
205 invariant { !s = sum (get c.visited) 0 (length c.visited) }
206 invariant { permitted c }
207 variant { length c.collection - length c.visited }
213 let harness1 () : unit
214 = let a = Array.make 42 0 in