Skip to main content

cp_ast_core/constraint/
expression.rs

1use super::types::ArithOp;
2use crate::structure::{Ident, Reference};
3
4/// Expression in constraints — represents numeric formulas.
5///
6/// Rev.1: 5 variants replacing the old 4.
7/// Lit/Var/BinOp/Pow/FnCall.
8#[derive(Debug, Clone, PartialEq)]
9pub enum Expression {
10    /// Integer literal: 1, 42, 1000000007.
11    Lit(i64),
12    /// Variable reference, such as `N` or `A[i]`.
13    Var(Reference),
14    /// Binary arithmetic: lhs op rhs.
15    BinOp {
16        op: ArithOp,
17        lhs: Box<Expression>,
18        rhs: Box<Expression>,
19    },
20    /// Power: base^exp (e.g., 10^9, 2^30).
21    Pow {
22        base: Box<Expression>,
23        exp: Box<Expression>,
24    },
25    /// Function call: min(a,b), max(a,b), abs(x), len(arr).
26    FnCall { name: Ident, args: Vec<Expression> },
27}
28
29impl Expression {
30    /// Evaluate to a constant if possible (no variable references).
31    #[must_use]
32    pub fn evaluate_constant(&self) -> Option<i64> {
33        match self {
34            Self::Lit(v) => Some(*v),
35            Self::Var(_) | Self::FnCall { .. } => None,
36            Self::BinOp { op, lhs, rhs } => {
37                let l = lhs.evaluate_constant()?;
38                let r = rhs.evaluate_constant()?;
39                match op {
40                    ArithOp::Add => l.checked_add(r),
41                    ArithOp::Sub => l.checked_sub(r),
42                    ArithOp::Mul => l.checked_mul(r),
43                    ArithOp::Div => {
44                        if r == 0 {
45                            None
46                        } else {
47                            l.checked_div(r)
48                        }
49                    }
50                }
51            }
52            Self::Pow { base, exp } => {
53                let b = base.evaluate_constant()?;
54                let e = exp.evaluate_constant()?;
55                let e_u32 = u32::try_from(e).ok()?;
56                b.checked_pow(e_u32)
57            }
58        }
59    }
60}