use crate::engine::fold::expr_binary_op::fold_expr_binary_op;
use toasty_core::stmt::{BinaryOp, Expr, Value};
#[test]
fn constant_eq_same_values_becomes_true() {
let mut lhs = Expr::Value(Value::from(5i64));
let mut rhs = Expr::Value(Value::from(5i64));
let result = fold_expr_binary_op(BinaryOp::Eq, &mut lhs, &mut rhs);
assert!(matches!(result, Some(Expr::Value(Value::Bool(true)))));
}
#[test]
fn constant_eq_different_values_becomes_false() {
let mut lhs = Expr::Value(Value::from(1i64));
let mut rhs = Expr::Value(Value::from(2i64));
let result = fold_expr_binary_op(BinaryOp::Eq, &mut lhs, &mut rhs);
assert!(matches!(result, Some(Expr::Value(Value::Bool(false)))));
}
#[test]
fn constant_ne_same_values_becomes_false() {
let mut lhs = Expr::Value(Value::from(5i64));
let mut rhs = Expr::Value(Value::from(5i64));
let result = fold_expr_binary_op(BinaryOp::Ne, &mut lhs, &mut rhs);
assert!(matches!(result, Some(Expr::Value(Value::Bool(false)))));
}
#[test]
fn constant_ne_different_values_becomes_true() {
let mut lhs = Expr::Value(Value::from("abc"));
let mut rhs = Expr::Value(Value::from("def"));
let result = fold_expr_binary_op(BinaryOp::Ne, &mut lhs, &mut rhs);
assert!(matches!(result, Some(Expr::Value(Value::Bool(true)))));
}
#[test]
fn constant_eq_with_null_becomes_null() {
let mut lhs = Expr::Value(Value::Null);
let mut rhs = Expr::Value(Value::from(5i64));
let result = fold_expr_binary_op(BinaryOp::Eq, &mut lhs, &mut rhs);
assert!(matches!(result, Some(Expr::Value(Value::Null))));
}
#[test]
fn constant_eq_null_with_null_becomes_null() {
let mut lhs = Expr::Value(Value::Null);
let mut rhs = Expr::Value(Value::Null);
let result = fold_expr_binary_op(BinaryOp::Eq, &mut lhs, &mut rhs);
assert!(matches!(result, Some(Expr::Value(Value::Null))));
}
#[test]
fn constant_lt_becomes_true() {
let mut lhs = Expr::Value(Value::from(1i64));
let mut rhs = Expr::Value(Value::from(5i64));
let result = fold_expr_binary_op(BinaryOp::Lt, &mut lhs, &mut rhs);
assert!(matches!(result, Some(Expr::Value(Value::Bool(true)))));
}
#[test]
fn constant_lt_becomes_false() {
let mut lhs = Expr::Value(Value::from(5i64));
let mut rhs = Expr::Value(Value::from(1i64));
let result = fold_expr_binary_op(BinaryOp::Lt, &mut lhs, &mut rhs);
assert!(matches!(result, Some(Expr::Value(Value::Bool(false)))));
}
#[test]
fn constant_le_equal_becomes_true() {
let mut lhs = Expr::Value(Value::from(5i64));
let mut rhs = Expr::Value(Value::from(5i64));
let result = fold_expr_binary_op(BinaryOp::Le, &mut lhs, &mut rhs);
assert!(matches!(result, Some(Expr::Value(Value::Bool(true)))));
}
#[test]
fn constant_le_becomes_false() {
let mut lhs = Expr::Value(Value::from(10i64));
let mut rhs = Expr::Value(Value::from(5i64));
let result = fold_expr_binary_op(BinaryOp::Le, &mut lhs, &mut rhs);
assert!(matches!(result, Some(Expr::Value(Value::Bool(false)))));
}
#[test]
fn constant_gt_becomes_true() {
let mut lhs = Expr::Value(Value::from(10i64));
let mut rhs = Expr::Value(Value::from(5i64));
let result = fold_expr_binary_op(BinaryOp::Gt, &mut lhs, &mut rhs);
assert!(matches!(result, Some(Expr::Value(Value::Bool(true)))));
}
#[test]
fn constant_gt_becomes_false() {
let mut lhs = Expr::Value(Value::from(1i64));
let mut rhs = Expr::Value(Value::from(5i64));
let result = fold_expr_binary_op(BinaryOp::Gt, &mut lhs, &mut rhs);
assert!(matches!(result, Some(Expr::Value(Value::Bool(false)))));
}
#[test]
fn constant_ge_equal_becomes_true() {
let mut lhs = Expr::Value(Value::from(5i64));
let mut rhs = Expr::Value(Value::from(5i64));
let result = fold_expr_binary_op(BinaryOp::Ge, &mut lhs, &mut rhs);
assert!(matches!(result, Some(Expr::Value(Value::Bool(true)))));
}
#[test]
fn constant_ge_becomes_false() {
let mut lhs = Expr::Value(Value::from(1i64));
let mut rhs = Expr::Value(Value::from(5i64));
let result = fold_expr_binary_op(BinaryOp::Ge, &mut lhs, &mut rhs);
assert!(matches!(result, Some(Expr::Value(Value::Bool(false)))));
}
#[test]
fn constant_lt_string_lexicographic() {
let mut lhs = Expr::Value(Value::from("abc"));
let mut rhs = Expr::Value(Value::from("def"));
let result = fold_expr_binary_op(BinaryOp::Lt, &mut lhs, &mut rhs);
assert!(matches!(result, Some(Expr::Value(Value::Bool(true)))));
}
#[test]
fn constant_lt_different_types_not_simplified() {
let mut lhs = Expr::Value(Value::from(5i64));
let mut rhs = Expr::Value(Value::from("abc"));
let result = fold_expr_binary_op(BinaryOp::Lt, &mut lhs, &mut rhs);
assert!(result.is_none());
}
#[test]
fn lt_with_non_constant_not_simplified() {
let mut lhs = Expr::arg(0);
let mut rhs = Expr::Value(Value::from(5i64));
let result = fold_expr_binary_op(BinaryOp::Lt, &mut lhs, &mut rhs);
assert!(result.is_none());
}
#[test]
fn x_eq_true_becomes_x() {
let mut lhs = Expr::arg(0);
let mut rhs = Expr::Value(Value::Bool(true));
let result = fold_expr_binary_op(BinaryOp::Eq, &mut lhs, &mut rhs);
assert!(matches!(result, Some(Expr::Arg(_))));
}
#[test]
fn true_eq_x_becomes_x() {
let mut lhs = Expr::Value(Value::Bool(true));
let mut rhs = Expr::arg(0);
let result = fold_expr_binary_op(BinaryOp::Eq, &mut lhs, &mut rhs);
assert!(matches!(result, Some(Expr::Arg(_))));
}
#[test]
fn x_eq_false_becomes_not_x() {
let mut lhs = Expr::arg(0);
let mut rhs = Expr::Value(Value::Bool(false));
let result = fold_expr_binary_op(BinaryOp::Eq, &mut lhs, &mut rhs);
assert!(matches!(result, Some(Expr::Not(_))));
}
#[test]
fn x_ne_true_becomes_not_x() {
let mut lhs = Expr::arg(0);
let mut rhs = Expr::Value(Value::Bool(true));
let result = fold_expr_binary_op(BinaryOp::Ne, &mut lhs, &mut rhs);
assert!(matches!(result, Some(Expr::Not(_))));
}
#[test]
fn x_ne_false_becomes_x() {
let mut lhs = Expr::arg(0);
let mut rhs = Expr::Value(Value::Bool(false));
let result = fold_expr_binary_op(BinaryOp::Ne, &mut lhs, &mut rhs);
assert!(matches!(result, Some(Expr::Arg(_))));
}
#[test]
fn canonicalize_eq_literal_on_left() {
let mut lhs = Expr::Value(Value::from(5i64));
let mut rhs = Expr::arg(0);
let result = fold_expr_binary_op(BinaryOp::Eq, &mut lhs, &mut rhs);
let Some(Expr::BinaryOp(binary_op)) = result else {
panic!("expected BinaryOp");
};
assert_eq!(binary_op.op, BinaryOp::Eq);
assert!(matches!(*binary_op.lhs, Expr::Arg(_)));
assert!(matches!(*binary_op.rhs, Expr::Value(Value::I64(5))));
}
#[test]
fn canonicalize_lt_literal_on_left() {
let mut lhs = Expr::Value(Value::from(5i64));
let mut rhs = Expr::arg(0);
let result = fold_expr_binary_op(BinaryOp::Lt, &mut lhs, &mut rhs);
let Some(Expr::BinaryOp(binary_op)) = result else {
panic!("expected BinaryOp");
};
assert_eq!(binary_op.op, BinaryOp::Gt);
assert!(matches!(*binary_op.lhs, Expr::Arg(_)));
assert!(matches!(*binary_op.rhs, Expr::Value(Value::I64(5))));
}
#[test]
fn canonicalize_gt_literal_on_left() {
let mut lhs = Expr::Value(Value::from(5i64));
let mut rhs = Expr::arg(0);
let result = fold_expr_binary_op(BinaryOp::Gt, &mut lhs, &mut rhs);
let Some(Expr::BinaryOp(binary_op)) = result else {
panic!("expected BinaryOp");
};
assert_eq!(binary_op.op, BinaryOp::Lt);
assert!(matches!(*binary_op.lhs, Expr::Arg(_)));
assert!(matches!(*binary_op.rhs, Expr::Value(Value::I64(5))));
}
#[test]
fn canonicalize_le_literal_on_left() {
let mut lhs = Expr::Value(Value::from(5i64));
let mut rhs = Expr::arg(0);
let result = fold_expr_binary_op(BinaryOp::Le, &mut lhs, &mut rhs);
let Some(Expr::BinaryOp(binary_op)) = result else {
panic!("expected BinaryOp");
};
assert_eq!(binary_op.op, BinaryOp::Ge);
assert!(matches!(*binary_op.lhs, Expr::Arg(_)));
assert!(matches!(*binary_op.rhs, Expr::Value(Value::I64(5))));
}
#[test]
fn canonicalize_ge_literal_on_left() {
let mut lhs = Expr::Value(Value::from(5i64));
let mut rhs = Expr::arg(0);
let result = fold_expr_binary_op(BinaryOp::Ge, &mut lhs, &mut rhs);
let Some(Expr::BinaryOp(binary_op)) = result else {
panic!("expected BinaryOp");
};
assert_eq!(binary_op.op, BinaryOp::Le);
assert!(matches!(*binary_op.lhs, Expr::Arg(_)));
assert!(matches!(*binary_op.rhs, Expr::Value(Value::I64(5))));
}
#[test]
fn no_canonicalize_when_literal_on_right() {
let mut lhs = Expr::arg(0);
let mut rhs = Expr::Value(Value::from(5i64));
let result = fold_expr_binary_op(BinaryOp::Lt, &mut lhs, &mut rhs);
assert!(result.is_none());
}