Skip to main content

oxilean_codegen/opt_algebraic/
types.rs

1//! Types for the Algebraic Simplification optimisation pass.
2
3use std::collections::HashMap;
4
5/// An algebraic expression tree.
6#[allow(dead_code)]
7#[derive(Debug, Clone, PartialEq, Eq)]
8pub enum AlgExpr {
9    /// An integer constant.
10    Const(i64),
11    /// A named variable.
12    Var(String),
13    /// Addition.
14    Add(Box<AlgExpr>, Box<AlgExpr>),
15    /// Subtraction.
16    Sub(Box<AlgExpr>, Box<AlgExpr>),
17    /// Multiplication.
18    Mul(Box<AlgExpr>, Box<AlgExpr>),
19    /// Integer division.
20    Div(Box<AlgExpr>, Box<AlgExpr>),
21    /// Negation.
22    Neg(Box<AlgExpr>),
23    /// Exponentiation.
24    Pow(Box<AlgExpr>, Box<AlgExpr>),
25    /// Integer modulo.
26    Mod(Box<AlgExpr>, Box<AlgExpr>),
27}
28
29/// An algebraic identity / rewrite rule (stored as human-readable strings for
30/// reporting purposes; actual application is performed programmatically).
31#[allow(dead_code)]
32#[derive(Debug, Clone)]
33pub struct SimplRule {
34    /// Short name identifying the rule (e.g. `"add_zero"`).
35    pub name: String,
36    /// The pattern this rule matches (e.g. `"x + 0"`).
37    pub pattern: String,
38    /// The replacement this rule produces (e.g. `"x"`).
39    pub replacement: String,
40}
41
42impl SimplRule {
43    /// Construct a new rule with the given name, pattern, and replacement.
44    pub fn new(
45        name: impl Into<String>,
46        pattern: impl Into<String>,
47        replacement: impl Into<String>,
48    ) -> Self {
49        SimplRule {
50            name: name.into(),
51            pattern: pattern.into(),
52            replacement: replacement.into(),
53        }
54    }
55}
56
57/// The result of simplifying an expression.
58#[allow(dead_code)]
59#[derive(Debug, Clone)]
60pub struct SimplResult {
61    /// The simplified expression.
62    pub expr: AlgExpr,
63    /// Human-readable description of each simplification step applied.
64    pub steps: Vec<String>,
65    /// `true` if at least one simplification was applied.
66    pub reduced: bool,
67}
68
69/// Configuration for the algebraic simplification pass.
70#[allow(dead_code)]
71#[derive(Debug, Clone)]
72pub struct AlgSimplConfig {
73    /// Maximum number of simplification passes to perform.
74    pub max_passes: usize,
75    /// Whether to evaluate constant sub-expressions eagerly.
76    pub fold_constants: bool,
77    /// Whether to expand products (e.g. `(a+b)*c = a*c + b*c`).
78    pub expand: bool,
79    /// Whether to factorise expressions (e.g. `a*c + b*c = (a+b)*c`).
80    pub factor: bool,
81}
82
83impl Default for AlgSimplConfig {
84    fn default() -> Self {
85        AlgSimplConfig {
86            max_passes: 20,
87            fold_constants: true,
88            expand: false,
89            factor: false,
90        }
91    }
92}
93
94/// Statistics gathered by the simplification pass.
95#[allow(dead_code)]
96#[derive(Debug, Clone, Default)]
97pub struct SimplStats {
98    /// Total number of identity rules applied.
99    pub rules_applied: usize,
100    /// Number of full simplification passes completed.
101    pub passes_completed: usize,
102    /// Node count of the expression before simplification.
103    pub size_before: usize,
104    /// Node count of the expression after simplification.
105    pub size_after: usize,
106}
107
108/// All built-in algebraic rewrite rules.
109pub fn builtin_rules() -> Vec<SimplRule> {
110    vec![
111        SimplRule::new("add_zero_right", "x + 0", "x"),
112        SimplRule::new("add_zero_left", "0 + x", "x"),
113        SimplRule::new("mul_one_right", "x * 1", "x"),
114        SimplRule::new("mul_one_left", "1 * x", "x"),
115        SimplRule::new("mul_zero_right", "x * 0", "0"),
116        SimplRule::new("mul_zero_left", "0 * x", "0"),
117        SimplRule::new("sub_zero", "x - 0", "x"),
118        SimplRule::new("add_self", "x + x", "2*x"),
119        SimplRule::new("sub_self", "x - x", "0"),
120        SimplRule::new("div_self", "x / x", "1"),
121        SimplRule::new("neg_zero", "0 - x", "-x"),
122        SimplRule::new("double_neg", "-(-x)", "x"),
123        SimplRule::new("pow_zero", "x ^ 0", "1"),
124        SimplRule::new("pow_one", "x ^ 1", "x"),
125        SimplRule::new("zero_pow", "0 ^ x", "0"),
126    ]
127}