use crate::value::Value;
use hamelin_lib::tree::ast::identifier::SimpleIdentifier;
use hamelin_lib::tree::builder::{boolean, field, field_ref, int, string, struct_literal};
use hamelin_lib::types::{INT, STRING};
use ordermap::OrderMap;
use super::test_helpers::{test_context, TestContext};
#[test]
fn test_eval_struct_literal() {
let ctx = test_context();
let expr = struct_literal()
.field("name", string("Alice"))
.field("age", int(30));
let result = ctx.eval_expr(&expr);
let mut expected_fields = OrderMap::new();
expected_fields.insert(
"name".parse::<SimpleIdentifier>().unwrap(),
Value::String("Alice".to_string()),
);
expected_fields.insert("age".parse::<SimpleIdentifier>().unwrap(), Value::Int(30));
assert_eq!(result, Value::Struct(expected_fields));
let expr = struct_literal()
.field(
"user",
struct_literal()
.field("id", int(1))
.field("name", string("Bob")),
)
.field("score", int(95));
let result = ctx.eval_expr(&expr);
let mut inner_fields = OrderMap::new();
inner_fields.insert("id".parse::<SimpleIdentifier>().unwrap(), Value::Int(1));
inner_fields.insert(
"name".parse::<SimpleIdentifier>().unwrap(),
Value::String("Bob".to_string()),
);
let mut outer_fields = OrderMap::new();
outer_fields.insert(
"user".parse::<SimpleIdentifier>().unwrap(),
Value::Struct(inner_fields),
);
outer_fields.insert("score".parse::<SimpleIdentifier>().unwrap(), Value::Int(95));
assert_eq!(result, Value::Struct(outer_fields));
}
#[test]
fn test_eval_struct_with_variables() {
let mut ctx = TestContext::default();
ctx.set("x", Value::Int(42), INT);
ctx.set("y", Value::String("test".to_string()), STRING);
let expr = struct_literal()
.field("field_x", field_ref("x"))
.field("field_y", field_ref("y"))
.field("constant", int(100));
let result = ctx.eval_expr(&expr);
let mut expected_fields = OrderMap::new();
expected_fields.insert(
"field_x".parse::<SimpleIdentifier>().unwrap(),
Value::Int(42),
);
expected_fields.insert(
"field_y".parse::<SimpleIdentifier>().unwrap(),
Value::String("test".to_string()),
);
expected_fields.insert(
"constant".parse::<SimpleIdentifier>().unwrap(),
Value::Int(100),
);
assert_eq!(result, Value::Struct(expected_fields));
}
#[test]
fn test_eval_field_lookup() {
let ctx = test_context();
let make_struct = || {
struct_literal()
.field("name", string("Alice"))
.field("age", int(30))
.field("active", boolean(true))
};
let expr = field(make_struct(), "name");
let result = ctx.eval_expr(&expr);
assert_eq!(result, Value::String("Alice".to_string()));
let expr = field(make_struct(), "age");
let result = ctx.eval_expr(&expr);
assert_eq!(result, Value::Int(30));
let expr = field(make_struct(), "active");
let result = ctx.eval_expr(&expr);
assert_eq!(result, Value::Boolean(true));
}
#[test]
fn test_eval_nested_field_lookup() {
let ctx = test_context();
let expr = field(
field(
struct_literal().field(
"user",
struct_literal().field(
"profile",
struct_literal()
.field("name", string("Bob"))
.field("verified", boolean(true)),
),
),
"user",
),
"profile",
);
let result = ctx.eval_expr(&expr);
let mut expected_fields = OrderMap::new();
expected_fields.insert(
"name".parse::<SimpleIdentifier>().unwrap(),
Value::String("Bob".to_string()),
);
expected_fields.insert(
"verified".parse::<SimpleIdentifier>().unwrap(),
Value::Boolean(true),
);
assert_eq!(result, Value::Struct(expected_fields));
}
#[test]
fn test_eval_empty_struct() {
let ctx = test_context();
let expr = struct_literal();
let result = ctx.eval_expr(&expr);
let expected_fields = OrderMap::new();
assert_eq!(result, Value::Struct(expected_fields));
}
#[test]
fn test_eval_struct_with_null_fields() {
use hamelin_lib::tree::builder::null;
let ctx = test_context();
let expr = struct_literal()
.field("name", string("Alice"))
.field("middle_name", null())
.field("age", int(30));
let result = ctx.eval_expr(&expr);
let mut expected_fields = OrderMap::new();
expected_fields.insert(
"name".parse::<SimpleIdentifier>().unwrap(),
Value::String("Alice".to_string()),
);
expected_fields.insert(
"middle_name".parse::<SimpleIdentifier>().unwrap(),
Value::Null,
);
expected_fields.insert("age".parse::<SimpleIdentifier>().unwrap(), Value::Int(30));
assert_eq!(result, Value::Struct(expected_fields));
}
#[test]
fn test_eval_struct_with_mixed_types() {
let ctx = test_context();
let expr = struct_literal()
.field("string_field", string("text"))
.field("int_field", int(42))
.field("bool_field", boolean(true))
.field("double_field", 3.14);
let result = ctx.eval_expr(&expr);
let mut expected_fields = OrderMap::new();
expected_fields.insert(
"string_field".parse::<SimpleIdentifier>().unwrap(),
Value::String("text".to_string()),
);
expected_fields.insert(
"int_field".parse::<SimpleIdentifier>().unwrap(),
Value::Int(42),
);
expected_fields.insert(
"bool_field".parse::<SimpleIdentifier>().unwrap(),
Value::Boolean(true),
);
expected_fields.insert(
"double_field".parse::<SimpleIdentifier>().unwrap(),
Value::Double(3.14),
);
assert_eq!(result, Value::Struct(expected_fields));
}
#[test]
fn test_eval_deeply_nested_struct() {
let ctx = test_context();
let expr = struct_literal().field(
"level1",
struct_literal().field(
"level2",
struct_literal().field(
"level3",
struct_literal()
.field("value", int(123))
.field("name", string("deep")),
),
),
);
let result = ctx.eval_expr(&expr);
let mut level3_fields = OrderMap::new();
level3_fields.insert(
"value".parse::<SimpleIdentifier>().unwrap(),
Value::Int(123),
);
level3_fields.insert(
"name".parse::<SimpleIdentifier>().unwrap(),
Value::String("deep".to_string()),
);
let mut level2_fields = OrderMap::new();
level2_fields.insert(
"level3".parse::<SimpleIdentifier>().unwrap(),
Value::Struct(level3_fields),
);
let mut level1_fields = OrderMap::new();
level1_fields.insert(
"level2".parse::<SimpleIdentifier>().unwrap(),
Value::Struct(level2_fields),
);
let mut expected_fields = OrderMap::new();
expected_fields.insert(
"level1".parse::<SimpleIdentifier>().unwrap(),
Value::Struct(level1_fields),
);
assert_eq!(result, Value::Struct(expected_fields));
}
#[test]
fn test_eval_struct_field_access_chain() {
let ctx = test_context();
let base_struct = struct_literal().field(
"user",
struct_literal().field("id", int(456)).field(
"profile",
struct_literal()
.field("name", string("Charlie"))
.field("email", string("charlie@example.com")),
),
);
let expr = field(field(field(base_struct, "user"), "profile"), "name");
let result = ctx.eval_expr(&expr);
assert_eq!(result, Value::String("Charlie".to_string()));
}
#[test]
fn test_eval_struct_with_array_fields() {
use hamelin_lib::tree::builder::array;
let ctx = test_context();
let expr = struct_literal()
.field("name", string("Alice"))
.field("scores", array().element(95).element(87).element(92))
.field("active", boolean(true));
let result = ctx.eval_expr(&expr);
let mut expected_fields = OrderMap::new();
expected_fields.insert(
"name".parse::<SimpleIdentifier>().unwrap(),
Value::String("Alice".to_string()),
);
expected_fields.insert(
"scores".parse::<SimpleIdentifier>().unwrap(),
Value::Array(vec![Value::Int(95), Value::Int(87), Value::Int(92)]),
);
expected_fields.insert(
"active".parse::<SimpleIdentifier>().unwrap(),
Value::Boolean(true),
);
assert_eq!(result, Value::Struct(expected_fields));
}