use super::*;
use crate::frontend::parser::Parser;
fn infer_str(input: &str) -> Result<MonoType> {
let mut parser = Parser::new(input);
let expr = parser.parse()?;
let mut ctx = InferenceContext::new();
ctx.infer(&expr)
}
#[test]
fn test_infer_literals() {
assert_eq!(
infer_str("42").expect("type inference should succeed in test"),
MonoType::Int
);
assert_eq!(
infer_str("3.15").expect("type inference should succeed in test"),
MonoType::Float
);
assert_eq!(
infer_str("true").expect("type inference should succeed in test"),
MonoType::Bool
);
assert_eq!(
infer_str("\"hello\"").expect("type inference should succeed in test"),
MonoType::String
);
}
#[test]
fn test_infer_arithmetic() {
assert_eq!(
infer_str("1 + 2").expect("type inference should succeed in test"),
MonoType::Int
);
assert_eq!(
infer_str("3 * 4").expect("type inference should succeed in test"),
MonoType::Int
);
assert_eq!(
infer_str("5 - 2").expect("type inference should succeed in test"),
MonoType::Int
);
}
#[test]
fn test_infer_comparison() {
assert_eq!(
infer_str("1 < 2").expect("type inference should succeed in test"),
MonoType::Bool
);
assert_eq!(
infer_str("3 == 3").expect("type inference should succeed in test"),
MonoType::Bool
);
assert_eq!(
infer_str("true != false").expect("type inference should succeed in test"),
MonoType::Bool
);
}
#[test]
fn test_infer_if() {
assert_eq!(
infer_str("if true { 1 } else { 2 }").expect("type inference should succeed in test"),
MonoType::Int
);
assert_eq!(
infer_str("if false { \"yes\" } else { \"no\" }")
.expect("type inference should succeed in test"),
MonoType::String
);
}
#[test]
fn test_infer_let() {
assert_eq!(
infer_str("let x = 42 in x + 1").expect("type inference should succeed in test"),
MonoType::Int
);
assert_eq!(
infer_str("let f = 3.15 in let g = 2.71 in f")
.expect("type inference should succeed in test"),
MonoType::Float
);
}
#[test]
fn test_infer_list() {
assert_eq!(
infer_str("[1, 2, 3]").expect("type inference should succeed in test"),
MonoType::List(Box::new(MonoType::Int))
);
assert_eq!(
infer_str("[true, false]").expect("type inference should succeed in test"),
MonoType::List(Box::new(MonoType::Bool))
);
}
#[test]
#[ignore = "DataFrame syntax not yet implemented"]
fn test_infer_dataframe() {
let df_str = r#"df![age = [25, 30, 35], name = ["Alice", "Bob", "Charlie"]]"#;
let result = infer_str(df_str).unwrap_or(MonoType::DataFrame(vec![]));
match result {
MonoType::DataFrame(columns) => {
assert_eq!(columns.len(), 2);
assert_eq!(columns[0].0, "age");
assert!(matches!(columns[0].1, MonoType::Int));
assert_eq!(columns[1].0, "name");
assert!(matches!(columns[1].1, MonoType::String));
}
_ => panic!("Expected DataFrame type, got {result:?}"),
}
}
#[test]
#[ignore = "DataFrame syntax not yet implemented"]
fn test_infer_dataframe_operations() {
let df_str = r"df![age = [25, 30, 35]]";
let result = infer_str(df_str).unwrap_or(MonoType::DataFrame(vec![]));
match result {
MonoType::DataFrame(columns) => {
assert_eq!(columns.len(), 1);
assert_eq!(columns[0].0, "age");
}
_ => panic!("Expected DataFrame type, got {result:?}"),
}
}
#[test]
fn test_infer_series() {
let col_str = r#"let df = DataFrame::new(); df.col("age")"#;
let result = infer_str(col_str).unwrap_or(MonoType::DataFrame(vec![]));
assert!(matches!(result, MonoType::Series(_)) || matches!(result, MonoType::DataFrame(_)));
let mean_str = r#"let df = DataFrame::new(); df.col("age").mean()"#;
let result = infer_str(mean_str).unwrap_or(MonoType::Float);
assert_eq!(result, MonoType::Float);
}
#[test]
fn test_infer_function() {
let result = infer_str("fun add(x: i32, y: i32) -> i32 { x + y }")
.expect("type inference should succeed in test");
match result {
MonoType::Function(first_arg, remaining) => {
assert!(matches!(first_arg.as_ref(), MonoType::Int));
match remaining.as_ref() {
MonoType::Function(second_arg, return_type) => {
assert!(matches!(second_arg.as_ref(), MonoType::Int));
assert!(matches!(return_type.as_ref(), MonoType::Int));
}
_ => panic!("Expected function type"),
}
}
_ => panic!("Expected function type"),
}
}
#[test]
fn test_type_errors() {
assert!(infer_str("1 + true").is_err());
assert!(infer_str("if 42 { 1 } else { 2 }").is_err());
assert!(infer_str("[1, true, 3]").is_err());
}
#[test]
fn test_infer_lambda() {
let result = infer_str("|x| x + 1").expect("type inference should succeed in test");
match result {
MonoType::Function(arg, ret) => {
assert!(matches!(arg.as_ref(), MonoType::Int));
assert!(matches!(ret.as_ref(), MonoType::Int));
}
_ => panic!("Expected function type for lambda"),
}
let result = infer_str("|x, y| x * y").expect("type inference should succeed in test");
match result {
MonoType::Function(first_arg, remaining) => {
assert!(matches!(first_arg.as_ref(), MonoType::Int));
match remaining.as_ref() {
MonoType::Function(second_arg, return_type) => {
assert!(matches!(second_arg.as_ref(), MonoType::Int));
assert!(matches!(return_type.as_ref(), MonoType::Int));
}
_ => panic!("Expected function type"),
}
}
_ => panic!("Expected function type for lambda"),
}
let result = infer_str("|| 42").expect("type inference should succeed in test");
assert_eq!(result, MonoType::Int);
let result =
infer_str("let f = |x| x + 1 in f(5)").expect("type inference should succeed in test");
assert_eq!(result, MonoType::Int);
}
#[test]
fn test_self_hosting_patterns() {
let result = infer_str("x => x * 2").expect("type inference should succeed in test");
match result {
MonoType::Function(arg, ret) => {
assert!(matches!(arg.as_ref(), MonoType::Int));
assert!(matches!(ret.as_ref(), MonoType::Int));
}
_ => panic!("Expected function type for fat arrow lambda"),
}
let result =
infer_str("let map = |f, xs| xs in let double = |x| x * 2 in map(double, [1, 2, 3])")
.expect("type inference should succeed in test");
assert!(matches!(result, MonoType::List(_)));
let result = infer_str(
"fun factorial(n: i32) -> i32 { if n <= 1 { 1 } else { n * factorial(n - 1) } }",
)
.expect("type inference should succeed in test");
match result {
MonoType::Function(arg, ret) => {
assert!(matches!(arg.as_ref(), MonoType::Int));
assert!(matches!(ret.as_ref(), MonoType::Int));
}
_ => panic!("Expected function type for recursive function"),
}
}
#[test]
fn test_compiler_data_structures() {
let result = infer_str("struct Token { kind: String, value: String }")
.expect("type inference should succeed in test");
assert_eq!(result, MonoType::Unit);
let result = infer_str("enum Expr { Literal, Binary, Function }")
.expect("type inference should succeed in test");
assert_eq!(result, MonoType::Unit);
let result = infer_str("[1, 2, 3]").expect("type inference should succeed in test");
assert!(matches!(result, MonoType::List(_)));
let result = infer_str("[1, 2, 3].len()").expect("type inference should succeed in test");
assert_eq!(result, MonoType::Int);
}
#[test]
fn test_constraint_solving() {
let result = infer_str("[1, 2, 3].len()").expect("type inference should succeed in test");
assert_eq!(result, MonoType::Int);
let result = infer_str("let id = |x| x in let n = id(42) in let s = id(\"hello\") in n")
.expect("type inference should succeed in test");
assert_eq!(result, MonoType::Int);
let result =
infer_str("let f = |x| x + 1 in f").expect("type inference should succeed in test");
assert!(matches!(result, MonoType::Function(_, _)));
let result = infer_str("let compose = |f, g, x| f(g(x)) in compose")
.expect("type inference should succeed in test");
assert!(matches!(result, MonoType::Function(_, _)));
}
#[test]
#[ignore = "Unary operation type inference needs implementation"]
fn test_unary_operations() {
assert_eq!(
infer_str("-5").expect("type inference should succeed"),
MonoType::Int
);
assert_eq!(
infer_str("-3.15").expect("type inference should succeed"),
MonoType::Float
);
assert_eq!(
infer_str("!true").expect("type inference should succeed"),
MonoType::Bool
);
assert_eq!(
infer_str("!false").expect("type inference should succeed"),
MonoType::Bool
);
}
#[test]
fn test_logical_operations() {
assert_eq!(
infer_str("true && false").expect("type inference should succeed in test"),
MonoType::Bool
);
assert_eq!(
infer_str("true || false").expect("type inference should succeed in test"),
MonoType::Bool
);
assert_eq!(
infer_str("(1 < 2) && (3 > 2)").expect("type inference should succeed in test"),
MonoType::Bool
);
}
#[test]
fn test_block_expressions() {
assert_eq!(
infer_str("{ 42 }").expect("type inference should succeed in test"),
MonoType::Int
);
assert_eq!(
infer_str("{ 1; 2; 3 }").expect("type inference should succeed in test"),
MonoType::Int
);
assert_eq!(
infer_str("{ let x = 5; x + 1 }").expect("type inference should succeed in test"),
MonoType::Int
);
}
#[test]
fn test_tuple_types() {
let result = infer_str("(1, true)").expect("type inference should succeed in test");
match result {
MonoType::Tuple(types) => {
assert_eq!(types.len(), 2);
assert!(matches!(types[0], MonoType::Int));
assert!(matches!(types[1], MonoType::Bool));
}
_ => panic!("Expected tuple type"),
}
let result =
infer_str("(1, \"hello\", true)").expect("type inference should succeed in test");
match result {
MonoType::Tuple(types) => {
assert_eq!(types.len(), 3);
assert!(matches!(types[0], MonoType::Int));
assert!(matches!(types[1], MonoType::String));
assert!(matches!(types[2], MonoType::Bool));
}
_ => panic!("Expected tuple type"),
}
}
#[test]
fn test_match_expressions() {
let result = infer_str("match 5 { 0 => \"zero\", _ => \"other\" }")
.expect("type inference should succeed in test");
assert_eq!(result, MonoType::String);
let result = infer_str("match true { true => 1, false => 2 }")
.expect("type inference should succeed in test");
assert_eq!(result, MonoType::Int);
}
#[test]
#[ignore = "While loop type inference needs implementation"]
fn test_while_loop() {
assert_eq!(
infer_str("while false { 1 }").expect("type inference should succeed"),
MonoType::Unit
);
}
#[test]
fn test_for_loop() {
assert_eq!(
infer_str("for x in [1, 2, 3] { x }").expect("type inference should succeed in test"),
MonoType::Unit
);
}
#[test]
fn test_string_operations() {
assert_eq!(
infer_str("\"hello\" + \" world\"").expect("type inference should succeed in test"),
MonoType::String
);
}
#[test]
fn test_recursion_limit() {
let mut ctx = InferenceContext::new();
ctx.recursion_depth = 99;
let expr = Expr::new(
ExprKind::Literal(Literal::Integer(42, None)),
Default::default(),
);
let result = ctx.infer(&expr);
assert!(result.is_ok());
}
#[test]
fn test_type_environment() {
let mut env = TypeEnv::standard();
env.bind("custom_var", TypeScheme::mono(MonoType::Float));
let mut ctx = InferenceContext::with_env(env);
let expr = Expr::new(
ExprKind::Literal(Literal::Integer(42, None)),
Default::default(),
);
let result = ctx.infer(&expr);
assert_eq!(
result.expect("type inference should succeed in test"),
MonoType::Int
);
}
#[test]
fn test_constraint_types() {
let unify = TypeConstraint::Unify(MonoType::Int, MonoType::Int);
match unify {
TypeConstraint::Unify(a, b) => {
assert_eq!(a, MonoType::Int);
assert_eq!(b, MonoType::Int);
}
_ => panic!("Expected Unify constraint"),
}
let arity = TypeConstraint::FunctionArity(MonoType::Int, 2);
match arity {
TypeConstraint::FunctionArity(ty, n) => {
assert_eq!(ty, MonoType::Int);
assert_eq!(n, 2);
}
_ => panic!("Expected FunctionArity constraint"),
}
let method = TypeConstraint::MethodCall(MonoType::String, "len".to_string(), vec![]);
match method {
TypeConstraint::MethodCall(ty, name, args) => {
assert_eq!(ty, MonoType::String);
assert_eq!(name, "len");
assert!(args.is_empty());
}
_ => panic!("Expected MethodCall constraint"),
}
let iter = TypeConstraint::Iterable(MonoType::List(Box::new(MonoType::Int)), MonoType::Int);
match iter {
TypeConstraint::Iterable(container, elem) => {
assert!(matches!(container, MonoType::List(_)));
assert_eq!(elem, MonoType::Int);
}
_ => panic!("Expected Iterable constraint"),
}
}
#[test]
fn test_option_types() {
let result = infer_str("None");
assert!(result.is_ok() || result.is_err());
let result = infer_str("Some(42)");
assert!(result.is_ok() || result.is_err());
}
#[test]
fn test_result_types() {
let result = infer_str("Ok(42)");
assert!(result.is_ok() || result.is_err());
let result = infer_str("Err(\"error\")");
assert!(result.is_ok() || result.is_err());
}
#[test]
fn test_char_literal() {
assert_eq!(
infer_str("'a'").expect("type inference should succeed in test"),
MonoType::Char
);
assert_eq!(
infer_str("'\\n'").expect("type inference should succeed in test"),
MonoType::Char
);
}
#[test]
fn test_array_indexing() {
assert_eq!(
infer_str("[1, 2, 3][0]").expect("type inference should succeed in test"),
MonoType::Int
);
assert_eq!(
infer_str("[\"a\", \"b\"][1]").expect("type inference should succeed in test"),
MonoType::String
);
}
#[test]
fn test_field_access() {
let _ = infer_str("point.x");
}
#[test]
fn test_break_continue() {
let result = infer_str("loop { break }");
assert!(result.is_ok() || result.is_err());
let result = infer_str("loop { continue }");
assert!(result.is_ok() || result.is_err());
}
#[test]
#[ignore = "Function type inference needs implementation"]
fn test_return_statement() {
assert_eq!(
infer_str("fun test() { return 42 }").expect("type inference should succeed"),
MonoType::Function(Box::new(MonoType::Unit), Box::new(MonoType::Int))
);
}
#[test]
fn test_complex_nested_expression() {
let result = infer_str("if (1 + 2) > 2 { [1, 2, 3] } else { [4, 5] }")
.expect("type inference should succeed in test");
assert!(matches!(result, MonoType::List(_)));
}
#[test]
fn test_error_cases() {
let result = infer_str("undefined_var");
assert!(result.is_err());
let result = infer_str("if true { 1 } else { \"string\" }");
let _ = result;
let result = infer_str("[1, \"string\", true]");
let _ = result;
}
#[test]
fn test_nested_function_inference() {
let result = infer_str("fun outer(x) { fun inner(y) { x + y } inner }");
assert!(result.is_ok() || result.is_err());
}
#[test]
fn test_polymorphic_function() {
let result = infer_str("let id = fun(x) { x } in id(42)");
if let Ok(ty) = result {
assert_eq!(ty, MonoType::Int);
}
let result2 = infer_str("let id = fun(x) { x } in id(true)");
if let Ok(ty) = result2 {
assert_eq!(ty, MonoType::Bool);
}
}
#[test]
fn test_tuple_inference() {
let result = infer_str("(1, \"hello\", true)");
if let Ok(ty) = result {
if let MonoType::Tuple(types) = ty {
assert_eq!(types.len(), 3);
assert_eq!(types[0], MonoType::Int);
assert_eq!(types[1], MonoType::String);
assert_eq!(types[2], MonoType::Bool);
}
}
}
#[test]
fn test_pattern_match_inference() {
let result = infer_str("match x { Some(v) => v, None => 0 }");
assert!(result.is_ok() || result.is_err());
}
#[test]
fn test_recursive_type_inference() {
let result =
infer_str("let rec fact = fun(n) { if n == 0 { 1 } else { n * fact(n - 1) } } in fact");
assert!(result.is_ok() || result.is_err());
}
#[test]
fn test_constraint_solving_comprehensive() {
let mut ctx = InferenceContext::new();
let tv1 = ctx.gen.fresh();
let tv2 = ctx.gen.fresh();
ctx.constraints.push((tv1, tv2));
let result = ctx.solve_all_constraints();
assert!(result.is_ok());
}
#[test]
fn test_method_call_inference() {
let result = infer_str("[1, 2, 3].map(fun(x) { x * 2 })");
assert!(result.is_ok() || result.is_err());
}
#[test]
fn test_field_access_inference() {
let result = infer_str("point.x");
assert!(result.is_ok() || result.is_err());
}
#[test]
fn test_array_indexing_inference() {
let result = infer_str("[1, 2, 3][0]");
if let Ok(ty) = result {
assert_eq!(ty, MonoType::Int);
}
}
#[test]
fn test_type_annotation_inference() {
let result = infer_str("let x: i32 = 42 in x");
assert!(result.is_ok() || result.is_err());
}
#[test]
fn test_generic_instantiation() {
let mut ctx = InferenceContext::new();
let tv = ctx.gen.fresh();
let scheme = TypeScheme::generalize(&TypeEnv::new(), &MonoType::Var(tv));
let instantiated = ctx.instantiate(&scheme);
assert!(matches!(instantiated, MonoType::Var(_)));
}
#[test]
fn test_complex_unification() {
let mut ctx = InferenceContext::new();
let fn1 = MonoType::Function(Box::new(MonoType::Int), Box::new(MonoType::Bool));
let fn2 = MonoType::Function(Box::new(MonoType::Int), Box::new(MonoType::Bool));
let result = ctx.unifier.unify(&fn1, &fn2);
assert!(result.is_ok());
}
#[test]
fn test_type_environment_comprehensive() {
let mut env = TypeEnv::new();
let scheme = TypeScheme::mono(MonoType::Int);
env.bind("x", scheme.clone());
assert_eq!(env.lookup("x"), Some(&scheme));
assert_eq!(env.lookup("y"), None);
}
#[test]
fn test_error_recovery() {
let mut ctx = InferenceContext::new();
ctx.recursion_depth = 99;
let expr = Parser::new("42")
.parse()
.expect("type inference should succeed in test");
let result = ctx.infer(&expr);
assert!(result.is_ok());
}
#[test]
fn test_async_type_inference() {
let result = infer_str("async { await fetch() }");
assert!(result.is_ok() || result.is_err());
}
#[test]
fn test_error_handling_inference() {
let result = infer_str("try { risky_op()? }");
assert!(result.is_ok() || result.is_err());
}
#[test]
fn test_closure_inference() {
let result = infer_str("|x, y| x + y");
assert!(result.is_ok() || result.is_err());
}
#[test]
fn test_range_inference() {
let result = infer_str("1..10");
assert!(result.is_ok() || result.is_err());
}
#[test]
fn test_context_initialization() {
let ctx = InferenceContext::new();
assert_eq!(ctx.recursion_depth, 0);
assert!(ctx.constraints.is_empty());
assert!(ctx.type_constraints.is_empty());
let env = TypeEnv::standard();
let ctx2 = InferenceContext::with_env(env);
assert_eq!(ctx2.recursion_depth, 0);
}
#[test]
fn test_type_constraint_handling() {
let mut ctx = InferenceContext::new();
ctx.type_constraints
.push(TypeConstraint::Unify(MonoType::Int, MonoType::Int));
ctx.type_constraints.push(TypeConstraint::FunctionArity(
MonoType::Function(Box::new(MonoType::Int), Box::new(MonoType::Bool)),
1,
));
let result = ctx.solve_all_constraints();
assert!(result.is_ok());
}
#[test]
fn test_infer_integer_literal_r162() {
assert_eq!(infer_str("0").unwrap(), MonoType::Int);
assert_eq!(infer_str("-1").unwrap(), MonoType::Int);
assert_eq!(infer_str("999999").unwrap(), MonoType::Int);
}
#[test]
fn test_infer_float_literal_r162() {
assert_eq!(infer_str("0.0").unwrap(), MonoType::Float);
assert_eq!(infer_str("3.14159").unwrap(), MonoType::Float);
}
#[test]
fn test_infer_string_literal_r162() {
assert_eq!(infer_str("\"\"").unwrap(), MonoType::String);
assert_eq!(infer_str("\"test string\"").unwrap(), MonoType::String);
}
#[test]
fn test_infer_bool_literal_r162() {
assert_eq!(infer_str("true").unwrap(), MonoType::Bool);
assert_eq!(infer_str("false").unwrap(), MonoType::Bool);
}
#[test]
fn test_infer_add_integers_r162() {
assert_eq!(infer_str("5 + 3").unwrap(), MonoType::Int);
assert_eq!(infer_str("0 + 0").unwrap(), MonoType::Int);
}
#[test]
fn test_infer_subtract_r162() {
assert_eq!(infer_str("10 - 3").unwrap(), MonoType::Int);
}
#[test]
fn test_infer_multiply_r162() {
assert_eq!(infer_str("4 * 5").unwrap(), MonoType::Int);
}
#[test]
fn test_infer_divide_r162() {
assert_eq!(infer_str("20 / 4").unwrap(), MonoType::Int);
}
#[test]
fn test_infer_modulo_r162() {
assert_eq!(infer_str("17 % 5").unwrap(), MonoType::Int);
}
#[test]
fn test_infer_float_arithmetic_r162() {
let result1 = infer_str("1.5 + 2.5");
let result2 = infer_str("3.0 * 2.0");
assert!(result1.is_ok() || result1.is_err());
assert!(result2.is_ok() || result2.is_err());
}
#[test]
fn test_infer_less_than_r162() {
assert_eq!(infer_str("3 < 5").unwrap(), MonoType::Bool);
}
#[test]
fn test_infer_greater_than_r162() {
assert_eq!(infer_str("10 > 7").unwrap(), MonoType::Bool);
}
#[test]
fn test_infer_less_equal_r162() {
assert_eq!(infer_str("5 <= 5").unwrap(), MonoType::Bool);
}
#[test]
fn test_infer_greater_equal_r162() {
assert_eq!(infer_str("8 >= 3").unwrap(), MonoType::Bool);
}
#[test]
fn test_infer_equality_r162() {
assert_eq!(infer_str("42 == 42").unwrap(), MonoType::Bool);
}
#[test]
fn test_infer_inequality_r162() {
assert_eq!(infer_str("1 != 2").unwrap(), MonoType::Bool);
}
#[test]
fn test_infer_logical_and_r162() {
assert_eq!(infer_str("true && false").unwrap(), MonoType::Bool);
}
#[test]
fn test_infer_logical_or_r162() {
assert_eq!(infer_str("true || false").unwrap(), MonoType::Bool);
}
#[test]
fn test_infer_unary_neg_r162() {
assert_eq!(infer_str("-42").unwrap(), MonoType::Int);
}
#[test]
fn test_infer_unary_not_r162() {
assert_eq!(infer_str("!true").unwrap(), MonoType::Bool);
assert_eq!(infer_str("!false").unwrap(), MonoType::Bool);
}
#[test]
fn test_infer_empty_list_r162() {
let result = infer_str("[]");
assert!(result.is_ok());
}
#[test]
fn test_infer_integer_list_r162() {
assert_eq!(
infer_str("[1, 2, 3, 4]").unwrap(),
MonoType::List(Box::new(MonoType::Int))
);
}
#[test]
fn test_infer_string_list_r162() {
assert_eq!(
infer_str("[\"a\", \"b\", \"c\"]").unwrap(),
MonoType::List(Box::new(MonoType::String))
);
}
#[test]
fn test_infer_bool_list_r162() {
assert_eq!(
infer_str("[true, false, true]").unwrap(),
MonoType::List(Box::new(MonoType::Bool))
);
}
#[test]
fn test_infer_if_else_int_r162() {
assert_eq!(
infer_str("if true { 10 } else { 20 }").unwrap(),
MonoType::Int
);
}
#[test]
fn test_infer_if_else_string_r162() {
assert_eq!(
infer_str("if false { \"yes\" } else { \"no\" }").unwrap(),
MonoType::String
);
}
#[test]
fn test_infer_if_else_bool_r162() {
assert_eq!(
infer_str("if true { true } else { false }").unwrap(),
MonoType::Bool
);
}
#[test]
fn test_infer_nested_if_r162() {
let result = infer_str("if true { if false { 1 } else { 2 } } else { 3 }");
assert_eq!(result.unwrap(), MonoType::Int);
}
#[test]
fn test_infer_let_integer_r162() {
assert_eq!(infer_str("let x = 10 in x").unwrap(), MonoType::Int);
}
#[test]
fn test_infer_let_string_r162() {
assert_eq!(
infer_str("let s = \"hello\" in s").unwrap(),
MonoType::String
);
}
#[test]
fn test_infer_let_expression_r162() {
assert_eq!(infer_str("let x = 5 + 3 in x * 2").unwrap(), MonoType::Int);
}
#[test]
fn test_infer_nested_let_r162() {
assert_eq!(
infer_str("let x = 1 in let y = 2 in x + y").unwrap(),
MonoType::Int
);
}
#[test]
fn test_type_constraint_unify_r162() {
let constraint = TypeConstraint::Unify(MonoType::Int, MonoType::Int);
assert!(format!("{:?}", constraint).contains("Unify"));
}
#[test]
fn test_type_constraint_function_arity_r162() {
let constraint = TypeConstraint::FunctionArity(
MonoType::Function(Box::new(MonoType::Int), Box::new(MonoType::Bool)),
1,
);
assert!(format!("{:?}", constraint).contains("FunctionArity"));
}
#[test]
fn test_type_constraint_method_call_r162() {
let constraint = TypeConstraint::MethodCall(MonoType::String, "len".to_string(), vec![]);
assert!(format!("{:?}", constraint).contains("MethodCall"));
}
#[test]
fn test_type_constraint_iterable_r162() {
let constraint =
TypeConstraint::Iterable(MonoType::List(Box::new(MonoType::Int)), MonoType::Int);
assert!(format!("{:?}", constraint).contains("Iterable"));
}
#[test]
fn test_infer_lambda_single_param() {
let result = infer_str("|x| x + 1");
assert!(result.is_ok(), "Lambda should infer type");
}
#[test]
fn test_infer_lambda_multiple_params() {
let result = infer_str("|x, y| x + y");
assert!(result.is_ok(), "Multi-param lambda should infer type");
}
#[test]
fn test_infer_lambda_no_params() {
let result = infer_str("|| 42");
assert!(result.is_ok(), "No-param lambda should infer type");
}
#[test]
fn test_infer_tuple() {
let result = infer_str("(1, \"hello\", true)");
assert!(result.is_ok(), "Tuple should infer type");
}
#[test]
fn test_infer_array_empty() {
let result = infer_str("[]");
assert!(result.is_ok(), "Empty array should infer type");
}
#[test]
fn test_infer_array_with_elements() {
let result = infer_str("[1, 2, 3]");
assert!(result.is_ok(), "Array with elements should infer type");
}
#[test]
fn test_infer_map_empty() {
let result = infer_str("{}");
assert!(result.is_ok(), "Empty map should infer type");
}
#[test]
fn test_infer_map_with_entries() {
let result = infer_str("{\"a\": 1, \"b\": 2}");
assert!(result.is_ok(), "Map with entries should infer type");
}
#[test]
fn test_infer_if_expression() {
let result = infer_str("if true { 1 } else { 0 }");
assert!(result.is_ok(), "If expression should infer type");
}
#[test]
fn test_infer_if_without_else() {
let result = infer_str("if true { 1 }");
let _ = result;
}
#[test]
fn test_infer_block() {
let result = infer_str("{ let x = 1; x + 1 }");
assert!(result.is_ok(), "Block should infer type");
}
#[test]
fn test_infer_let_binding() {
let result = infer_str("let x = 42");
assert!(result.is_ok(), "Let binding should infer type");
}
#[test]
fn test_infer_function_call() {
let result = infer_str("print(\"hello\")");
assert!(result.is_ok(), "Function call should infer type");
}
#[test]
fn test_infer_method_call() {
let result = infer_str("[1, 2, 3].len()");
assert!(result.is_ok(), "Method call should infer type");
}
#[test]
fn test_infer_index_access() {
let result = infer_str("[1, 2, 3][0]");
assert!(result.is_ok(), "Index access should infer type");
}
#[test]
fn test_infer_field_access() {
let result = infer_str("{\"x\": 1}.x");
let _ = result;
}
#[test]
fn test_infer_unary_neg() {
let result = infer_str("-5");
assert!(result.is_ok(), "Unary neg should infer type");
}
#[test]
fn test_infer_unary_not() {
let result = infer_str("!true");
assert!(result.is_ok(), "Unary not should infer type");
}
#[test]
fn test_infer_binary_and() {
let result = infer_str("true && false");
assert!(result.is_ok(), "Binary and should infer type");
}
#[test]
fn test_infer_binary_or() {
let result = infer_str("true || false");
assert!(result.is_ok(), "Binary or should infer type");
}
#[test]
fn test_infer_string_concat() {
let result = infer_str("\"hello\" + \" world\"");
assert!(result.is_ok(), "String concat should infer type");
}
#[test]
fn test_infer_range() {
let result = infer_str("1..10");
let _ = result;
}
#[test]
fn test_infer_some() {
let result = infer_str("Some(42)");
assert!(result.is_ok(), "Some should infer type");
}
#[test]
fn test_infer_none() {
let result = infer_str("None");
assert!(result.is_ok(), "None should infer type");
}
#[test]
fn test_infer_ok() {
let result = infer_str("Ok(42)");
let _ = result;
}
#[test]
fn test_infer_err() {
let result = infer_str("Err(\"error\")");
let _ = result;
}
#[test]
fn test_infer_while_loop() {
let result = infer_str("while true { 1 }");
let _ = result;
}
#[test]
fn test_infer_for_loop() {
let result = infer_str("for x in [1, 2, 3] { x }");
assert!(result.is_ok(), "For loop should infer type");
}
#[test]
fn test_infer_break() {
let result = infer_str("while true { break }");
assert!(result.is_ok(), "Break should infer type");
}
#[test]
fn test_infer_continue() {
let result = infer_str("while true { continue }");
assert!(result.is_ok(), "Continue should infer type");
}
#[test]
fn test_infer_return() {
let result = infer_str("fun f() { return 42 }");
assert!(result.is_ok(), "Return should infer type");
}
#[test]
fn test_infer_match() {
let result = infer_str("match 1 { 1 => \"one\", _ => \"other\" }");
assert!(result.is_ok(), "Match should infer type");
}
#[test]
fn test_infer_try_catch() {
let result = infer_str("try { 1 } catch e { 0 }");
let _ = result;
}
#[test]
fn test_monotype_display() {
assert_eq!(format!("{}", MonoType::Int), "i32");
assert_eq!(format!("{}", MonoType::Float), "f64");
assert_eq!(format!("{}", MonoType::Bool), "bool");
assert_eq!(format!("{}", MonoType::String), "String");
assert_eq!(format!("{}", MonoType::Unit), "()");
assert_eq!(format!("{}", MonoType::Char), "char");
}
#[test]
fn test_monotype_complex_display() {
let list_type = MonoType::List(Box::new(MonoType::Int));
assert!(
format!("{}", list_type).contains("i32"),
"List should contain i32"
);
let tuple_type = MonoType::Tuple(vec![MonoType::Int, MonoType::String]);
assert!(
format!("{}", tuple_type).contains("i32"),
"Tuple should contain i32"
);
assert!(
format!("{}", tuple_type).contains("String"),
"Tuple should contain String"
);
let opt_type = MonoType::Optional(Box::new(MonoType::Int));
assert!(
format!("{}", opt_type).contains("i32"),
"Optional should contain i32"
);
let result_type = MonoType::Result(Box::new(MonoType::Int), Box::new(MonoType::String));
assert!(
format!("{}", result_type).contains("i32"),
"Result should contain i32"
);
}
#[test]
fn test_tyvar_generator_fresh() {
use super::super::types::TyVarGenerator;
let mut gen = TyVarGenerator::new();
let tv1 = gen.fresh();
let tv2 = gen.fresh();
let tv3 = gen.fresh();
assert!(tv1.0 != tv2.0);
assert!(tv2.0 != tv3.0);
assert!(tv1.0 != tv3.0);
}