1use crate::{
2 ghost::Plain,
3 invariant::{InhabitedInvariant, Subset},
4 logic::ops::{AddLogic, DivLogic, MulLogic, NegLogic, RemLogic, SubLogic},
5 prelude::*,
6};
7use core::{
8 cmp::Ordering,
9 ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Sub, SubAssign},
10};
11
12#[intrinsic("int")]
30#[builtin("int")]
31pub struct Int;
32
33impl Clone for Int {
34 #[check(ghost)]
35 #[ensures(result == *self)]
36 fn clone(&self) -> Self {
37 *self
38 }
39}
40impl Copy for Int {}
41impl Plain for Int {
42 #[trusted]
43 #[ensures(*result == *snap)]
44 #[check(ghost)]
45 #[allow(unused_variables)]
46 fn into_ghost(snap: Snapshot<Self>) -> Ghost<Self> {
47 Ghost::conjure()
48 }
49}
50
51impl Int {
53 #[logic]
62 #[builtin("int.Power.power")]
63 #[allow(unused_variables)]
64 pub fn pow(self, p: Int) -> Int {
65 dead
66 }
67
68 #[logic]
77 #[builtin("bv.Pow2int.pow2")]
78 #[allow(unused_variables)]
79 pub fn pow2(self) -> Int {
80 dead
81 }
82
83 #[logic]
92 #[builtin("int.MinMax.max")]
93 #[allow(unused_variables)]
94 pub fn max(self, x: Int) -> Int {
95 dead
96 }
97
98 #[logic]
107 #[builtin("int.MinMax.min")]
108 #[allow(unused_variables)]
109 pub fn min(self, x: Int) -> Int {
110 dead
111 }
112
113 #[logic]
122 #[builtin("int.EuclideanDivision.div")]
123 #[allow(unused_variables)]
124 pub fn div_euclid(self, d: Int) -> Int {
125 dead
126 }
127
128 #[logic]
137 #[builtin("int.EuclideanDivision.mod")]
138 #[allow(unused_variables)]
139 pub fn rem_euclid(self, d: Int) -> Int {
140 dead
141 }
142
143 #[logic(open)]
154 pub fn abs_diff(self, other: Int) -> Int {
155 if self < other { other - self } else { self - other }
156 }
157}
158
159impl AddLogic for Int {
160 type Output = Self;
161 #[logic]
162 #[builtin("int.Int.(+)")]
163 #[allow(unused_variables)]
164 fn add_logic(self, other: Self) -> Self {
165 dead
166 }
167}
168
169impl SubLogic for Int {
170 type Output = Self;
171 #[logic]
172 #[builtin("int.Int.(-)")]
173 #[allow(unused_variables)]
174 fn sub_logic(self, other: Self) -> Self {
175 dead
176 }
177}
178
179impl MulLogic for Int {
180 type Output = Self;
181 #[logic]
182 #[builtin("int.Int.(*)")]
183 #[allow(unused_variables)]
184 fn mul_logic(self, other: Self) -> Self {
185 dead
186 }
187}
188
189impl DivLogic for Int {
190 type Output = Self;
191 #[logic]
192 #[builtin("int.ComputerDivision.div")]
193 #[allow(unused_variables)]
194 fn div_logic(self, other: Self) -> Self {
195 dead
196 }
197}
198
199impl RemLogic for Int {
200 type Output = Self;
201 #[logic]
202 #[builtin("int.ComputerDivision.mod")]
203 #[allow(unused_variables)]
204 fn rem_logic(self, other: Self) -> Self {
205 dead
206 }
207}
208
209impl NegLogic for Int {
210 type Output = Self;
211 #[logic]
212 #[builtin("int.Int.(-_)")]
213 fn neg_logic(self) -> Self {
214 dead
215 }
216}
217
218impl Int {
222 #[trusted]
237 #[check(ghost)]
238 #[ensures(*result == value@)]
239 #[allow(unreachable_code)]
240 #[allow(unused_variables)]
241 pub fn new(value: i128) -> Ghost<Self> {
242 Ghost::conjure()
243 }
244
245 #[trusted]
246 #[check(ghost)]
247 #[ensures(^self == *self + 1)]
248 pub fn incr_ghost(&mut self) {}
249
250 #[trusted]
251 #[check(ghost)]
252 #[ensures(^self == *self - 1)]
253 pub fn decr_ghost(&mut self) {}
254}
255
256impl PartialEq for Int {
257 #[trusted]
258 #[check(ghost)]
259 #[ensures(result == (*self == *other))]
260 #[allow(unused_variables)]
261 fn eq(&self, other: &Self) -> bool {
262 panic!()
263 }
264
265 #[check(ghost)]
266 #[ensures(result == (*self != *other))]
267 fn ne(&self, other: &Self) -> bool {
268 !self.eq(other)
269 }
270}
271
272impl PartialOrd for Int {
273 #[trusted]
274 #[check(ghost)]
275 #[ensures(result == Some((*self).cmp_log(*other)))]
276 #[allow(unused_variables)]
277 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
278 panic!()
279 }
280
281 #[trusted]
282 #[check(ghost)]
283 #[ensures(result == (*self < *other))]
284 #[allow(unused_variables)]
285 fn lt(&self, other: &Self) -> bool {
286 panic!()
287 }
288
289 #[trusted]
290 #[check(ghost)]
291 #[ensures(result == (*self <= *other))]
292 #[allow(unused_variables)]
293 fn le(&self, other: &Self) -> bool {
294 panic!()
295 }
296
297 #[trusted]
298 #[check(ghost)]
299 #[ensures(result == (*self > *other))]
300 #[allow(unused_variables)]
301 fn gt(&self, other: &Self) -> bool {
302 panic!()
303 }
304
305 #[trusted]
306 #[check(ghost)]
307 #[ensures(result == (*self >= *other))]
308 #[allow(unused_variables)]
309 fn ge(&self, other: &Self) -> bool {
310 panic!()
311 }
312}
313
314impl Add for Int {
315 type Output = Int;
316 #[trusted]
317 #[check(ghost)]
318 #[ensures(result == self + other)]
319 #[allow(unused_variables)]
320 fn add(self, other: Int) -> Self {
321 panic!()
322 }
323}
324
325impl Sub for Int {
326 type Output = Int;
327 #[trusted]
328 #[check(ghost)]
329 #[ensures(result == self - other)]
330 #[allow(unused_variables)]
331 fn sub(self, other: Int) -> Self {
332 panic!()
333 }
334}
335
336impl Mul for Int {
337 type Output = Int;
338 #[trusted]
339 #[check(ghost)]
340 #[ensures(result == self * other)]
341 #[allow(unused_variables)]
342 fn mul(self, other: Int) -> Self {
343 panic!()
344 }
345}
346
347impl Div for Int {
348 type Output = Int;
349 #[trusted]
350 #[check(ghost)]
351 #[requires(other != 0)]
352 #[ensures(result == self / other)]
353 #[allow(unused_variables)]
354 fn div(self, other: Int) -> Self {
355 panic!()
356 }
357}
358
359impl Rem for Int {
360 type Output = Int;
361 #[trusted]
362 #[check(ghost)]
363 #[requires(other != 0)]
364 #[ensures(result == self % other)]
365 #[allow(unused_variables)]
366 fn rem(self, other: Int) -> Self {
367 panic!()
368 }
369}
370
371impl Neg for Int {
372 type Output = Int;
373 #[trusted]
374 #[check(ghost)]
375 #[ensures(result == -self)]
376 fn neg(self) -> Self {
377 panic!()
378 }
379}
380
381impl AddAssign for Int {
382 #[check(ghost)]
383 #[ensures(^self == *self + rhs)]
384 fn add_assign(&mut self, rhs: Int) {
385 *self = *self + rhs;
386 }
387}
388
389impl SubAssign for Int {
390 #[check(ghost)]
391 #[ensures(^self == *self - rhs)]
392 fn sub_assign(&mut self, rhs: Int) {
393 *self = *self - rhs;
394 }
395}
396
397impl MulAssign for Int {
398 #[check(ghost)]
399 #[ensures(^self == *self * rhs)]
400 fn mul_assign(&mut self, rhs: Int) {
401 *self = *self * rhs;
402 }
403}
404
405impl DivAssign for Int {
406 #[check(ghost)]
407 #[requires(rhs != 0)]
408 #[ensures(^self == *self / rhs)]
409 fn div_assign(&mut self, rhs: Int) {
410 *self = *self / rhs;
411 }
412}
413
414impl RemAssign for Int {
415 #[check(ghost)]
416 #[requires(rhs != 0)]
417 #[ensures(^self == *self % rhs)]
418 fn rem_assign(&mut self, rhs: Int) {
419 *self = *self % rhs;
420 }
421}
422
423#[derive(Copy)]
424struct NatInner(Int);
425
426impl Invariant for NatInner {
427 #[logic]
428 fn invariant(self) -> bool {
429 self.0 >= 0
430 }
431}
432
433impl InhabitedInvariant for NatInner {
434 #[logic]
435 #[ensures(result.invariant())]
436 fn inhabits() -> Self {
437 Self(0)
438 }
439}
440
441impl Clone for NatInner {
442 #[check(ghost)]
443 #[ensures(result == *self)]
444 fn clone(&self) -> Self {
445 *self
446 }
447}
448
449#[derive(Copy)]
451pub struct Nat(Subset<NatInner>);
452
453impl View for Nat {
454 type ViewTy = Int;
455 #[logic(open)]
456 fn view(self) -> Int {
457 self.to_int()
458 }
459}
460
461impl Clone for Nat {
462 #[check(ghost)]
463 #[ensures(result == *self)]
464 fn clone(&self) -> Self {
465 *self
466 }
467}
468
469impl Plain for Nat {
470 #[check(ghost)]
471 #[ensures(*result == *s)]
472 #[allow(unused_variables)]
473 fn into_ghost(s: Snapshot<Self>) -> Ghost<Self> {
474 ghost! {
475 let n: Snapshot<Int> = snapshot!(s.to_int());
476 let _ = snapshot!(Self::ext_eq);
477 Self(Subset::new(NatInner(n.into_ghost().into_inner())))
478 }
479 }
480}
481
482impl Nat {
483 #[logic]
484 #[ensures(result >= 0)]
485 pub fn to_int(self) -> Int {
486 self.0.inner().0
487 }
488
489 #[logic]
490 #[requires(n >= 0)]
491 #[ensures(result.to_int() == n)]
492 pub fn new(n: Int) -> Nat {
493 Nat(Subset::new_logic(NatInner(n)))
494 }
495
496 #[logic(open)]
497 #[ensures(#[trigger(self == other)] result == (self == other))]
498 pub fn ext_eq(self, other: Self) -> bool {
499 let _ = Subset::<NatInner>::inner_inj;
500 self.to_int() == other.to_int()
501 }
502}
503
504impl AddLogic for Nat {
505 type Output = Self;
506 #[logic]
507 #[ensures(result@ == self@ + other@)]
508 fn add_logic(self, other: Self) -> Self {
509 Self::new(self.to_int() + other.to_int())
510 }
511}
512
513impl MulLogic for Nat {
514 type Output = Self;
515 #[logic]
516 #[ensures(result@ == self@ * other@)]
517 fn mul_logic(self, other: Self) -> Self {
518 Self::new(self.to_int() * other.to_int())
519 }
520}
521
522impl PartialOrdLogic for Nat {
523 #[logic(open)]
524 fn lt_log(self, other: Self) -> bool {
525 self.to_int() < other.to_int()
526 }
527
528 #[logic(open)]
529 fn le_log(self, other: Self) -> bool {
530 self.to_int() <= other.to_int()
531 }
532
533 #[logic]
534 #[ensures(!(self < self))]
535 fn irreflexive(self) {}
536
537 #[logic]
538 #[requires(x < y)]
539 #[requires(y < z)]
540 #[ensures(x < z)]
541 fn transitive(x: Self, y: Self, z: Self) {}
542
543 #[logic(law)]
544 #[ensures((self <= other) == (self < other || self == other))]
545 fn le_lt_log(self, other: Self) {
546 let _ = Nat::ext_eq;
547 }
548}
549
550impl OrdLogic for Nat {
551 #[logic(law)]
552 #[ensures(self < other || self == other || other < self)]
553 fn lt_log_total(self, other: Self) {}
554}
555
556#[derive(Copy)]
558pub struct Positive(Subset<PositiveInner>);
559
560#[derive(Copy)]
561struct PositiveInner(Int);
562
563impl Invariant for PositiveInner {
564 #[logic]
565 fn invariant(self) -> bool {
566 self.0 > 0int
567 }
568}
569impl InhabitedInvariant for PositiveInner {
570 #[logic]
571 #[ensures(result.invariant())]
572 fn inhabits() -> Self {
573 Self(1int)
574 }
575}
576
577impl Clone for PositiveInner {
578 #[check(ghost)]
579 #[ensures(result == *self)]
580 fn clone(&self) -> Self {
581 *self
582 }
583}
584
585impl View for Positive {
586 type ViewTy = Int;
587 #[logic(open)]
588 fn view(self) -> Int {
589 self.to_int()
590 }
591}
592
593impl Clone for Positive {
594 #[check(ghost)]
595 #[ensures(result == *self)]
596 fn clone(&self) -> Self {
597 *self
598 }
599}
600
601impl Plain for Positive {
602 #[check(ghost)]
603 #[ensures(*result == *s)]
604 #[allow(unused_variables)]
605 fn into_ghost(s: Snapshot<Self>) -> Ghost<Self> {
606 ghost! {
607 let n: Snapshot<Int> = snapshot!(s.to_int());
608 let _ = snapshot!(Self::ext_eq);
609 Self(Subset::new(PositiveInner(n.into_ghost().into_inner())))
610 }
611 }
612}
613
614impl Positive {
615 #[logic]
616 #[ensures(result > 0)]
617 pub fn to_int(self) -> Int {
618 self.0.inner().0
619 }
620
621 #[logic]
622 #[requires(n > 0)]
623 #[ensures(result.to_int() == n)]
624 pub fn new(n: Int) -> Self {
625 Self(Subset::new_logic(PositiveInner(n)))
626 }
627
628 #[logic(open)]
629 #[ensures(#[trigger(self == other)] result == (self == other))]
630 pub fn ext_eq(self, other: Self) -> bool {
631 let _ = Subset::<PositiveInner>::inner_inj;
632 self.to_int() == other.to_int()
633 }
634}
635
636impl AddLogic for Positive {
637 type Output = Self;
638
639 #[logic]
640 #[ensures(result@ == self@ + other@)]
641 fn add_logic(self, other: Self) -> Self {
642 Self::new(self.to_int() + other.to_int())
643 }
644}
645
646impl MulLogic for Positive {
647 type Output = Self;
648
649 #[logic]
650 #[ensures(result@ == self@ * other@)]
651 fn mul_logic(self, other: Self) -> Self {
652 Self::new(self.to_int() * other.to_int())
653 }
654}
655
656impl PartialOrdLogic for Positive {
657 #[logic(open)]
658 fn lt_log(self, other: Self) -> bool {
659 self.to_int() < other.to_int()
660 }
661
662 #[logic(open)]
663 fn le_log(self, other: Self) -> bool {
664 self.to_int() <= other.to_int()
665 }
666
667 #[logic]
668 #[ensures(!(self < self))]
669 fn irreflexive(self) {}
670
671 #[logic]
672 #[requires(x < y)]
673 #[requires(y < z)]
674 #[ensures(x < z)]
675 fn transitive(x: Self, y: Self, z: Self) {}
676
677 #[logic(law)]
678 #[ensures((self <= other) == (self < other || self == other))]
679 fn le_lt_log(self, other: Self) {
680 let _ = Positive::ext_eq;
681 }
682}
683
684impl OrdLogic for Positive {
685 #[logic(law)]
686 #[ensures(self < other || self == other || other < self)]
687 fn lt_log_total(self, other: Self) {
688 let _ = Positive::ext_eq;
689 }
690}