Skip to main content

ostd/specs/mm/frame/linked_list/
linked_list_specs.rs

1use vstd::prelude::*;
2
3use vstd_extra::cast_ptr::*;
4use vstd_extra::ownership::*;
5use vstd_extra::prelude::*;
6
7use super::linked_list_owners::*;
8use crate::mm::frame::linked_list::Link;
9use crate::mm::frame::*;
10use crate::mm::{Paddr, PagingLevel, Vaddr};
11use crate::specs::arch::mm::{MAX_NR_PAGES, MAX_PADDR, PAGE_SIZE};
12
13verus! {
14
15impl CursorModel {
16    pub open spec fn move_next_spec(self) -> Self {
17        if self.list_model.list.len() > 0 {
18            if self.rear.len() > 0 {
19                let cur = self.rear[0];
20                Self {
21                    fore: self.fore.insert(self.fore.len() as int, cur),
22                    rear: self.rear.remove(0),
23                    list_model: self.list_model,
24                }
25            } else {
26                Self {
27                    fore: Seq::<LinkModel>::empty(),
28                    rear: self.fore,
29                    list_model: self.list_model,
30                }
31            }
32        } else {
33            self
34        }
35    }
36
37    pub open spec fn move_prev_spec(self) -> Self {
38        if self.list_model.list.len() > 0 {
39            if self.fore.len() > 0 {
40                let cur = self.fore[self.fore.len() - 1];
41                Self {
42                    fore: self.fore.remove(self.fore.len() - 1),
43                    rear: self.rear.insert(0, cur),
44                    list_model: self.list_model,
45                }
46            } else {
47                Self {
48                    fore: self.rear,
49                    rear: Seq::<LinkModel>::empty(),
50                    list_model: self.list_model,
51                }
52            }
53        } else {
54            self
55        }
56    }
57
58    pub open spec fn remove(self) -> Self {
59        let rear = self.rear.remove(0);
60
61        Self {
62            fore: self.fore,
63            rear: rear,
64            list_model: LinkedListModel { list: self.fore.add(rear) },
65        }
66    }
67
68    pub open spec fn insert(self, link: LinkModel) -> Self {
69        let fore = self.fore.insert(self.fore.len() as int, link);
70
71        Self {
72            fore: fore,
73            rear: self.rear,
74            list_model: LinkedListModel { list: fore.add(self.rear) },
75        }
76    }
77}
78
79impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> CursorOwner<M> {
80    pub open spec fn remove_owner_spec(self, post: Self) -> bool
81        recommends
82            self.index < self.length(),
83    {
84        &&& post.list_own.list == self.list_own.list.remove(self.index)
85        &&& post.index == self.index
86    }
87
88    pub proof fn remove_owner_spec_implies_model_spec(self, post: Self)
89        requires
90            self.remove_owner_spec(post),
91            0 <= self.index < self.length(),
92        ensures
93            post@ == self@.remove(),
94    {
95        let idx = self.index;
96        let s = self.list_own.list;
97        let ps = post.list_own.list;
98
99        LinkedListOwner::<M>::view_preserves_len(s);
100        LinkedListOwner::<M>::view_preserves_len(ps);
101
102        let vh_s = LinkedListOwner::<M>::view_helper(s);
103        let vh_ps = LinkedListOwner::<M>::view_helper(ps);
104
105        assert(post@.fore =~= self@.fore) by {
106            assert forall|j: int| 0 <= j < vh_ps.take(idx).len() implies vh_ps.take(idx)[j]
107                == vh_s.take(idx)[j] by {
108                LinkedListOwner::<M>::view_helper_index(ps, j);
109                LinkedListOwner::<M>::view_helper_index(s, j);
110            };
111        };
112
113        assert(post@.rear =~= self@.remove().rear) by {
114            assert forall|j: int| 0 <= j < vh_ps.skip(idx).len() implies #[trigger] vh_ps.skip(
115                idx,
116            )[j] == vh_s.skip(idx).remove(0)[j] by {
117                LinkedListOwner::<M>::view_helper_index(ps, idx + j);
118                LinkedListOwner::<M>::view_helper_index(s, idx + j + 1);
119            };
120        };
121
122        assert forall|j: int| 0 <= j < vh_ps.len() implies #[trigger] vh_ps[j] == vh_s.take(
123            idx,
124        ).add(vh_s.skip(idx).remove(0))[j] by {
125            LinkedListOwner::<M>::view_helper_index(ps, j);
126            if j < idx {
127                LinkedListOwner::<M>::view_helper_index(s, j);
128            } else {
129                LinkedListOwner::<M>::view_helper_index(s, j + 1);
130            }
131        };
132        assert(vh_ps =~= vh_s.take(idx).add(vh_s.skip(idx).remove(0)));
133        assert(post@.list_model == self@.remove().list_model);
134    }
135
136    pub open spec fn insert_owner_spec(self, link: LinkOwner, post: Self) -> bool
137        recommends
138            self.index < self.length(),
139    {
140        // The list model (`view_helper`) depends only on the element sequence,
141        // not on `list_id`, so this carries no `list_id` clause — letting it
142        // hold even when the insert mints a fresh id for a previously-empty list.
143        &&& post.list_own.list == self.list_own.list.insert(self.index, link)
144        &&& post.index == self.index + 1
145    }
146
147    pub proof fn insert_owner_spec_implies_model_spec(self, link: LinkOwner, post: Self)
148        requires
149            self.insert_owner_spec(link, post),
150            0 <= self.index <= self.length(),
151        ensures
152            post@ == self@.insert(link@),
153    {
154        let idx = self.index;
155        let s = self.list_own.list;
156        let ps = post.list_own.list;
157
158        LinkedListOwner::<M>::view_preserves_len(s);
159        LinkedListOwner::<M>::view_preserves_len(ps);
160        LinkedListOwner::<M>::view_helper_insert(s, idx, link);
161
162        let vh_s = LinkedListOwner::<M>::view_helper(s);
163        let vh_ps = LinkedListOwner::<M>::view_helper(ps);
164
165        assert(post@.fore =~= self@.insert(link@).fore) by {
166            assert forall|j: int| 0 <= j < vh_ps.take(idx + 1).len() implies vh_ps.take(idx + 1)[j]
167                == vh_s.take(idx).insert(idx as int, link@)[j] by {
168                LinkedListOwner::<M>::view_helper_index(ps, j);
169                if j < idx {
170                    LinkedListOwner::<M>::view_helper_index(s, j);
171                }
172            };
173        };
174
175        assert(post@.rear =~= self@.insert(link@).rear) by {
176            assert forall|j: int| 0 <= j < vh_ps.skip(idx + 1).len() implies vh_ps.skip(idx + 1)[j]
177                == vh_s.skip(idx)[j] by {
178                LinkedListOwner::<M>::view_helper_index(ps, idx + 1 + j);
179                LinkedListOwner::<M>::view_helper_index(s, idx + j);
180            };
181        };
182
183        let new_fore = vh_s.take(idx).insert(idx as int, link@);
184        assert forall|j: int| 0 <= j < vh_ps.len() implies #[trigger] vh_ps[j] == new_fore.add(
185            vh_s.skip(idx),
186        )[j] by {
187            LinkedListOwner::<M>::view_helper_index(ps, j);
188            if j < idx {
189                LinkedListOwner::<M>::view_helper_index(s, j);
190            } else if j > idx {
191                LinkedListOwner::<M>::view_helper_index(s, j - 1);
192            }
193        };
194        assert(vh_ps =~= new_fore.add(vh_s.skip(idx)));
195        assert(post@.list_model == self@.insert(link@).list_model);
196    }
197
198    pub open spec fn move_next_owner_spec(self) -> Self {
199        if self.length() == 0 {
200            self
201        } else if self.index == self.length() {
202            Self { list_own: self.list_own, index: 0 }
203        } else if self.index == self.length() - 1 {
204            Self { list_own: self.list_own, index: self.index + 1 }
205        } else {
206            Self { list_own: self.list_own, index: self.index + 1 }
207        }
208    }
209
210    pub open spec fn move_prev_owner_spec(self) -> Self {
211        if self.length() == 0 {
212            self
213        } else if self.index == self.length() {
214            Self { list_own: self.list_own, index: self.index - 1 }
215        } else if self.index == 0 {
216            Self { list_own: self.list_own, index: self.length() }
217        } else {
218            Self { list_own: self.list_own, index: self.index - 1 }
219        }
220    }
221}
222
223} // verus!