Skip to main content

parse_scope

Function parse_scope 

Source
pub fn parse_scope<R>(
    parser: &Tabnas,
    src: &str,
    use_value: impl FnOnce(Value) -> R,
) -> Result<R, TabnasError>
Expand description

Parse one document and hand the unrealized value to a closure, with the expression arena held open for as long as it runs.

This is the parse-once, evaluate-many workflow: inside the closure the expression nodes are live, so evaluation can reduce them, and whatever the closure returns outlives them.

The arena is released when this returns, so the closure must not let an expression HANDLE escape in what it returns. Return a reduced value, as the example below does, or call realize on the tree and return that; parse_with is the same parse with the realizing already done. A handle that escapes names a node that no longer exists, and realize and simplify then PANIC rather than report the lost expression as an empty array. The closure return type is a type parameter, so nothing in the signature can realize it for a caller, and nothing in it can stop a handle from being returned.

use tabnas::Value;
use tabnas_expr::{evaluation, EvalSite, Evaluate, Op};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let parser = tabnas_expr::make();
    let add: Evaluate = std::sync::Arc::new(
        |_site: &mut EvalSite<'_>, _op: &Op, terms: &[Value]| match terms {
            [Value::Number(left), Value::Number(right)] => Value::Number(left + right),
            _ => Value::Null,
        },
    );
    let total = tabnas_expr::parse_scope(&parser, "1+2", |value| {
        evaluation(&mut EvalSite::detached(), &value, &add)
    })?;
    assert_eq!(total, Value::Number(3.0));
    Ok(())
}