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}
94