1
#![forbid(unsafe_code)]
2

            
3
use std::fmt;
4

            
5
use itertools::Itertools;
6
use merc_data::DataExpression;
7

            
8
/// A rewrite specification is a set of rewrite rules, given by [Rule].
9
#[derive(Debug, Default, Clone)]
10
pub struct RewriteSpecification {
11
    rewrite_rules: Vec<Rule>,
12
}
13

            
14
impl RewriteSpecification {
15
    /// Create a new, empty rewrite specification.
16
31
    pub fn new(rewrite_rules: Vec<Rule>) -> RewriteSpecification {
17
31
        RewriteSpecification { rewrite_rules }
18
31
    }
19

            
20
    /// Returns the rewrite rules of this specification.
21
57
    pub fn rewrite_rules(&self) -> &[Rule] {
22
57
        &self.rewrite_rules
23
57
    }
24
}
25

            
26
/// A condition of a conditional rewrite rule.
27
///
28
/// Either `lhs == rhs` or `lhs != rhs` depending on equality being true.
29
#[derive(Clone, Debug, Eq, Hash, PartialEq, Ord, PartialOrd)]
30
pub struct Condition {
31
    pub lhs: DataExpression,
32
    pub rhs: DataExpression,
33
    pub equality: bool,
34
}
35

            
36
/// A rewrite rule.
37
#[derive(Debug, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
38
pub struct Rule {
39
    /// A conjunction of clauses
40
    pub conditions: Vec<Condition>,
41
    pub lhs: DataExpression,
42
    pub rhs: DataExpression,
43
}
44

            
45
impl fmt::Display for RewriteSpecification {
46
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
47
        for rule in &self.rewrite_rules {
48
            writeln!(f, "{rule}")?;
49
        }
50
        Ok(())
51
    }
52
}
53

            
54
impl fmt::Display for Rule {
55
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56
        if self.conditions.is_empty() {
57
            write!(f, "{} = {}", self.lhs, self.rhs)
58
        } else {
59
            write!(
60
                f,
61
                "{} -> {} = {}",
62
                self.conditions.iter().format(", "),
63
                self.lhs,
64
                self.rhs
65
            )
66
        }
67
    }
68
}
69

            
70
impl fmt::Display for Condition {
71
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
72
        if self.equality {
73
            write!(f, "{} == {}", self.lhs, self.rhs)
74
        } else {
75
            write!(f, "{} <> {}", self.lhs, self.rhs)
76
        }
77
    }
78
}