bool_logic/
ast.rs

1use std::fmt;
2
3#[derive(Debug, Clone, PartialEq, Eq)]
4pub enum Expr<T> {
5    Any(Any<T>),
6    All(All<T>),
7    Not(Not<T>),
8    Var(Var<T>),
9    Const(bool),
10}
11
12#[derive(Debug, Clone, PartialEq, Eq)]
13pub struct Any<T>(pub Vec<Expr<T>>);
14
15#[derive(Debug, Clone, PartialEq, Eq)]
16pub struct All<T>(pub Vec<Expr<T>>);
17
18#[derive(Debug, Clone, PartialEq, Eq)]
19pub struct Not<T>(pub Box<Expr<T>>);
20
21#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
22pub struct Var<T>(pub T);
23
24pub fn expr<T>(x: impl Into<Expr<T>>) -> Expr<T> {
25    x.into()
26}
27
28pub fn any<T>(x: impl Into<Any<T>>) -> Any<T> {
29    x.into()
30}
31
32pub fn all<T>(x: impl Into<All<T>>) -> All<T> {
33    x.into()
34}
35
36pub fn not<T>(x: impl Into<Expr<T>>) -> Not<T> {
37    x.into().into()
38}
39
40pub fn var<T>(x: impl Into<Var<T>>) -> Var<T> {
41    x.into()
42}
43
44#[must_use]
45pub fn const_<T>(x: bool) -> Expr<T> {
46    x.into()
47}
48
49impl<T> Expr<T> {
50    pub fn is_any(&self) -> bool {
51        matches!(self, Self::Any(_))
52    }
53
54    pub fn is_all(&self) -> bool {
55        matches!(self, Self::All(_))
56    }
57
58    pub fn is_not(&self) -> bool {
59        matches!(self, Self::Not(_))
60    }
61
62    pub fn is_var(&self) -> bool {
63        matches!(self, Self::Var(_))
64    }
65
66    pub fn is_const(&self) -> bool {
67        matches!(self, Self::Const(_))
68    }
69
70    pub fn is_const_true(&self) -> bool {
71        matches!(self, Self::Const(true))
72    }
73
74    pub fn is_const_false(&self) -> bool {
75        matches!(self, Self::Const(false))
76    }
77}
78
79impl<T> Expr<T> {
80    pub fn as_mut_any(&mut self) -> Option<&mut Any<T>> {
81        match self {
82            Expr::Any(any) => Some(any),
83            _ => None,
84        }
85    }
86
87    pub fn as_mut_all(&mut self) -> Option<&mut All<T>> {
88        match self {
89            Expr::All(all) => Some(all),
90            _ => None,
91        }
92    }
93
94    pub fn as_mut_not(&mut self) -> Option<&mut Not<T>> {
95        match self {
96            Expr::Not(not) => Some(not),
97            _ => None,
98        }
99    }
100
101    pub fn as_mut_var(&mut self) -> Option<&mut Var<T>> {
102        match self {
103            Expr::Var(var) => Some(var),
104            _ => None,
105        }
106    }
107
108    pub fn as_mut_const(&mut self) -> Option<&mut bool> {
109        match self {
110            Expr::Const(b) => Some(b),
111            _ => None,
112        }
113    }
114}
115
116impl<T> Expr<T> {
117    pub fn as_any(&self) -> Option<&Any<T>> {
118        match self {
119            Expr::Any(any) => Some(any),
120            _ => None,
121        }
122    }
123
124    pub fn as_all(&self) -> Option<&All<T>> {
125        match self {
126            Expr::All(all) => Some(all),
127            _ => None,
128        }
129    }
130
131    pub fn as_not(&self) -> Option<&Not<T>> {
132        match self {
133            Expr::Not(not) => Some(not),
134            _ => None,
135        }
136    }
137
138    pub fn as_var(&self) -> Option<&Var<T>> {
139        match self {
140            Expr::Var(var) => Some(var),
141            _ => None,
142        }
143    }
144
145    pub fn as_const(&self) -> Option<&bool> {
146        match self {
147            Expr::Const(b) => Some(b),
148            _ => None,
149        }
150    }
151}
152
153impl<T> Expr<T> {
154    pub fn is_empty_not_any(&self) -> bool {
155        if let Expr::Not(Not(not)) = self {
156            if let Expr::Any(Any(list)) = &**not {
157                return list.is_empty();
158            }
159        }
160        false
161    }
162
163    pub fn is_empty_not_all(&self) -> bool {
164        if let Expr::Not(Not(not)) = self {
165            if let Expr::All(All(list)) = &**not {
166                return list.is_empty();
167            }
168        }
169        false
170    }
171
172    pub fn is_expr_not_var(&self) -> bool {
173        if let Expr::Not(Not(not)) = self {
174            return not.is_var();
175        }
176        false
177    }
178
179    pub fn as_mut_not_any(&mut self) -> Option<&mut Any<T>> {
180        if let Expr::Not(Not(not)) = self {
181            if let Expr::Any(any) = &mut **not {
182                return Some(any);
183            }
184        }
185        None
186    }
187
188    pub fn as_mut_not_all(&mut self) -> Option<&mut All<T>> {
189        if let Expr::Not(Not(not)) = self {
190            if let Expr::All(any) = &mut **not {
191                return Some(any);
192            }
193        }
194        None
195    }
196
197    pub fn as_mut_expr_list(&mut self) -> Option<&mut Vec<Expr<T>>> {
198        match self {
199            Expr::Any(Any(list)) | Expr::All(All(list)) => Some(list),
200            _ => None,
201        }
202    }
203}
204
205impl<T> From<Any<T>> for Expr<T> {
206    fn from(any: Any<T>) -> Self {
207        Expr::Any(any)
208    }
209}
210
211impl<T> From<All<T>> for Expr<T> {
212    fn from(all: All<T>) -> Self {
213        Expr::All(all)
214    }
215}
216
217impl<T> From<Not<T>> for Expr<T> {
218    fn from(not: Not<T>) -> Self {
219        Expr::Not(not)
220    }
221}
222
223impl<T> From<Var<T>> for Expr<T> {
224    fn from(var: Var<T>) -> Self {
225        Expr::Var(var)
226    }
227}
228
229impl<T> From<bool> for Expr<T> {
230    fn from(b: bool) -> Self {
231        Expr::Const(b)
232    }
233}
234
235impl<T> From<Vec<Expr<T>>> for Any<T> {
236    fn from(exprs: Vec<Expr<T>>) -> Self {
237        Any(exprs)
238    }
239}
240
241impl<T> From<Vec<Expr<T>>> for All<T> {
242    fn from(exprs: Vec<Expr<T>>) -> Self {
243        All(exprs)
244    }
245}
246
247impl<T> From<Box<Expr<T>>> for Not<T> {
248    fn from(expr: Box<Expr<T>>) -> Self {
249        Not(expr)
250    }
251}
252
253impl<T> From<Expr<T>> for Not<T> {
254    fn from(expr: Expr<T>) -> Self {
255        Not(Box::new(expr))
256    }
257}
258
259impl<T> From<Any<T>> for Not<T> {
260    fn from(any: Any<T>) -> Self {
261        Not(Box::new(any.into()))
262    }
263}
264
265impl<T> From<All<T>> for Not<T> {
266    fn from(all: All<T>) -> Self {
267        Not(Box::new(all.into()))
268    }
269}
270
271impl<T> From<Var<T>> for Not<T> {
272    fn from(var: Var<T>) -> Self {
273        Not(Box::new(var.into()))
274    }
275}
276
277impl<T> From<T> for Not<T> {
278    fn from(var: T) -> Self {
279        Self::from(Var(var))
280    }
281}
282
283impl<T> From<T> for Var<T> {
284    fn from(var: T) -> Self {
285        Var(var)
286    }
287}
288
289macro_rules! impl_from_tuple {
290    ($ty:ident, ()) => {
291        impl_from_tuple!(@expand $ty, ());
292    };
293    ($ty:ident, ($x:tt, $($xs:tt,)*)) => {
294        impl_from_tuple!($ty, ($($xs,)*));
295        impl_from_tuple!(@expand $ty, ($x, $($xs,)*));
296    };
297    (@expand $ty:ident, ($($tt:tt,)*)) => {
298        #[doc(hidden)] // too ugly
299        #[allow(non_camel_case_types)]
300        impl<T, $($tt),*> From<($($tt,)*)>  for $ty<T>
301        where
302            $($tt: Into<Expr<T>>,)*
303        {
304            fn from(($($tt,)*): ($($tt,)*)) -> Self {
305                Self::from(vec![$(Into::into($tt)),*])
306            }
307        }
308    };
309}
310
311impl_from_tuple!(
312    Any,
313    (
314        x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, //
315        x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, //
316        x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35,
317    )
318);
319
320impl_from_tuple!(
321    All,
322    (
323        x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, //
324        x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, //
325        x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35,
326    )
327);
328
329impl<T> fmt::Display for Expr<T>
330where
331    T: fmt::Display,
332{
333    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
334        match self {
335            Expr::Any(Any(any)) => fmt_list(f, "any", any),
336            Expr::All(All(all)) => fmt_list(f, "all", all),
337            Expr::Not(Not(not)) => write!(f, "not({not})"),
338            Expr::Var(Var(x)) => write!(f, "{x}"),
339            Expr::Const(b) => write!(f, "{b}"),
340        }
341    }
342}
343
344fn fmt_list<T>(f: &mut fmt::Formatter<'_>, name: &str, list: &[Expr<T>]) -> fmt::Result
345where
346    T: fmt::Display,
347{
348    write!(f, "{name}(")?;
349    for (i, e) in list.iter().enumerate() {
350        if i != 0 {
351            write!(f, ", ")?;
352        }
353        write!(f, "{e}")?;
354    }
355    write!(f, ")")
356}