toasty_core/stmt/
expr_or.rs

1use super::Expr;
2use std::ops;
3
4/// A logical "or" of multiple expressions.
5///
6/// Returns `true` if at least one operand evaluates to `true`. An `ExprOr`
7/// always has at least two operands; use [`Expr::or_from_vec`] which returns
8/// `Expr::Value(false)` for empty input and unwraps single-element input.
9///
10/// # Examples
11///
12/// ```text
13/// or(a, b, c)  // returns `true` if any of `a`, `b`, or `c` is `true`
14/// ```
15#[derive(Debug, Clone, PartialEq)]
16pub struct ExprOr {
17    /// The expressions to "or" together.
18    pub operands: Vec<Expr>,
19}
20
21impl Expr {
22    /// Creates an OR expression from two operands.
23    ///
24    /// Flattens nested ORs: `or(or(a, b), c)` produces `or(a, b, c)`.
25    pub fn or(lhs: impl Into<Self>, rhs: impl Into<Self>) -> Self {
26        let mut lhs = lhs.into();
27        let rhs = rhs.into();
28
29        match (&mut lhs, rhs) {
30            (Self::Or(lhs_or), Self::Or(rhs_or)) => {
31                lhs_or.operands.extend(rhs_or.operands);
32                lhs
33            }
34            (Self::Or(lhs_or), rhs) => {
35                lhs_or.operands.push(rhs);
36                lhs
37            }
38            (_, Self::Or(mut lhs_or)) => {
39                lhs_or.operands.push(lhs);
40                lhs_or.into()
41            }
42            (_, rhs) => ExprOr {
43                operands: vec![lhs, rhs],
44            }
45            .into(),
46        }
47    }
48
49    /// Creates an OR expression from a vector of operands.
50    ///
51    /// Returns `Expr::Value(false)` for an empty vector and unwraps
52    /// single-element vectors into the element itself.
53    pub fn or_from_vec(operands: Vec<Self>) -> Self {
54        if operands.is_empty() {
55            return false.into();
56        }
57
58        if operands.len() == 1 {
59            return operands.into_iter().next().unwrap();
60        }
61
62        ExprOr { operands }.into()
63    }
64}
65
66impl ops::Deref for ExprOr {
67    type Target = [Expr];
68
69    fn deref(&self) -> &Self::Target {
70        self.operands.deref()
71    }
72}
73
74impl<'a> IntoIterator for &'a ExprOr {
75    type IntoIter = std::slice::Iter<'a, Expr>;
76    type Item = &'a Expr;
77
78    fn into_iter(self) -> Self::IntoIter {
79        self.operands.iter()
80    }
81}
82
83impl<'a> IntoIterator for &'a mut ExprOr {
84    type IntoIter = std::slice::IterMut<'a, Expr>;
85    type Item = &'a mut Expr;
86
87    fn into_iter(self) -> Self::IntoIter {
88        self.operands.iter_mut()
89    }
90}
91
92impl From<ExprOr> for Expr {
93    fn from(value: ExprOr) -> Self {
94        Self::Or(value)
95    }
96}