1use crate::model::Expression;
8use crate::types::Type;
9use serde::{Deserialize, Serialize};
10use std::collections::BTreeMap;
11
12#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
14pub enum Value {
15 Bool(bool),
17 U64(u64),
19 U128(u128),
21 I64(i64),
23 Address(String),
25}
26
27impl Value {
28 pub fn get_type(&self) -> Type {
30 match self {
31 Self::Bool(_) => Type::Bool,
32 Self::U64(_) => Type::U64,
33 Self::U128(_) => Type::U128,
34 Self::I64(_) => Type::I64,
35 Self::Address(_) => Type::Address,
36 }
37 }
38
39 pub fn to_bool(&self) -> Result<bool, EvaluationError> {
41 match self {
42 Self::Bool(b) => Ok(*b),
43 Self::U64(n) => Ok(*n != 0),
44 Self::U128(n) => Ok(*n != 0),
45 Self::I64(n) => Ok(*n != 0),
46 Self::Address(a) => Ok(!a.is_empty()),
47 }
48 }
49
50 #[allow(dead_code)]
52 fn as_u64(&self) -> Result<u64, EvaluationError> {
53 match self {
54 Self::U64(n) => Ok(*n),
55 Self::U128(n) => {
56 if *n <= u64::MAX as u128 {
57 Ok(*n as u64)
58 } else {
59 Err(EvaluationError::ConversionOverflow)
60 }
61 }
62 Self::I64(n) => {
63 if *n >= 0 {
64 Ok(*n as u64)
65 } else {
66 Err(EvaluationError::ConversionOverflow)
67 }
68 }
69 _ => Err(EvaluationError::TypeError),
70 }
71 }
72
73 #[allow(dead_code)]
74 fn as_i64(&self) -> Result<i64, EvaluationError> {
75 match self {
76 Self::I64(n) => Ok(*n),
77 Self::U64(n) => {
78 if *n <= i64::MAX as u64 {
79 Ok(*n as i64)
80 } else {
81 Err(EvaluationError::ConversionOverflow)
82 }
83 }
84 _ => Err(EvaluationError::TypeError),
85 }
86 }
87}
88
89impl std::fmt::Display for Value {
90 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
91 match self {
92 Self::Bool(b) => write!(f, "{}", b),
93 Self::U64(n) => write!(f, "{}", n),
94 Self::U128(n) => write!(f, "{}", n),
95 Self::I64(n) => write!(f, "{}", n),
96 Self::Address(a) => write!(f, "{}", a),
97 }
98 }
99}
100
101#[derive(Debug, Clone, PartialEq, Eq)]
103pub enum EvaluationError {
104 Overflow,
106 Underflow,
108 TypeError,
110 DivisionByZero,
112 UndefinedVariable(String),
114 UndefinedFunction(String),
116 InvalidArgument(String),
118 ConversionOverflow,
120 Custom(String),
122}
123
124impl std::fmt::Display for EvaluationError {
125 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
126 match self {
127 Self::Overflow => write!(f, "arithmetic overflow"),
128 Self::Underflow => write!(f, "arithmetic underflow"),
129 Self::TypeError => write!(f, "type error"),
130 Self::DivisionByZero => write!(f, "division by zero"),
131 Self::UndefinedVariable(name) => write!(f, "undefined variable '{}'", name),
132 Self::UndefinedFunction(name) => write!(f, "undefined function '{}'", name),
133 Self::InvalidArgument(msg) => write!(f, "invalid argument: {}", msg),
134 Self::ConversionOverflow => write!(f, "conversion overflow"),
135 Self::Custom(msg) => write!(f, "{}", msg),
136 }
137 }
138}
139
140pub type EvalResult<T> = Result<T, EvaluationError>;
142
143pub type EvalFunction = fn(&[Value]) -> EvalResult<Value>;
145
146pub struct ExecutionContext {
148 pub state_vars: BTreeMap<String, Value>,
150 pub functions: BTreeMap<String, EvalFunction>,
152}
153
154impl ExecutionContext {
155 pub fn new() -> Self {
157 Self {
158 state_vars: BTreeMap::new(),
159 functions: BTreeMap::new(),
160 }
161 }
162
163 pub fn set_state(&mut self, name: String, value: Value) {
165 self.state_vars.insert(name, value);
166 }
167
168 pub fn register_function(&mut self, name: String, func: fn(&[Value]) -> EvalResult<Value>) {
170 self.functions.insert(name, func);
171 }
172}
173
174impl Default for ExecutionContext {
175 fn default() -> Self {
176 Self::new()
177 }
178}
179
180pub struct Evaluator {
182 context: ExecutionContext,
183}
184
185impl Evaluator {
186 pub fn new(context: ExecutionContext) -> Self {
188 Self { context }
189 }
190
191 pub fn evaluate(&self, expr: &Expression) -> EvalResult<Value> {
193 match expr {
194 Expression::Boolean(b) => Ok(Value::Bool(*b)),
195
196 Expression::Int(val) => {
197 if *val < 0 {
199 Ok(Value::I64(*val as i64))
200 } else if *val <= u64::MAX as i128 {
201 Ok(Value::U64(*val as u64))
202 } else {
203 Ok(Value::U128(*val as u128))
204 }
205 }
206
207 Expression::Var(name) => self
208 .context
209 .state_vars
210 .get(name)
211 .cloned()
212 .ok_or_else(|| EvaluationError::UndefinedVariable(name.clone())),
213
214 Expression::LayerVar { layer, var } => {
215 let qualified_name = format!("{}::{}", layer, var);
217 self.context
218 .state_vars
219 .get(&qualified_name)
220 .cloned()
221 .or_else(|| self.context.state_vars.get(var).cloned())
222 .ok_or(EvaluationError::UndefinedVariable(qualified_name))
223 }
224
225 Expression::PhaseQualifiedVar { phase, layer, var } => {
226 let qualified_name = format!("{}::{}::{}", phase, layer, var);
229 self.context
230 .state_vars
231 .get(&qualified_name)
232 .cloned()
233 .or_else(|| {
234 let layer_var = format!("{}::{}", layer, var);
235 self.context.state_vars.get(&layer_var).cloned()
236 })
237 .or_else(|| self.context.state_vars.get(var).cloned())
238 .ok_or(EvaluationError::UndefinedVariable(qualified_name))
239 }
240
241 Expression::PhaseConstraint {
242 phase: _,
243 constraint,
244 } => {
245 self.evaluate(constraint)
248 }
249
250 Expression::CrossPhaseRelation {
251 phase1: _,
252 expr1,
253 phase2: _,
254 expr2,
255 op,
256 } => {
257 let left_val = self.evaluate(expr1)?;
260 let right_val = self.evaluate(expr2)?;
261 self.eval_binary_op(&left_val, op, &right_val)
262 }
263
264 Expression::BinaryOp { left, op, right } => {
265 let left_val = self.evaluate(left)?;
266 let right_val = self.evaluate(right)?;
267 self.eval_binary_op(&left_val, op, &right_val)
268 }
269
270 Expression::Logical { left, op, right } => {
271 use crate::model::LogicalOp;
272
273 let left_val = self.evaluate(left)?.to_bool()?;
274
275 match op {
277 LogicalOp::And => {
278 if !left_val {
279 return Ok(Value::Bool(false));
280 }
281 let right_val = self.evaluate(right)?.to_bool()?;
282 Ok(Value::Bool(right_val))
283 }
284 LogicalOp::Or => {
285 if left_val {
286 return Ok(Value::Bool(true));
287 }
288 let right_val = self.evaluate(right)?.to_bool()?;
289 Ok(Value::Bool(right_val))
290 }
291 }
292 }
293
294 Expression::Not(expr) => {
295 let val = self.evaluate(expr)?.to_bool()?;
296 Ok(Value::Bool(!val))
297 }
298
299 Expression::FunctionCall { name, args } => {
300 let func = self
301 .context
302 .functions
303 .get(name)
304 .ok_or_else(|| EvaluationError::UndefinedFunction(name.clone()))?;
305
306 let arg_vals: EvalResult<Vec<Value>> =
307 args.iter().map(|arg| self.evaluate(arg)).collect();
308
309 func(&arg_vals?)
310 }
311
312 Expression::Tuple(exprs) => {
313 if exprs.is_empty() {
315 Ok(Value::Bool(true))
316 } else {
317 self.evaluate(&exprs[0])
318 }
319 }
320 }
321 }
322
323 fn eval_binary_op(
325 &self,
326 left: &Value,
327 op: &crate::model::BinaryOp,
328 right: &Value,
329 ) -> EvalResult<Value> {
330 use crate::model::BinaryOp;
331
332 match op {
333 BinaryOp::Eq => Ok(Value::Bool(left == right)),
334
335 BinaryOp::Neq => Ok(Value::Bool(left != right)),
336
337 BinaryOp::Lt => match (left, right) {
338 (Value::U64(l), Value::U64(r)) => Ok(Value::Bool(l < r)),
339 (Value::I64(l), Value::I64(r)) => Ok(Value::Bool(l < r)),
340 (Value::U128(l), Value::U128(r)) => Ok(Value::Bool(l < r)),
341 _ => Err(EvaluationError::TypeError),
342 },
343
344 BinaryOp::Gt => match (left, right) {
345 (Value::U64(l), Value::U64(r)) => Ok(Value::Bool(l > r)),
346 (Value::I64(l), Value::I64(r)) => Ok(Value::Bool(l > r)),
347 (Value::U128(l), Value::U128(r)) => Ok(Value::Bool(l > r)),
348 _ => Err(EvaluationError::TypeError),
349 },
350
351 BinaryOp::Lte => match (left, right) {
352 (Value::U64(l), Value::U64(r)) => Ok(Value::Bool(l <= r)),
353 (Value::I64(l), Value::I64(r)) => Ok(Value::Bool(l <= r)),
354 (Value::U128(l), Value::U128(r)) => Ok(Value::Bool(l <= r)),
355 _ => Err(EvaluationError::TypeError),
356 },
357
358 BinaryOp::Gte => match (left, right) {
359 (Value::U64(l), Value::U64(r)) => Ok(Value::Bool(l >= r)),
360 (Value::I64(l), Value::I64(r)) => Ok(Value::Bool(l >= r)),
361 (Value::U128(l), Value::U128(r)) => Ok(Value::Bool(l >= r)),
362 _ => Err(EvaluationError::TypeError),
363 },
364 }
365 }
366}
367
368#[cfg(test)]
369mod tests {
370 use super::*;
371
372 #[test]
373 fn test_value_type_detection() {
374 assert_eq!(Value::Bool(true).get_type(), Type::Bool);
375 assert_eq!(Value::U64(42).get_type(), Type::U64);
376 assert_eq!(Value::I64(-42).get_type(), Type::I64);
377 }
378
379 #[test]
380 fn test_simple_evaluation() {
381 let ctx = ExecutionContext::new();
382 let evaluator = Evaluator::new(ctx);
383
384 let expr = Expression::Boolean(true);
385 let result = evaluator.evaluate(&expr);
386 assert_eq!(result, Ok(Value::Bool(true)));
387 }
388
389 #[test]
390 fn test_state_variable_evaluation() {
391 let mut ctx = ExecutionContext::new();
392 ctx.set_state("balance".to_string(), Value::U64(100));
393
394 let evaluator = Evaluator::new(ctx);
395 let expr = Expression::Var("balance".to_string());
396
397 let result = evaluator.evaluate(&expr);
398 assert_eq!(result, Ok(Value::U64(100)));
399 }
400
401 #[test]
402 fn test_comparison_evaluation() {
403 let ctx = ExecutionContext::new();
404 let evaluator = Evaluator::new(ctx);
405
406 let expr = Expression::BinaryOp {
407 left: Box::new(Expression::Int(10)),
408 op: crate::model::BinaryOp::Lt,
409 right: Box::new(Expression::Int(20)),
410 };
411
412 let result = evaluator.evaluate(&expr);
413 assert_eq!(result, Ok(Value::Bool(true)));
414 }
415
416 #[test]
417 fn test_logical_short_circuit() {
418 let ctx = ExecutionContext::new();
419 let evaluator = Evaluator::new(ctx);
420
421 let expr = Expression::Logical {
423 left: Box::new(Expression::Boolean(false)),
424 op: crate::model::LogicalOp::And,
425 right: Box::new(Expression::Var("undefined".to_string())),
426 };
427
428 let result = evaluator.evaluate(&expr);
429 assert_eq!(result, Ok(Value::Bool(false)));
430 }
431}