use argus_core::prelude::*; use argus_core::signals::traits::{SignalAbs, TrySignalCast}; use num_traits::{Num, NumCast}; use crate::Trace; pub fn eval_num_expr(root: &NumExpr, trace: &impl Trace) -> ArgusResult> where T: Num + NumCast, Signal: TrySignalCast>, Signal: TrySignalCast>, Signal: TrySignalCast>, for<'a> &'a Signal: std::ops::Neg>, for<'a> &'a Signal: std::ops::Add<&'a Signal, Output = Signal>, for<'a> &'a Signal: std::ops::Sub<&'a Signal, Output = Signal>, for<'a> &'a Signal: std::ops::Mul<&'a Signal, Output = Signal>, for<'a> &'a Signal: std::ops::Div<&'a Signal, Output = Signal>, Signal: SignalAbs, { match root { NumExpr::IntLit(val) => Signal::constant(*val).try_cast(), NumExpr::UIntLit(val) => Signal::constant(*val).try_cast(), NumExpr::FloatLit(val) => Signal::constant(*val).try_cast(), NumExpr::IntVar { name } => trace.get::(name.as_str()).unwrap().try_cast(), NumExpr::UIntVar { name } => trace.get::(name.as_str()).unwrap().try_cast(), NumExpr::FloatVar { name } => trace.get::(name.as_str()).unwrap().try_cast(), NumExpr::Neg { arg } => eval_num_expr(arg, trace).map(|sig| -&sig), NumExpr::Add { args } => { let mut ret: Signal = Signal::::zero(); for arg in args.iter() { let arg = eval_num_expr(arg, trace)?; ret = &ret + &arg; } Ok(ret) } NumExpr::Sub { lhs, rhs } => { let lhs = eval_num_expr(lhs, trace)?; let rhs = eval_num_expr(rhs, trace)?; Ok(&lhs - &rhs) } NumExpr::Mul { args } => { let mut ret: Signal = Signal::::one(); for arg in args.iter() { let arg = eval_num_expr(arg, trace)?; ret = &ret * &arg; } Ok(ret) } NumExpr::Div { dividend, divisor } => { let dividend = eval_num_expr(dividend, trace)?; let divisor = eval_num_expr(divisor, trace)?; Ok(÷nd / &divisor) } NumExpr::Abs { arg } => { let arg = eval_num_expr(arg, trace)?; Ok(arg.abs()) } } }