datalogic_rs/builder/
control_builder.rs

1use crate::arena::DataArena;
2use crate::logic::ControlOp;
3use crate::logic::{Logic, OperatorType};
4
5/// Builder for control flow operations.
6///
7/// This builder provides a fluent interface for creating control flow operations
8/// such as if, and, or, etc.
9pub struct ControlBuilder<'a> {
10    /// The arena in which all allocations will be made.
11    arena: &'a DataArena,
12}
13
14impl<'a> ControlBuilder<'a> {
15    /// Creates a new control flow builder.
16    pub fn new(arena: &'a DataArena) -> Self {
17        Self { arena }
18    }
19
20    /// Creates an 'and' operation.
21    pub fn and_op(&self) -> LogicalOperationBuilder<'a> {
22        LogicalOperationBuilder::new(self.arena, ControlOp::And)
23    }
24
25    /// Creates an 'or' operation.
26    pub fn or_op(&self) -> LogicalOperationBuilder<'a> {
27        LogicalOperationBuilder::new(self.arena, ControlOp::Or)
28    }
29
30    /// Creates a 'not' operation.
31    pub fn not_op(&self, value: Logic<'a>) -> Logic<'a> {
32        Logic::operator(
33            OperatorType::Control(ControlOp::Not),
34            vec![value],
35            self.arena,
36        )
37    }
38
39    /// Creates an 'if' operation builder.
40    pub fn if_op(&self) -> IfBuilder<'a> {
41        IfBuilder::new(self.arena)
42    }
43}
44
45/// Builder for logical operations (AND, OR).
46pub struct LogicalOperationBuilder<'a> {
47    /// The arena in which all allocations will be made.
48    arena: &'a DataArena,
49    /// The logical operation to use.
50    operation: ControlOp,
51    /// The operands collected so far.
52    operands: Vec<Logic<'a>>,
53}
54
55impl<'a> LogicalOperationBuilder<'a> {
56    /// Creates a new logical operation builder.
57    pub fn new(arena: &'a DataArena, operation: ControlOp) -> Self {
58        Self {
59            arena,
60            operation,
61            operands: Vec::new(),
62        }
63    }
64
65    /// Adds an operand to the logical operation.
66    pub fn operand(mut self, operand: Logic<'a>) -> Self {
67        self.operands.push(operand);
68        self
69    }
70
71    /// Adds a variable as an operand to the logical operation.
72    pub fn var(mut self, path: &str) -> Self {
73        let var = Logic::variable(path, None, self.arena);
74        self.operands.push(var);
75        self
76    }
77
78    /// Adds a literal value as an operand to the logical operation.
79    pub fn value<T: Into<crate::value::DataValue<'a>>>(mut self, value: T) -> Self {
80        let val = Logic::literal(value.into(), self.arena);
81        self.operands.push(val);
82        self
83    }
84
85    /// Adds an integer as an operand to the logical operation.
86    pub fn int(mut self, value: i64) -> Self {
87        let val = Logic::literal(crate::value::DataValue::integer(value), self.arena);
88        self.operands.push(val);
89        self
90    }
91
92    /// Adds a float as an operand to the logical operation.
93    pub fn float(mut self, value: f64) -> Self {
94        let val = Logic::literal(crate::value::DataValue::float(value), self.arena);
95        self.operands.push(val);
96        self
97    }
98
99    /// Adds a string as an operand to the logical operation.
100    pub fn string(mut self, value: &str) -> Self {
101        let val = Logic::literal(
102            crate::value::DataValue::string(self.arena, value),
103            self.arena,
104        );
105        self.operands.push(val);
106        self
107    }
108
109    /// Adds a boolean as an operand to the logical operation.
110    pub fn bool(mut self, value: bool) -> Self {
111        let val = Logic::literal(crate::value::DataValue::bool(value), self.arena);
112        self.operands.push(val);
113        self
114    }
115
116    /// Builds the logical operation with the collected operands.
117    ///
118    /// If no operands have been added, it will use a literal true or false
119    /// depending on the operation (true for AND, false for OR).
120    pub fn build(self) -> Logic<'a> {
121        if self.operands.is_empty() {
122            // Default for AND is true, for OR is false
123            let default_value = match self.operation {
124                ControlOp::And => true,
125                ControlOp::Or => false,
126                _ => true, // Shouldn't happen for this builder
127            };
128            return Logic::literal(crate::value::DataValue::bool(default_value), self.arena);
129        }
130
131        Logic::operator(
132            OperatorType::Control(self.operation),
133            self.operands,
134            self.arena,
135        )
136    }
137}
138
139/// Builder for if-then-else operations.
140pub struct IfBuilder<'a> {
141    /// The arena in which all allocations will be made.
142    arena: &'a DataArena,
143    /// The condition.
144    condition: Option<Logic<'a>>,
145    /// The 'then' branch.
146    then_branch: Option<Logic<'a>>,
147    /// The 'else' branch.
148    else_branch: Option<Logic<'a>>,
149}
150
151impl<'a> IfBuilder<'a> {
152    /// Creates a new if-then-else builder.
153    pub fn new(arena: &'a DataArena) -> Self {
154        Self {
155            arena,
156            condition: None,
157            then_branch: None,
158            else_branch: None,
159        }
160    }
161
162    /// Sets the condition for the if-then-else operation.
163    pub fn condition(mut self, condition: Logic<'a>) -> Self {
164        self.condition = Some(condition);
165        self
166    }
167
168    /// Sets the 'then' branch of the if-then-else operation.
169    pub fn then(mut self, then_branch: Logic<'a>) -> Self {
170        self.then_branch = Some(then_branch);
171        self
172    }
173
174    /// Sets the 'else' branch of the if-then-else operation.
175    pub fn else_branch(mut self, else_branch: Logic<'a>) -> Self {
176        self.else_branch = Some(else_branch);
177        self
178    }
179
180    /// Builds the if-then-else operation.
181    ///
182    /// If condition is not set, it will use a literal false.
183    /// If then branch is not set, it will use a literal true.
184    /// If else branch is not set, it will use a literal false.
185    pub fn build(self) -> Logic<'a> {
186        let condition = self
187            .condition
188            .unwrap_or_else(|| Logic::literal(crate::value::DataValue::bool(false), self.arena));
189
190        let then_branch = self
191            .then_branch
192            .unwrap_or_else(|| Logic::literal(crate::value::DataValue::bool(true), self.arena));
193
194        let else_branch = self
195            .else_branch
196            .unwrap_or_else(|| Logic::literal(crate::value::DataValue::bool(false), self.arena));
197
198        // If-then-else is represented as an array where the first element is the condition,
199        // the second is the then branch, and the third is the else branch.
200        Logic::operator(
201            OperatorType::Control(ControlOp::If),
202            vec![condition, then_branch, else_branch],
203            self.arena,
204        )
205    }
206}