1use crate::{
2 logic::ra::{
3 RA, UnitRA,
4 update::{LocalUpdate, Update},
5 },
6 prelude::*,
7};
8
9macro_rules! ra_tuples {
10 ($(($t:ident, $n:tt, $v:ident, $r:ident))*) => {
11
12impl<$($t : RA),*> RA for ($($t),*) {
13 #[logic(open)]
14 fn op(self, other: Self) -> Option<Self> {
15 match ($(self.$n.op(other.$n)),*) {
16 ($(Some($v)),*) => Some(($($v),*)),
17 _ => None,
18 }
19 }
20
21 #[logic(open)]
22 #[ensures(result == (exists<factor> self.op(factor) == Some(other)))]
23 fn incl(self, other: Self) -> bool {
24 $(self.$n.incl(other.$n))&&*
25 }
26
27 #[logic(open, inline)]
28 #[ensures(#[trigger(self == other)] result == (self == other))]
29 fn eq(self, other: Self) -> bool {
30 $(self.$n.eq(other.$n))&&*
31 }
32
33 #[logic(law)]
34 #[ensures(a.op(b) == b.op(a))]
35 fn commutative(a: Self, b: Self) {}
36
37 #[logic]
38 #[ensures(a.op(b).and_then_logic(|ab: Self| ab.op(c)) == b.op(c).and_then_logic(|bc| a.op(bc)))]
39 fn associative(a: Self, b: Self, c: Self) {}
40
41 #[logic(open)]
42 fn core(self) -> Option<Self> {
43 match ($(self.$n.core()),*) {
44 ($(Some($v)),*) => Some(($($v),*)),
45 _ => None,
46 }
47 }
48
49 #[logic]
50 #[requires(self.core() != None)]
51 #[ensures({
52 let c = self.core().unwrap_logic();
53 c.op(c) == Some(c)
54 })]
55 #[ensures(self.core().unwrap_logic().op(self) == Some(self))]
56 fn core_idemp(self) {
57 $(
58 self.$n.core_idemp();
59 )*
60 }
61
62 #[logic]
63 #[requires(i.op(i) == Some(i))]
64 #[requires(i.op(self) == Some(self))]
65 #[ensures(match self.core() {
66 Some(c) => i.incl(c),
67 None => false,
68 })]
69 fn core_is_maximal_idemp(self, i: Self) {
70 $(
71 self.$n.core_is_maximal_idemp(i.$n);
72 )*
73 }
74
75 ra_tuples! { @cancelation $(($n, $v))* }
76}
77
78impl<$($t : UnitRA),*> UnitRA for ($($t),*) {
79 #[logic]
80 #[ensures(forall<x: Self> #[trigger(x.op(result))] x.op(result) == Some(x))]
81 fn unit() -> Self {
82 ($($t::unit()),*)
83 }
84
85 #[logic(open)]
86 #[ensures(self.core() == Some(result))]
87 fn core_total(self) -> Self {
88 ($(self.$n.core_total()),*)
89 }
90
91 #[logic]
92 #[ensures(self.core_total().op(self.core_total()) == Some(self.core_total()))]
93 #[ensures(self.core_total().op(self) == Some(self))]
94 fn core_total_idemp(self) {
95 $(
96 self.$n.core_total_idemp();
97 )*
98 }
99}
100
101impl<$($r : RA),* , $($t : Update<$r>),*> Update<($($r),*)> for ($($t),*) {
102 type Choice = ($($t::Choice),*);
103
104 #[logic(open, inline)]
105 fn premise(self, from: ($($r),*)) -> bool {
106 $(
107 self.$n.premise(from.$n)
108 )&&*
109 }
110
111 #[logic(open, inline)]
112 #[requires(self.premise(from))]
113 fn update(self, from: ($($r),*), ch: Self::Choice) -> ($($r),*) {
114 ($(self.$n.update(from.$n, ch.$n)),*)
115 }
116
117 #[logic]
118 #[requires(self.premise(from))]
119 #[requires(from.op(frame) != None)]
120 #[ensures(self.update(from, result).op(frame) != None)]
121 fn frame_preserving(self, from: ($($r),*), frame: ($($r),*)) -> Self::Choice {
122 ( $(
123 self.$n.frame_preserving(from.$n, frame.$n)
124 ),* )
125 }
126}
127
128impl<$($r : RA),* , $($t : LocalUpdate<$r>),*> LocalUpdate<($($r),*)> for ($($t),*) {
129 #[logic(open, inline)]
130 fn premise(self, from_auth: ($($r),*), from_frag: ($($r),*)) -> bool {
131 $(
132 self.$n.premise(from_auth.$n, from_frag.$n)
133 )&&*
134 }
135
136 #[logic(open, inline)]
137 fn update(self, from_auth: ($($r),*), from_frag: ($($r),*)) -> (($($r),*), ($($r),*)) {
138 $(
139 let $v = self.$n.update(from_auth.$n, from_frag.$n);
140 )*
141 (($($v.0),*), ($($v.1),*))
142 }
143
144 ra_tuples! { @local_upd_frame_preserve
145 type_r: $($r)* ;
146 list: $(($n, $v))* ;
147 with_type_r: ;
148 }
149
150}
151
152 };
153
154 (@local_upd_frame_preserve
156 type_r: $($r:ident)* ;
157 list: ($n1:tt, $v1:ident) $(($n_t:tt, $v_t:tt))* ;
158 with_type_r: $(($n:tt, $v:ident, $t:ty))* ;
159 ) => {
160 ra_tuples! { @local_upd_frame_preserve
161 type_r: $($r)* ;
162 list: $(($n_t, $v_t))* ;
163 with_type_r: $(($n, $v, $t))* ($n1, $v1, ($($r),*)) ;
164 }
165 };
166
167 (@local_upd_frame_preserve
168 type_r: $($r:ident)* ;
169 list: ;
170 with_type_r: $(($n:tt, $v:ident, $t:ty))* ;
171 ) => {
172 #[logic]
173 #[requires(self.premise(from_auth, from_frag))]
174 #[requires(Some(from_frag).op(frame) == Some(Some(from_auth)))]
175 #[ensures({
176 let (to_auth, to_frag) = self.update(from_auth, from_frag);
177 Some(to_frag).op(frame) == Some(Some(to_auth))
178 })]
179 fn frame_preserving(self, from_auth: ($($r),*), from_frag: ($($r),*), frame: Option<($($r),*)>) {
180 $(
181 self.$n.frame_preserving(from_auth.$n, from_frag.$n, frame.map_logic(|f: $t| f.$n));
182 )*
183 }
184 };
185
186
187 (@cancelation ($n1:tt, $v1:ident) $(($n:tt, $v:ident))*) => {
189 #[logic(open)]
190 #[ensures(result == (forall<x, y> self.op(x) != None ==>
191 self.op(x) == self.op(y) ==> x == y))]
192 fn cancelable(self) -> bool {
193 proof_assert!(
194 forall<$v1, $($v),*> self.0.op($v1) != None ==> $(self.$n.op($v) != None ==>)*
196 (forall<x, y> self.op(x) != None ==> self.op(y) != None ==> self.op(x) == self.op(y) ==> x == y) ==>
198 forall<x, y> self.0.op(x) != None ==> self.0.op(y) != None ==>
200 self.op((x, $($v),*)) == self.op((y, $($v),*)) ==> x == y
201 );
202 pearlite! {
203 (forall<$v1> self.0.op($v1) == None) ||
204 $(
205 (forall<$v> self.$n.op($v) == None) ||
206 )*
207 ( self.$n1.cancelable() && $(self.$n.cancelable())&&* )
208 }
209 }
210 };
211}
212
213ra_tuples! { (T1, 0, v1, R1) (T2, 1, v2, R2) }
214ra_tuples! { (T1, 0, v1, R1) (T2, 1, v2, R2) (T3, 2, v3, R3) }
215ra_tuples! { (T1, 0, v1, R1) (T2, 1, v2, R2) (T3, 2, v3, R3) (T4, 3, v4, R4) }
216