use shape_ast::ast::TypeAnnotation;
use shape_value::{ValueWord, ValueWordExt};
use std::collections::HashMap;
#[derive(Debug, Clone)]
pub(crate) struct ActiveSpecialization {
pub const_bindings: Vec<(String, ValueWord)>,
pub type_bindings: HashMap<String, TypeAnnotation>,
}
#[cfg(test)]
mod tests {
use shape_ast::ast::TypeAnnotation;
#[test]
fn test_callsite_type_args_recorded_for_generic_function() {
use shape_runtime::type_system::inference::TypeInferenceEngine;
let code = r#"
fn identity<T>(x: T) -> T { x }
identity(42)
"#;
let program = shape_ast::parser::parse_program(code).expect("parse");
let mut engine = TypeInferenceEngine::new();
let _ = engine.infer_program(&program);
let has_type_arg = engine
.callsite_type_args
.values()
.any(|args| {
args.iter().any(|(name, ann)| {
name == "T" && *ann == TypeAnnotation::Basic("int".to_string())
})
});
assert!(
has_type_arg,
"callsite_type_args should contain T=int for identity(42), got: {:?}",
engine.callsite_type_args
);
}
#[test]
fn test_callsite_type_args_recorded_for_number_generic() {
use shape_runtime::type_system::inference::TypeInferenceEngine;
let code = r#"
fn double<T>(x: T) -> T { x }
double(3.14)
"#;
let program = shape_ast::parser::parse_program(code).expect("parse");
let mut engine = TypeInferenceEngine::new();
let _ = engine.infer_program(&program);
let has_type_arg = engine
.callsite_type_args
.values()
.any(|args| {
args.iter().any(|(name, ann)| {
name == "T" && *ann == TypeAnnotation::Basic("number".to_string())
})
});
assert!(
has_type_arg,
"callsite_type_args should contain T=number for double(3.14), got: {:?}",
engine.callsite_type_args
);
}
#[test]
fn test_compile_time_int_array() {
let result = crate::test_utils::eval("[1, 2, 3]");
assert!(result.is_heap(), "array should be heap-allocated");
}
#[test]
fn test_compile_time_float_array() {
let result = crate::test_utils::eval("[1.0, 2.0, 3.0]");
assert!(result.is_heap(), "array should be heap-allocated");
}
#[test]
fn test_compile_time_bool_array() {
let result = crate::test_utils::eval("[true, false, true]");
assert!(result.is_heap(), "array should be heap-allocated");
}
#[test]
fn test_generic_struct_field_access() {
let result = crate::test_utils::eval(
r#"
type Wrapper<T> { value: T }
let w = Wrapper { value: 42 }
w.value
"#,
);
assert_eq!(result.as_i64(), Some(42));
}
#[test]
fn test_generic_struct_string_field() {
let result = crate::test_utils::eval(
r#"
type Box<T> { item: T }
let b = Box { item: "hello" }
b.item
"#,
);
assert_eq!(result.as_str(), Some("hello"));
}
#[test]
fn test_generic_struct_two_params() {
let result = crate::test_utils::eval(
r#"
type Pair<A, B> { first: A, second: B }
let p = Pair { first: 42, second: "hi" }
p.first
"#,
);
assert_eq!(result.as_i64(), Some(42));
}
}