use std::process::Output;
use std::sync::Arc;
use crate::evaluator::{ExpressionEvaluator, EvaluationError, Session, GlobalVariables};
use crate::function_registry::{FunctionRegistry, ScalarFunction, Function};
use crate::{functions, lexer, models};
use crate::models::DataValue;
pub struct PowerFxEngine {
function_registry: Arc<FunctionRegistry>,
evaluator: Arc<ExpressionEvaluator>,
}
impl PowerFxEngine {
pub fn new() -> PowerFxEngine {
let function_registry = Arc::new(FunctionRegistry::new());
let evaluator = Arc::new(ExpressionEvaluator::new(function_registry.clone()));
function_registry.register_function("Table", Function::Scalar(Arc::new(functions::table::Table::new(evaluator.clone()))));
function_registry.register_function("First", Function::Scalar(Arc::new(functions::table::First::new(evaluator.clone()))));
function_registry.register_function("Last", Function::Scalar(Arc::new(functions::table::Last::new(evaluator.clone()))));
function_registry.register_function("Index", Function::Scalar(Arc::new(functions::table::Index::new(evaluator.clone()))));
function_registry.register_function("Filter", Function::Scalar(Arc::new(functions::table::Filter::new(evaluator.clone()))));
function_registry.register_function("Set", Function::Scalar(Arc::new(functions::context::Set::new(evaluator.clone()))));
function_registry.register_function("If", Function::Scalar(Arc::new(functions::logical::If::new(evaluator.clone()))));
function_registry.register_function("And", Function::Scalar(Arc::new(functions::logical::And::new(evaluator.clone()))));
function_registry.register_function("Or", Function::Scalar(Arc::new(functions::logical::Or::new(evaluator.clone()))));
function_registry.register_function("Not", Function::Scalar(Arc::new(functions::logical::Not::new(evaluator.clone()))));
function_registry.register_function("Abs", Function::Scalar(Arc::new(functions::math::Abs::new(evaluator.clone()))));
function_registry.register_function("Sqrt", Function::Scalar(Arc::new(functions::math::Sqrt::new(evaluator.clone()))));
function_registry.register_function("Left", Function::Scalar(Arc::new(functions::text::Left::new(evaluator.clone()))));
function_registry.register_function("Mid", Function::Scalar(Arc::new(functions::text::Mid::new(evaluator.clone()))));
function_registry.register_function("Right", Function::Scalar(Arc::new(functions::text::Right::new(evaluator.clone()))));
function_registry.register_function("Upper", Function::Scalar(Arc::new(functions::text::Upper::new(evaluator.clone()))));
function_registry.register_function("Lower", Function::Scalar(Arc::new(functions::text::Lower::new(evaluator.clone()))));
function_registry.register_function("Average", Function::Scalar(Arc::new(functions::aggregation::Average::new(evaluator.clone()))));
function_registry.register_function("Sum", Function::Scalar(Arc::new(functions::aggregation::Sum::new(evaluator.clone()))));
function_registry.register_function("Min", Function::Scalar(Arc::new(functions::aggregation::Min::new(evaluator.clone()))));
function_registry.register_function("Max", Function::Scalar(Arc::new(functions::aggregation::Max::new(evaluator.clone()))));
PowerFxEngine {
function_registry,
evaluator,
}
}
pub fn register_scalar_function(&self, name: &str, factory: fn(Arc<ExpressionEvaluator>) -> Arc<dyn ScalarFunction>) {
let function = factory(self.evaluator.clone());
self.function_registry.register_function(name, Function::Scalar(function));
}
pub fn evaluate(&self, expression: &str, session: Option<&mut Session>) -> Result<DataValue, EvaluationError> {
let expressions = match lexer::parse(expression) {
Ok(e) => e,
Err(e) => return Err(EvaluationError::ParseError(e.to_string())),
};
let ctx = match session {
Some(c) => c,
None => &mut Session::new(),
};
let mut result = models::DataValue::Blank;
for expression in expressions {
result = match self.evaluator.evaluate_expression(ctx, &expression) {
Ok(r) => r,
Err(e) => return Err(e),
};
}
Ok(result)
}
}