#![allow(clippy::missing_errors_doc)]
#![allow(clippy::too_many_lines)]
mod actors;
pub mod codegen_minimal;
pub mod constant_folder; mod dataframe;
mod effects;
pub mod inline_expander; mod advanced_math; mod ast_analysis; mod bindings; mod block_categorization; mod block_transpiler; mod body_generation; pub mod builtin_type_inference;
mod call_helpers; mod call_transpilation; mod comprehensions; mod control_flow; mod dataframe_builder;
mod dataframe_helpers;
mod dataframe_transpilers; mod dispatcher;
mod expr_dispatcher; pub mod expression_analysis;
mod expressions;
pub mod function_analysis;
mod function_param_inference; mod function_signature; mod function_transpiler; pub mod import_helpers;
mod imports; mod input_builtins; #[cfg(test)]
mod integration_tests; mod lambda_transpiler; mod lifetime_helpers; mod math_builtins; mod method_call_refactored;
mod method_transpilers; pub mod mutation_detection;
mod network_builtins; pub mod param_usage_analysis;
#[cfg(test)]
mod param_usage_analysis_tests; pub mod pattern_bindings;
mod patterns;
mod print_helpers; mod program_transpiler; mod result_type;
pub mod return_type_helpers;
mod statements;
#[cfg(test)]
mod statements_tests; pub mod std_imports;
mod string_body_conversion; mod system_builtins; #[cfg(test)]
mod tests_compound_assignment;
pub mod type_analysis;
mod type_conversion_refactored;
mod type_conversions; mod type_inference;
mod type_transpilers; mod types;
#[cfg(test)]
mod types_tests; mod utility_builtins; use crate::frontend::ast::{Attribute, Expr, ExprKind, Type};
use anyhow::Result;
use proc_macro2::TokenStream;
type BlockCategorization<'a> = (
Vec<TokenStream>, Vec<TokenStream>, Vec<TokenStream>, bool, Option<&'a Expr>, Vec<TokenStream>, Vec<TokenStream>, );
#[derive(Debug, Clone)]
pub struct FunctionSignature {
pub name: String,
pub param_types: Vec<String>,
}
pub struct Transpiler {
pub in_async_context: bool,
pub in_loop_context: std::cell::Cell<bool>,
pub mutable_vars: std::collections::HashSet<String>,
pub function_signatures: std::collections::HashMap<String, FunctionSignature>,
pub module_names: std::collections::HashSet<String>,
pub string_vars: std::cell::RefCell<std::collections::HashSet<String>>,
pub current_function_return_type: std::cell::RefCell<Option<crate::frontend::ast::Type>>,
pub global_vars: std::sync::RwLock<std::collections::HashSet<String>>,
pub const_vars: std::sync::RwLock<std::collections::HashSet<String>>,
pub variable_types: std::cell::RefCell<std::collections::HashMap<String, String>>,
pub struct_field_types: std::cell::RefCell<std::collections::HashMap<(String, String), String>>,
pub current_struct_name: std::cell::RefCell<Option<String>>,
pub auto_boxed_fields: std::cell::RefCell<std::collections::HashMap<(String, String), String>>,
pub call_site_arg_types:
std::cell::RefCell<std::collections::HashMap<String, Vec<String>>>,
}
impl Default for Transpiler {
fn default() -> Self {
Self::new()
}
}
impl Clone for Transpiler {
fn clone(&self) -> Self {
Self {
in_async_context: self.in_async_context,
in_loop_context: std::cell::Cell::new(self.in_loop_context.get()),
mutable_vars: self.mutable_vars.clone(),
function_signatures: self.function_signatures.clone(),
module_names: self.module_names.clone(),
string_vars: std::cell::RefCell::new(self.string_vars.borrow().clone()),
current_function_return_type: std::cell::RefCell::new(
self.current_function_return_type.borrow().clone(),
),
global_vars: std::sync::RwLock::new(
self.global_vars
.read()
.expect("rwlock should not be poisoned")
.clone(),
),
const_vars: std::sync::RwLock::new(
self.const_vars
.read()
.expect("rwlock should not be poisoned")
.clone(),
),
variable_types: std::cell::RefCell::new(self.variable_types.borrow().clone()),
struct_field_types: std::cell::RefCell::new(self.struct_field_types.borrow().clone()),
current_struct_name: std::cell::RefCell::new(self.current_struct_name.borrow().clone()),
auto_boxed_fields: std::cell::RefCell::new(self.auto_boxed_fields.borrow().clone()),
call_site_arg_types: std::cell::RefCell::new(
self.call_site_arg_types.borrow().clone(),
),
}
}
}
impl Transpiler {
pub fn new() -> Self {
Self {
in_async_context: false,
in_loop_context: std::cell::Cell::new(false),
mutable_vars: std::collections::HashSet::new(),
function_signatures: std::collections::HashMap::new(),
module_names: std::collections::HashSet::new(),
string_vars: std::cell::RefCell::new(std::collections::HashSet::new()),
current_function_return_type: std::cell::RefCell::new(None),
global_vars: std::sync::RwLock::new(std::collections::HashSet::new()),
const_vars: std::sync::RwLock::new(std::collections::HashSet::new()),
variable_types: std::cell::RefCell::new(std::collections::HashMap::new()),
struct_field_types: std::cell::RefCell::new(std::collections::HashMap::new()),
current_struct_name: std::cell::RefCell::new(None),
auto_boxed_fields: std::cell::RefCell::new(std::collections::HashMap::new()),
call_site_arg_types: std::cell::RefCell::new(std::collections::HashMap::new()),
}
}
pub fn transpile(&mut self, expr: &Expr) -> Result<TokenStream> {
self.transpile_to_program(expr)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::frontend::ast::{
BinaryOp, Expr, ExprKind, Literal, Param, Pattern, Span, Type, TypeKind,
};
fn create_test_literal_expr(value: i64) -> Expr {
Expr {
kind: ExprKind::Literal(Literal::Integer(value, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}
}
fn create_test_binary_expr(op: BinaryOp, left: Expr, right: Expr) -> Expr {
Expr {
kind: ExprKind::Binary {
op,
left: Box::new(left),
right: Box::new(right),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}
}
fn create_test_variable_expr(name: &str) -> Expr {
Expr {
kind: ExprKind::Identifier(name.to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}
}
fn create_simple_type(name: &str) -> Type {
Type {
kind: TypeKind::Named(name.to_string()),
span: Span::default(),
}
}
#[test]
fn test_transpiler_creation() {
let transpiler = Transpiler::new();
assert!(!transpiler.in_async_context);
assert!(transpiler.mutable_vars.is_empty());
assert!(transpiler.function_signatures.is_empty());
let default_transpiler = Transpiler::default();
assert!(!default_transpiler.in_async_context);
assert!(default_transpiler.mutable_vars.is_empty());
}
#[test]
fn test_function_signature_collection() {
let mut transpiler = Transpiler::new();
let func_expr = Expr {
kind: ExprKind::Function {
name: "test_func".to_string(),
type_params: vec![],
params: vec![
Param {
pattern: Pattern::Identifier("x".to_string()),
ty: create_simple_type("i64"),
span: Span::default(),
is_mutable: false,
default_value: None,
},
Param {
pattern: Pattern::Identifier("y".to_string()),
ty: create_simple_type("String"),
span: Span::default(),
is_mutable: false,
default_value: None,
},
],
return_type: Some(create_simple_type("i64")),
body: Box::new(create_test_literal_expr(42)),
is_async: false,
is_pub: false,
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
transpiler.collect_signatures_from_expr(&func_expr);
assert!(
!transpiler.function_signatures.is_empty() || transpiler.function_signatures.is_empty()
);
}
#[test]
fn test_type_to_string() {
let int_type = create_simple_type("i64");
let float_type = create_simple_type("f64");
let string_type = create_simple_type("String");
let bool_type = create_simple_type("bool");
let int_result = Transpiler::type_to_string(&int_type);
assert!(!int_result.is_empty());
let float_result = Transpiler::type_to_string(&float_type);
assert!(!float_result.is_empty());
let string_result = Transpiler::type_to_string(&string_type);
assert!(!string_result.is_empty());
let bool_result = Transpiler::type_to_string(&bool_type);
assert!(!bool_result.is_empty());
let list_type = Type {
kind: TypeKind::List(Box::new(create_simple_type("i64"))),
span: Span::default(),
};
let list_result = Transpiler::type_to_string(&list_type);
assert!(!list_result.is_empty());
}
#[test]
fn test_contains_hashmap() {
let object_expr = Expr {
kind: ExprKind::ObjectLiteral { fields: vec![] },
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let literal_expr = create_test_literal_expr(42);
let has_hashmap_obj = Transpiler::contains_hashmap(&object_expr);
let has_hashmap_literal = Transpiler::contains_hashmap(&literal_expr);
let _ = has_hashmap_obj;
let _ = has_hashmap_literal;
}
#[test]
fn test_contains_dataframe() {
let df_expr = Expr {
kind: ExprKind::DataFrame { columns: vec![] },
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let literal_expr = create_test_literal_expr(42);
let has_dataframe_df = Transpiler::contains_dataframe(&df_expr);
let has_dataframe_literal = Transpiler::contains_dataframe(&literal_expr);
let _ = has_dataframe_df;
let _ = has_dataframe_literal;
}
#[test]
fn test_analyze_mutability() {
let mut transpiler = Transpiler::new();
let assign_expr = Expr {
kind: ExprKind::Assign {
target: Box::new(create_test_variable_expr("x")),
value: Box::new(create_test_literal_expr(42)),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
transpiler.analyze_expr_mutability(&assign_expr);
let assign_expr2 = Expr {
kind: ExprKind::Assign {
target: Box::new(create_test_variable_expr("y")),
value: Box::new(create_test_literal_expr(24)),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
transpiler.analyze_expr_mutability(&assign_expr2);
}
#[test]
fn test_basic_transpile() {
let mut transpiler = Transpiler::new();
let literal_expr = create_test_literal_expr(42);
let result = transpiler.transpile(&literal_expr);
assert!(result.is_ok());
let token_stream = result.expect("operation should succeed in test");
let code = token_stream.to_string();
assert!(code.contains("42"));
}
#[test]
fn test_block_transpile() {
let mut transpiler = Transpiler::new();
let block_expr = Expr {
kind: ExprKind::Block(vec![
create_test_literal_expr(1),
create_test_literal_expr(2),
create_test_literal_expr(3),
]),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let result = transpiler.transpile(&block_expr);
assert!(result.is_ok() || result.is_err());
if let Ok(token_stream) = result {
let code = token_stream.to_string();
assert!(!code.is_empty());
}
}
#[test]
fn test_transpile_to_program() {
let mut transpiler = Transpiler::new();
let literal_expr = create_test_literal_expr(42);
let result = transpiler.transpile_to_program(&literal_expr);
assert!(result.is_ok());
let token_stream = result.expect("operation should succeed in test");
let code = token_stream.to_string();
assert!(code.contains("fn main"));
assert!(code.contains("42"));
}
#[test]
fn test_transpile_program_with_dependencies() {
let mut transpiler = Transpiler::new();
let object_expr = Expr {
kind: ExprKind::ObjectLiteral { fields: vec![] },
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let result = transpiler.transpile_to_program(&object_expr);
assert!(result.is_ok() || result.is_err());
if let Ok(token_stream) = result {
let code = token_stream.to_string();
assert!(!code.is_empty());
}
}
#[test]
fn test_function_transpilation() {
let mut transpiler = Transpiler::new();
let func_expr = Expr {
kind: ExprKind::Function {
name: "add".to_string(),
type_params: vec![],
params: vec![
Param {
pattern: Pattern::Identifier("a".to_string()),
ty: create_simple_type("i64"),
span: Span::default(),
is_mutable: false,
default_value: None,
},
Param {
pattern: Pattern::Identifier("b".to_string()),
ty: create_simple_type("i64"),
span: Span::default(),
is_mutable: false,
default_value: None,
},
],
return_type: Some(create_simple_type("i64")),
body: Box::new(create_test_binary_expr(
BinaryOp::Add,
create_test_variable_expr("a"),
create_test_variable_expr("b"),
)),
is_async: false,
is_pub: false,
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let result = transpiler.transpile_to_program(&func_expr);
assert!(result.is_ok() || result.is_err());
if let Ok(token_stream) = result {
let code = token_stream.to_string();
assert!(!code.is_empty());
}
}
#[test]
fn test_transpile_error_handling() {
let mut transpiler = Transpiler::new();
let complex_expr = Expr {
kind: ExprKind::Binary {
op: BinaryOp::Add,
left: Box::new(create_test_variable_expr("undefined_var")),
right: Box::new(create_test_literal_expr(42)),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let result = transpiler.transpile(&complex_expr);
assert!(result.is_ok() || result.is_err()); }
#[test]
fn test_async_context() {
let mut transpiler = Transpiler::new();
assert!(!transpiler.in_async_context);
transpiler.in_async_context = true;
assert!(transpiler.in_async_context);
let literal_expr = create_test_literal_expr(42);
let result = transpiler.transpile(&literal_expr);
assert!(result.is_ok()); }
#[test]
fn test_multiple_function_signatures() {
let mut transpiler = Transpiler::new();
let functions = vec![
("func1", vec!["i64", "String"]),
("func2", vec!["f64", "bool"]),
("func3", vec!["String"]),
];
for (name, param_type_names) in &functions {
let params: Vec<_> = param_type_names
.iter()
.enumerate()
.map(|(i, ty_name)| Param {
pattern: Pattern::Identifier(format!("param{i}")),
ty: create_simple_type(ty_name),
span: Span::default(),
is_mutable: false,
default_value: None,
})
.collect();
let func_expr = Expr {
kind: ExprKind::Function {
name: (*name).to_string(),
type_params: vec![],
params,
body: Box::new(create_test_literal_expr(42)),
return_type: Some(create_simple_type("i64")),
is_async: false,
is_pub: false,
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
transpiler.collect_signatures_from_expr(&func_expr);
}
}
#[test]
fn test_import_resolution() {
let transpiler = Transpiler::new();
let literal_expr = create_test_literal_expr(42);
let result = transpiler.resolve_imports(&literal_expr);
assert!(result.is_ok() || result.is_err());
if let Ok(resolved) = result {
if let ExprKind::Literal(Literal::Integer(val, None)) = resolved.kind {
assert_eq!(val, 42);
} else {
}
}
}
#[test]
fn test_complex_expression_chains() {
let mut transpiler = Transpiler::new();
let inner_add = create_test_binary_expr(
BinaryOp::Add,
create_test_literal_expr(1),
create_test_literal_expr(2),
);
let multiply =
create_test_binary_expr(BinaryOp::Multiply, inner_add, create_test_literal_expr(3));
let final_add =
create_test_binary_expr(BinaryOp::Add, multiply, create_test_literal_expr(4));
let result = transpiler.transpile(&final_add);
assert!(result.is_ok() || result.is_err());
if let Ok(token_stream) = result {
let code = token_stream.to_string();
assert!(!code.is_empty());
}
}
#[test]
fn test_is_call_to_main_true() {
let main_call = Expr {
kind: ExprKind::Call {
func: Box::new(create_test_variable_expr("main")),
args: vec![],
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(Transpiler::is_call_to_main(&main_call));
}
#[test]
fn test_is_call_to_main_false() {
let other_call = Expr {
kind: ExprKind::Call {
func: Box::new(create_test_variable_expr("other_func")),
args: vec![],
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(!Transpiler::is_call_to_main(&other_call));
}
#[test]
fn test_is_standard_library_std() {
assert!(Transpiler::is_standard_library("std"));
assert!(Transpiler::is_standard_library("core"));
assert!(Transpiler::is_standard_library("alloc"));
}
#[test]
fn test_is_standard_library_third_party() {
assert!(Transpiler::is_standard_library("tokio"));
assert!(Transpiler::is_standard_library("serde"));
assert!(Transpiler::is_standard_library("serde_json"));
assert!(Transpiler::is_standard_library("polars"));
}
#[test]
fn test_is_standard_library_false() {
assert!(!Transpiler::is_standard_library("my_module"));
assert!(!Transpiler::is_standard_library("custom_lib"));
}
#[test]
fn test_contains_imports_true() {
let _transpiler = Transpiler::new();
let import_expr = Expr {
kind: ExprKind::Import {
module: "std::io".to_string(),
items: Some(vec!["Read".to_string()]),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(Transpiler::contains_imports(&import_expr));
}
#[test]
fn test_contains_imports_false() {
let literal_expr = create_test_literal_expr(42);
assert!(!Transpiler::contains_imports(&literal_expr));
}
#[test]
fn test_contains_file_imports_relative() {
let _transpiler = Transpiler::new();
let file_import = Expr {
kind: ExprKind::Import {
module: "./my_module".to_string(),
items: None,
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(Transpiler::contains_file_imports(&file_import));
}
#[test]
fn test_contains_file_imports_parent() {
let file_import = Expr {
kind: ExprKind::Import {
module: "../parent_module".to_string(),
items: None,
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(Transpiler::contains_file_imports(&file_import));
}
#[test]
fn test_contains_file_imports_std_false() {
let std_import = Expr {
kind: ExprKind::Import {
module: "std::collections::HashMap".to_string(),
items: None,
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(!Transpiler::contains_file_imports(&std_import));
}
#[test]
fn test_is_statement_expr_let() {
let let_expr = Expr {
kind: ExprKind::Let {
name: "x".to_string(),
value: Box::new(create_test_literal_expr(42)),
body: Box::new(create_test_literal_expr(0)),
type_annotation: None,
is_mutable: false,
else_block: None,
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(Transpiler::is_statement_expr(&let_expr));
}
#[test]
fn test_is_statement_expr_assign() {
let assign_expr = Expr {
kind: ExprKind::Assign {
target: Box::new(create_test_variable_expr("x")),
value: Box::new(create_test_literal_expr(42)),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(Transpiler::is_statement_expr(&assign_expr));
}
#[test]
fn test_is_statement_expr_while() {
let while_expr = Expr {
kind: ExprKind::While {
condition: Box::new(create_test_literal_expr(1)),
body: Box::new(create_test_literal_expr(2)),
label: None,
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(Transpiler::is_statement_expr(&while_expr));
}
#[test]
fn test_is_statement_expr_false() {
let literal_expr = create_test_literal_expr(42);
assert!(!Transpiler::is_statement_expr(&literal_expr));
}
#[test]
fn test_generate_use_statements_both() {
let transpiler = Transpiler::new();
let result = transpiler.generate_use_statements(true, true);
let code = result.to_string();
assert!(code.contains("polars"));
assert!(code.contains("HashMap"));
}
#[test]
fn test_collect_module_names_single_module() {
let mut transpiler = Transpiler::new();
let module_expr = Expr {
kind: ExprKind::Module {
name: "test_module".to_string(),
body: Box::new(create_test_literal_expr(42)),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
transpiler.collect_module_names_from_expr(&module_expr);
assert!(transpiler.module_names.contains("test_module"));
}
#[test]
fn test_collect_module_names_block() {
let mut transpiler = Transpiler::new();
let module1 = Expr {
kind: ExprKind::Module {
name: "mod1".to_string(),
body: Box::new(create_test_literal_expr(1)),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let module2 = Expr {
kind: ExprKind::Module {
name: "mod2".to_string(),
body: Box::new(create_test_literal_expr(2)),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let block_expr = Expr {
kind: ExprKind::Block(vec![module1, module2]),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
transpiler.collect_module_names_from_expr(&block_expr);
assert!(transpiler.module_names.contains("mod1"));
assert!(transpiler.module_names.contains("mod2"));
}
#[test]
fn test_mark_target_mutable_identifier() {
let mut transpiler = Transpiler::new();
let target = create_test_variable_expr("x");
transpiler.mark_target_mutable(&target);
assert!(transpiler.mutable_vars.contains("x"));
}
#[test]
fn test_analyze_block_mutability_empty() {
let mut transpiler = Transpiler::new();
transpiler.analyze_block_mutability(&[]);
assert!(transpiler.mutable_vars.is_empty());
}
#[test]
fn test_analyze_block_mutability_with_assign() {
let mut transpiler = Transpiler::new();
let assign_expr = Expr {
kind: ExprKind::Assign {
target: Box::new(create_test_variable_expr("y")),
value: Box::new(create_test_literal_expr(10)),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
transpiler.analyze_block_mutability(&[assign_expr]);
assert!(transpiler.mutable_vars.contains("y"));
}
#[test]
fn test_analyze_if_mutability_simple() {
let mut transpiler = Transpiler::new();
let condition = create_test_literal_expr(1);
let then_branch = create_test_variable_expr("z");
transpiler.analyze_if_mutability(&condition, &then_branch, None);
}
#[test]
fn test_analyze_two_expr_mutability_literals() {
let mut transpiler = Transpiler::new();
let expr1 = create_test_literal_expr(5);
let expr2 = create_test_literal_expr(10);
transpiler.analyze_two_expr_mutability(&expr1, &expr2);
assert!(transpiler.mutable_vars.is_empty());
}
#[test]
fn test_analyze_match_mutability_simple() {
let mut transpiler = Transpiler::new();
let match_expr = create_test_variable_expr("val");
let arms = vec![];
transpiler.analyze_match_mutability(&match_expr, &arms);
}
#[test]
fn test_analyze_call_mutability_simple() {
let mut transpiler = Transpiler::new();
let func = create_test_variable_expr("my_func");
let args = vec![create_test_literal_expr(42)];
transpiler.analyze_call_mutability(&func, &args);
}
#[test]
fn test_has_standalone_functions_single() {
let func_expr = Expr {
kind: ExprKind::Function {
name: "foo".to_string(),
type_params: vec![],
params: vec![],
return_type: None,
body: Box::new(create_test_literal_expr(1)),
is_async: false,
is_pub: false,
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(Transpiler::has_standalone_functions(&func_expr));
}
#[test]
fn test_has_standalone_functions_block() {
let func_expr = Expr {
kind: ExprKind::Function {
name: "bar".to_string(),
type_params: vec![],
params: vec![],
return_type: None,
body: Box::new(create_test_literal_expr(2)),
is_async: false,
is_pub: false,
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let block_expr = Expr {
kind: ExprKind::Block(vec![func_expr, create_test_literal_expr(3)]),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(Transpiler::has_standalone_functions(&block_expr));
}
#[test]
fn test_has_standalone_functions_false() {
let literal_expr = create_test_literal_expr(100);
assert!(!Transpiler::has_standalone_functions(&literal_expr));
}
#[test]
fn test_type_to_string_reference() {
let ref_type = Type {
kind: TypeKind::Reference {
inner: Box::new(create_simple_type("i64")),
is_mut: false,
lifetime: None,
},
span: Span::default(),
};
let result = Transpiler::type_to_string(&ref_type);
assert!(result.contains('&') || result.contains("i64"));
}
#[test]
fn test_collect_signatures_multiple_functions() {
let mut transpiler = Transpiler::new();
let func1 = Expr {
kind: ExprKind::Function {
name: "func1".to_string(),
type_params: vec![],
params: vec![],
return_type: None,
body: Box::new(create_test_literal_expr(1)),
is_async: false,
is_pub: false,
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let func2 = Expr {
kind: ExprKind::Function {
name: "func2".to_string(),
type_params: vec![],
params: vec![],
return_type: None,
body: Box::new(create_test_literal_expr(2)),
is_async: false,
is_pub: false,
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let block_expr = Expr {
kind: ExprKind::Block(vec![func1, func2]),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
transpiler.collect_signatures_from_expr(&block_expr);
assert_eq!(transpiler.function_signatures.len(), 2);
}
#[test]
fn test_collect_module_names_nested() {
let mut transpiler = Transpiler::new();
let inner_module = Expr {
kind: ExprKind::Module {
name: "inner".to_string(),
body: Box::new(create_test_literal_expr(99)),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let outer_module = Expr {
kind: ExprKind::Module {
name: "outer".to_string(),
body: Box::new(inner_module),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
transpiler.collect_module_names_from_expr(&outer_module);
assert!(transpiler.module_names.contains("outer"));
assert!(transpiler.module_names.contains("inner"));
}
}