datalogic_rs/builder/
arithmetic_builder.rs

1use crate::arena::DataArena;
2use crate::logic::ArithmeticOp;
3use crate::logic::{Logic, OperatorType};
4
5/// Builder for arithmetic operations.
6///
7/// This builder provides a fluent interface for creating arithmetic operations
8/// such as addition, subtraction, multiplication, etc.
9pub struct ArithmeticBuilder<'a> {
10    /// The arena in which all allocations will be made.
11    arena: &'a DataArena,
12}
13
14impl<'a> ArithmeticBuilder<'a> {
15    /// Creates a new arithmetic builder.
16    pub fn new(arena: &'a DataArena) -> Self {
17        Self { arena }
18    }
19
20    /// Creates an addition operation.
21    pub fn add_op(&self) -> ArithmeticOperationBuilder<'a> {
22        ArithmeticOperationBuilder::new(self.arena, ArithmeticOp::Add)
23    }
24
25    /// Creates a subtraction operation.
26    pub fn subtract_op(&self) -> ArithmeticOperationBuilder<'a> {
27        ArithmeticOperationBuilder::new(self.arena, ArithmeticOp::Subtract)
28    }
29
30    /// Creates a multiplication operation.
31    pub fn multiply_op(&self) -> ArithmeticOperationBuilder<'a> {
32        ArithmeticOperationBuilder::new(self.arena, ArithmeticOp::Multiply)
33    }
34
35    /// Creates a division operation.
36    pub fn divide_op(&self) -> ArithmeticOperationBuilder<'a> {
37        ArithmeticOperationBuilder::new(self.arena, ArithmeticOp::Divide)
38    }
39
40    /// Creates a modulo operation.
41    pub fn modulo_op(&self) -> ArithmeticOperationBuilder<'a> {
42        ArithmeticOperationBuilder::new(self.arena, ArithmeticOp::Modulo)
43    }
44
45    /// Creates a minimum operation.
46    pub fn min_op(&self) -> ArithmeticOperationBuilder<'a> {
47        ArithmeticOperationBuilder::new(self.arena, ArithmeticOp::Min)
48    }
49
50    /// Creates a maximum operation.
51    pub fn max_op(&self) -> ArithmeticOperationBuilder<'a> {
52        ArithmeticOperationBuilder::new(self.arena, ArithmeticOp::Max)
53    }
54
55    /// Creates an absolute value operation.
56    pub fn abs_op(&self) -> ArithmeticOperationBuilder<'a> {
57        ArithmeticOperationBuilder::new(self.arena, ArithmeticOp::Abs)
58    }
59
60    /// Creates a ceiling operation.
61    pub fn ceil_op(&self) -> ArithmeticOperationBuilder<'a> {
62        ArithmeticOperationBuilder::new(self.arena, ArithmeticOp::Ceil)
63    }
64
65    /// Creates a floor operation.
66    pub fn floor_op(&self) -> ArithmeticOperationBuilder<'a> {
67        ArithmeticOperationBuilder::new(self.arena, ArithmeticOp::Floor)
68    }
69}
70
71/// Builder for an arithmetic operation with its operands.
72pub struct ArithmeticOperationBuilder<'a> {
73    /// The arena in which all allocations will be made.
74    arena: &'a DataArena,
75    /// The arithmetic operation to use.
76    operation: ArithmeticOp,
77    /// The operands collected so far.
78    operands: Vec<Logic<'a>>,
79}
80
81impl<'a> ArithmeticOperationBuilder<'a> {
82    /// Creates a new arithmetic operation builder.
83    pub fn new(arena: &'a DataArena, operation: ArithmeticOp) -> Self {
84        Self {
85            arena,
86            operation,
87            operands: Vec::new(),
88        }
89    }
90
91    /// Adds an operand to the arithmetic operation.
92    pub fn operand(mut self, operand: Logic<'a>) -> Self {
93        self.operands.push(operand);
94        self
95    }
96
97    /// Adds a variable as an operand to the arithmetic operation.
98    pub fn var(mut self, path: &str) -> Self {
99        let var = Logic::variable(path, None, self.arena);
100        self.operands.push(var);
101        self
102    }
103
104    /// Adds a literal value as an operand to the arithmetic operation.
105    pub fn value<T: Into<crate::value::DataValue<'a>>>(mut self, value: T) -> Self {
106        let val = Logic::literal(value.into(), self.arena);
107        self.operands.push(val);
108        self
109    }
110
111    /// Adds an integer value as an operand to the arithmetic operation.
112    pub fn int(mut self, value: i64) -> Self {
113        let val = Logic::literal(crate::value::DataValue::integer(value), self.arena);
114        self.operands.push(val);
115        self
116    }
117
118    /// Adds a float value as an operand to the arithmetic operation.
119    pub fn float(mut self, value: f64) -> Self {
120        let val = Logic::literal(crate::value::DataValue::float(value), self.arena);
121        self.operands.push(val);
122        self
123    }
124
125    /// Adds a string value as an operand to the arithmetic operation.
126    pub fn string(mut self, value: &str) -> Self {
127        let val = Logic::literal(
128            crate::value::DataValue::string(self.arena, value),
129            self.arena,
130        );
131        self.operands.push(val);
132        self
133    }
134
135    /// Adds a boolean value as an operand to the arithmetic operation.
136    pub fn bool(mut self, value: bool) -> Self {
137        let val = Logic::literal(crate::value::DataValue::bool(value), self.arena);
138        self.operands.push(val);
139        self
140    }
141
142    /// Builds the arithmetic operation with the collected operands.
143    ///
144    /// If no operands have been added, it will use appropriate defaults:
145    /// - For addition: 0
146    /// - For multiplication: 1
147    /// - For others: 0
148    pub fn build(self) -> Logic<'a> {
149        if self.operands.is_empty() {
150            // Default for different operations
151            let default_value = match self.operation {
152                ArithmeticOp::Add => 0i64,
153                ArithmeticOp::Multiply => 1i64,
154                _ => 0i64,
155            };
156            return Logic::literal(crate::value::DataValue::integer(default_value), self.arena);
157        }
158
159        // For unary operations, handle them specially
160        if self.operands.len() == 1 {
161            match self.operation {
162                ArithmeticOp::Subtract => {
163                    // Unary minus: [-, x] means -x (negate)
164                    let zero = Logic::literal(crate::value::DataValue::integer(0), self.arena);
165                    return Logic::operator(
166                        OperatorType::Arithmetic(self.operation),
167                        vec![zero, self.operands[0].clone()],
168                        self.arena,
169                    );
170                }
171                _ => {
172                    // For other operations, just return the operand for unary case
173                    return self.operands[0].clone();
174                }
175            }
176        }
177
178        Logic::operator(
179            OperatorType::Arithmetic(self.operation),
180            self.operands,
181            self.arena,
182        )
183    }
184}