Skip to main content

shape_ast/ast/
operators.rs

1//! Operator types for Shape AST
2
3use serde::{Deserialize, Serialize};
4
5/// Kind of range: exclusive (..) or inclusive (..=)
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
7pub enum RangeKind {
8    /// Exclusive range: start..end (excludes end)
9    Exclusive,
10    /// Inclusive range: start..=end (includes end)
11    Inclusive,
12}
13
14#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
15pub enum BinaryOp {
16    // Arithmetic
17    Add,
18    Sub,
19    Mul,
20    Div,
21    Mod,
22    Pow,
23
24    // Comparison
25    Greater,
26    Less,
27    GreaterEq,
28    LessEq,
29    Equal,
30    NotEqual,
31
32    // Fuzzy comparison
33    FuzzyEqual,   // ~=
34    FuzzyGreater, // ~>
35    FuzzyLess,    // ~<
36
37    // Bitwise
38    BitAnd,
39    BitOr,
40    BitXor,
41    BitShl,
42    BitShr,
43
44    // Logical
45    And,
46    Or,
47
48    // Null handling
49    NullCoalesce, // ??
50    ErrorContext, // !!
51
52    // Pipeline
53    Pipe, // |>
54}
55
56#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
57pub enum UnaryOp {
58    Not,
59    Neg,
60    BitNot,
61}
62
63/// Tolerance specification for fuzzy comparisons
64/// Used with `within` syntax: `a ~= b within 0.02` or `a ~= b within 2%`
65#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
66pub enum FuzzyTolerance {
67    /// Absolute tolerance: `within 5` means |a - b| <= 5
68    Absolute(f64),
69    /// Percentage tolerance: `within 2%` means |a - b| / avg(|a|, |b|) <= 0.02
70    Percentage(f64),
71}
72
73impl FuzzyTolerance {
74    /// Check if two values are within tolerance
75    pub fn is_within(&self, a: f64, b: f64) -> bool {
76        let diff = (a - b).abs();
77        match self {
78            FuzzyTolerance::Absolute(tol) => diff <= *tol,
79            FuzzyTolerance::Percentage(pct) => {
80                let avg = (a.abs() + b.abs()) / 2.0;
81                if avg == 0.0 {
82                    diff == 0.0
83                } else {
84                    diff / avg <= *pct
85                }
86            }
87        }
88    }
89
90    /// Get the tolerance value (percentage in 0-1 form, or absolute)
91    pub fn value(&self) -> f64 {
92        match self {
93            FuzzyTolerance::Absolute(v) | FuzzyTolerance::Percentage(v) => *v,
94        }
95    }
96}
97
98/// Fuzzy comparison operator type
99#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
100pub enum FuzzyOp {
101    /// Fuzzy equal: ~=
102    Equal,
103    /// Fuzzy greater: ~>
104    Greater,
105    /// Fuzzy less: ~<
106    Less,
107}