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)] #[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, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, 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, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, 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}