1
//! Normalising rules for `Neq` and `Eq`.
2

            
3
use conjure_cp::ast::{Expression as Expr, SymbolTable, Typeable};
4
use conjure_cp::rule_engine::{
5
    ApplicationError::RuleNotApplicable, ApplicationResult, Reduction, register_rule,
6
};
7

            
8
use conjure_cp::ast::ReturnType::{Matrix, Set};
9
use conjure_cp::essence_expr;
10

            
11
/// Converts a negated `Neq` to an `Eq`
12
///
13
/// ```text
14
/// not(neq(x)) ~> eq(x)
15
/// ```
16
#[register_rule(("Base", 8800))]
17
fn negated_neq_to_eq(expr: &Expr, _: &SymbolTable) -> ApplicationResult {
18
    match expr {
19
        Expr::Not(_, a) => match a.as_ref() {
20
            Expr::Neq(_, b, c) if (b.is_safe() && c.is_safe()) => {
21
                Ok(Reduction::pure(essence_expr!(&b = &c)))
22
            }
23
            _ => Err(RuleNotApplicable),
24
        },
25
        _ => Err(RuleNotApplicable),
26
    }
27
}
28

            
29
/// Converts a negated `Eq` to an `Neq`
30
///
31
/// ```text
32
/// not(eq(x)) ~> neq(x)
33
/// ```
34
/// don't want this to apply to sets
35
///
36
/// Also can't apply to matrices, since undefinedness between two matrices with different domains
37
/// causes a != b to actually have a different meaning than !(a = b)
38
#[register_rule(("Base", 8800))]
39
fn negated_eq_to_neq(expr: &Expr, _: &SymbolTable) -> ApplicationResult {
40
    match expr {
41
        Expr::Not(_, a) => match a.as_ref() {
42
            Expr::Eq(_, b, c) if (b.is_safe() && c.is_safe()) => {
43
                if matches!(b.as_ref().return_type(), Set(_) | Matrix(_)) {
44
                    return Err(RuleNotApplicable);
45
                }
46
                if matches!(c.as_ref().return_type(), Set(_) | Matrix(_)) {
47
                    return Err(RuleNotApplicable);
48
                }
49
                Ok(Reduction::pure(essence_expr!(&b != &c)))
50
            }
51
            _ => Err(RuleNotApplicable),
52
        },
53
        _ => Err(RuleNotApplicable),
54
    }
55
}