use crate::backend::transpiler::return_type_helpers::{
expr_is_string, returns_boolean, returns_object_literal, returns_string,
returns_string_literal, returns_vec,
};
use crate::backend::transpiler::Transpiler;
use crate::frontend::ast::{
BinaryOp, Expr, ExprKind, Literal, Param, Pattern, Span, Type, TypeKind, UnaryOp,
};
use crate::frontend::parser::Parser;
fn create_transpiler() -> Transpiler {
Transpiler::new()
}
fn _create_transpiler_dup() -> Transpiler {
Transpiler::new()
}
#[test]
fn test_transpile_if_with_else() {
let mut transpiler = create_transpiler();
let code = "if true { 1 } else { 2 }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler
.transpile(&ast)
.expect("transpile should succeed in test");
let rust_str = result.to_string();
assert!(rust_str.contains("if"));
assert!(rust_str.contains("else"));
}
#[test]
fn test_transpile_if_without_else() {
let mut transpiler = create_transpiler();
let code = "let x = true; if x { 1 }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler
.transpile(&ast)
.expect("transpile should succeed in test");
let rust_str = result.to_string();
assert!(rust_str.contains("if") && rust_str.contains("x"));
assert!(!rust_str.is_empty());
}
#[test]
fn test_transpile_let_binding() {
let mut transpiler = create_transpiler();
let code = "let x = 5; x";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler
.transpile(&ast)
.expect("transpile should succeed in test");
let rust_str = result.to_string();
assert!(rust_str.contains("let"));
assert!(rust_str.contains("x"));
assert!(rust_str.contains("5"));
}
#[test]
fn test_transpile_mutable_let() {
let mut transpiler = create_transpiler();
let code = "let mut x = 5; x";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler
.transpile(&ast)
.expect("transpile should succeed in test");
let rust_str = result.to_string();
assert!(rust_str.contains("mut"));
}
#[test]
fn test_transpile_for_loop() {
let mut transpiler = create_transpiler();
let code = "for x in [1, 2, 3] { x }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler
.transpile(&ast)
.expect("transpile should succeed in test");
let rust_str = result.to_string();
assert!(rust_str.contains("for"));
assert!(rust_str.contains("in"));
}
#[test]
fn test_transpile_while_loop() {
let mut transpiler = create_transpiler();
let code = "while true { }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler
.transpile(&ast)
.expect("transpile should succeed in test");
let rust_str = result.to_string();
assert!(rust_str.contains("while"));
}
#[test]
fn test_function_with_parameters() {
let mut transpiler = create_transpiler();
let code = "fun add(x, y) { x + y }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler
.transpile(&ast)
.expect("transpile should succeed in test");
let rust_str = result.to_string();
assert!(rust_str.contains("fn add"));
assert!(rust_str.contains("x"));
assert!(rust_str.contains("y"));
}
#[test]
fn test_function_without_parameters() {
let mut transpiler = create_transpiler();
let code = "fun hello() { \"world\" }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler
.transpile(&ast)
.expect("transpile should succeed in test");
let rust_str = result.to_string();
assert!(rust_str.contains("fn hello"));
assert!(rust_str.contains("()"));
}
#[test]
fn test_match_expression() {
let mut transpiler = create_transpiler();
let code = "match x { 1 => \"one\", _ => \"other\" }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler
.transpile(&ast)
.expect("transpile should succeed in test");
let rust_str = result.to_string();
assert!(rust_str.contains("match"));
}
#[test]
fn test_lambda_expression() {
let mut transpiler = create_transpiler();
let code = "(x) => x + 1";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler
.transpile(&ast)
.expect("transpile should succeed in test");
let rust_str = result.to_string();
assert!(rust_str.contains("|") || rust_str.contains("move"));
}
#[test]
fn test_reserved_keyword_handling() {
let mut transpiler = create_transpiler();
let code = "let move = 5; move"; let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler
.transpile(&ast)
.expect("transpile should succeed in test");
let rust_str = result.to_string();
assert!(
rust_str.contains("r#move"),
"Expected r#move in: {rust_str}"
);
}
#[test]
fn test_generic_function() {
let mut transpiler = create_transpiler();
let code = "fun identity<T>(x: T) -> T { x }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler
.transpile(&ast)
.expect("transpile should succeed in test");
let rust_str = result.to_string();
assert!(rust_str.contains("fn identity"));
}
#[test]
fn test_main_function_special_case() {
let mut transpiler = create_transpiler();
let code = "fun main() { println(\"Hello\") }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler
.transpile(&ast)
.expect("transpile should succeed in test");
let rust_str = result.to_string();
assert!(!rust_str.contains("fn main() ->"));
assert!(!rust_str.contains("fn main () ->"));
}
#[test]
fn test_dataframe_function_call() {
let mut transpiler = create_transpiler();
let code = "col(\"name\")";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler
.transpile(&ast)
.expect("transpile should succeed in test");
let rust_str = result.to_string();
assert!(rust_str.contains("polars") || rust_str.contains("col"));
}
#[test]
fn test_regular_function_call_string_conversion() {
let mut transpiler = create_transpiler();
let code = "my_func(\"test\")";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler
.transpile(&ast)
.expect("transpile should succeed in test");
let rust_str = result.to_string();
assert!(rust_str.contains("my_func"));
assert!(rust_str.contains("to_string") || rust_str.contains("\"test\""));
}
#[test]
fn test_nested_expressions() {
let mut transpiler = create_transpiler();
let code = "if true { let x = 5; x + 1 } else { 0 }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler
.transpile(&ast)
.expect("transpile should succeed in test");
let rust_str = result.to_string();
assert!(rust_str.contains("if"));
assert!(rust_str.contains("let"));
assert!(rust_str.contains("else"));
}
#[test]
fn test_type_inference_integration() {
let mut transpiler = create_transpiler();
let code1 = "fun apply(f, x) { f(x) }";
let mut parser1 = Parser::new(code1);
let ast1 = parser1.parse().expect("Failed to parse");
let result1 = transpiler
.transpile(&ast1)
.expect("operation should succeed in test");
let rust_str1 = result1.to_string();
assert!(rust_str1.contains("impl Fn"));
let code2 = "fun double(n) { n * 2 }";
let mut parser2 = Parser::new(code2);
let ast2 = parser2.parse().expect("Failed to parse");
let result2 = transpiler
.transpile(&ast2)
.expect("operation should succeed in test");
let rust_str2 = result2.to_string();
assert!(rust_str2.contains("n : i32") || rust_str2.contains("n: i32"));
let code3 = "fun greet(name) { \"Hello \" + name }";
let mut parser3 = Parser::new(code3);
let ast3 = parser3.parse().expect("Failed to parse");
let result3 = transpiler
.transpile(&ast3)
.expect("operation should succeed in test");
let rust_str3 = result3.to_string();
assert!(
rust_str3.contains("name : & str") || rust_str3.contains("name: &str"),
"Expected &str parameter type, got: {rust_str3}"
);
}
#[test]
fn test_return_type_inference() {
let mut transpiler = create_transpiler();
let code = "fun double(n) { n * 2 }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler
.transpile(&ast)
.expect("transpile should succeed in test");
let rust_str = result.to_string();
assert!(rust_str.contains("-> i32"));
}
#[test]
fn test_void_function_no_return_type() {
let mut transpiler = create_transpiler();
let code = "fun print_hello() { println(\"Hello\") }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler
.transpile(&ast)
.expect("transpile should succeed in test");
let rust_str = result.to_string();
assert!(!rust_str.contains("-> "));
}
#[test]
fn test_complex_function_combinations() {
let mut transpiler = create_transpiler();
let code = "fun transform(f, n, m) { f(n + m) * 2 }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler
.transpile(&ast)
.expect("transpile should succeed in test");
let rust_str = result.to_string();
assert!(rust_str.contains("impl Fn"));
assert!(rust_str.contains("n : i32") || rust_str.contains("n: i32"));
assert!(rust_str.contains("m : i32") || rust_str.contains("m: i32"));
}
#[test]
fn test_is_variable_mutated() {
use crate::frontend::ast::{Expr, ExprKind, Span};
let assign_expr = Expr::new(
ExprKind::Assign {
target: Box::new(Expr::new(
ExprKind::Identifier("x".to_string()),
Span { start: 0, end: 0 },
)),
value: Box::new(Expr::new(
ExprKind::Literal(crate::frontend::ast::Literal::Integer(42, None)),
Span { start: 0, end: 0 },
)),
},
Span { start: 0, end: 0 },
);
assert!(super::mutation_detection::is_variable_mutated(
"x",
&assign_expr
));
assert!(!super::mutation_detection::is_variable_mutated(
"y",
&assign_expr
));
}
#[test]
fn test_transpile_break_continue() {
let mut transpiler = create_transpiler();
let code = "while true { if x { break } else { continue } }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler
.transpile(&ast)
.expect("transpile should succeed in test");
let rust_str = result.to_string();
assert!(rust_str.contains("break"));
assert!(rust_str.contains("continue"));
}
#[test]
fn test_transpile_match_expression() {
let mut transpiler = create_transpiler();
let code = "match x { 1 => \"one\", 2 => \"two\", _ => \"other\" }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler
.transpile(&ast)
.expect("transpile should succeed in test");
let rust_str = result.to_string();
assert!(rust_str.contains("match"));
assert!(rust_str.contains("1 =>") || rust_str.contains("1i64 =>"));
assert!(rust_str.contains("2 =>") || rust_str.contains("2i64 =>"));
assert!(rust_str.contains("_ =>"));
}
#[test]
fn test_transpile_struct_declaration() {
let mut transpiler = create_transpiler();
let code = "struct Point { x: i32, y: i32 }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler
.transpile(&ast)
.expect("transpile should succeed in test");
let rust_str = result.to_string();
assert!(rust_str.contains("struct Point"));
assert!(rust_str.contains("x : i32") || rust_str.contains("x: i32"));
assert!(rust_str.contains("y : i32") || rust_str.contains("y: i32"));
}
#[test]
fn test_transpile_enum_declaration() {
let mut transpiler = create_transpiler();
let code = "enum Color { Red, Green, Blue }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler
.transpile(&ast)
.expect("transpile should succeed in test");
let rust_str = result.to_string();
assert!(rust_str.contains("enum Color"));
assert!(rust_str.contains("Red"));
assert!(rust_str.contains("Green"));
assert!(rust_str.contains("Blue"));
}
#[test]
fn test_transpile_impl_block() {
let code = "impl Point { fun new(x: i32, y: i32) -> Point { Point { x: x, y: y } } }";
let mut parser = Parser::new(code);
let result = parser.parse();
assert!(
result.is_ok(),
"impl blocks should be supported now (PARSER-009)"
);
let ast = result.expect("parse should succeed in test");
let mut transpiler = Transpiler::new();
let transpile_result = transpiler.transpile_to_program(&ast);
assert!(
transpile_result.is_ok(),
"impl block should transpile successfully"
);
}
#[test]
fn test_transpile_async_function() {
let mut transpiler = create_transpiler();
let code = "async fun fetch_data() { await http_get(\"url\") }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler
.transpile(&ast)
.expect("transpile should succeed in test");
let rust_str = result.to_string();
assert!(rust_str.contains("async fn"));
assert!(rust_str.contains("await"));
}
#[test]
fn test_transpile_try_catch() {
let mut transpiler = create_transpiler();
let code = "try { risky_operation() } catch (e) { handle_error(e) }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler
.transpile(&ast)
.expect("transpile should succeed in test");
let rust_str = result.to_string();
assert!(rust_str.contains("match") || rust_str.contains("risky_operation"));
}
#[test]
fn test_is_variable_mutated_extended() {
use crate::frontend::ast::{Expr, ExprKind, Span};
fn make_ident(name: &str) -> Expr {
Expr::new(ExprKind::Identifier(name.to_string()), Span::new(0, 1))
}
let assign_expr = Expr::new(
ExprKind::Assign {
target: Box::new(make_ident("x")),
value: Box::new(make_ident("y")),
},
Span::new(0, 1),
);
assert!(super::mutation_detection::is_variable_mutated(
"x",
&assign_expr
));
assert!(!super::mutation_detection::is_variable_mutated(
"z",
&assign_expr
));
let compound_expr = Expr::new(
ExprKind::CompoundAssign {
target: Box::new(make_ident("count")),
op: crate::frontend::ast::BinaryOp::Add,
value: Box::new(make_ident("1")),
},
Span::new(0, 1),
);
assert!(super::mutation_detection::is_variable_mutated(
"count",
&compound_expr
));
assert!(!super::mutation_detection::is_variable_mutated(
"other",
&compound_expr
));
let pre_inc = Expr::new(
ExprKind::PreIncrement {
target: Box::new(make_ident("i")),
},
Span::new(0, 1),
);
assert!(super::mutation_detection::is_variable_mutated(
"i", &pre_inc
));
let post_inc = Expr::new(
ExprKind::PostIncrement {
target: Box::new(make_ident("j")),
},
Span::new(0, 1),
);
assert!(super::mutation_detection::is_variable_mutated(
"j", &post_inc
));
let block = Expr::new(
ExprKind::Block(vec![assign_expr, make_ident("other")]),
Span::new(0, 1),
);
assert!(super::mutation_detection::is_variable_mutated("x", &block));
assert!(!super::mutation_detection::is_variable_mutated(
"other", &block
));
}
#[test]
fn test_transpile_return() {
let mut transpiler = create_transpiler();
let code = "fun test() { return 42 }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler
.transpile(&ast)
.expect("transpile should succeed in test");
let rust_str = result.to_string();
assert!(rust_str.contains("return"));
assert!(rust_str.contains("42"));
}
#[test]
fn test_transpile_break_continue_extended() {
let mut transpiler = create_transpiler();
let code = "while true { break }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler
.transpile(&ast)
.expect("transpile should succeed in test");
let rust_str = result.to_string();
assert!(rust_str.contains("break"));
let code2 = "for x in [1,2,3] { continue }";
let mut parser2 = Parser::new(code2);
let ast2 = parser2.parse().expect("Failed to parse");
let result2 = transpiler
.transpile(&ast2)
.expect("operation should succeed in test");
let rust_str2 = result2.to_string();
assert!(rust_str2.contains("continue"));
}
#[test]
fn test_transpile_match() {
let mut transpiler = create_transpiler();
let code = "match x { 1 => \"one\", 2 => \"two\", _ => \"other\" }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler
.transpile(&ast)
.expect("transpile should succeed in test");
let rust_str = result.to_string();
assert!(rust_str.contains("match"));
assert!(rust_str.contains("=>"));
assert!(rust_str.contains("_"));
}
#[test]
fn test_transpile_pattern_matching() {
let mut transpiler = create_transpiler();
let code = "let (a, b) = (1, 2); a + b";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler
.transpile(&ast)
.expect("transpile should succeed in test");
let rust_str = result.to_string();
assert!(rust_str.contains("let"));
let code2 = "match list { [] => 0, [x] => x, _ => -1 }";
let mut parser2 = Parser::new(code2);
if let Ok(ast2) = parser2.parse() {
let result2 = transpiler
.transpile(&ast2)
.expect("operation should succeed in test");
let rust_str2 = result2.to_string();
assert!(rust_str2.contains("match"));
}
}
#[test]
fn test_transpile_loop() {
let mut transpiler = create_transpiler();
let code = "loop { break }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler
.transpile(&ast)
.expect("transpile should succeed in test");
let rust_str = result.to_string();
assert!(rust_str.contains("loop"));
assert!(rust_str.contains("break"));
}
#[test]
fn test_is_variable_mutated_comprehensive() {
let code = "let mut x = 5; x = 10; x";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let is_mutated = super::mutation_detection::is_variable_mutated("x", &ast);
assert!(is_mutated);
let code2 = "let y = 5; y + 10";
let mut parser2 = Parser::new(code2);
let ast2 = parser2.parse().expect("Failed to parse");
let is_mutated2 = super::mutation_detection::is_variable_mutated("y", &ast2);
assert!(!is_mutated2);
}
#[test]
fn test_compound_assignment() {
let mut transpiler = create_transpiler();
let code = "let mut x = 5; x += 10; x";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler
.transpile(&ast)
.expect("transpile should succeed in test");
let rust_str = result.to_string();
assert!(rust_str.contains("mut"));
assert!(rust_str.contains("+="));
}
#[test]
fn test_increment_operations() {
let mut transpiler = create_transpiler();
let code = "let mut x = 5; ++x";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler
.transpile(&ast)
.expect("transpile should succeed in test");
let rust_str = result.to_string();
assert!(rust_str.contains("mut"));
let code2 = "let mut y = 5; y++";
let mut parser2 = Parser::new(code2);
let ast2 = parser2.parse().expect("Failed to parse");
let result2 = transpiler
.transpile(&ast2)
.expect("operation should succeed in test");
let rust_str2 = result2.to_string();
assert!(rust_str2.contains("mut"));
}
#[test]
fn test_match_expression_transpilation() {
let mut transpiler = create_transpiler();
let code = "match x { 1 => \"one\", 2 => \"two\", _ => \"other\" }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler
.transpile(&ast)
.expect("transpile should succeed in test");
let rust_str = result.to_string();
assert!(rust_str.contains("match"));
assert!(rust_str.contains("=>"));
assert!(rust_str.contains("_"));
}
#[test]
fn test_pattern_guards() {
let mut transpiler = create_transpiler();
let code = "match x { n if n > 0 => \"positive\", _ => \"non-positive\" }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler
.transpile(&ast)
.expect("transpile should succeed in test");
let rust_str = result.to_string();
assert!(rust_str.contains("if"));
}
#[test]
fn test_try_catch() {
let mut transpiler = create_transpiler();
let code = "try { risky_op() } catch(e) { handle(e) }";
let mut parser = Parser::new(code);
if let Ok(ast) = parser.parse() {
let result = transpiler.transpile(&ast);
assert!(result.is_ok() || result.is_err());
}
}
#[test]
fn test_async_function() {
let mut transpiler = create_transpiler();
let code = "async fun fetch_data() { await get_data() }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler
.transpile(&ast)
.expect("transpile should succeed in test");
let rust_str = result.to_string();
assert!(rust_str.contains("async"));
}
#[test]
fn test_list_comprehension() {
let mut transpiler = create_transpiler();
let code = "[x * 2 for x in [1, 2, 3]]";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler.transpile(&ast);
assert!(result.is_ok() || result.is_err());
}
#[test]
fn test_module_definition() {
let mut transpiler = create_transpiler();
let code = "mod utils { fun helper() { 42 } }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler.transpile(&ast);
if let Ok(rust_str) = result {
let str = rust_str.to_string();
assert!(str.contains("mod") || !str.is_empty());
}
}
#[test]
fn test_import_statement() {
let mut transpiler = create_transpiler();
let code = "import \"std::fs\"";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler.transpile(&ast);
assert!(result.is_ok() || result.is_err());
}
#[test]
fn test_export_statement() {
let mut transpiler = create_transpiler();
let code = "export fun public_func() { 42 }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler.transpile(&ast);
assert!(result.is_ok() || result.is_err());
}
#[test]
fn test_return_statement() {
let mut transpiler = create_transpiler();
let code = "fun early_return() { if true { return 42 } 0 }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler
.transpile(&ast)
.expect("transpile should succeed in test");
let rust_str = result.to_string();
assert!(rust_str.contains("return"));
}
#[test]
fn test_break_continue() {
let mut transpiler = create_transpiler();
let code = "while true { if done { break } }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler
.transpile(&ast)
.expect("transpile should succeed in test");
let rust_str = result.to_string();
assert!(rust_str.contains("break"));
let code2 = "for x in items { if skip { continue } }";
let mut parser2 = Parser::new(code2);
let ast2 = parser2.parse().expect("Failed to parse");
let result2 = transpiler
.transpile(&ast2)
.expect("operation should succeed in test");
let rust_str2 = result2.to_string();
assert!(rust_str2.contains("continue"));
}
#[test]
fn test_nested_blocks() {
let mut transpiler = create_transpiler();
let code = "{ let x = 1; { let y = 2; x + y } }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler
.transpile(&ast)
.expect("transpile should succeed in test");
let rust_str = result.to_string();
assert!(rust_str.contains("{"));
assert!(rust_str.contains("}"));
}
#[test]
fn test_method_chaining() {
let mut transpiler = create_transpiler();
let code = "[1, 2, 3].iter().sum()"; let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler.transpile(&ast);
assert!(result.is_ok(), "Failed to transpile method chaining");
}
#[test]
fn test_string_interpolation() {
let mut transpiler = create_transpiler();
let code = r#"let name = "world"; f"Hello {name}!""#;
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler.transpile(&ast);
if let Ok(rust_str) = result {
let str = rust_str.to_string();
assert!(str.contains("format!") || !str.is_empty());
}
}
#[test]
fn test_tuple_destructuring() {
let mut transpiler = create_transpiler();
let code = "let (a, b, c) = (1, 2, 3); a + b + c";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler
.transpile(&ast)
.expect("transpile should succeed in test");
let rust_str = result.to_string();
assert!(rust_str.contains("let"));
assert!(rust_str.contains("("));
}
#[test]
fn test_array_destructuring() {
let mut transpiler = create_transpiler();
let code = "let [first, second] = [1, 2]; first + second";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler.transpile(&ast);
assert!(result.is_ok() || result.is_err());
}
#[test]
fn test_object_destructuring() {
let mut transpiler = create_transpiler();
let code = "let {x, y} = point; x + y";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler.transpile(&ast);
assert!(result.is_ok() || result.is_err());
}
#[test]
fn test_default_parameters() {
let mut transpiler = create_transpiler();
let code = "fun greet(name = \"World\") { f\"Hello {name}\" }";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler.transpile(&ast);
assert!(result.is_ok() || result.is_err());
}
#[test]
fn test_is_variable_mutated_assign() {
use crate::frontend::ast::{Expr, ExprKind, Span};
let target = Box::new(Expr::new(
ExprKind::Identifier("x".to_string()),
Span::default(),
));
let value = Box::new(Expr::new(
ExprKind::Literal(crate::frontend::ast::Literal::Integer(5, None)),
Span::default(),
));
let assign_expr = Expr::new(ExprKind::Assign { target, value }, Span::default());
assert!(super::mutation_detection::is_variable_mutated(
"x",
&assign_expr
));
assert!(!super::mutation_detection::is_variable_mutated(
"y",
&assign_expr
));
}
#[test]
fn test_is_variable_mutated_compound_assign() {
use crate::frontend::ast::{BinaryOp, Expr, ExprKind, Span};
let target = Box::new(Expr::new(
ExprKind::Identifier("x".to_string()),
Span::default(),
));
let value = Box::new(Expr::new(
ExprKind::Literal(crate::frontend::ast::Literal::Integer(5, None)),
Span::default(),
));
let compound_expr = Expr::new(
ExprKind::CompoundAssign {
target,
op: BinaryOp::Add,
value,
},
Span::default(),
);
assert!(super::mutation_detection::is_variable_mutated(
"x",
&compound_expr
));
assert!(!super::mutation_detection::is_variable_mutated(
"y",
&compound_expr
));
}
#[test]
fn test_is_variable_mutated_increment_decrement() {
use crate::frontend::ast::{Expr, ExprKind, Span};
let target = Box::new(Expr::new(
ExprKind::Identifier("x".to_string()),
Span::default(),
));
let pre_inc = Expr::new(
ExprKind::PreIncrement {
target: target.clone(),
},
Span::default(),
);
assert!(super::mutation_detection::is_variable_mutated(
"x", &pre_inc
));
let post_inc = Expr::new(
ExprKind::PostIncrement {
target: target.clone(),
},
Span::default(),
);
assert!(super::mutation_detection::is_variable_mutated(
"x", &post_inc
));
let pre_dec = Expr::new(
ExprKind::PreDecrement {
target: target.clone(),
},
Span::default(),
);
assert!(super::mutation_detection::is_variable_mutated(
"x", &pre_dec
));
let post_dec = Expr::new(ExprKind::PostDecrement { target }, Span::default());
assert!(super::mutation_detection::is_variable_mutated(
"x", &post_dec
));
}
#[test]
fn test_is_variable_mutated_in_blocks() {
use crate::frontend::ast::{Expr, ExprKind, Span};
let target = Box::new(Expr::new(
ExprKind::Identifier("x".to_string()),
Span::default(),
));
let value = Box::new(Expr::new(
ExprKind::Literal(crate::frontend::ast::Literal::Integer(5, None)),
Span::default(),
));
let assign_expr = Expr::new(ExprKind::Assign { target, value }, Span::default());
let block_expr = Expr::new(ExprKind::Block(vec![assign_expr]), Span::default());
assert!(super::mutation_detection::is_variable_mutated(
"x",
&block_expr
));
assert!(!super::mutation_detection::is_variable_mutated(
"y",
&block_expr
));
}
#[test]
fn test_is_variable_mutated_in_if_branches() {
use crate::frontend::ast::{Expr, ExprKind, Literal, Span};
let target = Box::new(Expr::new(
ExprKind::Identifier("x".to_string()),
Span::default(),
));
let value = Box::new(Expr::new(
ExprKind::Literal(Literal::Integer(5, None)),
Span::default(),
));
let assign_expr = Expr::new(ExprKind::Assign { target, value }, Span::default());
let condition = Box::new(Expr::new(
ExprKind::Literal(Literal::Bool(true)),
Span::default(),
));
let then_branch = Box::new(assign_expr);
let if_expr = Expr::new(
ExprKind::If {
condition,
then_branch,
else_branch: None,
},
Span::default(),
);
assert!(super::mutation_detection::is_variable_mutated(
"x", &if_expr
));
assert!(!super::mutation_detection::is_variable_mutated(
"y", &if_expr
));
}
#[test]
fn test_is_variable_mutated_in_binary_expressions() {
use crate::frontend::ast::{BinaryOp, Expr, ExprKind, Literal, Span};
let target = Box::new(Expr::new(
ExprKind::Identifier("x".to_string()),
Span::default(),
));
let value = Box::new(Expr::new(
ExprKind::Literal(Literal::Integer(5, None)),
Span::default(),
));
let assign_expr = Expr::new(ExprKind::Assign { target, value }, Span::default());
let right = Expr::new(
ExprKind::Literal(Literal::Integer(10, None)),
Span::default(),
);
let binary_expr = Expr::new(
ExprKind::Binary {
left: Box::new(assign_expr),
op: BinaryOp::Add,
right: Box::new(right),
},
Span::default(),
);
assert!(super::mutation_detection::is_variable_mutated(
"x",
&binary_expr
));
assert!(!super::mutation_detection::is_variable_mutated(
"y",
&binary_expr
));
}
#[test]
fn test_looks_like_numeric_function() {
let transpiler = create_transpiler();
assert!(super::function_analysis::looks_like_numeric_function("sin"));
assert!(super::function_analysis::looks_like_numeric_function("cos"));
assert!(super::function_analysis::looks_like_numeric_function("tan"));
assert!(super::function_analysis::looks_like_numeric_function(
"sqrt"
));
assert!(super::function_analysis::looks_like_numeric_function("abs"));
assert!(super::function_analysis::looks_like_numeric_function(
"floor"
));
assert!(super::function_analysis::looks_like_numeric_function(
"ceil"
));
assert!(super::function_analysis::looks_like_numeric_function(
"round"
));
assert!(super::function_analysis::looks_like_numeric_function("pow"));
assert!(super::function_analysis::looks_like_numeric_function("log"));
assert!(super::function_analysis::looks_like_numeric_function("exp"));
assert!(super::function_analysis::looks_like_numeric_function("min"));
assert!(super::function_analysis::looks_like_numeric_function("max"));
assert!(!super::function_analysis::looks_like_numeric_function(
"println"
));
assert!(!super::function_analysis::looks_like_numeric_function(
"assert"
));
assert!(!super::function_analysis::looks_like_numeric_function(
"custom_function"
));
assert!(!super::function_analysis::looks_like_numeric_function(""));
}
#[test]
fn test_pattern_needs_slice() {
use crate::frontend::ast::Pattern;
let transpiler = create_transpiler();
let list_pattern = Pattern::List(vec![]);
assert!(transpiler.pattern_needs_slice(&list_pattern));
let id_pattern = Pattern::Identifier("x".to_string());
assert!(!transpiler.pattern_needs_slice(&id_pattern));
let wildcard_pattern = Pattern::Wildcard;
assert!(!transpiler.pattern_needs_slice(&wildcard_pattern));
}
#[test]
fn test_value_creates_vec() {
use crate::frontend::ast::{Expr, ExprKind, Literal, Span};
let transpiler = create_transpiler();
let list_expr = Expr::new(ExprKind::List(vec![]), Span::default());
assert!(transpiler.value_creates_vec(&list_expr));
let literal_expr = Expr::new(
ExprKind::Literal(Literal::Integer(42, None)),
Span::default(),
);
assert!(!transpiler.value_creates_vec(&literal_expr));
let id_expr = Expr::new(ExprKind::Identifier("x".to_string()), Span::default());
assert!(!transpiler.value_creates_vec(&id_expr));
}
#[test]
fn test_is_variable_mutated_assignment() {
use crate::frontend::ast::{Expr, ExprKind, Span};
let target = Expr::new(ExprKind::Identifier("x".to_string()), Span::default());
let value = Expr::new(
ExprKind::Literal(Literal::Integer(42, None)),
Span::default(),
);
let assign_expr = Expr::new(
ExprKind::Assign {
target: Box::new(target),
value: Box::new(value),
},
Span::default(),
);
assert!(super::mutation_detection::is_variable_mutated(
"x",
&assign_expr
));
assert!(!super::mutation_detection::is_variable_mutated(
"y",
&assign_expr
));
}
#[test]
fn test_is_variable_mutated_pre_increment() {
use crate::frontend::ast::{Expr, ExprKind, Span};
let target = Expr::new(ExprKind::Identifier("i".to_string()), Span::default());
let inc_expr = Expr::new(
ExprKind::PreIncrement {
target: Box::new(target),
},
Span::default(),
);
assert!(super::mutation_detection::is_variable_mutated(
"i", &inc_expr
));
}
#[test]
fn test_is_variable_mutated_block() {
use crate::frontend::ast::{Expr, ExprKind, Span};
let target = Expr::new(ExprKind::Identifier("x".to_string()), Span::default());
let value = Expr::new(
ExprKind::Literal(Literal::Integer(10, None)),
Span::default(),
);
let assign_expr = Expr::new(
ExprKind::Assign {
target: Box::new(target),
value: Box::new(value),
},
Span::default(),
);
let block_expr = Expr::new(ExprKind::Block(vec![assign_expr]), Span::default());
assert!(super::mutation_detection::is_variable_mutated(
"x",
&block_expr
));
}
#[test]
fn test_looks_like_numeric_function_arithmetic() {
let transpiler = create_transpiler();
assert!(super::function_analysis::looks_like_numeric_function("add"));
assert!(super::function_analysis::looks_like_numeric_function(
"multiply"
));
assert!(super::function_analysis::looks_like_numeric_function(
"sqrt"
));
assert!(super::function_analysis::looks_like_numeric_function("pow"));
assert!(!super::function_analysis::looks_like_numeric_function(
"concat"
));
}
#[test]
fn test_looks_like_numeric_function_trig() {
let transpiler = create_transpiler();
assert!(super::function_analysis::looks_like_numeric_function("sin"));
assert!(super::function_analysis::looks_like_numeric_function("cos"));
assert!(super::function_analysis::looks_like_numeric_function(
"atan2"
));
assert!(!super::function_analysis::looks_like_numeric_function(
"uppercase"
));
}
#[test]
fn test_is_void_function_call_println() {
use crate::frontend::ast::{Expr, ExprKind, Span};
let transpiler = create_transpiler();
let func = Expr::new(ExprKind::Identifier("println".to_string()), Span::default());
let call_expr = Expr::new(
ExprKind::Call {
func: Box::new(func),
args: vec![],
},
Span::default(),
);
assert!(super::function_analysis::is_void_function_call(&call_expr));
}
#[test]
fn test_is_void_function_call_assert() {
use crate::frontend::ast::{Expr, ExprKind, Span};
let transpiler = create_transpiler();
let func = Expr::new(ExprKind::Identifier("assert".to_string()), Span::default());
let call_expr = Expr::new(
ExprKind::Call {
func: Box::new(func),
args: vec![],
},
Span::default(),
);
assert!(super::function_analysis::is_void_function_call(&call_expr));
}
#[test]
fn test_is_void_expression_unit() {
use crate::frontend::ast::{Expr, ExprKind, Span};
let transpiler = create_transpiler();
let unit_expr = Expr::new(ExprKind::Literal(Literal::Unit), Span::default());
assert!(super::function_analysis::is_void_expression(&unit_expr));
}
#[test]
fn test_is_void_expression_assignment() {
use crate::frontend::ast::{Expr, ExprKind, Span};
let transpiler = create_transpiler();
let target = Expr::new(ExprKind::Identifier("x".to_string()), Span::default());
let value = Expr::new(
ExprKind::Literal(Literal::Integer(5, None)),
Span::default(),
);
let assign_expr = Expr::new(
ExprKind::Assign {
target: Box::new(target),
value: Box::new(value),
},
Span::default(),
);
assert!(super::function_analysis::is_void_expression(&assign_expr));
}
#[test]
fn test_returns_closure_false() {
use crate::frontend::ast::{Expr, ExprKind, Literal, Span};
let transpiler = create_transpiler();
let int_expr = Expr::new(
ExprKind::Literal(Literal::Integer(42, None)),
Span::default(),
);
assert!(!super::function_analysis::returns_closure(&int_expr));
}
#[test]
fn test_returns_string_literal_direct() {
use crate::frontend::ast::{Expr, ExprKind, Span};
let string_expr = Expr::new(
ExprKind::Literal(Literal::String("hello".to_string())),
Span::default(),
);
assert!(returns_string_literal(&string_expr));
}
#[test]
fn test_returns_string_literal_in_block() {
use crate::frontend::ast::{Expr, ExprKind, Span};
let string_expr = Expr::new(
ExprKind::Literal(Literal::String("world".to_string())),
Span::default(),
);
let block_expr = Expr::new(ExprKind::Block(vec![string_expr]), Span::default());
assert!(returns_string_literal(&block_expr));
}
#[test]
fn test_returns_boolean_comparison() {
use crate::frontend::ast::{BinaryOp, Expr, ExprKind, Span};
let left = Expr::new(
ExprKind::Literal(Literal::Integer(5, None)),
Span::default(),
);
let right = Expr::new(
ExprKind::Literal(Literal::Integer(10, None)),
Span::default(),
);
let comparison_expr = Expr::new(
ExprKind::Binary {
left: Box::new(left),
op: BinaryOp::Less,
right: Box::new(right),
},
Span::default(),
);
assert!(returns_boolean(&comparison_expr));
}
#[test]
fn test_returns_boolean_unary_not() {
use crate::frontend::ast::{Expr, ExprKind, Span, UnaryOp};
let inner = Expr::new(ExprKind::Literal(Literal::Bool(true)), Span::default());
let not_expr = Expr::new(
ExprKind::Unary {
op: UnaryOp::Not,
operand: Box::new(inner),
},
Span::default(),
);
assert!(returns_boolean(¬_expr));
}
#[test]
fn test_returns_vec_array_literal() {
use crate::frontend::ast::{Expr, ExprKind, Span};
let transpiler = create_transpiler();
let array_expr = Expr::new(
ExprKind::List(vec![
Expr::new(
ExprKind::Literal(Literal::Integer(1, None)),
Span::default(),
),
Expr::new(
ExprKind::Literal(Literal::Integer(2, None)),
Span::default(),
),
]),
Span::default(),
);
assert!(returns_vec(&array_expr));
}
#[test]
fn test_returns_string_concatenation() {
use crate::frontend::ast::{BinaryOp, Expr, ExprKind, Span};
let transpiler = create_transpiler();
let left = Expr::new(
ExprKind::Literal(Literal::String("hello".to_string())),
Span::default(),
);
let right = Expr::new(
ExprKind::Literal(Literal::String("world".to_string())),
Span::default(),
);
let concat_expr = Expr::new(
ExprKind::Binary {
left: Box::new(left),
op: BinaryOp::Add,
right: Box::new(right),
},
Span::default(),
);
assert!(returns_string(&concat_expr));
}
#[test]
fn test_value_creates_vec_list() {
use crate::frontend::ast::{Expr, ExprKind, Literal, Span};
let transpiler = create_transpiler();
let elem1 = Expr::new(
ExprKind::Literal(Literal::Integer(1, None)),
Span::default(),
);
let elem2 = Expr::new(
ExprKind::Literal(Literal::Integer(2, None)),
Span::default(),
);
let list_expr = Expr::new(ExprKind::List(vec![elem1, elem2]), Span::default());
assert!(transpiler.value_creates_vec(&list_expr));
}
#[test]
fn test_trueno_sum_transpiles_to_kahan_sum() {
let mut transpiler = create_transpiler();
let code = "let arr = [1.0, 2.0, 3.0]; trueno_sum(arr)";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler
.transpile(&ast)
.expect("transpile should succeed in test");
let rust_str = result.to_string();
assert!(
rust_str.contains("trueno_bridge") && rust_str.contains("kahan_sum"),
"trueno_sum should transpile to trueno_bridge::kahan_sum, got: {rust_str}"
);
}
#[test]
fn test_trueno_mean_transpiles_correctly() {
let mut transpiler = create_transpiler();
let code = "let data = [1.0, 2.0, 3.0, 4.0]; trueno_mean(data)";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler
.transpile(&ast)
.expect("transpile should succeed in test");
let rust_str = result.to_string();
assert!(
rust_str.contains("trueno_bridge") && rust_str.contains("mean"),
"trueno_mean should transpile to trueno_bridge::mean, got: {rust_str}"
);
}
#[test]
fn test_trueno_variance_transpiles_correctly() {
let mut transpiler = create_transpiler();
let code = "let vals = [2.0, 4.0, 4.0, 4.0, 5.0]; trueno_variance(vals)";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler
.transpile(&ast)
.expect("transpile should succeed in test");
let rust_str = result.to_string();
assert!(
rust_str.contains("trueno_bridge") && rust_str.contains("variance"),
"trueno_variance should transpile to trueno_bridge::variance, got: {rust_str}"
);
}
#[test]
fn test_trueno_std_dev_transpiles_correctly() {
let mut transpiler = create_transpiler();
let code = "let samples = [1.0, 2.0, 3.0]; trueno_std_dev(samples)";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler
.transpile(&ast)
.expect("transpile should succeed in test");
let rust_str = result.to_string();
assert!(
rust_str.contains("trueno_bridge") && rust_str.contains("std_dev"),
"trueno_std_dev should transpile to trueno_bridge::std_dev, got: {rust_str}"
);
}
#[test]
fn test_trueno_dot_transpiles_correctly() {
let mut transpiler = create_transpiler();
let code = "let a = [1.0, 2.0, 3.0]; let b = [4.0, 5.0, 6.0]; trueno_dot(a, b)";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler
.transpile(&ast)
.expect("transpile should succeed in test");
let rust_str = result.to_string();
assert!(
rust_str.contains("trueno_bridge") && rust_str.contains("dot"),
"trueno_dot should transpile to trueno_bridge::dot, got: {rust_str}"
);
}
#[test]
fn test_transpile_if_comprehensive() {
let mut transpiler = Transpiler::new();
let code = "if x > 0 { println(\"positive\") }";
let mut parser = Parser::new(code);
if let Ok(ast) = parser.parse() {
let result = transpiler.transpile(&ast);
assert!(result.is_ok());
let output = result.expect("result should be Ok in test").to_string();
assert!(output.contains("if"));
}
let code = "if x > 0 { 1 } else { -1 }";
let mut parser = Parser::new(code);
if let Ok(ast) = parser.parse() {
let result = transpiler.transpile(&ast);
assert!(result.is_ok());
}
let code = "if x > 0 { 1 } else if x < 0 { -1 } else { 0 }";
let mut parser = Parser::new(code);
if let Ok(ast) = parser.parse() {
let result = transpiler.transpile(&ast);
assert!(result.is_ok());
}
}
#[test]
fn test_transpile_let_comprehensive() {
let mut transpiler = Transpiler::new();
let test_cases = vec![
"let x = 5",
"let mut y = 10",
"const PI = 3.15",
"let (a, b) = (1, 2)",
"let [x, y, z] = [1, 2, 3]",
"let Some(value) = opt",
"let Ok(result) = try_something()",
"let {name, age} = person",
"let x: int = 42",
"let f: fn(int) -> int = |x| x * 2",
];
for code in test_cases {
let mut parser = Parser::new(code);
if let Ok(ast) = parser.parse() {
let _ = transpiler.transpile(&ast);
}
}
}
#[test]
fn test_transpile_function_comprehensive() {
let mut transpiler = Transpiler::new();
let test_cases = vec![
"fn simple() { }",
"fn main() { println(\"Hello\") }",
"fn add(a: int, b: int) -> int { a + b }",
"fn generic<T>(x: T) -> T { x }",
"async fn fetch() { await get() }",
"fn* generator() { yield 1; yield 2 }",
"pub fn public() { }",
"#[test] fn test_function() { // Test passes without panic }",
"fn with_default(x = 10) { x }",
"fn recursive(n) { if n <= 0 { 0 } else { n + recursive(n-1) } }",
];
for code in test_cases {
let mut parser = Parser::new(code);
if let Ok(ast) = parser.parse() {
let _ = transpiler.transpile(&ast);
}
}
}
#[test]
fn test_transpile_call_comprehensive() {
let mut transpiler = Transpiler::new();
let test_cases = vec![
"print(\"hello\")",
"println(\"world\")",
"eprint(\"error\")",
"eprintln(\"error line\")",
"dbg!(value)",
"sqrt(16)",
"pow(2, 8)",
"abs(-5)",
"min(3, 7)",
"max(3, 7)",
"floor(3.7)",
"ceil(3.2)",
"round(3.5)",
"sin(0)",
"cos(0)",
"tan(0)",
"log(1)",
"exp(0)",
"int(3.15)",
"float(42)",
"str(123)",
"bool(1)",
"char(65)",
"vec![1, 2, 3]",
"Vec::new()",
"HashMap::new()",
"HashSet::from([1, 2, 3])",
"input()",
"input(\"Enter: \")",
"// Test passes without panic",
"assert_eq!(1, 1)",
"assert_ne!(1, 2)",
"debug_assert!(x > 0)",
"df.select(\"col1\", \"col2\")",
"DataFrame::new()",
"custom_function(1, 2, 3)",
"object.method()",
"chain().of().calls()",
];
for code in test_cases {
let mut parser = Parser::new(code);
if let Ok(ast) = parser.parse() {
let _ = transpiler.transpile(&ast);
}
}
}
#[test]
fn test_transpile_lambda_comprehensive() {
let mut transpiler = Transpiler::new();
let test_cases = vec![
"x => x",
"x => x * 2",
"(x, y) => x + y",
"() => 42",
"(a, b, c) => a + b + c",
"x => { let y = x * 2; y + 1 }",
"async x => await fetch(x)",
"(...args) => args.length",
];
for code in test_cases {
let mut parser = Parser::new(code);
if let Ok(ast) = parser.parse() {
let _ = transpiler.transpile(&ast);
}
}
}
#[test]
fn test_is_variable_mutated_property() {
let mut transpiler = Transpiler::new();
let test_cases = vec![
("let mut x = 0; x = 5", true),
("let mut x = 0; x += 1", true),
("let mut arr = []; arr.push(1)", true),
("let x = 5; let y = x + 1", false),
("let x = 5; println(x)", false),
];
for (code, _expected) in test_cases {
let mut parser = Parser::new(code);
if let Ok(ast) = parser.parse() {
let _ = transpiler.transpile(&ast);
}
}
}
#[test]
fn test_control_flow_statements() {
let mut transpiler = Transpiler::new();
let test_cases = vec![
"while x < 10 { x += 1 }",
"for i in 0..10 { println(i) }",
"for x in array { process(x) }",
"loop { if done { break } }",
"match x { 1 => \"one\", 2 => \"two\", _ => \"other\" }",
"match opt { Some(x) => x * 2, None => 0 }",
"return",
"return 42",
"break",
"break 'label",
"continue",
"continue 'label",
];
for code in test_cases {
let mut parser = Parser::new(code);
if let Ok(ast) = parser.parse() {
let _ = transpiler.transpile(&ast);
}
}
}
#[test]
fn test_try_catch_statements() {
let mut transpiler = Transpiler::new();
let test_cases = vec![
"try { risky() } catch(e) { handle(e) }",
"try { risky() } finally { cleanup() }",
"try { risky() } catch(e) { handle(e) } finally { cleanup() }",
"throw Error(\"message\")",
"throw CustomError { code: 500 }",
];
for code in test_cases {
let mut parser = Parser::new(code);
if let Ok(ast) = parser.parse() {
let _ = transpiler.transpile(&ast);
}
}
}
#[test]
fn test_class_statements() {
let mut transpiler = Transpiler::new();
let test_cases = vec![
"class Empty { }",
"class Point { x: int; y: int }",
"class Circle { radius: float; fn area() { 3.15 * radius * radius } }",
"class Derived extends Base { }",
"class Generic<T> { value: T }",
];
for code in test_cases {
let mut parser = Parser::new(code);
if let Ok(ast) = parser.parse() {
let _ = transpiler.transpile(&ast);
}
}
}
#[test]
fn test_import_export_statements() {
let mut transpiler = Transpiler::new();
let test_cases = vec![
"import std",
"import std.io",
"from std import println",
"from math import { sin, cos, tan }",
"export fn public() { }",
"export const PI = 3.15",
"export { func1, func2 }",
];
for code in test_cases {
let mut parser = Parser::new(code);
if let Ok(ast) = parser.parse() {
let _ = transpiler.transpile(&ast);
}
}
}
#[test]
fn test_edge_cases() {
let mut transpiler = Transpiler::new();
let test_cases = vec!["", ";", "{ }", "( )", "let x", "fn f"];
for code in test_cases {
let mut parser = Parser::new(code);
if let Ok(ast) = parser.parse() {
let _ = transpiler.transpile(&ast);
}
}
}
#[test]
fn test_helper_functions() {
let transpiler = Transpiler::new();
assert!(transpiler.pattern_needs_slice(&Pattern::List(vec![])));
let vec_expr = Expr {
kind: ExprKind::List(vec![]),
span: Span::default(),
attributes: vec![],
leading_comments: Vec::new(),
trailing_comment: None,
};
assert!(transpiler.value_creates_vec(&vec_expr));
assert!(super::function_analysis::looks_like_numeric_function(
"sqrt"
));
assert!(super::function_analysis::looks_like_numeric_function("pow"));
assert!(super::function_analysis::looks_like_numeric_function("abs"));
assert!(!super::function_analysis::looks_like_numeric_function(
"println"
));
}
#[test]
fn test_advanced_transpilation_patterns() {
let mut transpiler = Transpiler::new();
let advanced_cases = vec![
"let mut x = { let y = 5; y * 2 }",
"let (a, b, c) = (1, 2, 3)",
"let Point { x, y } = point",
"let [first, ..rest] = array",
"fn complex(x: Option<T>) -> Result<U, Error> { match x { Some(v) => Ok(transform(v)), None => Err(\"empty\") } }",
"fn generic<T: Clone + Debug>(items: Vec<T>) -> Vec<T> { items.iter().cloned().collect() }",
"fn async_complex() -> impl Future<Output = Result<String, Error>> { async { Ok(\"result\".to_string()) } }",
"match result { Ok(data) => { let processed = process(data); save(processed) }, Err(e) => log_error(e) }",
"if let Some(value) = optional { value * 2 } else { default_value() }",
"while let Some(item) = iterator.next() { process_item(item); }",
"for (index, value) in enumerated { println!(\"{}: {}\", index, value); }",
"data.filter(|x| x > 0).map(|x| x * 2).collect::<Vec<_>>()",
"async_function().await.unwrap_or_else(|e| handle_error(e))",
"object.method()?.another_method().chain().build()",
"vec![1, 2, 3].into_iter().enumerate().collect()",
"HashMap::from([(\"key1\", value1), (\"key2\", value2)])",
"BTreeSet::from_iter([1, 2, 3, 2, 1])",
"match complex_enum { Variant::A { field1, field2 } => process(field1, field2), Variant::B(data) => handle(data), _ => default() }",
"let closure = |x: i32, y: i32| -> Result<i32, String> { if x > 0 { Ok(x + y) } else { Err(\"negative\".to_string()) } }",
"items.fold(0, |acc, item| acc + item.value)",
"let complex_type: HashMap<String, Vec<Result<i32, Error>>> = HashMap::new()",
"#[derive(Debug, Clone)] #[serde(rename_all = \"camelCase\")] struct Complex { field: String }",
];
for code in advanced_cases {
let mut parser = Parser::new(code);
if let Ok(ast) = parser.parse() {
let result = transpiler.transpile(&ast);
assert!(result.is_ok() || result.is_err());
}
}
}
#[test]
fn test_error_path_coverage() {
let mut transpiler = Transpiler::new();
let error_cases = vec![
"let = 5",
"fn ()",
"match { }",
"if { }",
"for { }",
"while { }",
"let x: String = 42",
"let y: Vec<i32> = \"string\"",
"undefined_function()",
"some_var.nonexistent_method()",
"invalid.chain.of.calls()",
"((((((nested))))))",
"{ { { { { nested } } } } }",
"let _ = _",
"let .. = array",
"match x { .. => {} }",
"",
";",
"{ }",
"fn() {}",
"let;",
];
for code in error_cases {
let mut parser = Parser::new(code);
if let Ok(ast) = parser.parse() {
let result = transpiler.transpile(&ast);
assert!(result.is_ok() || result.is_err());
}
}
}
#[test]
fn test_transpiler_helper_methods_comprehensive() {
let transpiler = Transpiler::new();
assert!(super::function_analysis::looks_like_numeric_function(
"sqrt"
));
assert!(!super::function_analysis::looks_like_numeric_function(
"println"
));
let numeric_functions = vec![
"sin",
"cos",
"tan",
"asin",
"acos",
"atan",
"atan2",
"sinh",
"cosh",
"tanh",
"asinh",
"acosh",
"atanh",
"exp",
"exp2",
"ln",
"log",
"log2",
"log10",
"sqrt",
"cbrt",
"pow",
"powf",
"powi",
"abs",
"signum",
"copysign",
"floor",
"ceil",
"round",
"trunc",
"fract",
"min",
"max",
"clamp",
"to_degrees",
"to_radians",
];
for func in numeric_functions {
assert!(super::function_analysis::looks_like_numeric_function(func));
}
let non_numeric_functions = vec![
"println",
"print",
"format",
"write",
"read",
"push",
"pop",
"insert",
"remove",
"clear",
"len",
"is_empty",
"contains",
"starts_with",
"ends_with",
"split",
"join",
"replace",
"trim",
"to_uppercase",
"to_lowercase",
];
for func in non_numeric_functions {
assert!(!super::function_analysis::looks_like_numeric_function(func));
}
let slice_patterns = vec![
Pattern::List(vec![Pattern::Wildcard]),
Pattern::List(vec![
Pattern::Identifier("x".to_string()),
Pattern::Wildcard,
]),
Pattern::Tuple(vec![Pattern::List(vec![])]),
];
for pattern in slice_patterns {
transpiler.pattern_needs_slice(&pattern); }
let vec_expressions = vec![
Expr {
kind: ExprKind::List(vec![]),
span: Span::default(),
attributes: vec![],
leading_comments: Vec::new(),
trailing_comment: None,
},
Expr {
kind: ExprKind::Call {
func: Box::new(Expr {
kind: ExprKind::Identifier("vec".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: Vec::new(),
trailing_comment: None,
}),
args: vec![],
},
span: Span::default(),
attributes: vec![],
leading_comments: Vec::new(),
trailing_comment: None,
},
];
for expr in vec_expressions {
transpiler.value_creates_vec(&expr); }
}
#[test]
fn test_extreme_edge_cases() {
let mut transpiler = Transpiler::new();
let edge_cases = vec![
"let very_very_very_long_identifier_name_that_goes_on_and_on_and_on = 42",
"if true { if true { if true { if true { println!(\"deep\") } } } }",
"fn many_params(a: i32, b: i32, c: i32, d: i32, e: i32, f: i32, g: i32, h: i32) -> i32 { a + b + c + d + e + f + g + h }",
"fn generic_complex<T: Clone + Debug + Send + Sync + 'static>(x: T) -> T where T: PartialEq + Eq + Hash { x }",
"let 变量 = 42",
"let москва = \"city\"",
"let 🚀 = \"rocket\"",
"let big = 123456789012345678901234567890",
"let float = 123.456789012345678901234567890",
"let complex_string = \"String with \\n newlines \\t tabs \\\" quotes and 🚀 emojis\"",
"let raw_string = r#\"Raw string with \"quotes\" and #hashtags\"#",
"let nested = vec![vec![vec![1, 2], vec![3, 4]], vec![vec![5, 6], vec![7, 8]]]",
"println!(\"Format {} with {} multiple {} args\", 1, 2, 3)",
"vec![1; 1000]",
"format!(\"Complex formatting: {:#?}\", complex_data)",
];
for code in edge_cases {
let mut parser = Parser::new(code);
if let Ok(ast) = parser.parse() {
let result = transpiler.transpile(&ast);
assert!(result.is_ok() || result.is_err());
}
}
}
#[test]
fn test_is_variable_mutated_assign_v2() {
let target = Expr {
kind: ExprKind::Identifier("x".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let assign_expr = Expr {
kind: ExprKind::Assign {
target: Box::new(target),
value: Box::new(Expr {
kind: ExprKind::Literal(Literal::Integer(42, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(super::mutation_detection::is_variable_mutated(
"x",
&assign_expr
));
assert!(!super::mutation_detection::is_variable_mutated(
"y",
&assign_expr
));
}
#[test]
fn test_is_variable_mutated_compound_assign_v2() {
let target = Expr {
kind: ExprKind::Identifier("counter".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let compound_expr = Expr {
kind: ExprKind::CompoundAssign {
target: Box::new(target),
value: Box::new(Expr {
kind: ExprKind::Literal(Literal::Integer(1, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
op: BinaryOp::Add,
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(super::mutation_detection::is_variable_mutated(
"counter",
&compound_expr
));
}
#[test]
fn test_is_variable_mutated_pre_increment_v2() {
let target = Expr {
kind: ExprKind::Identifier("i".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let inc_expr = Expr {
kind: ExprKind::PreIncrement {
target: Box::new(target),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(super::mutation_detection::is_variable_mutated(
"i", &inc_expr
));
}
#[test]
fn test_is_variable_mutated_post_decrement() {
let target = Expr {
kind: ExprKind::Identifier("value".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let dec_expr = Expr {
kind: ExprKind::PostDecrement {
target: Box::new(target),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(super::mutation_detection::is_variable_mutated(
"value", &dec_expr
));
}
#[test]
fn test_is_variable_mutated_in_block() {
let assign = Expr {
kind: ExprKind::Assign {
target: Box::new(Expr {
kind: ExprKind::Identifier("x".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
value: Box::new(Expr {
kind: ExprKind::Literal(Literal::Integer(10, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let block_expr = Expr {
kind: ExprKind::Block(vec![assign]),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(super::mutation_detection::is_variable_mutated(
"x",
&block_expr
));
}
#[test]
fn test_is_variable_mutated_in_if() {
let assign = Expr {
kind: ExprKind::Assign {
target: Box::new(Expr {
kind: ExprKind::Identifier("flag".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
value: Box::new(Expr {
kind: ExprKind::Literal(Literal::Bool(true)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let if_expr = Expr {
kind: ExprKind::If {
condition: Box::new(assign),
then_branch: Box::new(Expr {
kind: ExprKind::Literal(Literal::Unit),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
else_branch: None,
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(super::mutation_detection::is_variable_mutated(
"flag", &if_expr
));
}
#[test]
fn test_is_variable_mutated_in_while() {
let inc = Expr {
kind: ExprKind::PreIncrement {
target: Box::new(Expr {
kind: ExprKind::Identifier("count".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let while_expr = Expr {
kind: ExprKind::While {
condition: Box::new(Expr {
kind: ExprKind::Literal(Literal::Bool(true)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
body: Box::new(inc),
label: None,
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(super::mutation_detection::is_variable_mutated(
"count",
&while_expr
));
}
#[test]
fn test_is_variable_mutated_in_for() {
let assign = Expr {
kind: ExprKind::Assign {
target: Box::new(Expr {
kind: ExprKind::Identifier("sum".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
value: Box::new(Expr {
kind: ExprKind::Literal(Literal::Integer(0, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let for_expr = Expr {
kind: ExprKind::For {
var: "item".to_string(),
pattern: Some(Pattern::Identifier("item".to_string())),
iter: Box::new(Expr {
kind: ExprKind::List(vec![]),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
body: Box::new(assign),
label: None,
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(super::mutation_detection::is_variable_mutated(
"sum", &for_expr
));
}
#[test]
fn test_is_variable_mutated_in_match() {
use crate::frontend::ast::MatchArm;
let assign = Expr {
kind: ExprKind::Assign {
target: Box::new(Expr {
kind: ExprKind::Identifier("result".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
value: Box::new(Expr {
kind: ExprKind::Literal(Literal::Integer(1, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let match_expr = Expr {
kind: ExprKind::Match {
expr: Box::new(Expr {
kind: ExprKind::Literal(Literal::Integer(1, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
arms: vec![MatchArm {
pattern: Pattern::Wildcard,
guard: None,
body: Box::new(assign),
span: Span::default(),
}],
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(super::mutation_detection::is_variable_mutated(
"result",
&match_expr
));
}
#[test]
fn test_is_variable_mutated_in_let() {
let inc = Expr {
kind: ExprKind::PreIncrement {
target: Box::new(Expr {
kind: ExprKind::Identifier("x".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let let_expr = Expr {
kind: ExprKind::Let {
name: "y".to_string(),
value: Box::new(Expr {
kind: ExprKind::Literal(Literal::Integer(5, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
body: Box::new(inc),
type_annotation: None,
is_mutable: false,
else_block: None,
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(super::mutation_detection::is_variable_mutated(
"x", &let_expr
));
}
#[test]
fn test_is_variable_mutated_in_binary() {
let assign = Expr {
kind: ExprKind::Assign {
target: Box::new(Expr {
kind: ExprKind::Identifier("a".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
value: Box::new(Expr {
kind: ExprKind::Literal(Literal::Integer(1, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let binary_expr = Expr {
kind: ExprKind::Binary {
left: Box::new(assign),
op: BinaryOp::Add,
right: Box::new(Expr {
kind: ExprKind::Literal(Literal::Integer(2, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(super::mutation_detection::is_variable_mutated(
"a",
&binary_expr
));
}
#[test]
fn test_is_variable_mutated_in_unary() {
let inc = Expr {
kind: ExprKind::PreIncrement {
target: Box::new(Expr {
kind: ExprKind::Identifier("val".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let unary_expr = Expr {
kind: ExprKind::Unary {
op: UnaryOp::Not,
operand: Box::new(inc),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(super::mutation_detection::is_variable_mutated(
"val",
&unary_expr
));
}
#[test]
fn test_is_variable_mutated_in_call() {
let assign = Expr {
kind: ExprKind::Assign {
target: Box::new(Expr {
kind: ExprKind::Identifier("arg".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
value: Box::new(Expr {
kind: ExprKind::Literal(Literal::Integer(42, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let call_expr = Expr {
kind: ExprKind::Call {
func: Box::new(Expr {
kind: ExprKind::Identifier("foo".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
args: vec![assign],
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(super::mutation_detection::is_variable_mutated(
"arg", &call_expr
));
}
#[test]
fn test_is_variable_mutated_in_method_call() {
let assign = Expr {
kind: ExprKind::Assign {
target: Box::new(Expr {
kind: ExprKind::Identifier("obj".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
value: Box::new(Expr {
kind: ExprKind::Literal(Literal::Integer(1, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let method_expr = Expr {
kind: ExprKind::MethodCall {
receiver: Box::new(assign),
method: "process".to_string(),
args: vec![],
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(super::mutation_detection::is_variable_mutated(
"obj",
&method_expr
));
}
#[test]
fn test_is_variable_mutated_immutable_access() {
let literal = Expr {
kind: ExprKind::Literal(Literal::Integer(42, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(!super::mutation_detection::is_variable_mutated(
"x", &literal
));
let ident = Expr {
kind: ExprKind::Identifier("x".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(!super::mutation_detection::is_variable_mutated("x", &ident));
}
#[test]
fn test_needs_lifetime_parameter_no_refs() {
let transpiler = Transpiler::new();
let params = vec![Param {
pattern: Pattern::Identifier("x".to_string()),
ty: Type {
kind: TypeKind::Named("i32".to_string()),
span: Span::default(),
},
default_value: None,
span: Span::default(),
is_mutable: false,
}];
assert!(!super::type_analysis::needs_lifetime_parameter(
¶ms, None
));
}
#[test]
fn test_needs_lifetime_parameter_requires_lifetime() {
let ref_type = Type {
kind: TypeKind::Reference {
is_mut: false,
lifetime: None,
inner: Box::new(Type {
kind: TypeKind::Named("str".to_string()),
span: Span::default(),
}),
},
span: Span::default(),
};
let params = vec![
Param {
pattern: Pattern::Identifier("a".to_string()),
ty: ref_type.clone(),
default_value: None,
span: Span::default(),
is_mutable: false,
},
Param {
pattern: Pattern::Identifier("b".to_string()),
ty: ref_type.clone(),
default_value: None,
span: Span::default(),
is_mutable: false,
},
];
let return_type = Some(&ref_type);
assert!(super::type_analysis::needs_lifetime_parameter(
¶ms,
return_type
));
}
#[test]
fn test_is_reference_type_true() {
let ref_ty = Type {
kind: TypeKind::Reference {
is_mut: false,
lifetime: None,
inner: Box::new(Type {
kind: TypeKind::Named("str".to_string()),
span: Span::default(),
}),
},
span: Span::default(),
};
assert!(super::type_analysis::is_reference_type(&ref_ty));
}
#[test]
fn test_is_reference_type_false() {
let named_ty = Type {
kind: TypeKind::Named("String".to_string()),
span: Span::default(),
};
assert!(!super::type_analysis::is_reference_type(&named_ty));
}
#[test]
fn test_is_string_type_true() {
let string_ty = Type {
kind: TypeKind::Named("String".to_string()),
span: Span::default(),
};
assert!(super::type_analysis::is_string_type(&string_ty));
}
#[test]
fn test_is_string_type_false() {
let int_ty = Type {
kind: TypeKind::Named("i32".to_string()),
span: Span::default(),
};
assert!(!super::type_analysis::is_string_type(&int_ty));
}
#[test]
fn test_body_needs_string_conversion_string_literal() {
let body = Expr::new(
ExprKind::Literal(Literal::String("hello".to_string())),
Span::default(),
);
assert!(super::type_analysis::body_needs_string_conversion(&body));
}
#[test]
fn test_body_needs_string_conversion_identifier() {
let body = Expr::new(ExprKind::Identifier("s".to_string()), Span::default());
assert!(super::type_analysis::body_needs_string_conversion(&body));
}
#[test]
fn test_body_needs_string_conversion_integer() {
let body = Expr::new(
ExprKind::Literal(Literal::Integer(42, None)),
Span::default(),
);
assert!(!super::type_analysis::body_needs_string_conversion(&body));
}
#[test]
fn test_transpile_iterator_methods_map() {
use quote::quote;
let transpiler = Transpiler::new();
let obj = quote! { vec };
let f = quote! { |x| x * 2 };
let result = transpiler
.transpile_iterator_methods(&obj, "map", &[f])
.expect("operation should succeed in test");
let code = result.to_string();
assert!(code.contains("iter"));
assert!(code.contains("map"));
assert!(code.contains("collect"));
}
#[test]
fn test_transpile_iterator_methods_filter() {
use quote::quote;
let transpiler = Transpiler::new();
let obj = quote! { vec };
let f = quote! { |x| x > 10 };
let result = transpiler
.transpile_iterator_methods(&obj, "filter", &[f])
.expect("operation should succeed in test");
let code = result.to_string();
assert!(code.contains("into_iter"));
assert!(code.contains("filter"));
assert!(code.contains("collect"));
}
#[test]
fn test_transpile_iterator_methods_reduce() {
use quote::quote;
let transpiler = Transpiler::new();
let obj = quote! { vec };
let f = quote! { |acc, x| acc + x };
let result = transpiler
.transpile_iterator_methods(&obj, "reduce", &[f])
.expect("operation should succeed in test");
let code = result.to_string();
assert!(code.contains("into_iter"));
assert!(code.contains("reduce"));
assert!(!code.contains("collect")); }
#[test]
fn test_transpile_map_set_methods_items() {
use proc_macro2::Span as ProcSpan;
use quote::quote;
let transpiler = Transpiler::new();
let obj = quote! { map };
let method_ident = proc_macro2::Ident::new("items", ProcSpan::call_site());
let result = transpiler
.transpile_map_set_methods(&obj, &method_ident, "items", &[])
.expect("operation should succeed in test");
let code = result.to_string();
assert!(code.contains("iter"));
assert!(code.contains("clone"));
}
#[test]
fn test_transpile_map_set_methods_update() {
use proc_macro2::Span as ProcSpan;
use quote::quote;
let transpiler = Transpiler::new();
let obj = quote! { map };
let method_ident = proc_macro2::Ident::new("update", ProcSpan::call_site());
let arg = quote! { other_map };
let result = transpiler
.transpile_map_set_methods(&obj, &method_ident, "update", &[arg])
.expect("operation should succeed in test");
let code = result.to_string();
assert!(code.contains("extend"));
}
#[test]
fn test_transpile_set_operations_union() {
use quote::quote;
let transpiler = Transpiler::new();
let obj = quote! { set1 };
let arg = quote! { set2 };
let result = transpiler
.transpile_set_operations(&obj, "union", &[arg])
.expect("operation should succeed in test");
let code = result.to_string();
assert!(code.contains("union"));
assert!(code.contains("cloned"));
assert!(code.contains("HashSet"));
}
#[test]
fn test_looks_like_numeric_function_true() {
let transpiler = Transpiler::new();
assert!(super::function_analysis::looks_like_numeric_function("abs"));
assert!(super::function_analysis::looks_like_numeric_function(
"sqrt"
));
assert!(super::function_analysis::looks_like_numeric_function("pow"));
}
#[test]
fn test_looks_like_numeric_function_false() {
let transpiler = Transpiler::new();
assert!(!super::function_analysis::looks_like_numeric_function(
"print"
));
assert!(!super::function_analysis::looks_like_numeric_function(
"hello"
));
}
#[test]
fn test_returns_boolean_literal() {
let body = Expr {
kind: ExprKind::Literal(Literal::Bool(true)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(returns_boolean(&body));
}
#[test]
fn test_returns_boolean_comparison_v2() {
let body = Expr {
kind: ExprKind::Binary {
left: Box::new(Expr {
kind: ExprKind::Literal(Literal::Integer(5, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
op: BinaryOp::Equal,
right: Box::new(Expr {
kind: ExprKind::Literal(Literal::Integer(5, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(returns_boolean(&body));
}
#[test]
fn test_returns_string_literal_true() {
let body = Expr {
kind: ExprKind::Literal(Literal::String("test".to_string())),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(returns_string_literal(&body));
}
#[test]
fn test_returns_string_literal_false() {
let body = Expr {
kind: ExprKind::Literal(Literal::Integer(42, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(!returns_string_literal(&body));
}
#[test]
fn test_returns_vec_macro() {
let transpiler = Transpiler::new();
let body = Expr {
kind: ExprKind::MacroInvocation {
name: "vec!".to_string(),
args: vec![],
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(returns_vec(&body));
}
#[test]
fn test_returns_vec_list() {
let transpiler = Transpiler::new();
let body = Expr {
kind: ExprKind::List(vec![Expr {
kind: ExprKind::Literal(Literal::Integer(1, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}]),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(returns_vec(&body));
}
#[test]
fn test_returns_object_literal_true() {
let body = Expr {
kind: ExprKind::ObjectLiteral { fields: vec![] },
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(returns_object_literal(&body));
}
#[test]
fn test_returns_object_literal_false() {
let body = Expr {
kind: ExprKind::Literal(Literal::Integer(42, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(!returns_object_literal(&body));
}
#[test]
fn test_expr_is_string_literal() {
let transpiler = Transpiler::new();
let expr = Expr {
kind: ExprKind::Literal(Literal::String("test".to_string())),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(expr_is_string(&expr));
}
#[test]
fn test_expr_is_string_interpolation() {
let transpiler = Transpiler::new();
let expr = Expr {
kind: ExprKind::StringInterpolation { parts: vec![] },
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(expr_is_string(&expr));
}
#[test]
fn test_has_non_unit_expression_true() {
let transpiler = Transpiler::new();
let body = Expr {
kind: ExprKind::Literal(Literal::Integer(42, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(super::function_analysis::has_non_unit_expression(&body));
}
#[test]
fn test_has_non_unit_expression_false() {
let transpiler = Transpiler::new();
let body = Expr {
kind: ExprKind::Literal(Literal::Unit),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(!super::function_analysis::has_non_unit_expression(&body));
}
#[test]
fn test_is_void_expression_unit_v2() {
let _transpiler = Transpiler::new();
let expr = Expr {
kind: ExprKind::Literal(Literal::Unit),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(super::function_analysis::is_void_expression(&expr));
}
#[test]
fn test_generate_body_tokens_with_string_conversion() {
let transpiler = Transpiler::new();
let body = Expr {
kind: ExprKind::Literal(Literal::String("hello".to_string())),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let result = transpiler.generate_body_tokens_with_string_conversion(&body, false);
assert!(result.is_ok());
}
#[test]
fn test_generate_body_tokens_with_string_conversion_async() {
let transpiler = Transpiler::new();
let body = Expr {
kind: ExprKind::Literal(Literal::String("async_result".to_string())),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let result = transpiler.generate_body_tokens_with_string_conversion(&body, true);
assert!(result.is_ok());
}
#[test]
fn test_generate_param_tokens_with_lifetime_empty() {
let transpiler = Transpiler::new();
let body = Expr {
kind: ExprKind::Literal(Literal::Integer(42, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let result = transpiler.generate_param_tokens_with_lifetime(&[], &body, "test_fn");
assert!(result.is_ok());
assert!(result.unwrap().is_empty());
}
#[test]
fn test_generate_param_tokens_with_lifetime_with_ref() {
let transpiler = Transpiler::new();
let body = Expr {
kind: ExprKind::Identifier("x".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let params = vec![Param {
pattern: Pattern::Identifier("x".to_string()),
ty: Type {
kind: TypeKind::Reference {
is_mut: false,
lifetime: None,
inner: Box::new(Type {
kind: TypeKind::Named("String".to_string()),
span: Span::default(),
}),
},
span: Span::default(),
},
span: Span::default(),
is_mutable: false,
default_value: None,
}];
let result = transpiler.generate_param_tokens_with_lifetime(¶ms, &body, "test_fn");
assert!(result.is_ok());
}
#[test]
fn test_generate_return_type_tokens_with_lifetime_none() {
let transpiler = Transpiler::new();
let body = Expr {
kind: ExprKind::Literal(Literal::Integer(42, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let result = transpiler.generate_return_type_tokens_with_lifetime("test_fn", None, &body);
assert!(result.is_ok());
}
#[test]
fn test_generate_return_type_tokens_with_lifetime_ref() {
let transpiler = Transpiler::new();
let body = Expr {
kind: ExprKind::Identifier("x".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let return_type = Type {
kind: TypeKind::Reference {
is_mut: false,
lifetime: None,
inner: Box::new(Type {
kind: TypeKind::Named("str".to_string()),
span: Span::default(),
}),
},
span: Span::default(),
};
let result =
transpiler.generate_return_type_tokens_with_lifetime("test_fn", Some(&return_type), &body);
assert!(result.is_ok());
}
#[test]
fn test_transpile_function_pub() {
let transpiler = Transpiler::new();
let body = Expr {
kind: ExprKind::Literal(Literal::Integer(42, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let result = transpiler.transpile_function(
"pub_fn",
&[],
&[],
&body,
false,
None,
true, &[],
);
assert!(result.is_ok());
let tokens = result.unwrap().to_string();
assert!(tokens.contains("pub"));
}
#[test]
fn test_transpile_function_async() {
let transpiler = Transpiler::new();
let body = Expr {
kind: ExprKind::Literal(Literal::Integer(42, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let result = transpiler.transpile_function(
"async_fn",
&[],
&[],
&body,
true, None,
false,
&[],
);
assert!(result.is_ok());
let tokens = result.unwrap().to_string();
assert!(tokens.contains("async"));
}
#[test]
fn test_transpile_function_with_type_params() {
let transpiler = Transpiler::new();
let body = Expr {
kind: ExprKind::Identifier("x".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let params = vec![Param {
pattern: Pattern::Identifier("x".to_string()),
ty: Type {
kind: TypeKind::Named("T".to_string()),
span: Span::default(),
},
span: Span::default(),
is_mutable: false,
default_value: None,
}];
let result = transpiler.transpile_function(
"generic_fn",
&["T".to_string()],
¶ms,
&body,
false,
None,
false,
&[],
);
assert!(result.is_ok());
}
#[test]
fn test_transpile_function_with_return_type() {
let transpiler = Transpiler::new();
let body = Expr {
kind: ExprKind::Literal(Literal::Integer(42, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let return_type = Type {
kind: TypeKind::Named("i64".to_string()),
span: Span::default(),
};
let result = transpiler.transpile_function(
"typed_fn",
&[],
&[],
&body,
false,
Some(&return_type),
false,
&[],
);
assert!(result.is_ok());
let tokens = result.unwrap().to_string();
assert!(tokens.contains("i64"));
}
#[test]
fn test_infer_param_type_simple() {
let transpiler = Transpiler::new();
let param = Param {
pattern: Pattern::Identifier("x".to_string()),
ty: Type {
kind: TypeKind::Named("unknown".to_string()),
span: Span::default(),
},
span: Span::default(),
is_mutable: false,
default_value: None,
};
let body = Expr {
kind: ExprKind::Binary {
left: Box::new(Expr {
kind: ExprKind::Identifier("x".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
op: BinaryOp::Add,
right: Box::new(Expr {
kind: ExprKind::Literal(Literal::Integer(1, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let result = transpiler.infer_param_type(¶m, &body, "test_fn");
assert!(!result.is_empty());
}
#[test]
fn test_generate_param_tokens_multiple() {
let transpiler = Transpiler::new();
let params = vec![
Param {
pattern: Pattern::Identifier("a".to_string()),
ty: Type {
kind: TypeKind::Named("i64".to_string()),
span: Span::default(),
},
span: Span::default(),
is_mutable: false,
default_value: None,
},
Param {
pattern: Pattern::Identifier("b".to_string()),
ty: Type {
kind: TypeKind::Named("i64".to_string()),
span: Span::default(),
},
span: Span::default(),
is_mutable: false,
default_value: None,
},
];
let body = Expr {
kind: ExprKind::Binary {
left: Box::new(Expr {
kind: ExprKind::Identifier("a".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
op: BinaryOp::Add,
right: Box::new(Expr {
kind: ExprKind::Identifier("b".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let result = transpiler.generate_param_tokens(¶ms, &body, "add_fn");
assert!(result.is_ok());
assert_eq!(result.unwrap().len(), 2);
}
#[test]
fn test_generate_return_type_tokens_explicit() {
let transpiler = Transpiler::new();
let body = Expr {
kind: ExprKind::Literal(Literal::Integer(42, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let return_type = Type {
kind: TypeKind::Named("i64".to_string()),
span: Span::default(),
};
let result = transpiler.generate_return_type_tokens("test_fn", Some(&return_type), &body, &[]);
assert!(result.is_ok());
let tokens = result.unwrap().to_string();
assert!(tokens.contains("i64"));
}
#[test]
fn test_generate_body_tokens_sync() {
let transpiler = Transpiler::new();
let body = Expr {
kind: ExprKind::Block(vec![Expr {
kind: ExprKind::Literal(Literal::Integer(1, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}]),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let result = transpiler.generate_body_tokens(&body, false);
assert!(result.is_ok());
}
#[test]
fn test_generate_body_tokens_async() {
let transpiler = Transpiler::new();
let body = Expr {
kind: ExprKind::Literal(Literal::Integer(42, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let result = transpiler.generate_body_tokens(&body, true);
assert!(result.is_ok());
}
#[test]
fn test_generate_type_param_tokens_simple() {
let transpiler = Transpiler::new();
let result = transpiler.generate_type_param_tokens(&["T".to_string(), "U".to_string()]);
assert!(result.is_ok());
assert_eq!(result.unwrap().len(), 2);
}
#[test]
fn test_generate_type_param_tokens_with_bounds() {
let transpiler = Transpiler::new();
let result = transpiler.generate_type_param_tokens(&["T: Clone".to_string()]);
assert!(result.is_ok());
let tokens = result.unwrap();
assert_eq!(tokens.len(), 1);
assert!(tokens[0].to_string().contains("Clone"));
}
#[test]
fn test_transpile_block_empty() {
let transpiler = Transpiler::new();
let result = transpiler.transpile_block(&[]);
assert!(result.is_ok());
}
#[test]
fn test_transpile_block_with_statements() {
let transpiler = Transpiler::new();
let exprs = vec![Expr {
kind: ExprKind::Identifier("x".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}];
let result = transpiler.transpile_block(&exprs);
assert!(result.is_ok());
}
#[test]
fn test_transpile_lambda_simple() {
let transpiler = Transpiler::new();
let params = vec![Param {
pattern: Pattern::Identifier("x".to_string()),
ty: Type {
kind: TypeKind::Named("unknown".to_string()),
span: Span::default(),
},
span: Span::default(),
is_mutable: false,
default_value: None,
}];
let body = Expr {
kind: ExprKind::Binary {
left: Box::new(Expr {
kind: ExprKind::Identifier("x".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
op: BinaryOp::Multiply,
right: Box::new(Expr {
kind: ExprKind::Literal(Literal::Integer(2, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let result = transpiler.transpile_lambda(¶ms, &body);
assert!(result.is_ok());
let tokens = result.unwrap().to_string();
assert!(tokens.contains("|"));
}
#[test]
fn test_transpile_call_simple_fn() {
let transpiler = Transpiler::new();
let func = Expr {
kind: ExprKind::Identifier("my_func".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let args = vec![Expr {
kind: ExprKind::Literal(Literal::Integer(42, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}];
let result = transpiler.transpile_call(&func, &args);
assert!(result.is_ok());
}
#[test]
fn test_transpile_method_call_simple() {
let transpiler = Transpiler::new();
let object = Expr {
kind: ExprKind::Identifier("vec".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let args = vec![];
let result = transpiler.transpile_method_call(&object, "len", &args);
assert!(result.is_ok());
let tokens = result.unwrap().to_string();
assert!(tokens.contains("len"));
}
#[test]
fn test_transpile_method_call_with_args() {
let transpiler = Transpiler::new();
let object = Expr {
kind: ExprKind::Identifier("vec".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let args = vec![Expr {
kind: ExprKind::Literal(Literal::Integer(42, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}];
let result = transpiler.transpile_method_call(&object, "push", &args);
assert!(result.is_ok());
}
#[test]
fn test_transpile_pipeline_simple() {
use crate::frontend::ast::PipelineStage;
let transpiler = Transpiler::new();
let expr = Expr {
kind: ExprKind::Identifier("data".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let stages = vec![PipelineStage {
op: Box::new(Expr {
kind: ExprKind::Identifier("filter".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
span: Span::default(),
}];
let result = transpiler.transpile_pipeline(&expr, &stages);
assert!(result.is_ok());
}
#[test]
fn test_transpile_function_infer_return_type() {
let transpiler = Transpiler::new();
let params = vec![Param {
pattern: Pattern::Identifier("x".to_string()),
ty: Type {
kind: TypeKind::Named("i32".to_string()),
span: Span::default(),
},
span: Span::default(),
is_mutable: false,
default_value: None,
}];
let body = Expr {
kind: ExprKind::Binary {
left: Box::new(Expr {
kind: ExprKind::Identifier("x".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
op: BinaryOp::Multiply,
right: Box::new(Expr {
kind: ExprKind::Identifier("x".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let result =
transpiler.transpile_function("square", &[], ¶ms, &body, false, None, false, &[]);
assert!(result.is_ok());
}
#[test]
fn test_transpile_function_nested_array_param() {
let transpiler = Transpiler::new();
let params = vec![Param {
pattern: Pattern::Identifier("matrix".to_string()),
ty: Type {
kind: TypeKind::Named("unknown".to_string()),
span: Span::default(),
},
span: Span::default(),
is_mutable: false,
default_value: None,
}];
let body = Expr {
kind: ExprKind::IndexAccess {
object: Box::new(Expr {
kind: ExprKind::IndexAccess {
object: Box::new(Expr {
kind: ExprKind::Identifier("matrix".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
index: Box::new(Expr {
kind: ExprKind::Identifier("i".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
index: Box::new(Expr {
kind: ExprKind::Identifier("j".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let result =
transpiler.transpile_function("get_element", &[], ¶ms, &body, false, None, false, &[]);
assert!(result.is_ok());
}
#[test]
fn test_transpile_function_references_global() {
let transpiler = Transpiler::new();
let body = Expr {
kind: ExprKind::Binary {
left: Box::new(Expr {
kind: ExprKind::Identifier("GLOBAL_CONFIG".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
op: BinaryOp::Add,
right: Box::new(Expr {
kind: ExprKind::Identifier("x".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let params = vec![Param {
pattern: Pattern::Identifier("x".to_string()),
ty: Type {
kind: TypeKind::Named("i32".to_string()),
span: Span::default(),
},
span: Span::default(),
is_mutable: false,
default_value: None,
}];
let result =
transpiler.transpile_function("add_global", &[], ¶ms, &body, false, None, false, &[]);
assert!(result.is_ok());
}
#[test]
fn test_transpile_function_with_test_attribute() {
use crate::frontend::ast::Attribute;
let transpiler = Transpiler::new();
let body = Expr {
kind: ExprKind::Literal(Literal::Bool(true)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let attrs = vec![Attribute {
name: "test".to_string(),
args: vec![],
span: Span::default(),
}];
let result = transpiler.transpile_function(
"test_something",
&[],
&[],
&body,
false,
None,
false,
&attrs,
);
assert!(result.is_ok());
}
#[test]
fn test_transpile_function_with_derive_attribute() {
use crate::frontend::ast::Attribute;
let transpiler = Transpiler::new();
let body = Expr {
kind: ExprKind::Literal(Literal::Integer(42, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let attrs = vec![Attribute {
name: "derive".to_string(),
args: vec!["Clone".to_string(), "Debug".to_string()],
span: Span::default(),
}];
let result =
transpiler.transpile_function("get_value", &[], &[], &body, false, None, true, &attrs);
assert!(result.is_ok());
}
#[test]
fn test_generate_function_signature_async_generic() {
use quote::format_ident;
use quote::quote;
let transpiler = Transpiler::new();
let fn_name = format_ident!("async_generic_fn");
let type_param_tokens = vec![quote! { T: Clone }];
let param_tokens = vec![quote! { x: T }];
let return_type_tokens = quote! { -> T };
let body_tokens = quote! { x.clone() };
let result = transpiler.generate_function_signature(
true,
true,
&fn_name,
&type_param_tokens,
¶m_tokens,
&return_type_tokens,
&body_tokens,
&[],
);
assert!(result.is_ok());
}
#[test]
fn test_try_transpile_dataframe_builder_inline() {
let transpiler = Transpiler::new();
let expr = Expr {
kind: ExprKind::Identifier("df".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let result = transpiler.try_transpile_dataframe_builder_inline(&expr);
assert!(result.is_ok());
}
#[test]
fn test_transpile_function_match_string_arms() {
use crate::frontend::ast::MatchArm;
let transpiler = Transpiler::new();
let params = vec![Param {
pattern: Pattern::Identifier("x".to_string()),
ty: Type {
kind: TypeKind::Named("i32".to_string()),
span: Span::default(),
},
span: Span::default(),
is_mutable: false,
default_value: None,
}];
let body = Expr {
kind: ExprKind::Match {
expr: Box::new(Expr {
kind: ExprKind::Identifier("x".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
arms: vec![
MatchArm {
pattern: Pattern::Literal(Literal::Integer(1, None)),
guard: None,
body: Box::new(Expr {
kind: ExprKind::Literal(Literal::String("one".to_string())),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
span: Span::default(),
},
MatchArm {
pattern: Pattern::Wildcard,
guard: None,
body: Box::new(Expr {
kind: ExprKind::Literal(Literal::String("other".to_string())),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
span: Span::default(),
},
],
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let result = transpiler.transpile_function(
"to_string",
&[],
¶ms,
&body,
false,
Some(&Type {
kind: TypeKind::Named("String".to_string()),
span: Span::default(),
}),
false,
&[],
);
assert!(result.is_ok());
}
#[test]
fn test_transpile_function_mutable_ref_lifetime() {
let transpiler = Transpiler::new();
let params = vec![Param {
pattern: Pattern::Identifier("s".to_string()),
ty: Type {
kind: TypeKind::Reference {
is_mut: true,
lifetime: None,
inner: Box::new(Type {
kind: TypeKind::Named("String".to_string()),
span: Span::default(),
}),
},
span: Span::default(),
},
span: Span::default(),
is_mutable: false,
default_value: None,
}];
let body = Expr {
kind: ExprKind::Identifier("s".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let result = transpiler.transpile_function(
"modify",
&[],
¶ms,
&body,
false,
Some(&Type {
kind: TypeKind::Reference {
is_mut: true,
lifetime: None,
inner: Box::new(Type {
kind: TypeKind::Named("String".to_string()),
span: Span::default(),
}),
},
span: Span::default(),
}),
false,
&[],
);
assert!(result.is_ok());
}
#[test]
fn test_generate_body_tokens_with_string_conversion_if() {
let transpiler = Transpiler::new();
let body = Expr {
kind: ExprKind::If {
condition: Box::new(Expr {
kind: ExprKind::Literal(Literal::Bool(true)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
then_branch: Box::new(Expr {
kind: ExprKind::Literal(Literal::String("yes".to_string())),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
else_branch: Some(Box::new(Expr {
kind: ExprKind::Literal(Literal::String("no".to_string())),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
})),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let result = transpiler.generate_body_tokens_with_string_conversion(&body, false);
assert!(result.is_ok());
}
#[test]
fn test_transpile_call_col_function() {
let transpiler = Transpiler::new();
let func = Expr {
kind: ExprKind::Identifier("col".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let args = vec![Expr {
kind: ExprKind::Literal(Literal::String("name".to_string())),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}];
let result = transpiler.transpile_call(&func, &args);
assert!(result.is_ok());
}
#[test]
fn test_transpile_pipeline_multiple_stages() {
use crate::frontend::ast::PipelineStage;
let transpiler = Transpiler::new();
let expr = Expr {
kind: ExprKind::List(vec![
Expr {
kind: ExprKind::Literal(Literal::Integer(1, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
},
Expr {
kind: ExprKind::Literal(Literal::Integer(2, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
},
]),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let stages = vec![
PipelineStage {
op: Box::new(Expr {
kind: ExprKind::Identifier("filter".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
span: Span::default(),
},
PipelineStage {
op: Box::new(Expr {
kind: ExprKind::Identifier("map".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
span: Span::default(),
},
];
let result = transpiler.transpile_pipeline(&expr, &stages);
assert!(result.is_ok());
}
#[test]
fn test_infer_return_type_from_params_typed() {
let transpiler = Transpiler::new();
let params = vec![Param {
pattern: Pattern::Identifier("x".to_string()),
ty: Type {
kind: TypeKind::Named("i32".to_string()),
span: Span::default(),
},
span: Span::default(),
is_mutable: false,
default_value: None,
}];
let body = Expr {
kind: ExprKind::Identifier("x".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let result = transpiler.infer_return_type_from_params(&body, ¶ms);
assert!(result.is_ok());
}
#[test]
fn test_infer_return_type_from_params_empty() {
let transpiler = Transpiler::new();
let body = Expr {
kind: ExprKind::Literal(Literal::Integer(42, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let result = transpiler.infer_return_type_from_params(&body, &[]);
assert!(result.is_ok());
}
#[test]
fn test_is_nested_array_param_simple() {
let transpiler = Transpiler::new();
let expr = Expr {
kind: ExprKind::Identifier("x".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let result = transpiler.is_nested_array_param("matrix", &expr);
assert!(!result);
}
#[test]
fn test_is_nested_array_param_nested() {
let transpiler = Transpiler::new();
let expr = Expr {
kind: ExprKind::IndexAccess {
object: Box::new(Expr {
kind: ExprKind::IndexAccess {
object: Box::new(Expr {
kind: ExprKind::Identifier("matrix".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
index: Box::new(Expr {
kind: ExprKind::Literal(Literal::Integer(0, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
index: Box::new(Expr {
kind: ExprKind::Literal(Literal::Integer(1, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let result = transpiler.is_nested_array_param("matrix", &expr);
assert!(result);
}
#[test]
fn test_references_globals_local() {
let transpiler = Transpiler::new();
let expr = Expr {
kind: ExprKind::Identifier("local_var".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let result = transpiler.references_globals(&expr);
assert!(!result);
}
#[test]
fn test_references_globals_uppercase() {
let transpiler = Transpiler::new();
let expr = Expr {
kind: ExprKind::Identifier("GLOBAL_CONFIG".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let _result = transpiler.references_globals(&expr);
}
#[test]
fn test_compute_final_return_type_normal() {
use quote::format_ident;
use quote::quote;
let transpiler = Transpiler::new();
let fn_name = format_ident!("my_func");
let return_type_tokens = quote! { -> i32 };
let result = transpiler.compute_final_return_type(&fn_name, &return_type_tokens);
assert!(!result.is_empty());
}
#[test]
fn test_compute_final_return_type_test_fn() {
use quote::format_ident;
use quote::quote;
let transpiler = Transpiler::new();
let fn_name = format_ident!("test_something");
let return_type_tokens = quote! { -> i32 };
let result = transpiler.compute_final_return_type(&fn_name, &return_type_tokens);
assert!(!result.is_empty());
}
#[test]
fn test_generate_visibility_token_pub() {
let transpiler = Transpiler::new();
let result = transpiler.generate_visibility_token(true);
let tokens = result.to_string();
assert!(tokens.contains("pub"));
}
#[test]
fn test_generate_visibility_token_private() {
let transpiler = Transpiler::new();
let result = transpiler.generate_visibility_token(false);
let tokens = result.to_string();
assert!(!tokens.contains("pub"));
}
#[test]
fn test_process_attributes_empty() {
let transpiler = Transpiler::new();
let (attrs, modifiers) = transpiler.process_attributes(&[]);
assert!(attrs.is_empty());
assert!(modifiers.is_empty());
}
#[test]
fn test_process_attributes_with_test() {
use crate::frontend::ast::Attribute;
let transpiler = Transpiler::new();
let attrs = vec![Attribute {
name: "test".to_string(),
args: vec![],
span: Span::default(),
}];
let (regular, modifiers) = transpiler.process_attributes(&attrs);
assert!(!regular.is_empty() || !modifiers.is_empty());
}
#[test]
fn test_generate_function_declaration_sync() {
use quote::format_ident;
use quote::quote;
let transpiler = Transpiler::new();
let fn_name = format_ident!("my_func");
let visibility = quote! { pub };
let modifiers = quote! {};
let param_tokens = vec![quote! { x: i32 }];
let return_type = quote! { -> i32 };
let body = quote! { x + 1 };
let result = transpiler.generate_function_declaration(
false,
&[],
&[],
&visibility,
&modifiers,
&fn_name,
¶m_tokens,
&return_type,
&body,
);
assert!(result.is_ok());
}
#[test]
fn test_generate_function_declaration_async() {
use quote::format_ident;
use quote::quote;
let transpiler = Transpiler::new();
let fn_name = format_ident!("async_func");
let visibility = quote! {};
let modifiers = quote! {};
let param_tokens = vec![];
let return_type = quote! { -> String };
let body = quote! { "hello".to_string() };
let result = transpiler.generate_function_declaration(
true,
&[],
&[],
&visibility,
&modifiers,
&fn_name,
¶m_tokens,
&return_type,
&body,
);
assert!(result.is_ok());
}
#[test]
fn test_transpile_match_with_string_arms_direct() {
use crate::frontend::ast::MatchArm;
let transpiler = Transpiler::new();
let expr = Expr {
kind: ExprKind::Identifier("x".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let arms = vec![
MatchArm {
pattern: Pattern::Literal(Literal::Integer(1, None)),
guard: None,
body: Box::new(Expr {
kind: ExprKind::Literal(Literal::String("one".to_string())),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
span: Span::default(),
},
MatchArm {
pattern: Pattern::Wildcard,
guard: None,
body: Box::new(Expr {
kind: ExprKind::Literal(Literal::String("other".to_string())),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
span: Span::default(),
},
];
let result = transpiler.transpile_match_with_string_arms(&expr, &arms);
assert!(result.is_ok());
}
#[test]
fn test_transpile_type_with_lifetime_named() {
let transpiler = Transpiler::new();
let ty = Type {
kind: TypeKind::Named("String".to_string()),
span: Span::default(),
};
let result = transpiler.transpile_type_with_lifetime(&ty);
assert!(result.is_ok());
}
#[test]
fn test_transpile_type_with_lifetime_ref() {
let transpiler = Transpiler::new();
let ty = Type {
kind: TypeKind::Reference {
is_mut: false,
lifetime: None,
inner: Box::new(Type {
kind: TypeKind::Named("str".to_string()),
span: Span::default(),
}),
},
span: Span::default(),
};
let result = transpiler.transpile_type_with_lifetime(&ty);
assert!(result.is_ok());
}
#[test]
fn test_try_transpile_dataframe_function_col() {
let transpiler = Transpiler::new();
let args = vec![Expr {
kind: ExprKind::Literal(Literal::String("name".to_string())),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}];
let result = transpiler.try_transpile_dataframe_function("col", &args);
assert!(result.is_ok());
}
#[test]
fn test_try_transpile_dataframe_function_unknown() {
let transpiler = Transpiler::new();
let args = vec![];
let result = transpiler.try_transpile_dataframe_function("unknown_func", &args);
assert!(result.is_ok());
}
#[test]
fn test_generate_function_declaration_generic() {
use quote::format_ident;
use quote::quote;
let transpiler = Transpiler::new();
let fn_name = format_ident!("generic_func");
let visibility = quote! { pub };
let modifiers = quote! {};
let type_params = vec![quote! { T: Clone }];
let param_tokens = vec![quote! { x: T }];
let return_type = quote! { -> T };
let body = quote! { x.clone() };
let result = transpiler.generate_function_declaration(
false,
&type_params,
&[],
&visibility,
&modifiers,
&fn_name,
¶m_tokens,
&return_type,
&body,
);
assert!(result.is_ok());
}