1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
//! Print expression of computations in the flag algebra.

extern crate num;

use std::fmt::*;

/// Expressions that represent a computation in flag algebras.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Expr {
    Add(Box<Expr>, Box<Expr>),
    Mul(Box<Expr>, Box<Expr>),
    Neg(Box<Expr>),
    Unlab(Box<Expr>),
    Zero,
    One,
    Num(String),
    Flag(String),
    Var(usize),
}

impl Expr {
    pub fn add(a: Self, b: Self) -> Self {
        Add(Box::new(a), Box::new(b))
    }
    pub fn mul(a: Self, b: Self) -> Self {
        Mul(Box::new(a), Box::new(b))
    }
    pub fn neg(self) -> Self {
        Neg(Box::new(self))
    }
    pub fn sub(a: Self, b: Self) -> Self {
        Self::add(a, b.neg())
    }
    pub fn unlab(self) -> Self {
        Unlab(Box::new(self))
    }
    pub fn num<N>(n: &N) -> Self
    where
        N: num::Num + Display,
    {
        if n == &N::zero() {
            Zero
        } else if n == &N::one() {
            One
        } else {
            Num(format!("{}", n))
        }
    }
}

use self::Expr::*;

impl Display for Expr {
    fn fmt(&self, f: &mut Formatter) -> Result {
        match self.simplify0() {
            Add(a, b) => {
                if let Neg(b1) = *b {
                    write!(f, "{} - {}", a, b1)
                } else {
                    write!(f, "{} + {}", a, b)
                }
            }
            Mul(a, b) => write!(f, "{}*{}", a, b),
            Neg(a) => write!(f, "-{}", a),
            Unlab(a) => write!(f, "[|{}|]", a),
            Zero => write!(f, "0"),
            One => write!(f, "1"),
            Num(s) => write!(f, "{}", s),
            Flag(s) => write!(f, "{}", s),
            Var(_) => write!(f, "x"),
        }
    }
}

impl Expr {
    fn simplify0(&self) -> Self {
        match self {
            Add(a0, b0) => {
                let a = a0.simplify0();
                let b = b0.simplify0();
                if a == Zero {
                    b
                } else if b == Zero {
                    a
                } else {
                    Expr::add(a, b)
                }
            }
            Mul(a0, b0) => {
                let a = a0.simplify0();
                let b = b0.simplify0();
                if a == One {
                    b
                } else if b == One {
                    a
                } else if a == Zero || b == Zero {
                    Zero
                } else {
                    Expr::mul(a, b)
                }
            }
            Neg(a0) => {
                let a = a0.simplify0();
                if a == Zero {
                    Zero
                } else {
                    Expr::neg(a)
                }
            }
            Unlab(a0) => {
                let a = a0.simplify0();
                if a == Zero {
                    Zero
                } else {
                    Expr::unlab(a)
                }
            }
            a => a.clone(),
        }
    }
}