mac/
inspect.rs

1//! Inspect Macros
2
3/// Evaluates an expression, prints a stringified version of the expression
4/// along with the evaluated value, and then returns that value.
5///
6/// # Example
7///
8/// ```
9/// # #[macro_use] extern crate mac;
10///
11/// # fn main() {
12/// fn lcm_2_to_4() -> u32 {
13///     let mut i = 1;
14///     loop {
15///         if inspect!(i % 2, i % 3, i % 4) == (0, 0, 0) {
16///             return inspect!("done: i = " => i);
17///         }
18///         i += 1;
19///     }
20/// }
21/// assert_eq!(lcm_2_to_4(), 12);
22/// # }
23/// ```
24///
25/// Returns `12`, and prints the following to stdout:
26///
27/// ```ignore
28/// src/inspect.rs:94 - (i % 2, i % 3, i % 4) = (1, 1, 1)
29/// src/inspect.rs:94 - (i % 2, i % 3, i % 4) = (0, 2, 2)
30/// src/inspect.rs:94 - (i % 2, i % 3, i % 4) = (1, 0, 3)
31/// src/inspect.rs:94 - (i % 2, i % 3, i % 4) = (0, 1, 0)
32/// src/inspect.rs:94 - (i % 2, i % 3, i % 4) = (1, 2, 1)
33/// src/inspect.rs:94 - (i % 2, i % 3, i % 4) = (0, 0, 2)
34/// src/inspect.rs:94 - (i % 2, i % 3, i % 4) = (1, 1, 3)
35/// src/inspect.rs:94 - (i % 2, i % 3, i % 4) = (0, 2, 0)
36/// src/inspect.rs:94 - (i % 2, i % 3, i % 4) = (1, 0, 1)
37/// src/inspect.rs:94 - (i % 2, i % 3, i % 4) = (0, 1, 2)
38/// src/inspect.rs:94 - (i % 2, i % 3, i % 4) = (1, 2, 3)
39/// src/inspect.rs:94 - (i % 2, i % 3, i % 4) = (0, 0, 0)
40/// src/inspect.rs:95 - done: i = 12
41/// ```
42
43#[macro_export]
44macro_rules! inspect {
45    ($prefix:expr => $expr:expr) => {{
46        let val = $expr;
47        println!("{}:{} - {}{:?}", file!(), line!(), $prefix, val);
48        val
49    }};
50    ($expr:expr) => {
51        inspect!(concat!(stringify!($expr), " = ") => $expr)
52    };
53    ($prefix:expr => $($expr:expr),+) => {
54        inspect!($prefix => ($($expr),+))
55    };
56    ($($expr:expr),+) => {
57        inspect!(($($expr),+))
58    };
59}
60
61#[test]
62fn test_inspect() {
63    assert_eq!(inspect!("foo"), "foo");
64    assert_eq!(inspect!("" => "foo"), "foo");
65    assert_eq!(inspect!(1 + 2, 2 + 3, 3 + 4), (3, 5, 7));
66    assert_eq!(inspect!("" => 1 + 2, 2 + 3, 3 + 4), (3, 5, 7));
67
68    fn fib(n: u64) -> u64 {
69        inspect!("fib :: n = " => n);
70        inspect! { "ret = " => match n {
71            0 | 1 => n,
72            n => fib(n-1) + fib(n-2)
73        }}
74    }
75
76    fn fib_iter(n: u64) -> u64 {
77        inspect!("fib_iter :: n = " => n);
78        let (mut a, mut b) = (0, 1);
79        for _ in 0..n {
80            inspect!(a, b);
81            let tmp = b;
82            b += a;
83            a = tmp;
84        }
85        inspect!("ret = " => a)
86    }
87
88    assert_eq!(fib(4), 3);
89    assert_eq!(fib_iter(7), 13);
90
91    // Uncomment the following to see the output in `cargo test`.
92    // panic!()
93}