1#[cfg(creusot)]
2use crate::logic::such_that;
3use crate::{
4 logic::ra::{
5 RA,
6 update::{LocalUpdate, Update},
7 },
8 prelude::*,
9};
10
11pub enum Sum<T, U> {
16 Left(T),
17 Right(U),
18}
19
20impl<R1: RA, R2: RA> RA for Sum<R1, R2> {
21 #[logic(open)]
22 fn op(self, other: Self) -> Option<Self> {
23 match (self, other) {
24 (Self::Left(x), Self::Left(y)) => x.op(y).map_logic(|l| Self::Left(l)),
25 (Self::Right(x), Self::Right(y)) => x.op(y).map_logic(|r| Self::Right(r)),
26 _ => None,
27 }
28 }
29
30 #[logic(open)]
31 #[ensures(match result {
32 Some(c) => factor.op(c) == Some(self),
33 None => forall<c: Self> factor.op(c) != Some(self),
34 })]
35 fn factor(self, factor: Self) -> Option<Self> {
36 match (self, factor) {
37 (Self::Left(x), Self::Left(y)) => x.factor(y).map_logic(|l| Self::Left(l)),
38 (Self::Right(x), Self::Right(y)) => x.factor(y).map_logic(|r| Self::Right(r)),
39 _ => None,
40 }
41 }
42
43 #[logic(open(self), law)]
44 #[ensures(a.op(b) == b.op(a))]
45 fn commutative(a: Self, b: Self) {}
46
47 #[logic(open(self), law)]
48 #[ensures(a.op(b).and_then_logic(|ab: Self| ab.op(c)) == b.op(c).and_then_logic(|bc| a.op(bc)))]
49 fn associative(a: Self, b: Self, c: Self) {}
50
51 #[logic(open)]
52 #[ensures(match result {
53 Some(c) => c.op(c) == Some(c) && c.op(self) == Some(self),
54 None => true
55 })]
56 fn core(self) -> Option<Self> {
57 match self {
58 Self::Left(x) => x.core().map_logic(|l| Self::Left(l)),
59 Self::Right(x) => x.core().map_logic(|r| Self::Right(r)),
60 }
61 }
62
63 #[logic]
64 #[requires(i.op(i) == Some(i))]
65 #[requires(i.op(self) == Some(self))]
66 #[ensures(match self.core() {
67 Some(c) => i.incl(c),
68 None => false,
69 })]
70 fn core_is_maximal_idemp(self, i: Self) {
71 match (self, i) {
72 (Sum::Left(s), Sum::Left(i)) => s.core_is_maximal_idemp(i),
73 (Sum::Right(s), Sum::Right(i)) => s.core_is_maximal_idemp(i),
74 _ => (),
75 }
76 }
77}
78
79pub struct SumUpdateL<U>(pub U);
80
81impl<R1: RA, R2: RA, U: Update<R1>> Update<Sum<R1, R2>> for SumUpdateL<U> {
82 type Choice = U::Choice;
83
84 #[logic(open)]
85 fn premise(self, from: Sum<R1, R2>) -> bool {
86 match from {
87 Sum::Left(from) => self.0.premise(from),
88 Sum::Right(_) => false,
89 }
90 }
91
92 #[logic(open)]
93 #[requires(self.premise(from))]
94 fn update(self, from: Sum<R1, R2>, ch: U::Choice) -> Sum<R1, R2> {
95 match from {
96 Sum::Left(from) => Sum::Left(self.0.update(from, ch)),
97 x => x, }
99 }
100
101 #[logic]
102 #[requires(self.premise(from))]
103 #[requires(from.op(frame) != None)]
104 #[ensures(self.update(from, result).op(frame) != None)]
105 fn frame_preserving(self, from: Sum<R1, R2>, frame: Sum<R1, R2>) -> U::Choice {
106 match (from, frame) {
107 (Sum::Left(from), Sum::Left(frame)) => self.0.frame_preserving(from, frame),
108 _ => such_that(|_| true),
109 }
110 }
111}
112
113pub struct SumUpdateR<U>(pub U);
114
115impl<R: RA, U: Update<R>, V: RA> Update<Sum<V, R>> for SumUpdateR<U> {
116 type Choice = U::Choice;
117
118 #[logic(open)]
119 fn premise(self, from: Sum<V, R>) -> bool {
120 match from {
121 Sum::Right(from) => self.0.premise(from),
122 Sum::Left(_) => false,
123 }
124 }
125
126 #[logic(open)]
127 #[requires(self.premise(from))]
128 fn update(self, from: Sum<V, R>, ch: U::Choice) -> Sum<V, R> {
129 match from {
130 Sum::Right(from) => Sum::Right(self.0.update(from, ch)),
131 x => x, }
133 }
134
135 #[logic]
136 #[requires(self.premise(from))]
137 #[requires(from.op(frame) != None)]
138 #[ensures(self.update(from, result).op(frame) != None)]
139 fn frame_preserving(self, from: Sum<V, R>, frame: Sum<V, R>) -> U::Choice {
140 match (from, frame) {
141 (Sum::Right(from), Sum::Right(frame)) => self.0.frame_preserving(from, frame),
142 _ => such_that(|_| true),
143 }
144 }
145}
146
147pub struct SumLocalUpdateL<U>(pub U);
148
149impl<R1: RA, R2: RA, U: LocalUpdate<R1>> LocalUpdate<Sum<R1, R2>> for SumLocalUpdateL<U> {
150 #[logic(open)]
151 fn premise(self, from_auth: Sum<R1, R2>, from_frag: Sum<R1, R2>) -> bool {
152 match (from_auth, from_frag) {
153 (Sum::Left(from_auth), Sum::Left(from_frag)) => self.0.premise(from_auth, from_frag),
154 (Sum::Right(_), Sum::Right(_)) => false,
155 _ => true,
156 }
157 }
158
159 #[logic(open)]
160 fn update(self, from_auth: Sum<R1, R2>, from_frag: Sum<R1, R2>) -> (Sum<R1, R2>, Sum<R1, R2>) {
161 match (from_auth, from_frag) {
162 (Sum::Left(from_auth), Sum::Left(from_frag)) => {
163 let (to_auth, to_frag) = self.0.update(from_auth, from_frag);
164 (Sum::Left(to_auth), Sum::Left(to_frag))
165 }
166 _ => such_that(|_| true),
167 }
168 }
169
170 #[logic]
171 #[requires(self.premise(from_auth, from_frag))]
172 #[requires(Some(from_frag).op(frame) == Some(Some(from_auth)))]
173 #[ensures({
174 let (to_auth, to_frag) = self.update(from_auth, from_frag);
175 Some(to_frag).op(frame) == Some(Some(to_auth))
176 })]
177 fn frame_preserving(
178 self,
179 from_auth: Sum<R1, R2>,
180 from_frag: Sum<R1, R2>,
181 frame: Option<Sum<R1, R2>>,
182 ) {
183 match (from_auth, from_frag, frame) {
184 (Sum::Left(from_auth), Sum::Left(from_frag), Some(Sum::Left(frame))) => {
185 self.0.frame_preserving(from_auth, from_frag, Some(frame))
186 }
187 (Sum::Left(from_auth), Sum::Left(from_frag), None) => {
188 self.0.frame_preserving(from_auth, from_frag, None)
189 }
190 _ => (),
191 }
192 }
193}
194
195pub struct SumLocalUpdateR<U>(pub U);
196
197impl<R1: RA, R2: RA, U: LocalUpdate<R2>> LocalUpdate<Sum<R1, R2>> for SumLocalUpdateR<U> {
198 #[logic(open)]
199 fn premise(self, from_auth: Sum<R1, R2>, from_frag: Sum<R1, R2>) -> bool {
200 match (from_auth, from_frag) {
201 (Sum::Right(from_auth), Sum::Right(from_frag)) => self.0.premise(from_auth, from_frag),
202 (Sum::Left(_), Sum::Left(_)) => false,
203 _ => true,
204 }
205 }
206
207 #[logic(open)]
208 fn update(self, from_auth: Sum<R1, R2>, from_frag: Sum<R1, R2>) -> (Sum<R1, R2>, Sum<R1, R2>) {
209 match (from_auth, from_frag) {
210 (Sum::Right(from_auth), Sum::Right(from_frag)) => {
211 let (to_auth, to_frag) = self.0.update(from_auth, from_frag);
212 (Sum::Right(to_auth), Sum::Right(to_frag))
213 }
214 _ => such_that(|_| true),
215 }
216 }
217
218 #[logic]
219 #[requires(self.premise(from_auth, from_frag))]
220 #[requires(Some(from_frag).op(frame) == Some(Some(from_auth)))]
221 #[ensures({
222 let (to_auth, to_frag) = self.update(from_auth, from_frag);
223 Some(to_frag).op(frame) == Some(Some(to_auth))
224 })]
225 fn frame_preserving(
226 self,
227 from_auth: Sum<R1, R2>,
228 from_frag: Sum<R1, R2>,
229 frame: Option<Sum<R1, R2>>,
230 ) {
231 match (from_auth, from_frag, frame) {
232 (Sum::Right(from_auth), Sum::Right(from_frag), Some(Sum::Right(frame))) => {
233 self.0.frame_preserving(from_auth, from_frag, Some(frame))
234 }
235 (Sum::Right(from_auth), Sum::Right(from_frag), None) => {
236 self.0.frame_preserving(from_auth, from_frag, None)
237 }
238 _ => (),
239 }
240 }
241}