use evalexpr::{DefaultNumericTypes, HashMapContext, Node, Value};
use crate::prelude::*;
#[derive(Debug, Clone)]
pub struct Expression {
pub(crate) definition: String,
pub(crate) compiled: Node<DefaultNumericTypes>,
}
impl Expression {
pub fn new(expression: &str) -> StatResult<Self> {
let compiled = evalexpr::build_operator_tree(expression)
.map_err(|err| StatError::ExpressionError {
expression: expression.to_string(),
details: err.to_string(),
})?;
Ok(Self {
definition: expression.to_string(),
compiled,
})
}
pub(crate) fn evaluate(&self, context: &HashMapContext) -> f32 {
self.compiled
.eval_with_context(context)
.unwrap_or(Value::Float(0.0))
.as_number()
.unwrap_or(0.0) as f32
}
}
impl PartialEq for Expression {
fn eq(&self, other: &Self) -> bool {
self.definition == other.definition
}
}
#[derive(Debug, Clone)]
pub enum ModifierType {
Literal(f32),
Expression(Expression),
}
impl Default for ModifierType {
fn default() -> Self {
Self::Literal(0.0)
}
}
impl From<Expression> for ModifierType {
fn from(value: Expression) -> Self {
Self::Expression(value)
}
}
impl From<&str> for ModifierType {
fn from(value: &str) -> Self {
Self::Expression(Expression {
definition: value.to_string(),
compiled: evalexpr::build_operator_tree(value).unwrap(),
})
}
}
impl From<String> for ModifierType {
fn from(value: String) -> Self {
Self::Expression(Expression {
definition: value.clone(),
compiled: evalexpr::build_operator_tree(&value).unwrap(),
})
}
}
impl From<f32> for ModifierType {
fn from(value: f32) -> Self {
Self::Literal(value)
}
}
impl From<u32> for ModifierType {
fn from(value: u32) -> Self {
Self::Literal(value as f32)
}
}
impl From<i32> for ModifierType {
fn from(value: i32) -> Self {
Self::Literal(value as f32)
}
}