1#[derive(PartialEq, Debug)]
2enum Expr {
3 Bool(bool),
4 And(Box<Self>, Box<Self>),
5 Or(Box<Self>, Box<Self>),
6 Not(Box<Self>),
7}
8
9impl Expr {
10 fn eval(&self) -> bool {
11 match self {
12 &Self::Bool(b) => b,
13 Self::And(lhs, rhs) => lhs.eval() && rhs.eval(),
14 Self::Or(lhs, rhs) => lhs.eval() || rhs.eval(),
15 Self::Not(operand) => !operand.eval(),
16 }
17 }
18}
19
20fn and(lhs: impl Into<Expr>, rhs: impl Into<Expr>) -> Expr {
21 Expr::And(Box::new(lhs.into()), Box::new(rhs.into()))
22}
23
24fn or(lhs: impl Into<Expr>, rhs: impl Into<Expr>) -> Expr {
25 Expr::Or(Box::new(lhs.into()), Box::new(rhs.into()))
26}
27
28fn not(operand: impl Into<Expr>) -> Expr {
29 Expr::Not(Box::new(operand.into()))
30}
31
32impl From<bool> for Expr {
33 fn from(b: bool) -> Self {
34 Self::Bool(b)
35 }
36}
37
38fn main() {
39 truth_values::each_const(|[a, b]| {
40 assert_eq!(!(a || b), !a && !b);
41 assert_eq!(!(a && b), !a || !b);
42 });
43
44 let mut exprs = Vec::new();
45 exprs.extend(truth_values::gen_const().map(|[a, b]| {
46 let x = not(or(a, b));
47 let y = and(not(a), not(b));
48 (x, y)
49 }));
50 exprs.extend(truth_values::gen_const().map(|[a, b]| {
51 let x = not(and(a, b));
52 let y = or(not(a), not(b));
53 (x, y)
54 }));
55
56 for (x, y) in exprs {
57 println!("{} = {:?}", x.eval(), x);
58 println!("{} = {:?}", y.eval(), y);
59 println!();
60
61 assert_eq!(x.eval(), y.eval());
62 }
63}