use crate::eval::environment::Environment;
use crate::eval::evaluator::eval;
use crate::value::Value;
use hamelin_lib::tree::builder::{add, field_ref, is_not_null, is_null, null, ExpressionBuilder};
use hamelin_lib::tree::options::ExpressionTypeCheckOptions;
use hamelin_lib::type_check_expression;
use hamelin_lib::types::INT;
use std::sync::Arc;
use super::test_helpers::TestContext;
#[test]
fn test_eval_null_propagation() {
let mut ctx = TestContext::default();
ctx.set("x", Value::Null, INT);
let expr = type_check_expression(
add(field_ref("x"), 5).build(),
ExpressionTypeCheckOptions::builder()
.bindings(Arc::new(ctx.translation_env.clone()))
.build(),
)
.output;
let result = eval(&expr, &ctx.env).unwrap();
assert_eq!(result, Value::Null);
assert!(result.is_null());
}
#[test]
fn test_eval_is_null_operators() {
let env = Environment::new();
let expr = type_check_expression(
is_null(null()).build(),
ExpressionTypeCheckOptions::default(),
)
.output;
let result = eval(&expr, &env).unwrap();
assert_eq!(result, Value::Boolean(true));
let expr = type_check_expression(
is_not_null(42).build(),
ExpressionTypeCheckOptions::default(),
)
.output;
let result = eval(&expr, &env).unwrap();
assert_eq!(result, Value::Boolean(true));
let expr =
type_check_expression(is_null(42).build(), ExpressionTypeCheckOptions::default()).output;
let result = eval(&expr, &env).unwrap();
assert_eq!(result, Value::Boolean(false));
let expr = type_check_expression(
is_not_null(null()).build(),
ExpressionTypeCheckOptions::default(),
)
.output;
let result = eval(&expr, &env).unwrap();
assert_eq!(result, Value::Boolean(false));
}
#[test]
fn test_eval_null_literal() {
let ctx = TestContext::new();
let expr = null();
let result = ctx.eval_expr(&expr);
assert_eq!(result, Value::Null);
assert!(result.is_null());
}
#[test]
fn test_null_propagation_in_arithmetic() {
let mut ctx = TestContext::default();
ctx.set("null_var", Value::Null, INT);
ctx.set("null_var2", Value::Null, INT);
let expr = type_check_expression(
add(field_ref("null_var"), 42).build(),
ExpressionTypeCheckOptions::builder()
.bindings(Arc::new(ctx.translation_env.clone()))
.build(),
)
.output;
let result = eval(&expr, &ctx.env).unwrap();
assert_eq!(result, Value::Null);
let expr = type_check_expression(
add(42, field_ref("null_var")).build(),
ExpressionTypeCheckOptions::builder()
.bindings(Arc::new(ctx.translation_env.clone()))
.build(),
)
.output;
let result = eval(&expr, &ctx.env).unwrap();
assert_eq!(result, Value::Null);
let expr = type_check_expression(
add(field_ref("null_var"), field_ref("null_var2")).build(),
ExpressionTypeCheckOptions::builder()
.bindings(Arc::new(ctx.translation_env.clone()))
.build(),
)
.output;
let result = eval(&expr, &ctx.env).unwrap();
assert_eq!(result, Value::Null);
}
#[test]
fn test_null_propagation_in_comparisons() {
use hamelin_lib::tree::builder::{eq, gt};
let mut ctx = TestContext::default();
ctx.set("null_var", Value::Null, INT);
ctx.set("null_var2", Value::Null, INT);
let expr = type_check_expression(
eq(field_ref("null_var"), 42).build(),
ExpressionTypeCheckOptions::builder()
.bindings(Arc::new(ctx.translation_env.clone()))
.build(),
)
.output;
let result = eval(&expr, &ctx.env).unwrap();
assert_eq!(result, Value::Null);
let expr = type_check_expression(
eq(42, field_ref("null_var")).build(),
ExpressionTypeCheckOptions::builder()
.bindings(Arc::new(ctx.translation_env.clone()))
.build(),
)
.output;
let result = eval(&expr, &ctx.env).unwrap();
assert_eq!(result, Value::Null);
let expr = type_check_expression(
eq(field_ref("null_var"), field_ref("null_var2")).build(),
ExpressionTypeCheckOptions::builder()
.bindings(Arc::new(ctx.translation_env.clone()))
.build(),
)
.output;
let result = eval(&expr, &ctx.env).unwrap();
assert_eq!(result, Value::Null);
let expr = type_check_expression(
gt(field_ref("null_var"), 42).build(),
ExpressionTypeCheckOptions::builder()
.bindings(Arc::new(ctx.translation_env.clone()))
.build(),
)
.output;
let result = eval(&expr, &ctx.env).unwrap();
assert_eq!(result, Value::Null);
}