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", "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());
}
}
}