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
44pub fn const_<T>(x: bool) -> Expr<T> {
45 x.into()
46}
47
48impl<T> From<Any<T>> for Expr<T> {
49 fn from(any: Any<T>) -> Self {
50 Expr::Any(any)
51 }
52}
53
54impl<T> From<All<T>> for Expr<T> {
55 fn from(all: All<T>) -> Self {
56 Expr::All(all)
57 }
58}
59
60impl<T> From<Not<T>> for Expr<T> {
61 fn from(not: Not<T>) -> Self {
62 Expr::Not(not)
63 }
64}
65
66impl<T> From<Var<T>> for Expr<T> {
67 fn from(var: Var<T>) -> Self {
68 Expr::Var(var)
69 }
70}
71
72impl<T> From<bool> for Expr<T> {
73 fn from(b: bool) -> Self {
74 Expr::Const(b)
75 }
76}
77
78impl<T> From<Vec<Expr<T>>> for Any<T> {
79 fn from(exprs: Vec<Expr<T>>) -> Self {
80 Any(exprs)
81 }
82}
83
84impl<T> From<Vec<Expr<T>>> for All<T> {
85 fn from(exprs: Vec<Expr<T>>) -> Self {
86 All(exprs)
87 }
88}
89
90impl<T> From<Box<Expr<T>>> for Not<T> {
91 fn from(expr: Box<Expr<T>>) -> Self {
92 Not(expr)
93 }
94}
95
96impl<T> From<Expr<T>> for Not<T> {
97 fn from(expr: Expr<T>) -> Self {
98 Not(Box::new(expr))
99 }
100}
101
102impl<T> From<Any<T>> for Not<T> {
103 fn from(any: Any<T>) -> Self {
104 Not(Box::new(any.into()))
105 }
106}
107
108impl<T> From<All<T>> for Not<T> {
109 fn from(all: All<T>) -> Self {
110 Not(Box::new(all.into()))
111 }
112}
113
114impl<T> From<Var<T>> for Not<T> {
115 fn from(var: Var<T>) -> Self {
116 Not(Box::new(var.into()))
117 }
118}
119
120impl<T> From<T> for Not<T> {
121 fn from(var: T) -> Self {
122 Self::from(Var(var))
123 }
124}
125
126impl<T> From<T> for Var<T> {
127 fn from(var: T) -> Self {
128 Var(var)
129 }
130}
131
132macro_rules! impl_from_tuple {
133 ($ty:ident, ()) => {
134 impl_from_tuple!(@expand $ty, ());
135 };
136 ($ty:ident, ($x:tt, $($xs:tt,)*)) => {
137 impl_from_tuple!($ty, ($($xs,)*));
138 impl_from_tuple!(@expand $ty, ($x, $($xs,)*));
139 };
140 (@expand $ty:ident, ($($tt:tt,)*)) => {
141 #[doc(hidden)] #[allow(non_camel_case_types)]
143 impl<T, $($tt),*> From<($($tt,)*)> for $ty<T>
144 where
145 $($tt: Into<Expr<T>>,)*
146 {
147 fn from(($($tt,)*): ($($tt,)*)) -> Self {
148 Self::from(vec![$(Into::into($tt)),*])
149 }
150 }
151 };
152}
153
154impl_from_tuple!(
155 Any,
156 (
157 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,
160 )
161);
162
163impl_from_tuple!(
164 All,
165 (
166 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,
169 )
170);
171
172impl<T> fmt::Display for Expr<T>
173where
174 T: fmt::Display,
175{
176 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
177 match self {
178 Expr::Any(Any(any)) => fmt_list(f, "any", any),
179 Expr::All(All(all)) => fmt_list(f, "all", all),
180 Expr::Not(Not(not)) => write!(f, "not({not})"),
181 Expr::Var(Var(x)) => write!(f, "{x}"),
182 Expr::Const(b) => write!(f, "{b}"),
183 }
184 }
185}
186
187fn fmt_list<T>(f: &mut fmt::Formatter<'_>, name: &str, list: &[Expr<T>]) -> fmt::Result
188where
189 T: fmt::Display,
190{
191 write!(f, "{name}(")?;
192 for (i, e) in list.iter().enumerate() {
193 if i != 0 {
194 write!(f, ", ")?;
195 }
196 write!(f, "{e}")?;
197 }
198 write!(f, ")")
199}
200
201impl<T> Expr<T> {
202 pub fn as_mut_expr_list(&mut self) -> Option<&mut Vec<Expr<T>>> {
203 match self {
204 Expr::Any(Any(list)) | Expr::All(All(list)) => Some(list),
205 _ => None,
206 }
207 }
208
209 pub fn is_any(&self) -> bool {
210 matches!(self, Self::Any(_))
211 }
212
213 pub fn is_all(&self) -> bool {
214 matches!(self, Self::All(_))
215 }
216
217 pub fn is_not(&self) -> bool {
218 matches!(self, Self::Not(_))
219 }
220
221 pub fn is_var(&self) -> bool {
222 matches!(self, Self::Var(_))
223 }
224
225 pub fn is_const(&self) -> bool {
226 matches!(self, Self::Const(_))
227 }
228
229 pub fn is_const_true(&self) -> bool {
230 matches!(self, Self::Const(true))
231 }
232
233 pub fn is_const_false(&self) -> bool {
234 matches!(self, Self::Const(false))
235 }
236
237 pub fn as_var(&self) -> Option<&Var<T>> {
238 match self {
239 Expr::Var(var) => Some(var),
240 _ => None,
241 }
242 }
243
244 pub fn as_mut_any(&mut self) -> Option<&mut Any<T>> {
245 match self {
246 Expr::Any(any) => Some(any),
247 _ => None,
248 }
249 }
250
251 pub fn as_mut_all(&mut self) -> Option<&mut All<T>> {
252 match self {
253 Expr::All(all) => Some(all),
254 _ => None,
255 }
256 }
257
258 pub fn as_mut_not(&mut self) -> Option<&mut Not<T>> {
259 match self {
260 Expr::Not(not) => Some(not),
261 _ => None,
262 }
263 }
264
265 pub fn is_expr_not_var(&self) -> bool {
266 if let Expr::Not(Not(not)) = self {
267 return not.is_var();
268 }
269 false
270 }
271
272 pub fn as_mut_not_any(&mut self) -> Option<&mut Any<T>> {
273 if let Expr::Not(Not(not)) = self {
274 if let Expr::Any(any) = &mut **not {
275 return Some(any);
276 }
277 }
278 None
279 }
280
281 pub fn as_mut_not_all(&mut self) -> Option<&mut All<T>> {
282 if let Expr::Not(Not(not)) = self {
283 if let Expr::All(any) = &mut **not {
284 return Some(any);
285 }
286 }
287 None
288 }
289
290 pub fn is_empty_not_any(&self) -> bool {
291 if let Expr::Not(Not(not)) = self {
292 if let Expr::Any(Any(list)) = &**not {
293 return list.is_empty();
294 }
295 }
296 false
297 }
298
299 pub fn is_empty_not_all(&self) -> bool {
300 if let Expr::Not(Not(not)) = self {
301 if let Expr::All(All(list)) = &**not {
302 return list.is_empty();
303 }
304 }
305 false
306 }
307}