use crate::eval::environment::Environment;
use crate::reverse_eval::domain::Constraint;
use crate::reverse_eval::reverse::reverse_eval;
use crate::value::Value;
use hamelin_lib::tree::builder::*;
use hamelin_lib::tree::options::ExpressionTypeCheckOptions;
use hamelin_lib::tree::typed_ast::environment::TypeEnvironment;
use hamelin_lib::type_check_expression;
use hamelin_lib::types::INT;
use pretty_assertions::assert_eq;
use std::sync::Arc;
#[test]
fn test_reverse_eval_field_ref() {
let env = Environment::new();
let mut trans_env = TypeEnvironment::default();
trans_env.bind_str("x", INT);
let bindings = Arc::new(trans_env);
let expr = type_check_expression(
field_ref("x").build(),
ExpressionTypeCheckOptions::builder()
.bindings(bindings)
.build(),
)
.output;
let constraint = Constraint::Equals(Value::Int(10));
let result = reverse_eval(&expr, constraint, &env).expect("Reverse eval failed");
assert_eq!(result, Some(Constraint::Equals(Value::Int(10))));
}
#[test]
fn test_reverse_eval_int_literal_satisfied() {
let env = Environment::new();
let expr = type_check_expression(int(42).build(), ExpressionTypeCheckOptions::default()).output;
let constraint = Constraint::Equals(Value::Int(42));
let result = reverse_eval(&expr, constraint, &env).expect("Reverse eval failed");
assert_eq!(result, None);
}
#[test]
fn test_reverse_eval_int_literal_unsatisfied() {
let env = Environment::new();
let expr = type_check_expression(int(42).build(), ExpressionTypeCheckOptions::default()).output;
let constraint = Constraint::Equals(Value::Int(100));
let result = reverse_eval(&expr, constraint, &env);
assert!(result.is_err());
assert!(result.unwrap_err().to_string().contains("unsatisfiable"));
}
#[test]
fn test_reverse_eval_empty_constraint() {
let env = Environment::new();
let mut trans_env = TypeEnvironment::default();
trans_env.bind_str("x", INT);
let bindings = Arc::new(trans_env);
let expr = type_check_expression(
add(field_ref("x"), 5).build(),
ExpressionTypeCheckOptions::builder()
.bindings(bindings)
.build(),
)
.output;
let constraint = Constraint::Empty;
let result =
reverse_eval(&expr, constraint, &env).expect("Reverse eval should handle empty constraint");
assert_eq!(result, None);
}
#[test]
fn test_reverse_eval_universal_constraint() {
let env = Environment::new();
let mut trans_env = TypeEnvironment::default();
trans_env.bind_str("x", INT);
let bindings = Arc::new(trans_env);
let expr = type_check_expression(
field_ref("x").build(),
ExpressionTypeCheckOptions::builder()
.bindings(bindings)
.build(),
)
.output;
let constraint = Constraint::Universal;
let result = reverse_eval(&expr, constraint, &env).expect("Reverse eval failed");
assert_eq!(result, Some(Constraint::Universal));
}