bool_logic/
eval.rs

1use crate::ast::{All, Any, Expr, Not, Var};
2
3pub fn eval_with<T, F>(expr: &Expr<T>, f: &F) -> bool
4where
5    F: for<'v> Fn(&'v T) -> bool,
6{
7    match expr {
8        Expr::Any(Any(list)) => list.iter().any(|e| eval_with(e, f)),
9        Expr::All(All(list)) => list.iter().all(|e| eval_with(e, f)),
10        Expr::Not(Not(not)) => !eval_with(not, f),
11        Expr::Var(Var(var)) => f(var),
12        Expr::Const(b) => *b,
13    }
14}
15
16#[cfg(test)]
17mod tests {
18    use super::*;
19
20    use crate::ast::*;
21
22    #[test]
23    fn flatten_cfg_if() {
24        let (x0, x1, x2) = (var(0), var(1), var(2));
25        let src = expr(all((not(any((x0, x1))), x2)));
26        let dst = expr(all((not(x0), not(x1), x2)));
27
28        for i in 0..8 {
29            let assign = |x: &_| ((i >> x) & 1) == 1;
30            let lhs = eval_with(&src, &assign);
31            let rhs = eval_with(&dst, &assign);
32            assert_eq!(lhs, rhs, "i = {i}");
33        }
34    }
35}