1use super::super::super::modes::*;
2use super::super::super::prelude::*;
3use super::super::Loc;
4use super::super::imap::*;
5
6verus! {
7
8broadcast use super::super::super::group_vstd_default;
9
10pub open spec fn seq_to_map<V>(s: Seq<V>, off: int) -> IMap<int, V> {
11 IMap::new(|i: int| off <= i < off + s.len(), |i: int| s[i - off])
12}
13
14pub tracked struct GhostSeqAuth<V> {
66 ghost off: nat,
67 ghost len: nat,
68 auth: GhostIMapAuth<int, V>,
69}
70
71pub tracked struct GhostSubseq<V> {
72 ghost off: nat,
73 ghost len: nat,
74 frac: GhostISubmap<int, V>,
75}
76
77impl<V> GhostSeqAuth<V> {
78 #[verifier::type_invariant]
79 spec fn inv(self) -> bool {
80 &&& self.auth@.dom() =~= ISet::new(|i: int| self.off <= i < self.off + self.len)
81 }
82
83 pub closed spec fn id(self) -> Loc {
84 self.auth.id()
85 }
86
87 pub closed spec fn view(self) -> Seq<V> {
88 Seq::new(self.len, |i: int| self.auth@[self.off + i])
89 }
90
91 pub open spec fn len(self) -> nat {
92 self@.len()
93 }
94
95 pub open spec fn spec_index(self, idx: int) -> V
96 recommends
97 0 <= idx < self.len(),
98 {
99 self@[idx]
100 }
101
102 pub closed spec fn off(self) -> nat {
103 self.off
104 }
105
106 pub open spec fn subrange_abs(self, start_inclusive: int, end_exclusive: int) -> Seq<V>
107 recommends
108 self.off() <= start_inclusive <= end_exclusive <= self.off() + self@.len(),
109 {
110 self@[start_inclusive - self.off()..end_exclusive - self.off()]
111 }
112
113 pub proof fn new(s: Seq<V>, off: nat) -> (tracked result: (GhostSeqAuth<V>, GhostSubseq<V>))
114 ensures
115 result.0.off() == off,
116 result.0@ =~= s,
117 result.1.id() == result.0.id(),
118 result.1.off() == off,
119 result.1@ =~= s,
120 {
121 let tracked (mauth, mfrac) = GhostIMapAuth::<int, V>::new(seq_to_map(s, off as int));
122 let tracked auth = GhostSeqAuth { off: off, len: s.len(), auth: mauth };
123 let tracked frac = GhostSubseq { off: off, len: s.len(), frac: mfrac };
124 (auth, frac)
125 }
126
127 pub proof fn dummy() -> (tracked result: Self) {
128 let tracked (auth, subseq) = Self::new(Seq::empty(), 0);
129 auth
130 }
131
132 pub proof fn agree(tracked self: &GhostSeqAuth<V>, tracked frac: &GhostSubseq<V>)
133 requires
134 self.id() == frac.id(),
135 ensures
136 frac@.len() > 0 ==> {
137 &&& frac@ =~= self@[frac.off() - self.off()..frac.off() - self.off() + frac@.len()]
138 &&& frac.off() >= self.off()
139 &&& frac.off() + frac@.len() <= self.off() + self@.len()
140 },
141 {
142 frac.agree(self)
143 }
144
145 pub proof fn update_subrange_with(
146 tracked self: &mut GhostSeqAuth<V>,
147 tracked frac: &mut GhostSubseq<V>,
148 off: int,
149 v: Seq<V>,
150 )
151 requires
152 old(self).id() == old(frac).id(),
153 old(frac).off() <= off,
154 off + v.len() <= old(frac).off() + old(frac)@.len(),
155 ensures
156 final(self).id() == old(self).id(),
157 final(frac).id() == old(frac).id(),
158 final(frac).off() == old(frac).off(),
159 final(self)@ =~= old(self)@.update_subrange_with(off - final(self).off(), v),
160 final(frac)@ =~= old(frac)@.update_subrange_with(off - final(frac).off(), v),
161 final(self).off() == old(self).off(),
162 final(frac).off() == old(frac).off(),
163 {
164 let tracked mut mid = frac.split(off - frac.off());
165 let tracked mut end = mid.split(v.len() as int);
166 mid.update(self, v);
167 frac.combine(mid);
168 frac.combine(end);
169 }
170}
171
172impl<V> GhostSubseq<V> {
173 #[verifier::type_invariant]
174 spec fn inv(self) -> bool {
175 &&& self.frac@.dom() =~= ISet::new(|i: int| self.off <= i < self.off + self.len)
176 }
177
178 pub closed spec fn view(self) -> Seq<V> {
179 Seq::new(self.len, |i: int| self.frac@[self.off + i])
180 }
181
182 pub open spec fn len(self) -> nat {
183 self@.len()
184 }
185
186 pub open spec fn spec_index(self, idx: int) -> V
187 recommends
188 0 <= idx < self.len(),
189 {
190 self@[idx]
191 }
192
193 pub open spec fn subrange_abs(self, start_inclusive: int, end_exclusive: int) -> Seq<V>
194 recommends
195 self.off() <= start_inclusive <= end_exclusive <= self.off() + self@.len(),
196 {
197 self@[start_inclusive - self.off()..end_exclusive - self.off()]
198 }
199
200 pub closed spec fn off(self) -> nat {
201 self.off
202 }
203
204 pub closed spec fn id(self) -> Loc {
205 self.frac.id()
206 }
207
208 pub proof fn agree(tracked self: &GhostSubseq<V>, tracked auth: &GhostSeqAuth<V>)
209 requires
210 self.id() == auth.id(),
211 ensures
212 self@.len() > 0 ==> {
213 &&& self@ =~= auth@[self.off() - auth.off()..self.off() - auth.off() + self@.len()]
214 &&& self.off() >= auth.off()
215 &&& self.off() + self@.len() <= auth.off() + auth@.len()
216 },
217 {
218 use_type_invariant(self);
219 use_type_invariant(auth);
220
221 self.frac.agree(&auth.auth);
222
223 if self@.len() > 0 {
224 assert(self.frac@.contains_key(self.off as int));
225 assert(auth.auth@.contains_key(self.off as int));
226
227 assert(self.frac@.contains_key(self.off + self.len - 1));
228 assert(auth.auth@.contains_key(self.off + self.len - 1));
229 assert(self.off - auth.off + self.len - 1 < auth@.len());
230
231 assert forall|i: int| 0 <= i < self.len implies #[trigger] self.frac@[self.off + i]
232 == auth@[self.off - auth.off + i] by {
233 assert(self.frac@.contains_key(self.off + i));
234 assert(auth.auth@.contains_key(self.off + i));
235 };
236 }
237 }
238
239 pub proof fn agree_map(tracked self: &GhostSubseq<V>, tracked auth: &GhostIMapAuth<int, V>)
240 requires
241 self.id() == auth.id(),
242 ensures
243 forall|i|
244 0 <= i < self@.len() ==> #[trigger] auth@.contains_key(self.off() + i)
245 && auth@[self.off() + i] == self@[i],
246 {
247 use_type_invariant(self);
248
249 self.frac.agree(&auth);
250
251 assert forall|i: int| 0 <= i < self.len implies #[trigger] auth@.contains_key(self.off + i)
252 && self.frac@[self.off + i] == auth@[self.off + i] by {
253 assert(self.frac@.contains_key(self.off + i));
254 };
255 }
256
257 pub proof fn update(
258 tracked self: &mut GhostSubseq<V>,
259 tracked auth: &mut GhostSeqAuth<V>,
260 v: Seq<V>,
261 )
262 requires
263 old(self).id() == old(auth).id(),
264 v.len() == old(self)@.len(),
265 ensures
266 final(self).id() == final(auth).id(),
267 final(self).off() == old(self).off(),
268 final(auth).id() == old(auth).id(),
269 final(self)@ =~= v,
270 final(auth)@ =~= old(auth)@.update_subrange_with(
271 final(self).off() - final(auth).off(),
272 v,
273 ),
274 final(self).off() == old(self).off(),
275 final(auth).off() == old(auth).off(),
276 {
277 use_type_invariant(&*self);
278 use_type_invariant(&*auth);
279
280 self.update_map(&mut auth.auth, v);
281 }
282
283 pub proof fn update_map(
284 tracked self: &mut GhostSubseq<V>,
285 tracked auth: &mut GhostIMapAuth<int, V>,
286 v: Seq<V>,
287 )
288 requires
289 old(self).id() == old(auth).id(),
290 v.len() == old(self)@.len(),
291 ensures
292 final(self).id() == final(auth).id(),
293 final(self).off() == old(self).off(),
294 final(auth).id() == old(auth).id(),
295 final(self)@ =~= v,
296 final(auth)@ =~= IMap::new(
297 |i: int| old(auth)@.contains_key(i),
298 |i: int|
299 if final(self).off() <= i < final(self).off() + v.len() {
300 v[i - final(self).off()]
301 } else {
302 old(auth)@[i]
303 },
304 ),
305 {
306 use_type_invariant(&*self);
307
308 let vmap = seq_to_map(v, self.off as int);
309 assert(self.frac@.dom() == vmap.dom());
310 self.frac.agree(auth);
311 self.frac.update(auth, vmap);
312 }
313
314 pub proof fn split(tracked self: &mut GhostSubseq<V>, n: int) -> (tracked result: GhostSubseq<
315 V,
316 >)
317 requires
318 0 <= n <= old(self)@.len(),
319 ensures
320 final(self).id() == old(self).id(),
321 final(self).off() == old(self).off(),
322 result.id() == final(self).id(),
323 result.off() == old(self).off() + n,
324 final(self)@ =~= old(self)@[0..n],
325 result@ =~= old(self)@[n..old(self)@.len()],
326 {
327 let tracked mut mself = Self::dummy();
328 tracked_swap(self, &mut mself);
329
330 use_type_invariant(&mself);
331 let tracked mut mselffrac = mself.frac;
332
333 let tracked mfrac = mselffrac.split(
334 ISet::new(|i: int| mself.off + n <= i < mself.off + mself.len),
335 );
336 let tracked result = GhostSubseq {
337 off: (mself.off + n) as nat,
338 len: (mself.len - n) as nat,
339 frac: mfrac,
340 };
341
342 *self = Self { off: mself.off, len: n as nat, frac: mselffrac };
343 result
344 }
345
346 pub proof fn combine(tracked self: &mut GhostSubseq<V>, tracked r: GhostSubseq<V>)
347 requires
348 r.id() == old(self).id(),
349 r.off() == old(self).off() + old(self)@.len(),
350 ensures
351 final(self).id() == old(self).id(),
352 final(self)@ =~= old(self)@ + r@,
353 final(self).off() == old(self).off(),
354 {
355 let tracked mut mself = Self::dummy();
356 tracked_swap(self, &mut mself);
357
358 use_type_invariant(&mself);
359 use_type_invariant(&r);
360 let tracked mut mselffrac = mself.frac;
361
362 mselffrac.combine(r.frac);
363 *self = Self { frac: mselffrac, off: mself.off, len: mself.len + r.len };
364 }
365
366 pub proof fn disjoint(tracked &mut self, tracked other: &GhostSubseq<V>)
367 requires
368 old(self).id() == other.id(),
369 ensures
370 final(self).id() == old(self).id(),
371 final(self).off() == old(self).off(),
372 final(self)@ == old(self)@,
373 final(self)@.len() == 0 || other@.len() == 0 || final(self).off() + final(self)@.len()
374 <= other.off() || other.off() + other@.len() <= final(self).off(),
375 {
376 use_type_invariant(&*self);
377 use_type_invariant(other);
378
379 self.frac.disjoint(&other.frac);
380 assert(self@.len() == 0 || self.frac@.contains_key(self.off() as int));
381 assert(other@.len() == 0 || other.frac@.contains_key(other.off() as int));
382 }
383
384 pub proof fn dummy() -> (tracked result: Self) {
385 let tracked (auth, subseq) = GhostSeqAuth::<V>::new(Seq::empty(), 0);
386 subseq
387 }
388
389 pub proof fn new(off: nat, len: nat, tracked f: GhostISubmap<int, V>) -> (tracked result:
391 GhostSubseq<V>)
392 requires
393 f@.dom() == ISet::new(|i: int| off <= i < off + len),
394 ensures
395 result.id() == f.id(),
396 result.off() == off,
397 result@ == Seq::new(len, |i| f@[off + i]),
398 {
399 GhostSubseq { off: off, len: len, frac: f }
400 }
401}
402
403}