1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
//! The [`calc`] macro provides support for reasoning about a structured proof calculation.
#![allow(unused_imports)]
use super::pervasive::*;
use super::prelude::*;

verus! {

/// The `calc!` macro supports structured proofs through calculations.
///
/// In particular, one can show `a_1 R a_n` for some transitive relation `R` by performing a series
/// of steps `a_1 R a_2`, `a_2 R a_3`, ... `a_{n-1} R a_n`. The calc macro provides both convenient
/// syntax sugar to perform such a proof conveniently, without repeating oneself too often, or
/// exposing the internal steps to the outside context.
///
/// The expected usage looks like:
///
/// ```
/// calc! {
///   (R)
///   a_1; { /* proof that a_1 R a_2 */ }
///   a_2; { /* proof that a_2 R a_3 */ }
///    ...
///   a_n;
/// }
/// ```
///
/// Currently, the `calc!` macro supports common transitive relations for `R`, and this set of
/// relations may be extended in the future.
///
/// Note that `calc!` also supports stating intermediate relations, as long as they are consistent
/// with the main relation `R`. If consistency cannot be immediately shown, Verus will give a
/// helpful message about this. Intermediate relations can be specified by placing them right before
/// the proof block of that step.
///
/// A simple example of using intermediate relations looks like:
///
/// ```
/// let x: int = 2;
/// let y: int = 5;
/// calc! {
///   (<=)
///   x; (==) {}
///   5 - 3; (<) {}
///   5; {} // Notice that no intermediate relation is specified here, so `calc!` will consider the top-level relation `R`; here `<=`.
///   y;
/// }
/// ```
#[allow(unused_macros)]
#[macro_export]
macro_rules! calc {
    ($($tt:tt)*) => {
        ::builtin_macros::calc_proc_macro!($($tt)*)
    };
}

pub use calc;

} // verus!