Skip to main content

refining_core/
logical.rs

1//! Logical composition.
2
3use core::{fmt, marker::PhantomData};
4
5use crate::predicate::{Predicate, PredicateExpected};
6
7/// The `nothing` literal.
8pub const NOTHING: &str = "nothing";
9
10/// The `everything` literal.
11pub const ANYTHING: &str = "anything";
12
13/// The `false` literal.
14pub const FALSE: &str = "false";
15
16/// The `true` literal.
17pub const TRUE: &str = "true";
18
19/// Represents predicates that are never satisfied.
20pub struct False {
21    private: PhantomData<()>,
22}
23
24/// Represents predicates that are always satisfied.
25pub struct True {
26    private: PhantomData<()>,
27}
28
29impl<T: ?Sized> Predicate<T> for False {
30    fn check(_value: &T) -> bool {
31        false
32    }
33
34    fn expect(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
35        formatter.write_str(NOTHING)
36    }
37
38    fn expect_code(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
39        formatter.write_str(FALSE)
40    }
41}
42
43impl<T: ?Sized> Predicate<T> for True {
44    fn check(_value: &T) -> bool {
45        true
46    }
47
48    fn expect(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
49        formatter.write_str(ANYTHING)
50    }
51
52    fn expect_code(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
53        formatter.write_str(TRUE)
54    }
55}
56
57/// The `not` literal.
58pub const NOT: &str = "not";
59
60/// Represents predicates that are satisfied whenever `P` is *not* satisfied.
61pub struct Not<P: ?Sized> {
62    predicate: PhantomData<P>,
63}
64
65impl<T: ?Sized, P: Predicate<T> + ?Sized> Predicate<T> for Not<P> {
66    fn check(value: &T) -> bool {
67        !P::check(value)
68    }
69
70    fn expect(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
71        write!(formatter, "{NOT} ({expected})", expected = P::expected())
72    }
73
74    fn expect_code(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
75        write!(formatter, "{NOT}<{expected:?}>", expected = P::expected())
76    }
77}
78
79/// The `and` literal.
80pub const AND: &str = "and";
81
82/// Represents predicates that are satisfied when both `P` *and* `Q` are satisfied.
83pub struct And<P: ?Sized, Q: ?Sized> {
84    left: PhantomData<P>,
85    right: PhantomData<Q>,
86}
87
88impl<T: ?Sized, P: Predicate<T> + ?Sized, Q: Predicate<T> + ?Sized> Predicate<T> for And<P, Q> {
89    fn check(value: &T) -> bool {
90        P::check(value) && Q::check(value)
91    }
92
93    fn expect(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
94        write!(
95            formatter,
96            "({left}) {AND} ({right})",
97            left = P::expected(),
98            right = Q::expected(),
99        )
100    }
101
102    fn expect_code(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
103        write!(
104            formatter,
105            "{AND}<{left:?}, {right:?}>",
106            left = P::expected(),
107            right = Q::expected(),
108        )
109    }
110}
111
112/// The `or` literal.
113pub const OR: &str = "or";
114
115/// Represents predicates that are satisfied whenever at least `P` *or* `Q` are satisfied.
116pub struct Or<P: ?Sized, Q: ?Sized> {
117    left: PhantomData<P>,
118    right: PhantomData<Q>,
119}
120
121impl<T: ?Sized, P: Predicate<T> + ?Sized, Q: Predicate<T> + ?Sized> Predicate<T> for Or<P, Q> {
122    fn check(value: &T) -> bool {
123        P::check(value) || Q::check(value)
124    }
125
126    fn expect(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
127        write!(
128            formatter,
129            "({left}) {OR} ({right})",
130            left = P::expected(),
131            right = Q::expected(),
132        )
133    }
134
135    fn expect_code(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
136        write!(
137            formatter,
138            "{OR}<{left:?}, {right:?}>",
139            left = P::expected(),
140            right = Q::expected(),
141        )
142    }
143}
144
145/// The `xor` literal.
146pub const XOR: &str = "xor";
147
148/// Represents predicates that are satisfied whenever `P` *or* `Q` (but *not* both) are satisfied.
149pub struct Xor<P: ?Sized, Q: ?Sized> {
150    left: PhantomData<P>,
151    right: PhantomData<Q>,
152}
153
154impl<T: ?Sized, P: Predicate<T> + ?Sized, Q: Predicate<T> + ?Sized> Predicate<T> for Xor<P, Q> {
155    fn check(value: &T) -> bool {
156        P::check(value) ^ Q::check(value)
157    }
158
159    fn expect(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
160        write!(
161            formatter,
162            "({left}) {XOR} ({right})",
163            left = P::expected(),
164            right = Q::expected(),
165        )
166    }
167
168    fn expect_code(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
169        write!(
170            formatter,
171            "{XOR}<{left:?}, {right:?}>",
172            left = P::expected(),
173            right = Q::expected(),
174        )
175    }
176}
177
178/// Represents [`Not<And<P, Q>>`].
179pub type Nand<P, Q> = Not<And<P, Q>>;
180
181/// Represents [`Not<Or<P, Q>>`].
182pub type Nor<P, Q> = Not<Or<P, Q>>;
183
184/// Represents [`Not<Xor<P, Q>>`].
185pub type Xnor<P, Q> = Not<Xor<P, Q>>;
186
187/// Represents logical implication `P -> Q`, that is, [`Or<Not<P>, Q>`].
188pub type Implies<P, Q> = Or<Not<P>, Q>;
189
190/// Negates the given predicate.
191///
192/// For predicate `P`, `not!(P)` is [`Not<P>`].
193#[macro_export]
194macro_rules! not {
195    ($predicate: ty) => {
196        $crate::logical::Not<$predicate>
197    };
198}
199
200/// Given two or more predicates, composes them together with [`And`].
201///
202/// For predicates `P` and `Q`, `and!(P, Q)` is [`And<P, Q>`].
203///
204/// For predicates `P`, `Q`, and `R`, `and!(P, Q, R)` is [`And<P, And<Q, R>>`].
205///
206/// Ad infinitum...
207#[macro_export]
208macro_rules! and {
209    ($left: ty, $right: ty) => {
210        $crate::logical::And<$left, $right>
211    };
212    ($first: ty, $second: ty, $($rest: ty),+ $(,)?) => {
213        $crate::and!($first, $crate::and!($second, $($rest),+))
214    };
215}
216
217/// Given two or more predicates, composes them together with [`Or`].
218///
219/// For predicates `P` and `Q`, `or!(P, Q)` is [`Or<P, Q>`].
220///
221/// For predicates `P`, `Q`, and `R`, `or!(P, Q, R)` is [`Or<P, Or<Q, R>>`].
222///
223/// Ad infinitum...
224#[macro_export]
225macro_rules! or {
226    ($left: ty, $right: ty) => {
227        $crate::logical::Or<$left, $right>
228    };
229    ($first: ty, $second: ty, $($rest: ty),+ $(,)?) => {
230        $crate::or!($first, $crate::or!($second, $($rest),+))
231    };
232}
233
234/// Given two or more predicates, composes them together with [`Xor`].
235///
236/// For predicates `P` and `Q`, `xor!(P, Q)` is [`Xor<P, Q>`].
237///
238/// For predicates `P`, `Q`, and `R`, `xor!(P, Q, R)` is [`Xor<P, Xor<Q, R>>`].
239///
240/// Ad infinitum...
241#[macro_export]
242macro_rules! xor {
243    ($left: ty, $right: ty) => {
244        $crate::logical::Xor<$left, $right>
245    };
246    ($first: ty, $second: ty, $($rest: ty),+ $(,)?) => {
247        $crate::xor!($first, $crate::xor!($second, $($rest),+))
248    };
249}