formualizer-eval 0.14.0

High-performance Arrow-backed Excel formula engine with dependency graph and incremental recalculation
Documentation
use super::common::arrow_eval_config;
use crate::{
    args::ArgSchema,
    engine::{Engine, EvalConfig},
    function::{FamilyKernel, FnCaps, Function},
    operation_diagnostics::{OperationDiagnosticOptions, UnavailableOperation},
    test_workbook::TestWorkbook,
    traits::{ArgumentHandle, CalcValue, FunctionContext},
};
use formualizer_common::{ExcelError, ExcelErrorKind, LiteralValue};
use formualizer_parse::parser::parse;
use std::sync::{Arc, LazyLock};

struct Provider {
    name: &'static str,
    reporting: bool,
    error: bool,
}
impl Function for Provider {
    fn name(&self) -> &'static str {
        self.name
    }
    fn min_args(&self) -> usize {
        1
    }
    fn variadic(&self) -> bool {
        self.name == "MATCH"
    }
    fn caps(&self) -> FnCaps {
        FnCaps::PURE
    }
    fn reports_known_limitations(&self) -> bool {
        self.reporting
    }
    fn family_kernel(&self) -> Option<FamilyKernel> {
        (self.name == "MATCH").then_some(FamilyKernel::Lookup)
    }
    fn arg_schema(&self) -> &'static [ArgSchema] {
        static SCHEMA: LazyLock<Vec<ArgSchema>> = LazyLock::new(|| vec![ArgSchema::any()]);
        &SCHEMA
    }
    fn eval<'a, 'b, 'c>(
        &self,
        _: &'c [ArgumentHandle<'a, 'b>],
        _: &dyn FunctionContext<'b>,
    ) -> Result<CalcValue<'b>, ExcelError> {
        if self.error {
            Err(ExcelError::new(ExcelErrorKind::Div))
        } else {
            Ok(CalcValue::Scalar(LiteralValue::Number(42.0)))
        }
    }
}

fn evaluate(
    name: &'static str,
    reporting: bool,
    error: bool,
    active: bool,
    lift: bool,
    kernels: bool,
) -> Engine<TestWorkbook> {
    crate::builtins::load_builtins();
    let wb = TestWorkbook::new().with_function(Arc::new(Provider {
        name,
        reporting,
        error,
    }));
    let mut engine = Engine::new(
        wb,
        EvalConfig {
            enable_parallel: false,
            family_lift: lift,
            family_kernels: kernels,
            ..arrow_eval_config()
        },
    );
    engine.configure_operation_diagnostics(OperationDiagnosticOptions {
        sample_limit: 0,
        track_unverified_providers: true,
        ..Default::default()
    });
    engine
        .set_cell_value("Sheet1", 1, 26, LiteralValue::Number(1.0))
        .unwrap();
    engine
        .set_cell_value("Sheet1", 2, 26, LiteralValue::Number(2.0))
        .unwrap();
    let call = if name == "MATCH" {
        "MATCH($Z$1,$Z$1:$Z$2)".to_string()
    } else {
        format!("{name}($Z$1)")
    };
    for row in 1..=8 {
        engine
            .set_cell_value("Sheet1", row, 1, LiteralValue::Number(1.0))
            .unwrap();
        let expression = if active {
            format!("=IF(A{row}>0,IFERROR({call},7),5)")
        } else {
            format!("=IF(A{row}>0,5,{call})")
        };
        engine
            .set_cell_formula("Sheet1", row, 2, parse(&expression).unwrap())
            .unwrap();
    }
    engine.evaluate_all().unwrap();
    for row in 1..=8 {
        let expected = if !active {
            5.0
        } else if error {
            7.0
        } else {
            42.0
        };
        assert_eq!(
            engine.get_cell_value("Sheet1", row, 2),
            Some(LiteralValue::Number(expected))
        );
    }
    engine
}

#[test]
fn recalc_contract_unverified_provider_follows_executing_instance() {
    for name in ["LOCAL_COVERAGE", "ABS", "STDEV"] {
        for (lift, kernels) in [(false, false), (true, false), (false, true)] {
            for error in [false, true] {
                let engine = evaluate(name, false, error, true, lift, kernels);
                let report = engine.operation_diagnostics().unwrap().unwrap();
                assert_eq!(
                    report.logical_root_cell_count, 8,
                    "name={name} lift={lift} kernels={kernels} error={error}: {report:?}"
                );
                assert!(report.roots.iter().all(|root| matches!(
                    root.operation.as_ref(), UnavailableOperation::UnverifiedProvider { name: actual }
                    if actual == name
                )));
                assert!(report.samples.is_empty());
                assert_eq!(report.physical_function_dispatches, None);
            }
        }
    }
}

#[test]
fn recalc_contract_unverified_provider_cannot_inherit_a_family_kernel_attestation() {
    for (lift, kernels) in [(false, false), (true, false), (false, true)] {
        let engine = evaluate("MATCH", false, false, true, lift, kernels);
        let report = engine.operation_diagnostics().unwrap().unwrap();
        assert_eq!(report.logical_root_cell_count, 8, "{report:?}");
    }
}

#[test]
fn recalc_contract_unverified_provider_explicit_contract_and_inactive_controls() {
    for (reporting, active) in [(true, true), (false, false)] {
        let engine = evaluate("LOCAL_COVERAGE", reporting, false, active, true, true);
        assert!(
            engine
                .operation_diagnostics()
                .unwrap()
                .unwrap()
                .roots
                .is_empty()
        );
    }
}

#[test]
fn recalc_contract_unverified_provider_genuine_builtin_and_alias_controls() {
    crate::builtins::load_builtins();
    let mut engine = Engine::new(
        TestWorkbook::new(),
        EvalConfig {
            enable_parallel: false,
            ..arrow_eval_config()
        },
    );
    engine.configure_operation_diagnostics(OperationDiagnosticOptions {
        track_unverified_providers: true,
        ..Default::default()
    });
    for (row, formula) in [(1, "=ABS(-2)"), (2, "=STDEV({1;2})"), (3, "=_xlfn.ABS(-3)")] {
        engine
            .set_cell_formula("Sheet1", row, 1, parse(formula).unwrap())
            .unwrap();
    }
    engine.evaluate_all().unwrap();
    assert!(
        engine
            .operation_diagnostics()
            .unwrap()
            .unwrap()
            .roots
            .is_empty()
    );
}

#[test]
fn recalc_contract_reference_dispatch_is_measured_as_execution() {
    crate::builtins::load_builtins();
    let mut engine = Engine::new(
        TestWorkbook::new(),
        EvalConfig {
            enable_parallel: false,
            ..arrow_eval_config()
        },
    );
    engine
        .set_cell_value("Sheet1", 1, 1, LiteralValue::Number(1.0))
        .unwrap();
    engine.configure_operation_diagnostics(OperationDiagnosticOptions {
        physical_telemetry: true,
        ..Default::default()
    });
    let cell = crate::CellRef::new(0, crate::reference::Coord::new(0, 1, true, true));
    let interpreter = crate::interpreter::Interpreter::new_with_cell(&engine, "Sheet1", cell);
    interpreter
        .evaluate_ast_as_reference(&parse("=INDIRECT(\"A1\")").unwrap())
        .unwrap();
    let report = engine.operation_diagnostics().unwrap().unwrap();
    assert_eq!(report.physical_function_dispatches, Some(1));
    assert!(report.roots.is_empty());
}

struct ReferenceProvider;
impl Function for ReferenceProvider {
    fn name(&self) -> &'static str {
        "LOCAL_REFERENCE"
    }
    fn caps(&self) -> FnCaps {
        FnCaps::PURE | FnCaps::RETURNS_REFERENCE
    }
    fn eval<'a, 'b, 'c>(
        &self,
        _: &'c [ArgumentHandle<'a, 'b>],
        _: &dyn FunctionContext<'b>,
    ) -> Result<CalcValue<'b>, ExcelError> {
        panic!("this provider's value fallback must not run")
    }
    fn eval_reference<'a, 'b, 'c>(
        &self,
        _: &'c [ArgumentHandle<'a, 'b>],
        _: &dyn FunctionContext<'b>,
    ) -> Option<Result<formualizer_parse::parser::ReferenceType, ExcelError>> {
        Some(Ok(formualizer_parse::parser::ReferenceType::from_string(
            "A1",
        )
        .unwrap()))
    }
}
#[test]
fn recalc_contract_unverified_provider_reference_routes_keep_origins_and_values() {
    crate::builtins::load_builtins();
    let mut engine = Engine::new(
        TestWorkbook::new().with_function(Arc::new(ReferenceProvider)),
        EvalConfig {
            enable_parallel: false,
            ..arrow_eval_config()
        },
    );
    engine.configure_operation_diagnostics(OperationDiagnosticOptions {
        track_unverified_providers: true,
        ..Default::default()
    });
    engine
        .set_cell_value("Sheet1", 1, 1, LiteralValue::Number(17.0))
        .unwrap();
    engine
        .set_cell_formula("Sheet1", 1, 2, parse("=SUM(LOCAL_REFERENCE())").unwrap())
        .unwrap();
    engine.evaluate_all().unwrap();
    assert_eq!(
        engine.get_cell_value("Sheet1", 1, 2),
        Some(LiteralValue::Number(17.0))
    );
    let cell = crate::CellRef::new_absolute(0, 0, 2);
    let interpreter = crate::interpreter::Interpreter::new_with_cell(&engine, "Sheet1", cell);
    interpreter
        .evaluate_ast_as_reference(&parse("=LOCAL_REFERENCE()").unwrap())
        .unwrap();
    let report = engine.operation_diagnostics().unwrap().unwrap();
    assert_eq!(report.logical_root_cell_count, 2, "{report:?}");
    assert!(report.roots.iter().all(|root| matches!(
        root.operation.as_ref(), UnavailableOperation::UnverifiedProvider { name }
        if name == "LOCAL_REFERENCE"
    )));
    let columns: Vec<_> = report
        .roots
        .iter()
        .map(|root| root.cell.unwrap().coord.col())
        .collect();
    assert_eq!(columns, vec![1, 2]);
}