1
use conjure_cp::ast::Metadata;
2
use conjure_cp::ast::{Expression as Expr, Moo, SymbolTable};
3
use conjure_cp::into_matrix_expr;
4
use conjure_cp::rule_engine::{
5
    ApplicationError::RuleNotApplicable, ApplicationResult, Reduction, register_rule,
6
};
7

            
8
/// Removes a dimension from a matrix indexing operation, if the subject of the indexing is a
9
/// matrix literal.
10
///
11
/// ```plain
12
/// [[1,2,3],[4,5,6],[7,8,9]][j,i] ~~> [[1,2,3][i],[4,5,6][i],[7,8,9][i]][j]
13
/// ```
14
#[register_rule(("Base", 2000))]
15
24944
fn remove_dimension_from_matrix_indexing(expr: &Expr, _: &SymbolTable) -> ApplicationResult {
16
24944
    let Expr::SafeIndex(_, subject, mut indices) = expr.clone() else {
17
22361
        return Err(RuleNotApplicable);
18
    };
19

            
20
2583
    if indices.len() < 2 {
21
657
        return Err(RuleNotApplicable);
22
1926
    };
23

            
24
    // the indicies to use in the replacement expression.
25
1926
    let outer_indices = vec![indices.pop().unwrap()];
26

            
27
    // the indicies to use in the inner expressions.
28
1926
    let inner_indices = indices;
29

            
30
1926
    let (mut es, index_domain) = Moo::unwrap_or_clone(subject)
31
1926
        .unwrap_matrix_unchecked()
32
1926
        .ok_or(RuleNotApplicable)?;
33

            
34
36
    for e in es.iter_mut() {
35
36
        *e = Expr::SafeIndex(Metadata::new(), Moo::new(e.clone()), inner_indices.clone());
36
36
    }
37

            
38
12
    Ok(Reduction::pure(Expr::SafeIndex(
39
12
        Metadata::new(),
40
12
        Moo::new(into_matrix_expr![es;index_domain]),
41
12
        outer_indices,
42
12
    )))
43
24944
}