materially/
lib.rs

1//! A macro for [material implication](https://simple.wikipedia.org/wiki/Implication_(logic)).
2//!
3//! `a => b` ("`a` implies `b`") means `!a || b`.
4//!
5//! # Examples
6//!
7//! ```rust
8//! use materially::implies as i;
9//!
10//! assert!(i!(false => true));
11//! assert!(i!(false => false));
12//! assert!(i!(true => true));
13//! assert!(!i!(true => false));
14//!
15//! // Implication is right-associative
16//! assert!(i!(false => false => false));
17//!
18//! // let-chains style syntax is also supported
19//! assert!(i!(let Some(a) = Some(17) => a > 3 => let None = Some(17) => false));
20//! ```
21
22#![warn(missing_docs)]
23#![no_std]
24
25/// The implication macro.
26/// See the [crate-level documentation][crate] for examples.
27#[macro_export]
28macro_rules! implies {
29    ($($tt:tt)*) => {
30        $crate::implies_tt!(() $($tt)*)
31    };
32}
33
34#[doc(hidden)]
35pub use core::compile_error;
36
37#[doc(hidden)]
38#[macro_export]
39macro_rules! implies_tt {
40    (($($front:tt)*) => $($tail:tt)*) => {
41        if $($front)* {
42            $crate::implies_tt_tail!(() $($tail)*)
43        } else {
44            true
45        }
46    };
47
48    (($($front:tt)*) $next:tt $($tail:tt)*) => {
49        $crate::implies_tt!(($($front)* $next) $($tail)*)
50    };
51
52    (($($front:tt)*)) => {
53        {
54            $crate::compile_error!("`implies` macro invocation must contain at least one implication (`=>`)");
55            $($front)*
56        }
57    };
58}
59
60#[doc(hidden)]
61#[macro_export]
62macro_rules! implies_tt_tail {
63    (($($front:tt)*) => $($tail:tt)*) => {
64        if $($front)* {
65            $crate::implies_tt_tail!(() $($tail)*)
66        } else {
67            true
68        }
69    };
70
71    (($($front:tt)*) $next:tt $($tail:tt)*) => {
72        $crate::implies_tt_tail!(($($front)* $next) $($tail)*)
73    };
74
75    (($($front:tt)*)) => {
76        $($front)*
77    };
78}