2 (* The 2nd Verified Software Competition (VSTTE 2012)
3 https://sites.google.com/site/vstte2012/compet
6 Queue data structure implemented using a ring buffer
8 Alternative solution using a model stored in a ghost field *)
15 use import list.NthLengthAppend as L
16 use import array.Array as A
22 ghost mutable sequence: list 'a;
25 let size = A.length data in
28 len = L.length sequence /\
29 forall i: int. 0 <= i < len ->
31 nth i sequence = Some data[first + i]) /\
32 (0 <= first + i - size ->
33 nth i sequence = Some data[first + i - size])
35 by { first = 0; len = 0; data = make 1 (any 'a); sequence = Nil }
37 (* total capacity of the buffer *)
38 function size (b: buffer 'a) : int = A.length b.data
40 (* length = number of elements *)
41 function length (b: buffer 'a) : int = b.len
45 let create (n: int) (dummy: 'a) : buffer 'a
47 ensures { size result = n }
48 ensures { result.sequence = Nil }
49 = { first = 0; len = 0; data = make n dummy; sequence = Nil }
51 let length (b: buffer 'a) : int
52 ensures { result = length b }
55 let clear (b: buffer 'a) : unit
56 writes { b.len, b.sequence }
57 ensures { length b = 0 }
58 ensures { b.sequence = Nil }
59 = ghost (b.sequence <- Nil);
62 let push (b: buffer 'a) (x: 'a) : unit
63 requires { length b < size b }
64 writes { b.data.elts, b.len, b.sequence }
65 ensures { length b = (old (length b)) + 1 }
66 ensures { b.sequence = (old b.sequence) ++ Cons x Nil }
67 = ghost (b.sequence <- b.sequence ++ Cons x Nil);
68 let i = b.first + b.len in
69 let n = A.length b.data in
70 b.data[if i >= n then i - n else i] <- x;
73 let head (b: buffer 'a) : 'a
74 requires { length b > 0 }
75 ensures { match b.sequence with Nil -> false | Cons x _ -> result = x end }
78 let pop (b: buffer 'a) : 'a
79 requires { length b > 0 }
80 writes { b.first, b.len, b.sequence }
81 ensures { length b = (old (length b)) - 1 }
82 ensures { match old b.sequence with
84 | Cons x l -> result = x /\ b.sequence = l end }
85 = ghost match b.sequence with Nil -> absurd | Cons _ s -> b.sequence <- s end;
86 let r = b.data[b.first] in
88 let n = A.length b.data in
89 b.first <- b.first + 1;
90 if b.first = n then b.first <- 0;
100 let b = create 10 0 in
104 let x = pop b in assert { x = 1 };
105 let x = pop b in assert { x = 2 };
106 let x = pop b in assert { x = 3 };
110 let b = create 3 0 in
112 assert { sequence b = Cons 1 Nil };
114 assert { sequence b = Cons 1 (Cons 2 Nil) };
116 assert { sequence b = Cons 1 (Cons 2 (Cons 3 Nil)) };
117 let x = pop b in assert { x = 1 };
118 assert { sequence b = Cons 2 (Cons 3 Nil) };
120 assert { sequence b = Cons 2 (Cons 3 (Cons 4 Nil)) };
121 let x = pop b in assert { x = 2 };
122 assert { sequence b = Cons 3 (Cons 4 Nil) };
123 let x = pop b in assert { x = 3 };
124 assert { sequence b = Cons 4 Nil };
125 let x = pop b in assert { x = 4 };
130 let test (x: int) (y: int) (z: int) =
131 let b = create 2 0 in
134 assert { sequence b = Cons x (Cons y Nil) };
135 let h = pop b in assert { h = x };
136 assert { sequence b = Cons y Nil };
138 assert { sequence b = Cons y (Cons z Nil) };
139 let h = pop b in assert { h = y };
140 let h = pop b in assert { h = z }
144 (** With sequences instead of lists *)
149 use import seq.Seq as S
150 use import array.Array as A
156 ghost mutable sequence: S.seq 'a;
159 let size = A.length data in
162 len = S.length sequence /\
163 forall i: int. 0 <= i < len ->
165 S.get sequence i = data[first + i]) /\
166 (0 <= first + i - size ->
167 S.get sequence i = data[first + i - size])
169 by { first = 0; len = 0; data = make 1 (any 'a); sequence = S.empty }
171 (* total capacity of the buffer *)
172 function size (b: buffer 'a) : int = A.length b.data
174 (* length = number of elements *)
175 function length (b: buffer 'a) : int = b.len
179 let create (n: int) (dummy: 'a) : buffer 'a
181 ensures { size result = n }
182 ensures { result.sequence = S.empty }
183 = { first = 0; len = 0; data = make n dummy; sequence = S.empty }
185 let length (b: buffer 'a) : int
186 ensures { result = length b }
189 let clear (b: buffer 'a) : unit
190 writes { b.len, b.sequence }
191 ensures { length b = 0 }
192 ensures { b.sequence = S.empty }
193 = ghost (b.sequence <- S.empty);
196 let push (b: buffer 'a) (x: 'a) : unit
197 requires { length b < size b }
198 writes { b.data.elts, b.len, b.sequence }
199 ensures { length b = (old (length b)) + 1 }
200 ensures { b.sequence = S.snoc (old b.sequence) x }
201 = ghost (b.sequence <- S.snoc b.sequence x);
202 let i = b.first + b.len in
203 let n = A.length b.data in
204 b.data[if i >= n then i - n else i] <- x;
207 let head (b: buffer 'a) : 'a
208 requires { length b > 0 }
209 ensures { result = S.get b.sequence 0 }
212 let pop (b: buffer 'a) : 'a
213 requires { length b > 0 }
214 writes { b.first, b.len, b.sequence }
215 ensures { length b = (old (length b)) - 1 }
216 ensures { result = S.get (old b.sequence) 0 }
217 ensures { b.sequence = (old b.sequence)[1..] }
218 = ghost (b.sequence <- b.sequence[1..]);
219 let r = b.data[b.first] in
221 let n = A.length b.data in
222 b.first <- b.first + 1;
223 if b.first = n then b.first <- 0;
233 let b = create 10 0 in
237 let x = pop b in assert { x = 1 };
238 let x = pop b in assert { x = 2 };
239 let x = pop b in assert { x = 3 };
243 let b = create 3 0 in
245 assert { sequence b == cons 1 empty };
247 assert { sequence b == cons 1 (cons 2 empty) };
249 assert { sequence b == cons 1 (cons 2 (cons 3 empty)) };
250 let x = pop b in assert { x = 1 };
251 assert { sequence b == cons 2 (cons 3 empty) };
253 assert { sequence b == cons 2 (cons 3 (cons 4 empty)) };
254 let x = pop b in assert { x = 2 };
255 assert { sequence b == cons 3 (cons 4 empty) };
256 let x = pop b in assert { x = 3 };
257 assert { sequence b == cons 4 empty };
258 let x = pop b in assert { x = 4 };
263 let test (x: int) (y: int) (z: int) =
264 let b = create 2 0 in
267 assert { sequence b == cons x (cons y empty) };
268 let h = pop b in assert { h = x };
269 assert { sequence b == cons y empty };
271 assert { sequence b == cons y (cons z empty) };
272 let h = pop b in assert { h = y };
273 let h = pop b in assert { h = z }