1
use conjure_core::ast::{Expression, Model};
2
use conjure_core::rule::Rule;
3
use conjure_rules::get_rules;
4

            
5
struct RuleResult<'a> {
6
    rule: Rule<'a>,
7
    new_expression: Expression,
8
}
9

            
10
/// # Returns
11
/// - A new expression after applying the rules to `expression` and its sub-expressions.
12
/// - The same expression if no rules are applicable.
13
pub fn rewrite(expression: &Expression) -> Expression {
14
    let rules = get_rules();
15
    let mut new = expression.clone();
16
    while let Some(step) = rewrite_iteration(&new, &rules) {
17
        new = step;
18
    }
19
    new
20
}
21

            
22
/// # Returns
23
/// - Some(<new_expression>) after applying the first applicable rule to `expr` or a sub-expression.
24
/// - None if no rule is applicable to the expression or any sub-expression.
25
fn rewrite_iteration<'a>(
26
    expression: &'a Expression,
27
    rules: &'a Vec<Rule<'a>>,
28
) -> Option<Expression> {
29
    let rule_results = apply_all_rules(expression, rules);
30
    if let Some(new) = choose_rewrite(&rule_results) {
31
        return Some(new);
32
    } else {
33
        match expression.sub_expressions() {
34
            None => {}
35
            Some(mut sub) => {
36
                for i in 0..sub.len() {
37
                    if let Some(new) = rewrite_iteration(sub[i], rules) {
38
                        sub[i] = &new;
39
                        return Some(expression.with_sub_expressions(sub));
40
                    }
41
                }
42
            }
43
        }
44
    }
45
    None // No rules applicable to this branch of the expression
46
}
47

            
48
/// # Returns
49
/// - A list of RuleResults after applying all rules to `expression`.
50
/// - An empty list if no rules are applicable.
51
fn apply_all_rules<'a>(
52
    expression: &'a Expression,
53
    rules: &'a Vec<Rule<'a>>,
54
) -> Vec<RuleResult<'a>> {
55
    let mut results = Vec::new();
56
    for rule in rules {
57
        match rule.apply(expression) {
58
            Ok(new) => {
59
                results.push(RuleResult {
60
                    rule: rule.clone(),
61
                    new_expression: new,
62
                });
63
            }
64
            Err(_) => continue,
65
        }
66
    }
67
    results
68
}
69

            
70
/// # Returns
71
/// - Some(<new_expression>) after applying the first rule in `results`.
72
/// - None if `results` is empty.
73
fn choose_rewrite(results: &Vec<RuleResult>) -> Option<Expression> {
74
    if results.is_empty() {
75
        return None;
76
    }
77
    // Return the first result for now
78
    // println!("Applying rule: {:?}", results[0].rule);
79
    Some(results[0].new_expression.clone())
80
}
81

            
82
/// This rewrites the model by applying the rules to all constraints.
83
/// # Returns
84
/// - A new model with rewritten constraints.
85
/// - The same model if no rules are applicable.
86
pub fn rewrite_model(model: &Model) -> Model {
87
    let mut new_model = model.clone();
88

            
89
    new_model.constraints = rewrite(&model.constraints);
90

            
91
    new_model
92
}