extern crate alloc;
use crate::engine::parse_expression;
use crate::error::Result;
use crate::eval::eval_ast;
use crate::{EvalContext, Real};
use alloc::rc::Rc;
use bumpalo::Bump;
pub struct Evaluator {
arena: Bump,
}
impl Evaluator {
pub fn new() -> Self {
Self { arena: Bump::new() }
}
pub fn with_capacity(capacity: usize) -> Self {
Self {
arena: Bump::with_capacity(capacity),
}
}
pub fn eval(&self, expression: &str) -> Result<Real> {
let ctx = EvalContext::new();
self.eval_with_context(expression, Rc::new(ctx))
}
pub fn eval_with_context(&self, expression: &str, ctx: Rc<EvalContext>) -> Result<Real> {
let ast = parse_expression(expression, &self.arena)?;
eval_ast(&ast, Some(ctx), &self.arena)
}
pub fn reset(&mut self) {
self.arena.reset();
}
pub fn allocated_bytes(&self) -> usize {
self.arena.allocated_bytes()
}
}
impl Default for Evaluator {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::TryIntoHeaplessString;
#[test]
fn test_simple_evaluation() {
let evaluator = Evaluator::new();
let result = evaluator.eval("2 + 3 * 4").unwrap();
assert_eq!(result, 14.0);
}
#[test]
fn test_evaluation_with_variables() {
let evaluator = Evaluator::new();
let mut ctx = EvalContext::new();
let _ = ctx.set_parameter("x", 5.0);
let _ = ctx.set_parameter("y", 3.0);
let result = evaluator
.eval_with_context("x * y + 2", Rc::new(ctx))
.unwrap();
assert_eq!(result, 17.0);
}
#[test]
fn test_memory_reset() {
let mut evaluator = Evaluator::with_capacity(1024);
for i in 0..10 {
let expr = format!("{} + {}", i, i);
let _ = evaluator.eval(&expr).unwrap();
}
let bytes_before = evaluator.allocated_bytes();
assert!(bytes_before > 0);
evaluator.reset();
let result = evaluator.eval("42").unwrap();
assert_eq!(result, 42.0);
}
#[test]
fn test_with_constants() {
let evaluator = Evaluator::new();
let mut ctx = EvalContext::new();
ctx.constants
.insert("ANSWER".try_into_heapless().unwrap(), 42.0)
.unwrap();
let result = evaluator
.eval_with_context("ANSWER * 2", Rc::new(ctx))
.unwrap();
assert_eq!(result, 84.0);
}
}