1use crate::{
2 ghost::Plain,
3 invariant::{InhabitedInvariant, Subset},
4 logic::ops::{AddLogic, DivLogic, MulLogic, NegLogic, RemLogic, SubLogic},
5 prelude::*,
6};
7use core::ops::{
8 Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Sub, SubAssign,
9};
10
11#[intrinsic("int")]
29#[builtin("int")]
30pub struct Int;
31
32impl Clone for Int {
33 #[check(ghost)]
34 #[ensures(result == *self)]
35 fn clone(&self) -> Self {
36 *self
37 }
38}
39impl Copy for Int {}
40impl Plain for Int {
41 #[trusted]
42 #[ensures(*result == *snap)]
43 #[check(ghost)]
44 #[allow(unused_variables)]
45 fn into_ghost(snap: Snapshot<Self>) -> Ghost<Self> {
46 Ghost::conjure()
47 }
48}
49
50impl Int {
52 #[logic]
61 #[builtin("int.Power.power")]
62 #[allow(unused_variables)]
63 pub fn pow(self, p: Int) -> Int {
64 dead
65 }
66
67 #[logic]
76 #[builtin("bv.Pow2int.pow2")]
77 #[allow(unused_variables)]
78 pub fn pow2(self) -> Int {
79 dead
80 }
81
82 #[logic]
91 #[builtin("int.MinMax.max")]
92 #[allow(unused_variables)]
93 pub fn max(self, x: Int) -> Int {
94 dead
95 }
96
97 #[logic]
106 #[builtin("int.MinMax.min")]
107 #[allow(unused_variables)]
108 pub fn min(self, x: Int) -> Int {
109 dead
110 }
111
112 #[logic]
121 #[builtin("int.EuclideanDivision.div")]
122 #[allow(unused_variables)]
123 pub fn div_euclid(self, d: Int) -> Int {
124 dead
125 }
126
127 #[logic]
136 #[builtin("int.EuclideanDivision.mod")]
137 #[allow(unused_variables)]
138 pub fn rem_euclid(self, d: Int) -> Int {
139 dead
140 }
141
142 #[logic(open)]
153 pub fn abs_diff(self, other: Int) -> Int {
154 if self < other { other - self } else { self - other }
155 }
156}
157
158impl AddLogic for Int {
159 type Output = Self;
160 #[logic]
161 #[builtin("int.Int.(+)")]
162 #[allow(unused_variables)]
163 fn add_logic(self, other: Self) -> Self {
164 dead
165 }
166}
167
168impl SubLogic for Int {
169 type Output = Self;
170 #[logic]
171 #[builtin("int.Int.(-)")]
172 #[allow(unused_variables)]
173 fn sub_logic(self, other: Self) -> Self {
174 dead
175 }
176}
177
178impl MulLogic for Int {
179 type Output = Self;
180 #[logic]
181 #[builtin("int.Int.(*)")]
182 #[allow(unused_variables)]
183 fn mul_logic(self, other: Self) -> Self {
184 dead
185 }
186}
187
188impl DivLogic for Int {
189 type Output = Self;
190 #[logic]
191 #[builtin("int.ComputerDivision.div")]
192 #[allow(unused_variables)]
193 fn div_logic(self, other: Self) -> Self {
194 dead
195 }
196}
197
198impl RemLogic for Int {
199 type Output = Self;
200 #[logic]
201 #[builtin("int.ComputerDivision.mod")]
202 #[allow(unused_variables)]
203 fn rem_logic(self, other: Self) -> Self {
204 dead
205 }
206}
207
208impl NegLogic for Int {
209 type Output = Self;
210 #[logic]
211 #[builtin("int.Int.(-_)")]
212 fn neg_logic(self) -> Self {
213 dead
214 }
215}
216
217impl Int {
221 #[trusted]
236 #[check(ghost)]
237 #[ensures(*result == value@)]
238 #[allow(unreachable_code)]
239 #[allow(unused_variables)]
240 pub fn new(value: i128) -> Ghost<Self> {
241 Ghost::conjure()
242 }
243
244 #[trusted]
245 #[check(ghost)]
246 #[ensures(^self == *self + 1)]
247 pub fn incr_ghost(&mut self) {}
248
249 #[trusted]
250 #[check(ghost)]
251 #[ensures(^self == *self - 1)]
252 pub fn decr_ghost(&mut self) {}
253}
254
255impl PartialEq for Int {
256 #[trusted]
257 #[check(ghost)]
258 #[ensures(result == (*self == *other))]
259 #[allow(unused_variables)]
260 fn eq(&self, other: &Self) -> bool {
261 panic!()
262 }
263
264 #[check(ghost)]
265 #[ensures(result == (*self != *other))]
266 fn ne(&self, other: &Self) -> bool {
267 !self.eq(other)
268 }
269}
270
271impl PartialOrd for Int {
272 #[trusted]
273 #[check(ghost)]
274 #[ensures(result == Some((*self).cmp_log(*other)))]
275 #[allow(unused_variables)]
276 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
277 panic!()
278 }
279
280 #[trusted]
281 #[check(ghost)]
282 #[ensures(result == (*self).lt_log(*other))]
283 #[allow(unused_variables)]
284 fn lt(&self, other: &Self) -> bool {
285 panic!()
286 }
287
288 #[trusted]
289 #[check(ghost)]
290 #[ensures(result == (*self).le_log(*other))]
291 #[allow(unused_variables)]
292 fn le(&self, other: &Self) -> bool {
293 panic!()
294 }
295
296 #[trusted]
297 #[check(ghost)]
298 #[ensures(result == (*self).gt_log(*other))]
299 #[allow(unused_variables)]
300 fn gt(&self, other: &Self) -> bool {
301 panic!()
302 }
303
304 #[trusted]
305 #[check(ghost)]
306 #[ensures(result == (*self).ge_log(*other))]
307 #[allow(unused_variables)]
308 fn ge(&self, other: &Self) -> bool {
309 panic!()
310 }
311}
312
313impl Add for Int {
314 type Output = Int;
315 #[trusted]
316 #[check(ghost)]
317 #[ensures(result == self + other)]
318 #[allow(unused_variables)]
319 fn add(self, other: Int) -> Self {
320 panic!()
321 }
322}
323
324impl Sub for Int {
325 type Output = Int;
326 #[trusted]
327 #[check(ghost)]
328 #[ensures(result == self - other)]
329 #[allow(unused_variables)]
330 fn sub(self, other: Int) -> Self {
331 panic!()
332 }
333}
334
335impl Mul for Int {
336 type Output = Int;
337 #[trusted]
338 #[check(ghost)]
339 #[ensures(result == self * other)]
340 #[allow(unused_variables)]
341 fn mul(self, other: Int) -> Self {
342 panic!()
343 }
344}
345
346impl Div for Int {
347 type Output = Int;
348 #[trusted]
349 #[check(ghost)]
350 #[requires(other != 0)]
351 #[ensures(result == self / other)]
352 #[allow(unused_variables)]
353 fn div(self, other: Int) -> Self {
354 panic!()
355 }
356}
357
358impl Rem for Int {
359 type Output = Int;
360 #[trusted]
361 #[check(ghost)]
362 #[requires(other != 0)]
363 #[ensures(result == self % other)]
364 #[allow(unused_variables)]
365 fn rem(self, other: Int) -> Self {
366 panic!()
367 }
368}
369
370impl Neg for Int {
371 type Output = Int;
372 #[trusted]
373 #[check(ghost)]
374 #[ensures(result == -self)]
375 fn neg(self) -> Self {
376 panic!()
377 }
378}
379
380impl AddAssign for Int {
381 #[check(ghost)]
382 #[ensures(^self == *self + rhs)]
383 fn add_assign(&mut self, rhs: Int) {
384 *self = *self + rhs;
385 }
386}
387
388impl SubAssign for Int {
389 #[check(ghost)]
390 #[ensures(^self == *self - rhs)]
391 fn sub_assign(&mut self, rhs: Int) {
392 *self = *self - rhs;
393 }
394}
395
396impl MulAssign for Int {
397 #[check(ghost)]
398 #[ensures(^self == *self * rhs)]
399 fn mul_assign(&mut self, rhs: Int) {
400 *self = *self * rhs;
401 }
402}
403
404impl DivAssign for Int {
405 #[check(ghost)]
406 #[requires(rhs != 0)]
407 #[ensures(^self == *self / rhs)]
408 fn div_assign(&mut self, rhs: Int) {
409 *self = *self / rhs;
410 }
411}
412
413impl RemAssign for Int {
414 #[check(ghost)]
415 #[requires(rhs != 0)]
416 #[ensures(^self == *self % rhs)]
417 fn rem_assign(&mut self, rhs: Int) {
418 *self = *self % rhs;
419 }
420}
421
422struct NatInner(Int);
423
424impl Invariant for NatInner {
425 #[logic]
426 fn invariant(self) -> bool {
427 self.0 >= 0
428 }
429}
430
431impl InhabitedInvariant for NatInner {
432 #[logic]
433 #[ensures(result.invariant())]
434 fn inhabits() -> Self {
435 Self(0)
436 }
437}
438
439pub struct Nat(Subset<NatInner>);
441
442impl Nat {
443 #[logic]
444 #[ensures(result >= 0)]
445 pub fn to_int(self) -> Int {
446 pearlite! { self.0.inner().0 }
447 }
448
449 #[logic]
450 #[requires(n >= 0)]
451 #[ensures(result.to_int() == n)]
452 pub fn new(n: Int) -> Nat {
453 Nat(Subset::new_logic(NatInner(n)))
454 }
455
456 #[logic(open)]
457 #[ensures(result == (self == other))]
458 pub fn ext_eq(self, other: Self) -> bool {
459 let _ = Subset::<NatInner>::inner_inj;
460 self.to_int() == other.to_int()
461 }
462}
463
464impl AddLogic for Nat {
465 type Output = Self;
466 #[logic]
467 #[ensures(result.to_int() == self.to_int() + other.to_int())]
468 fn add_logic(self, other: Self) -> Self {
469 Self::new(self.to_int() + other.to_int())
470 }
471}
472
473impl MulLogic for Nat {
474 type Output = Self;
475 #[logic]
476 #[ensures(result.to_int() == self.to_int() * other.to_int())]
477 fn mul_logic(self, other: Self) -> Self {
478 Self::new(self.to_int() * other.to_int())
479 }
480}