expy 0.0.2

Embeddable & extensible expression evaluator
Documentation
//! Miscellaneous smoke tests.

use expy::{BinaryOp::*, Context, Expr, Value, eval, parse};


#[test]
fn parse_and_eval_ast() {
    let expr = parse("2 + 2").unwrap();
    let mut ctx = Context::empty();
    assert_eq!(ctx.eval(&expr).unwrap(), Value::from(4));
}

#[test]
fn eval_directly() {
    assert_eq!(eval("2 + 2").unwrap(), Value::from(4))
}

#[test]
fn block_comments() {
    assert_eq!(
        parse("2 + /**/ 2").unwrap(), Expr::binary(Add, Expr::literal(2), Expr::literal(2)));
    assert_eq!(parse("2+/**/2").unwrap(), Expr::binary(Add, Expr::literal(2), Expr::literal(2)));
    assert_eq!(
        parse("2 + /* two */ 2").unwrap(),
        Expr::binary(Add, Expr::literal(2), Expr::literal(2)));
    assert_eq!(
        parse("2 + /* not quite /* nested */ 2").unwrap(),
        Expr::binary(Add, Expr::literal(2), Expr::literal(2)));
    assert_eq!(
        parse("/* before */ 2 + /* in the middle */ 2 /* and after */").unwrap(),
        Expr::binary(Add, Expr::literal(2), Expr::literal(2)));
}

#[test]
fn line_comments() {
    assert_eq!(
        parse("2 + 2 // added").unwrap(), Expr::binary(Add, Expr::literal(2), Expr::literal(2)));
    assert_eq!(
        parse("2 + 2 // * invalid syntax commented out").unwrap(),
        Expr::binary(Add, Expr::literal(2), Expr::literal(2)));
    assert_eq!(parse("2 // + 2 valid syntax commented out").unwrap(), Expr::literal(2));
    assert_eq!(parse(r#"
        2 + // one line
        2   // another line
    "#).unwrap(),
        Expr::binary(Add, Expr::literal(2), Expr::literal(2)));
}

#[test]
fn identity_func_on_literals() {
    for value in ["true", "42", "3.14", "@foo"] {
        let expr = format!("id({value})");
        assert_eq!(eval(&expr).unwrap(), eval(value).unwrap());
    }
}

#[test]
fn trivial_equality() {
    for value in ["false", "13", "2.71", "@foo", /* function */ "abs"] {
        let expr = format!("{value} == {value}");
        assert!(eval(&expr).unwrap().unwrap_bool());
    }
}

const TRIES: usize = 32;
const MAX_OPS: usize = 64;

#[test]
fn paired_boolean_negation() {
    for boolean in ["true", "false"] {
        for i in 0..MAX_OPS / 2 {
            let expr = format!("{}{}", "!".repeat(i * 2), boolean);
            assert_eq!(eval(expr).unwrap(), eval(boolean).unwrap());
        }
    }
}

#[test]
fn paired_arithmetic_negation() {
    for _ in 0..TRIES {
        let int = fastrand::i32(0..65536);
        for i in 0..MAX_OPS / 2 {
            let expr = format!("{}{}", "-".repeat(i * 2), int);
            assert_eq!(eval(expr).unwrap(), eval(int.to_string()).unwrap());
        }
    }
}