11//! Sum types for ghost resources.
2- use vstd:: prelude:: * ;
32use vstd:: pcm:: Loc ;
3+ use vstd:: prelude:: * ;
44use vstd:: storage_protocol:: * ;
55
6-
76use crate :: resource:: storage_protocol:: csum:: * ;
87use crate :: sum:: * ;
98
10-
119verus ! {
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}
0 commit comments