Skip to content

Commit 4b33d71

Browse files
committed
Update library
1 parent 32b1db6 commit 4b33d71

3 files changed

Lines changed: 127 additions & 55 deletions

File tree

vstd_extra/src/resource/ghost_resource/csum.rs

Lines changed: 95 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,19 @@
11
//! Sum types for ghost resources.
2-
use vstd::prelude::*;
32
use vstd::pcm::Loc;
3+
use vstd::prelude::*;
44
use vstd::storage_protocol::*;
55

6-
76
use crate::resource::storage_protocol::csum::*;
87
use crate::sum::*;
98

10-
119
verus! {
1210

13-
/// `SumResourceStorage` is a storage resource that stores either an A or a B, but not both.
14-
pub tracked struct SumResourceStorage<A, B> {
11+
/// `SumResource` is a storage resource that stores either an A or a B, but not both.
12+
pub tracked struct SumResource<A, B> {
1513
tracked r: StorageResource<(), Sum<A, B>, CsumP<A, B>>,
1614
}
1715

18-
impl<A,B> SumResourceStorage<A, B>
19-
{
16+
impl<A, B> SumResource<A, B> {
2017
pub closed spec fn id(self) -> Loc {
2118
self.r.loc()
2219
}
@@ -36,41 +33,54 @@ impl<A,B> SumResourceStorage<A, B>
3633
pub open spec fn is_right(self) -> bool {
3734
self.protocol_monoid() is Cinr
3835
}
39-
36+
4037
pub open spec fn resource(self) -> Sum<A, B> {
4138
self.protocol_monoid().to_sum()
4239
}
4340

44-
pub proof fn alloc_empty() -> (tracked res:Self)
45-
ensures
46-
res.is_empty(),
41+
pub proof fn is_exclusive(tracked &mut self, tracked other: &Self)
42+
requires
43+
old(self).is_left() || old(self).is_right(),
44+
other.is_left() || other.is_right(),
45+
ensures
46+
*self == *old(self),
47+
self.id() != other.id(),
48+
{
49+
if (self.id() == other.id()) {
50+
self.r.validate_with_shared(&other.r);
51+
}
52+
}
53+
54+
pub proof fn alloc_empty() -> (tracked res: Self)
55+
ensures
56+
res.is_empty(),
4757
{
4858
let tracked r = StorageResource::alloc(CsumP::Unit, Map::tracked_empty());
49-
SumResourceStorage { r }
59+
SumResource { r }
5060
}
5161

5262
pub proof fn alloc_left(tracked a: A) -> (tracked res: Self)
53-
ensures
54-
res.is_left(),
55-
res.resource() is Left,
56-
res.resource()->Left_0 == a,
63+
ensures
64+
res.is_left(),
65+
res.resource() is Left,
66+
res.resource()->Left_0 == a,
5767
{
5868
let tracked mut m = Map::tracked_empty();
5969
m.tracked_insert((), Sum::Left(a));
6070
let tracked r = StorageResource::alloc(CsumP::Cinl(a), m);
61-
SumResourceStorage { r }
71+
SumResource { r }
6272
}
6373

6474
pub proof fn alloc_right(tracked b: B) -> (tracked res: Self)
65-
ensures
66-
res.is_right(),
67-
res.resource() is Right,
68-
res.resource()->Right_0 == b,
75+
ensures
76+
res.is_right(),
77+
res.resource() is Right,
78+
res.resource()->Right_0 == b,
6979
{
7080
let tracked mut m = Map::tracked_empty();
7181
m.tracked_insert((), Sum::Right(b));
7282
let tracked r = StorageResource::alloc(CsumP::Cinr(b), m);
73-
SumResourceStorage { r }
83+
SumResource { r }
7484
}
7585

7686
pub proof fn tracked_take(tracked self) -> (tracked res: Sum<A, B>)
@@ -81,7 +91,10 @@ impl<A,B> SumResourceStorage<A, B>
8191
{
8292
self.protocol_monoid().lemma_csum_withdraws();
8393
let tracked r = self.r;
84-
let tracked (_,mut m) = r.withdraw(CsumP::Unit, map![() => self.protocol_monoid().to_sum()]);
94+
let tracked (_, mut m) = r.withdraw(
95+
CsumP::Unit,
96+
map![() => self.protocol_monoid().to_sum()],
97+
);
8598
m.tracked_remove(())
8699
}
87100

@@ -105,6 +118,64 @@ impl<A,B> SumResourceStorage<A, B>
105118
sum.tracked_take_right()
106119
}
107120

121+
pub proof fn split_left(tracked self) -> (tracked res: (Self, Self))
122+
requires
123+
self.is_left(),
124+
ensures
125+
res.0.is_empty(),
126+
res.1.is_left(),
127+
res.0.id() == self.id(),
128+
res.1.id() == self.id(),
129+
res.1.protocol_monoid() == self.protocol_monoid(),
130+
res.1.resource() == self.resource(),
131+
{
132+
self.protocol_monoid().lemma_csum_withdraws();
133+
let tracked r = self.r;
134+
let tracked (r1, r2) = r.split(CsumP::Unit, CsumP::Cinl(self.resource()->Left_0));
135+
(SumResource { r: r1 }, SumResource { r: r2 })
136+
}
137+
138+
pub proof fn split_right(tracked self) -> (tracked res: (Self, Self))
139+
requires
140+
self.is_right(),
141+
ensures
142+
res.0.is_empty(),
143+
res.1.is_right(),
144+
res.0.id() == self.id(),
145+
res.1.id() == self.id(),
146+
res.1.protocol_monoid() == self.protocol_monoid(),
147+
res.1.resource() == self.resource(),
148+
{
149+
self.protocol_monoid().lemma_csum_withdraws();
150+
let tracked r = self.r;
151+
let tracked (r1, r2) = r.split(CsumP::Unit, CsumP::Cinr(self.resource()->Right_0));
152+
(SumResource { r: r1 }, SumResource { r: r2 })
153+
}
154+
155+
pub proof fn split_and_take_left(tracked self) -> (tracked res: (Self, A))
156+
requires
157+
self.is_left(),
158+
ensures
159+
res.0.is_empty(),
160+
res.0.id() == self.id(),
161+
res.1 == self.resource()->Left_0,
162+
{
163+
let tracked (r1, r2) = self.split_left();
164+
(r1, r2.tracked_take_left())
165+
}
166+
167+
pub proof fn split_and_take_right(tracked self) -> (tracked res: (Self, B))
168+
requires
169+
self.is_right(),
170+
ensures
171+
res.0.is_empty(),
172+
res.0.id() == self.id(),
173+
res.1 == self.resource()->Right_0,
174+
{
175+
let tracked (r1, r2) = self.split_right();
176+
(r1, r2.tracked_take_right())
177+
}
178+
108179
pub proof fn tracked_borrow(tracked &self) -> (tracked res: &Sum<A, B>)
109180
requires
110181
self.is_left() || self.is_right(),
@@ -129,7 +200,7 @@ impl<A,B> SumResourceStorage<A, B>
129200
ensures
130201
*res == self.resource()->Right_0,
131202
{
132-
self.tracked_borrow().tracked_borrow_right()
203+
self.tracked_borrow().tracked_borrow_right()
133204
}
134205

135206
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//! Ghost resources availbe for use in proofs, based on previous resource algebras.
2+
pub mod csum;
23
pub mod excl;
34
pub mod frac;
4-
pub mod csum;
55
pub mod tokens;
Lines changed: 31 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
//! Csum storage protocol.
2+
use core::panic;
23

3-
use vstd::prelude::*;
4+
use crate::sum::*;
45
use vstd::pcm::Loc;
56
use vstd::prelude::*;
7+
use vstd::prelude::*;
68
use vstd::storage_protocol::*;
7-
use crate::sum::*;
89

9-
verus!{
10+
verus! {
1011

1112
/// The Csum protocol monoid.
1213
pub ghost enum CsumP<A, B> {
@@ -17,7 +18,7 @@ pub ghost enum CsumP<A, B> {
1718
}
1819

1920
/// This protocol monoid allows exclusive ownership of either an A or a B, but not both. s
20-
impl<A,B> Protocol<(), Sum<A, B>> for CsumP<A, B> {
21+
impl<A, B> Protocol<(), Sum<A, B>> for CsumP<A, B> {
2122
open spec fn op(self, other: Self) -> Self {
2223
match (self, other) {
2324
(CsumP::Unit, x) => x,
@@ -29,8 +30,8 @@ impl<A,B> Protocol<(), Sum<A, B>> for CsumP<A, B> {
2930
open spec fn rel(self, s: Map<(), Sum<A, B>>) -> bool {
3031
match self {
3132
CsumP::Unit => s.is_empty(),
32-
CsumP::Cinl(a) => s.contains_key(()) && s[()] == Sum::<A,B>::Left(a),
33-
CsumP::Cinr(b) => s.contains_key(()) && s[()] == Sum::<A,B>::Right(b),
33+
CsumP::Cinl(a) => s.contains_key(()) && s[()] == Sum::<A, B>::Left(a),
34+
CsumP::Cinr(b) => s.contains_key(()) && s[()] == Sum::<A, B>::Right(b),
3435
_ => false,
3536
}
3637
}
@@ -49,33 +50,33 @@ impl<A,B> Protocol<(), Sum<A, B>> for CsumP<A, B> {
4950
}
5051
}
5152

52-
53-
impl<A,B> CsumP<A, B> {
54-
55-
pub open spec fn to_sum(self) -> Sum<A, B> {
56-
match self {
57-
CsumP::Cinl(a) => Sum::Left(a),
58-
CsumP::Cinr(b) => Sum::Right(b),
59-
_ => arbitrary()
53+
impl<A, B> CsumP<A, B> {
54+
pub open spec fn to_sum(self) -> Sum<A, B> {
55+
match self {
56+
CsumP::Cinl(a) => Sum::Left(a),
57+
CsumP::Cinr(b) => Sum::Right(b),
58+
_ => arbitrary(),
59+
}
6060
}
61-
}
6261

63-
pub proof fn lemma_csum_withdraws(self)
64-
requires
65-
self is Cinl || self is Cinr,
66-
ensures
67-
withdraws(self, CsumP::Unit, map![() => self.to_sum()]),
68-
{
69-
let res_map = map![() => self.to_sum()];
70-
71-
assert forall |q: Self, t1: Map<(), Sum<A, B>>| Self::rel(Self::op(self, q), t1) implies
72-
exists |t2: Map<(), Sum<A, B>>| #[trigger] Self::rel(Self::op(CsumP::Unit, q), t2) &&
73-
t2.dom().disjoint(res_map.dom()) &&
74-
t1 == t2.union_prefer_right(res_map) by {
62+
pub proof fn lemma_csum_withdraws(self)
63+
requires
64+
self is Cinl || self is Cinr,
65+
ensures
66+
withdraws(self, CsumP::Unit, map![() => self.to_sum()]),
67+
{
68+
let res_map = map![() => self.to_sum()];
69+
70+
assert forall|q: Self, t1: Map<(), Sum<A, B>>|
71+
Self::rel(Self::op(self, q), t1) implies exists|t2: Map<(), Sum<A, B>>| #[trigger]
72+
Self::rel(Self::op(CsumP::Unit, q), t2) && t2.dom().disjoint(res_map.dom()) && t1
73+
== t2.union_prefer_right(res_map) by {
7574
let empty_map = Map::<(), Sum<A, B>>::empty();
76-
assert(Self::rel(Self::op(CsumP::Unit, q), empty_map) && empty_map.dom().disjoint(res_map.dom()) && Self::rel(Self::op(self, q), res_map));
75+
assert(Self::rel(Self::op(CsumP::Unit, q), empty_map) && empty_map.dom().disjoint(
76+
res_map.dom(),
77+
) && Self::rel(Self::op(self, q), res_map));
7778
}
78-
}
79+
}
7980
}
8081

81-
}
82+
} // verus!

0 commit comments

Comments
 (0)