Coverage Report

Created: 2025-09-05 15:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/home/noah/src/ruchy/src/backend/transpiler/statements.rs
Line
Count
Source
1
//! Statement and control flow transpilation
2
3
#![allow(clippy::missing_errors_doc)]
4
#![allow(clippy::wildcard_imports)]
5
#![allow(clippy::collapsible_else_if)]
6
7
use super::*;
8
use crate::frontend::ast::{Literal, Param, Pattern, PipelineStage, UnaryOp};
9
use anyhow::{Result, bail};
10
use proc_macro2::TokenStream;
11
use quote::{format_ident, quote};
12
13
impl Transpiler {
14
    /// Checks if a variable is mutated (reassigned or modified) in an expression tree
15
45
    fn is_variable_mutated(name: &str, expr: &Expr) -> bool {
16
        use crate::frontend::ast::ExprKind;
17
        
18
45
        match &expr.kind {
19
            // Direct assignment to the variable
20
0
            ExprKind::Assign { target, value: _ } => {
21
0
                if let ExprKind::Identifier(var_name) = &target.kind {
22
0
                    if var_name == name {
23
0
                        return true;
24
0
                    }
25
0
                }
26
0
                false
27
            }
28
            // Compound assignment (+=, -=, etc.)
29
0
            ExprKind::CompoundAssign { target, value: _, .. } => {
30
0
                if let ExprKind::Identifier(var_name) = &target.kind {
31
0
                    if var_name == name {
32
0
                        return true;
33
0
                    }
34
0
                }
35
0
                false
36
            }
37
            // Pre/Post increment/decrement
38
0
            ExprKind::PreIncrement { target } | 
39
0
            ExprKind::PostIncrement { target } |
40
0
            ExprKind::PreDecrement { target } |
41
0
            ExprKind::PostDecrement { target } => {
42
0
                if let ExprKind::Identifier(var_name) = &target.kind {
43
0
                    if var_name == name {
44
0
                        return true;
45
0
                    }
46
0
                }
47
0
                false
48
            }
49
            // Check in blocks
50
1
            ExprKind::Block(exprs) => {
51
3
                
exprs.iter()1
.
any1
(|e| Self::is_variable_mutated(name, e))
52
            }
53
            // Check in if branches
54
0
            ExprKind::If { condition, then_branch, else_branch } => {
55
0
                Self::is_variable_mutated(name, condition) ||
56
0
                Self::is_variable_mutated(name, then_branch) ||
57
0
                else_branch.as_ref().is_some_and(|e| Self::is_variable_mutated(name, e))
58
            }
59
            // Check in while loops
60
0
            ExprKind::While { condition, body } => {
61
0
                Self::is_variable_mutated(name, condition) ||
62
0
                Self::is_variable_mutated(name, body)
63
            }
64
            // Check in for loops
65
0
            ExprKind::For { body, .. } => {
66
0
                Self::is_variable_mutated(name, body)
67
            }
68
            // Check in match expressions
69
0
            ExprKind::Match { expr, arms } => {
70
0
                Self::is_variable_mutated(name, expr) ||
71
0
                arms.iter().any(|arm| Self::is_variable_mutated(name, &arm.body))
72
            }
73
            // Check in nested let expressions
74
4
            ExprKind::Let { body, .. } | ExprKind::LetPattern { 
body0
, .. } => {
75
4
                Self::is_variable_mutated(name, body)
76
            }
77
            // Check in function bodies
78
0
            ExprKind::Function { body, .. } => {
79
0
                Self::is_variable_mutated(name, body)
80
            }
81
            // Check in lambda bodies
82
0
            ExprKind::Lambda { body, .. } => {
83
0
                Self::is_variable_mutated(name, body)
84
            }
85
            // Check binary operations
86
10
            ExprKind::Binary { left, right, .. } => {
87
10
                Self::is_variable_mutated(name, left) ||
88
10
                Self::is_variable_mutated(name, right)
89
            }
90
            // Check unary operations
91
0
            ExprKind::Unary { operand, .. } => {
92
0
                Self::is_variable_mutated(name, operand)
93
            }
94
            // Check function/method calls
95
2
            ExprKind::Call { func, args } => {
96
2
                Self::is_variable_mutated(name, func) ||
97
2
                args.iter().any(|a| Self::is_variable_mutated(name, a))
98
            }
99
0
            ExprKind::MethodCall { receiver, args, .. } => {
100
0
                Self::is_variable_mutated(name, receiver) ||
101
0
                args.iter().any(|a| Self::is_variable_mutated(name, a))
102
            }
103
            // Other expressions don't contain mutations
104
28
            _ => false,
105
        }
106
45
    }
107
108
    /// Transpiles if expressions
109
48
    pub fn transpile_if(
110
48
        &self,
111
48
        condition: &Expr,
112
48
        then_branch: &Expr,
113
48
        else_branch: Option<&Expr>,
114
48
    ) -> Result<TokenStream> {
115
48
        let cond_tokens = self.transpile_expr(condition)
?0
;
116
48
        let then_tokens = self.transpile_expr(then_branch)
?0
;
117
118
48
        if let Some(
else_expr23
) = else_branch {
119
23
            let else_tokens = self.transpile_expr(else_expr)
?0
;
120
23
            Ok(quote! {
121
23
                if #cond_tokens {
122
23
                    #then_tokens
123
23
                } else {
124
23
                    #else_tokens
125
23
                }
126
23
            })
127
        } else {
128
25
            Ok(quote! {
129
25
                if #cond_tokens {
130
25
                    #then_tokens
131
25
                }
132
25
            })
133
        }
134
48
    }
135
136
    /// Transpiles let bindings
137
15
    pub fn transpile_let(
138
15
        &self,
139
15
        name: &str,
140
15
        value: &Expr,
141
15
        body: &Expr,
142
15
        is_mutable: bool,
143
15
    ) -> Result<TokenStream> {
144
        // Handle Rust reserved keywords by prefixing with r#
145
15
        let safe_name = if Self::is_rust_reserved_keyword(name) {
146
1
            format!("r#{name}")
147
        } else {
148
14
            name.to_string()
149
        };
150
15
        let name_ident = format_ident!("{}", safe_name);
151
        
152
        // Auto-detect mutability: check if variable is in the mutable_vars set or is reassigned in body
153
15
        let effective_mutability = is_mutable || 
154
14
                                  self.mutable_vars.contains(name) || 
155
14
                                  Self::is_variable_mutated(name, body);
156
        
157
        // Convert string literals to String type at variable declaration time
158
        // This ensures string variables are String, not &str, making function calls work
159
15
        let value_tokens = match 
&value.kind12
{
160
0
            crate::frontend::ast::ExprKind::Literal(crate::frontend::ast::Literal::String(s)) => {
161
0
                quote! { #s.to_string() }
162
            }
163
15
            _ => self.transpile_expr(value)
?0
164
        };
165
        
166
        // HOTFIX: If body is Unit, this is a top-level let statement without scoping
167
10
        if matches!(
body.kind5
, crate::frontend::ast::ExprKind::Literal(crate::frontend::ast::Literal::Unit)) {
168
5
            if effective_mutability {
169
1
                Ok(quote! { let mut #name_ident = #value_tokens; })
170
            } else {
171
4
                Ok(quote! { let #name_ident = #value_tokens; })
172
            }
173
        } else {
174
            // Traditional let-in expression with proper scoping
175
10
            let body_tokens = self.transpile_expr(body)
?0
;
176
10
            if effective_mutability {
177
0
                Ok(quote! {
178
0
                    {
179
0
                        let mut #name_ident = #value_tokens;
180
0
                        #body_tokens
181
0
                    }
182
0
                })
183
            } else {
184
10
                Ok(quote! {
185
10
                    {
186
10
                        let #name_ident = #value_tokens;
187
10
                        #body_tokens
188
10
                    }
189
10
                })
190
            }
191
        }
192
15
    }
193
194
    /// Transpiles let pattern bindings (destructuring)
195
0
    pub fn transpile_let_pattern(
196
0
        &self,
197
0
        pattern: &crate::frontend::ast::Pattern,
198
0
        value: &Expr,
199
0
        body: &Expr,
200
0
    ) -> Result<TokenStream> {
201
0
        let pattern_tokens = self.transpile_pattern(pattern)?;
202
0
        let value_tokens = self.transpile_expr(value)?;
203
        
204
        // HOTFIX: If body is Unit, this is a top-level let statement without scoping
205
0
        if matches!(body.kind, crate::frontend::ast::ExprKind::Literal(crate::frontend::ast::Literal::Unit)) {
206
0
            Ok(quote! { let #pattern_tokens = #value_tokens })
207
        } else {
208
            // Traditional let-in expression with proper scoping
209
0
            let body_tokens = self.transpile_expr(body)?;
210
0
            Ok(quote! {
211
0
                {
212
0
                    let #pattern_tokens = #value_tokens;
213
0
                    #body_tokens
214
0
                }
215
0
            })
216
        }
217
0
    }
218
219
    /// Check if function name suggests numeric operations
220
23
    fn looks_like_numeric_function(&self, name: &str) -> bool {
221
23
        
matches!9
(name,
222
23
            "add" | 
"subtract"21
|
"multiply"21
|
"divide"21
|
"sum"21
|
"product"21
|
223
21
            "min" | "max" | "abs" | "sqrt" | "pow" | "mod" | "gcd" | "lcm" |
224
21
            "factorial" | 
"fibonacci"20
|
"prime"18
|
"even"18
|
"odd"18
|
"square"18
|
"cube"17
|
225
17
            "double" | 
"triple"14
|
"quadruple"14
// Added common numeric function names
226
        )
227
23
    }
228
229
230
    /// Check if expression is a void/unit function call
231
2
    fn is_void_function_call(&self, expr: &Expr) -> bool {
232
2
        match &expr.kind {
233
2
            crate::frontend::ast::ExprKind::Call { func, .. } => {
234
2
                if let crate::frontend::ast::ExprKind::Identifier(name) = &func.kind {
235
                    // Comprehensive list of void functions
236
2
                    
matches!1
(name.as_str(),
237
                        // Output functions
238
2
                        "println" | 
"print"1
|
"eprintln"1
|
"eprint"1
|
239
                        // Debug functions
240
1
                        "dbg" | "debug" | "trace" | "info" | "warn" | "error" |
241
                        // Control flow functions
242
1
                        "panic" | "assert" | "assert_eq" | "assert_ne" |
243
1
                        "todo" | "unimplemented" | "unreachable"
244
                    )
245
                } else {
246
0
                    false
247
                }
248
            }
249
0
            _ => false
250
        }
251
2
    }
252
    
253
    /// Check if an expression is void (returns unit/nothing)
254
15
    fn is_void_expression(&self, expr: &Expr) -> bool {
255
2
        match &expr.kind {
256
            // Unit literal is void
257
1
            crate::frontend::ast::ExprKind::Literal(crate::frontend::ast::Literal::Unit) => true,
258
            
259
            // Void function calls
260
2
            crate::frontend::ast::ExprKind::Call { .. } if self.is_void_function_call(expr
)1
=>
true1
,
261
            
262
            // Assignments are void
263
            crate::frontend::ast::ExprKind::Assign { .. } |
264
0
            crate::frontend::ast::ExprKind::CompoundAssign { .. } => true,
265
            
266
            // Loops are void
267
            crate::frontend::ast::ExprKind::While { .. } |
268
0
            crate::frontend::ast::ExprKind::For { .. } => true,
269
            
270
            // Let bindings - check the body expression
271
0
            crate::frontend::ast::ExprKind::Let { body, .. } => {
272
0
                self.is_void_expression(body)
273
            }
274
            
275
            // Block - check last expression
276
7
            crate::frontend::ast::ExprKind::Block(exprs) => {
277
7
                exprs.last().is_none_or(|e| self.is_void_expression(e))
278
            }
279
            
280
            // If expression - both branches must be void
281
1
            crate::frontend::ast::ExprKind::If { then_branch, else_branch, .. } => {
282
1
                self.is_void_expression(then_branch) && 
283
0
                else_branch.as_ref().is_none_or(|e| self.is_void_expression(e))
284
            }
285
            
286
            // Match expression - all arms must be void
287
0
            crate::frontend::ast::ExprKind::Match { arms, .. } => {
288
0
                arms.iter().all(|arm| self.is_void_expression(&arm.body))
289
            }
290
            
291
            // Return without value is void
292
0
            crate::frontend::ast::ExprKind::Return { value } if value.is_none() => true,
293
            
294
            // Everything else produces a value
295
5
            _ => false
296
        }
297
15
    }
298
299
    /// Check if expression has a non-unit value (i.e., returns something meaningful)
300
7
    fn has_non_unit_expression(&self, body: &Expr) -> bool {
301
7
        !self.is_void_expression(body)
302
7
    }
303
304
305
    /// Transpiles function definitions
306
    #[allow(clippy::too_many_arguments)]
307
    /// Infer parameter type based on usage in function body
308
14
    fn infer_param_type(&self, param: &Param, body: &Expr, func_name: &str) -> TokenStream {
309
        use super::type_inference::{is_param_used_as_function, is_param_used_numerically, is_param_used_as_function_argument};
310
        
311
14
        if is_param_used_as_function(&param.name(), body) {
312
2
            quote! { impl Fn(i32) -> i32 }
313
12
        } else if is_param_used_numerically(&param.name(), body) || 
314
5
                  self.looks_like_numeric_function(func_name) ||
315
4
                  is_param_used_as_function_argument(&param.name(), body) {
316
9
            quote! { i32 }
317
        } else {
318
3
            quote! { String }
319
        }
320
14
    }
321
322
    /// Generate parameter tokens with proper type inference
323
18
    fn generate_param_tokens(&self, params: &[Param], body: &Expr, func_name: &str) -> Result<Vec<TokenStream>> {
324
18
        params
325
18
            .iter()
326
19
            .
map18
(|p| {
327
19
                let param_name = format_ident!("{}", p.name());
328
19
                let type_tokens = if let Ok(tokens) = self.transpile_type(&p.ty) {
329
19
                    let token_str = tokens.to_string();
330
19
                    if token_str == "_" {
331
14
                        self.infer_param_type(p, body, func_name)
332
                    } else {
333
5
                        tokens
334
                    }
335
                } else {
336
0
                    self.infer_param_type(p, body, func_name)
337
                };
338
19
                Ok(quote! { #param_name: #type_tokens })
339
19
            })
340
18
            .collect()
341
18
    }
342
343
    /// Generate return type tokens based on function analysis
344
18
    fn generate_return_type_tokens(&self, name: &str, return_type: Option<&Type>, body: &Expr) -> Result<TokenStream> {
345
        // FIRST CHECK: Override for test functions
346
18
        if name.starts_with("test_") {
347
0
            return Ok(quote! {});
348
18
        }
349
        
350
18
        if let Some(
ty4
) = return_type {
351
4
            let ty_tokens = self.transpile_type(ty)
?0
;
352
4
            Ok(quote! { -> #ty_tokens })
353
14
        } else if name == "main" {
354
2
            Ok(quote! {})
355
12
        } else if self.looks_like_numeric_function(name) {
356
5
            Ok(quote! { -> i32 })
357
7
        } else if self.has_non_unit_expression(body) {
358
5
            Ok(quote! { -> i32 })
359
        } else {
360
2
            Ok(quote! {})
361
        }
362
18
    }
363
364
    /// Generate body tokens with async support
365
18
    fn generate_body_tokens(&self, body: &Expr, is_async: bool) -> Result<TokenStream> {
366
18
        if is_async {
367
0
            let mut async_transpiler = Transpiler::new();
368
0
            async_transpiler.in_async_context = true;
369
0
            async_transpiler.transpile_expr(body)
370
        } else {
371
            // Check if body is already a block to avoid double-wrapping
372
18
            match &body.kind {
373
17
                ExprKind::Block(exprs) => {
374
                    // For function bodies that are blocks, transpile the contents directly
375
17
                    if exprs.len() == 1 {
376
                        // Single expression block - transpile the expression directly
377
17
                        self.transpile_expr(&exprs[0])
378
                    } else {
379
                        // Multiple expressions - transpile as block but without outer braces
380
0
                        let statements: Result<Vec<_>> = exprs.iter().map(|e| self.transpile_expr(e)).collect();
381
0
                        let statements = statements?;
382
0
                        if exprs.is_empty() {
383
0
                            Ok(quote! {})
384
                        } else {
385
0
                            Ok(quote! { #(#statements)* })
386
                        }
387
                    }
388
                },
389
                _ => {
390
                    // Not a block - transpile normally
391
1
                    self.transpile_expr(body)
392
                }
393
            }
394
        }
395
18
    }
396
397
    /// Generate type parameter tokens with trait bound support
398
18
    fn generate_type_param_tokens(&self, type_params: &[String]) -> Result<Vec<TokenStream>> {
399
18
        Ok(type_params
400
18
            .iter()
401
18
            .map(|p| 
{3
402
3
                if p.contains(':') {
403
                    // Complex trait bound - parse as TokenStream
404
0
                    p.parse().unwrap_or_else(|_| quote! { T })
405
                } else {
406
                    // Simple type parameter
407
3
                    let ident = format_ident!("{}", p);
408
3
                    quote! { #ident }
409
                }
410
3
            })
411
18
            .collect())
412
18
    }
413
414
    /// Generate complete function signature
415
18
    fn generate_function_signature(
416
18
        &self,
417
18
        is_pub: bool,
418
18
        is_async: bool,
419
18
        fn_name: &proc_macro2::Ident,
420
18
        type_param_tokens: &[TokenStream],
421
18
        param_tokens: &[TokenStream],
422
18
        return_type_tokens: &TokenStream,
423
18
        body_tokens: &TokenStream,
424
18
        attributes: &[crate::frontend::ast::Attribute],
425
18
    ) -> Result<TokenStream> {
426
        // Override return type for test functions
427
18
        let final_return_type = if fn_name.to_string().starts_with("test_") {
428
0
            quote! {}
429
        } else {
430
18
            return_type_tokens.clone()
431
        };
432
18
        let visibility = if is_pub { 
quote!0
{ pub } } else { quote! {} };
433
        
434
        // Generate attribute tokens
435
18
        let attr_tokens: Vec<TokenStream> = attributes.iter()
436
18
            .map(|attr| 
{0
437
0
                let attr_name = format_ident!("{}", attr.name);
438
0
                if attr.args.is_empty() {
439
0
                    quote! { #[#attr_name] }
440
                } else {
441
0
                    let args: Vec<TokenStream> = attr.args.iter()
442
0
                        .map(|arg| arg.parse().unwrap_or_else(|_| quote! { #arg }))
443
0
                        .collect();
444
0
                    quote! { #[#attr_name(#(#args),*)] }
445
                }
446
0
            })
447
18
            .collect();
448
        
449
18
        Ok(match (type_param_tokens.is_empty(), is_async) {
450
15
            (true, false) => quote! {
451
                #(#attr_tokens)*
452
                #visibility fn #fn_name(#(#param_tokens),*) #final_return_type {
453
                    #body_tokens
454
                }
455
            },
456
0
            (true, true) => quote! {
457
                #(#attr_tokens)*
458
                #visibility async fn #fn_name(#(#param_tokens),*) #final_return_type {
459
                    #body_tokens
460
                }
461
            },
462
3
            (false, false) => quote! {
463
                #(#attr_tokens)*
464
                #visibility fn #fn_name<#(#type_param_tokens),*>(#(#param_tokens),*) #final_return_type {
465
                    #body_tokens
466
                }
467
            },
468
0
            (false, true) => quote! {
469
                #(#attr_tokens)*
470
                #visibility async fn #fn_name<#(#type_param_tokens),*>(#(#param_tokens),*) #final_return_type {
471
                    #body_tokens
472
                }
473
            },
474
        })
475
18
    }
476
477
18
    pub fn transpile_function(
478
18
        &self,
479
18
        name: &str,
480
18
        type_params: &[String],
481
18
        params: &[Param],
482
18
        body: &Expr,
483
18
        is_async: bool,
484
18
        return_type: Option<&Type>,
485
18
        is_pub: bool,
486
18
        attributes: &[crate::frontend::ast::Attribute],
487
18
    ) -> Result<TokenStream> {
488
18
        let fn_name = format_ident!("{}", name);
489
18
        let param_tokens = self.generate_param_tokens(params, body, name)
?0
;
490
18
        let body_tokens = self.generate_body_tokens(body, is_async)
?0
;
491
        
492
        // Check for #[test] attribute and override return type if found
493
18
        let has_test_attribute = attributes.iter().any(|attr| 
attr.name0
==
"test"0
);
494
        
495
18
        let effective_return_type = if has_test_attribute {
496
0
            None // Test functions should have unit return type
497
        } else {
498
18
            return_type
499
        };
500
        
501
18
        let return_type_tokens = self.generate_return_type_tokens(name, effective_return_type, body)
?0
;
502
18
        let type_param_tokens = self.generate_type_param_tokens(type_params)
?0
;
503
504
18
        self.generate_function_signature(
505
18
            is_pub, 
506
18
            is_async, 
507
18
            &fn_name, 
508
18
            &type_param_tokens, 
509
18
            &param_tokens, 
510
18
            &return_type_tokens, 
511
18
            &body_tokens,
512
18
            attributes
513
        )
514
18
    }
515
516
    /// Transpiles lambda expressions
517
11
    pub fn transpile_lambda(&self, params: &[Param], body: &Expr) -> Result<TokenStream> {
518
11
        let param_names: Vec<_> = params
519
11
            .iter()
520
13
            .
map11
(|p| format_ident!("{}", p.name()))
521
11
            .collect();
522
11
        let body_tokens = self.transpile_expr(body)
?0
;
523
524
        // Generate closure with proper formatting (no spaces around commas)
525
11
        if param_names.is_empty() {
526
0
            Ok(quote! { || #body_tokens })
527
        } else {
528
            // Use a more controlled approach to avoid extra spaces
529
11
            let param_list = param_names
530
11
                .iter()
531
11
                .map(std::string::ToString::to_string)
532
11
                .collect::<Vec<_>>()
533
11
                .join(",");
534
11
            let closure_str = format!("|{param_list}| {body_tokens}");
535
11
            closure_str
536
11
                .parse()
537
11
                .map_err(|e| anyhow::anyhow!(
"Failed to parse closure: {}"0
, e))
538
        }
539
11
    }
540
541
    /// Transpiles function calls
542
    /// 
543
    /// # Examples
544
    /// 
545
    /// ```
546
    /// use ruchy::{Transpiler, Parser};
547
    /// 
548
    /// let transpiler = Transpiler::new();
549
    /// let mut parser = Parser::new(r#"println("Hello, {}", name)"#);
550
    /// let ast = parser.parse().unwrap();
551
    /// let result = transpiler.transpile(&ast).unwrap().to_string();
552
    /// assert!(result.contains("println !"));
553
    /// assert!(result.contains("Hello, {}"));
554
    /// ```
555
    /// 
556
    /// ```
557
    /// use ruchy::{Transpiler, Parser};
558
    /// 
559
    /// let transpiler = Transpiler::new();
560
    /// let mut parser = Parser::new(r#"println("Simple message")"#);
561
    /// let ast = parser.parse().unwrap();
562
    /// let result = transpiler.transpile(&ast).unwrap().to_string();
563
    /// assert!(result.contains("println !"));
564
    /// assert!(result.contains("Simple message"));
565
    /// ```
566
    /// 
567
    /// ```
568
    /// use ruchy::{Transpiler, Parser};
569
    /// 
570
    /// let transpiler = Transpiler::new();
571
    /// let mut parser = Parser::new("some_function(\"test\")");
572
    /// let ast = parser.parse().unwrap();
573
    /// let result = transpiler.transpile(&ast).unwrap().to_string();
574
    /// assert!(result.contains("some_function"));
575
    /// assert!(result.contains("test"));
576
    /// ```
577
34
    pub fn transpile_call(&self, func: &Expr, args: &[Expr]) -> Result<TokenStream> {
578
34
        let func_tokens = self.transpile_expr(func)
?0
;
579
580
        // Check if this is a built-in function with special handling
581
34
        if let ExprKind::Identifier(name) = &func.kind {
582
34
            let base_name = if name.ends_with('!') {
583
0
                name.strip_suffix('!').unwrap()
584
            } else {
585
34
                name
586
            };
587
            
588
            // Try specialized handlers in order of precedence
589
34
            if let Some(
result4
) = self.try_transpile_print_macro(&func_tokens, base_name, args)
?0
{
590
4
                return Ok(result);
591
30
            }
592
            
593
30
            if let Some(
result0
) = self.try_transpile_math_function(base_name, args)
?0
{
594
0
                return Ok(result);
595
30
            }
596
            
597
30
            if let Some(
result0
) = self.try_transpile_input_function(base_name, args)
?0
{
598
0
                return Ok(result);
599
30
            }
600
            
601
30
            if let Some(
result0
) = self.try_transpile_assert_function(&func_tokens, base_name, args)
?0
{
602
0
                return Ok(result);
603
30
            }
604
            
605
30
            if let Some(
result14
) = self.try_transpile_type_conversion(base_name, args)
?0
{
606
14
                return Ok(result);
607
16
            }
608
            
609
16
            if let Some(
result0
) = self.try_transpile_math_functions(base_name, args)
?0
{
610
0
                return Ok(result);
611
16
            }
612
            
613
16
            if let Some(
result0
) = self.try_transpile_collection_constructor(base_name, args)
?0
{
614
0
                return Ok(result);
615
16
            }
616
            
617
16
            if let Some(
result1
) = self.try_transpile_dataframe_function(base_name, args)
?0
{
618
1
                return Ok(result);
619
15
            }
620
0
        }
621
622
        // Default: regular function call with string conversion
623
15
        self.transpile_regular_function_call(&func_tokens, args)
624
34
    }
625
626
627
    /// Transpiles println/print with string interpolation directly
628
0
    fn transpile_print_with_interpolation(
629
0
        &self,
630
0
        func_name: &str,
631
0
        parts: &[crate::frontend::ast::StringPart],
632
0
    ) -> Result<TokenStream> {
633
0
        if parts.is_empty() {
634
0
            let func_tokens = proc_macro2::Ident::new(func_name, proc_macro2::Span::call_site());
635
0
            return Ok(quote! { #func_tokens!("") });
636
0
        }
637
638
0
        let mut format_string = String::new();
639
0
        let mut args = Vec::new();
640
641
0
        for part in parts {
642
0
            match part {
643
0
                crate::frontend::ast::StringPart::Text(s) => {
644
0
                    // Escape any format specifiers in literal parts
645
0
                    format_string.push_str(&s.replace('{', "{{").replace('}', "}}"));
646
0
                }
647
0
                crate::frontend::ast::StringPart::Expr(expr) => {
648
0
                    format_string.push_str("{}");
649
0
                    let expr_tokens = self.transpile_expr(expr)?;
650
0
                    args.push(expr_tokens);
651
                }
652
0
                crate::frontend::ast::StringPart::ExprWithFormat { expr, format_spec } => {
653
                    // Include the format specifier in the format string
654
0
                    format_string.push('{');
655
0
                    format_string.push_str(format_spec);
656
0
                    format_string.push('}');
657
0
                    let expr_tokens = self.transpile_expr(expr)?;
658
0
                    args.push(expr_tokens);
659
                }
660
            }
661
        }
662
663
0
        let func_tokens = proc_macro2::Ident::new(func_name, proc_macro2::Span::call_site());
664
665
0
        Ok(quote! {
666
            #func_tokens!(#format_string #(, #args)*)
667
        })
668
0
    }
669
670
    /// Transpiles method calls
671
    #[allow(clippy::cognitive_complexity)]
672
20
    pub fn transpile_method_call(
673
20
        &self,
674
20
        object: &Expr,
675
20
        method: &str,
676
20
        args: &[Expr],
677
20
    ) -> Result<TokenStream> {
678
        // Use the old implementation for now since refactored version is in separate file
679
        // Integration with method_call_refactored.rs pending modularization
680
20
        self.transpile_method_call_old(object, method, args)
681
20
    }
682
    
683
    #[allow(dead_code)]
684
20
    fn transpile_method_call_old(
685
20
        &self,
686
20
        object: &Expr,
687
20
        method: &str,
688
20
        args: &[Expr],
689
20
    ) -> Result<TokenStream> {
690
20
        let obj_tokens = self.transpile_expr(object)
?0
;
691
20
        let method_ident = format_ident!("{}", method);
692
20
        let arg_tokens: Result<Vec<_>> = args.iter().map(|a| 
self7
.
transpile_expr7
(
a7
)).collect();
693
20
        let arg_tokens = arg_tokens
?0
;
694
695
        // Dispatch to specialized handlers based on method category
696
20
        match method {
697
            // Iterator operations (map, filter, reduce)
698
20
            "map" | 
"filter"19
|
"reduce"18
=> {
699
3
                self.transpile_iterator_methods(&obj_tokens, method, &arg_tokens)
700
            }
701
            // HashMap/HashSet methods (get, contains_key, items, etc.)
702
17
            "get" | 
"contains_key"16
|
"keys"16
|
"values"15
|
"entry"14
|
"items"14
|
703
13
            "update" | "add" => {
704
4
                self.transpile_map_set_methods(&obj_tokens, &method_ident, method, &arg_tokens)
705
            }
706
            // Set operations (union, intersection, difference, symmetric_difference)
707
13
            "union" | "intersection" | "difference" | "symmetric_difference" => {
708
0
                self.transpile_set_operations(&obj_tokens, method, &arg_tokens)
709
            }
710
            // Common collection methods (insert, remove, clear, len, is_empty, iter)
711
13
            "insert" | "remove" | "clear" | "len" | 
"is_empty"10
|
"iter"10
=> {
712
3
                Ok(quote! { #obj_tokens.#method_ident(#(#arg_tokens),*) })
713
            }
714
            // DataFrame operations
715
10
            "select" | "groupby" | "agg" | "sort" | 
"mean"9
|
"std"9
|
"min"9
716
9
            | "max" | "sum" | "count" | "drop_nulls" | "fill_null" | "pivot"
717
9
            | "melt" | "head" | "tail" | "sample" | "describe" => {
718
1
                Ok(quote! { #obj_tokens.#method_ident(#(#arg_tokens),*) })
719
            }
720
            // String methods (Python-style and Rust-style)
721
9
            "to_s" | "to_string" | "to_upper" | "to_lower" | "upper" | 
"lower"8
|
722
7
            "length" | "substring" | "strip" | 
"lstrip"6
|
"rstrip"6
|
723
6
            "startswith" | "endswith" | "split" | 
"replace"5
=> {
724
4
                self.transpile_string_methods(&obj_tokens, method, &arg_tokens)
725
            }
726
            // List/Vec methods (Python-style)
727
5
            "append" => {
728
                // Python's append() -> Rust's push()
729
1
                Ok(quote! { #obj_tokens.push(#(#arg_tokens),*) })
730
            }
731
4
            "extend" => {
732
                // Python's extend() -> Rust's extend()
733
0
                Ok(quote! { #obj_tokens.extend(#(#arg_tokens),*) })
734
            }
735
            // Collection methods that work as-is
736
4
            "push" | "pop" | "insert" | "remove" | "clear" | "len" | "is_empty" | 
"contains"3
=> {
737
1
                Ok(quote! { #obj_tokens.#method_ident(#(#arg_tokens),*) })
738
            }
739
            // Advanced collection methods (slice, concat, flatten, unique, join)
740
3
            "slice" | "concat" | "flatten" | "unique" | "join" => {
741
0
                self.transpile_advanced_collection_methods(&obj_tokens, method, &arg_tokens)
742
            }
743
            _ => {
744
                // Regular method call
745
3
                Ok(quote! { #obj_tokens.#method_ident(#(#arg_tokens),*) })
746
            }
747
        }
748
20
    }
749
    
750
    /// Handle iterator operations: map, filter, reduce
751
3
    fn transpile_iterator_methods(&self, obj_tokens: &TokenStream, method: &str, arg_tokens: &[TokenStream]) -> Result<TokenStream> {
752
3
        match method {
753
3
            "map" => {
754
                // vec.map(f) -> vec.iter().map(f).collect::<Vec<_>>()
755
1
                Ok(quote! { #obj_tokens.iter().map(#(#arg_tokens),*).collect::<Vec<_>>() })
756
            }
757
2
            "filter" => {
758
                // vec.filter(f) -> vec.into_iter().filter(f).collect::<Vec<_>>()
759
1
                Ok(quote! { #obj_tokens.into_iter().filter(#(#arg_tokens),*).collect::<Vec<_>>() })
760
            }
761
1
            "reduce" => {
762
                // vec.reduce(f) -> vec.into_iter().reduce(f)
763
1
                Ok(quote! { #obj_tokens.into_iter().reduce(#(#arg_tokens),*) })
764
            }
765
0
            _ => unreachable!("Non-iterator method passed to transpile_iterator_methods"),
766
        }
767
3
    }
768
    
769
    /// Handle HashMap/HashSet methods: get, `contains_key`, items, etc.
770
4
    fn transpile_map_set_methods(&self, obj_tokens: &TokenStream, method_ident: &proc_macro2::Ident, method: &str, arg_tokens: &[TokenStream]) -> Result<TokenStream> {
771
4
        match method {
772
4
            "get" => {
773
                // HashMap.get() returns Option<&V>, but we want owned values
774
1
                Ok(quote! { #obj_tokens.#method_ident(#(#arg_tokens),*).cloned() })
775
            }
776
3
            "contains_key" | "keys" | 
"values"2
|
"entry"1
|
"contains"1
=> {
777
2
                Ok(quote! { #obj_tokens.#method_ident(#(#arg_tokens),*) })
778
            }
779
1
            "items" => {
780
                // HashMap.items() -> iterator of (K, V) tuples (not references)
781
1
                Ok(quote! { #obj_tokens.iter().map(|(k, v)| (k.clone(), v.clone())) })
782
            }
783
0
            "update" => {
784
                // Python dict.update(other) -> Rust HashMap.extend(other)
785
0
                Ok(quote! { #obj_tokens.extend(#(#arg_tokens),*) })
786
            }
787
0
            "add" => {
788
                // Python set.add(item) -> Rust HashSet.insert(item)
789
0
                Ok(quote! { #obj_tokens.insert(#(#arg_tokens),*) })
790
            }
791
0
            _ => unreachable!("Non-map/set method {} passed to transpile_map_set_methods", method),
792
        }
793
4
    }
794
    
795
    /// Handle `HashSet` set operations: union, intersection, difference, `symmetric_difference`
796
0
    fn transpile_set_operations(&self, obj_tokens: &TokenStream, method: &str, arg_tokens: &[TokenStream]) -> Result<TokenStream> {
797
0
        if arg_tokens.len() != 1 {
798
0
            bail!("{} requires exactly 1 argument", method);
799
0
        }
800
0
        let other = &arg_tokens[0];
801
0
        let method_ident = format_ident!("{}", method);
802
0
        Ok(quote! { 
803
0
            {
804
0
                use std::collections::HashSet;
805
0
                #obj_tokens.#method_ident(&#other).cloned().collect::<HashSet<_>>()
806
0
            }
807
0
        })
808
0
    }
809
    
810
    /// Handle string methods: Python-style and Rust-style
811
4
    fn transpile_string_methods(&self, obj_tokens: &TokenStream, method: &str, arg_tokens: &[TokenStream]) -> Result<TokenStream> {
812
4
        match method {
813
4
            "to_s" | "to_string" => {
814
                // Convert any value to string - already a String stays String
815
0
                Ok(quote! { #obj_tokens })
816
            }
817
4
            "to_upper" | "upper" => {
818
1
                let rust_method = format_ident!("to_uppercase");
819
1
                Ok(quote! { #obj_tokens.#rust_method(#(#arg_tokens),*) })
820
            }
821
3
            "to_lower" | "lower" => {
822
1
                let rust_method = format_ident!("to_lowercase");
823
1
                Ok(quote! { #obj_tokens.#rust_method(#(#arg_tokens),*) })
824
            }
825
2
            "strip" => {
826
1
                Ok(quote! { #obj_tokens.trim().to_string() })
827
            }
828
1
            "lstrip" => {
829
0
                Ok(quote! { #obj_tokens.trim_start() })
830
            }
831
1
            "rstrip" => {
832
0
                Ok(quote! { #obj_tokens.trim_end() })
833
            }
834
1
            "startswith" => {
835
0
                Ok(quote! { #obj_tokens.starts_with(#(#arg_tokens),*) })
836
            }
837
1
            "endswith" => {
838
0
                Ok(quote! { #obj_tokens.ends_with(#(#arg_tokens),*) })
839
            }
840
1
            "split" => {
841
1
                Ok(quote! { #obj_tokens.split(#(#arg_tokens),*) })
842
            }
843
0
            "replace" => {
844
0
                Ok(quote! { #obj_tokens.replace(#(#arg_tokens),*) })
845
            }
846
0
            "length" => {
847
                // Map Ruchy's length() to Rust's len()
848
0
                let rust_method = format_ident!("len");
849
0
                Ok(quote! { #obj_tokens.#rust_method(#(#arg_tokens),*) })
850
            }
851
0
            "substring" => {
852
                // string.substring(start, end) -> string.chars().skip(start).take(end-start).collect()
853
0
                if arg_tokens.len() != 2 {
854
0
                    bail!("substring requires exactly 2 arguments");
855
0
                }
856
0
                let start = &arg_tokens[0];
857
0
                let end = &arg_tokens[1];
858
0
                Ok(quote! { 
859
0
                    #obj_tokens.chars()
860
0
                        .skip(#start as usize)
861
0
                        .take((#end as usize).saturating_sub(#start as usize))
862
0
                        .collect::<String>()
863
0
                })
864
            }
865
0
            _ => unreachable!("Non-string method {} passed to transpile_string_methods", method),
866
        }
867
4
    }
868
    
869
    /// Handle advanced collection methods: slice, concat, flatten, unique, join
870
0
    fn transpile_advanced_collection_methods(&self, obj_tokens: &TokenStream, method: &str, arg_tokens: &[TokenStream]) -> Result<TokenStream> {
871
0
        match method {
872
0
            "slice" => {
873
                // vec.slice(start, end) -> vec[start..end].to_vec()
874
0
                if arg_tokens.len() != 2 {
875
0
                    bail!("slice requires exactly 2 arguments");
876
0
                }
877
0
                let start = &arg_tokens[0];
878
0
                let end = &arg_tokens[1];
879
0
                Ok(quote! { #obj_tokens[#start as usize..#end as usize].to_vec() })
880
            }
881
0
            "concat" => {
882
                // vec.concat(other) -> [vec, other].concat()
883
0
                if arg_tokens.len() != 1 {
884
0
                    bail!("concat requires exactly 1 argument");
885
0
                }
886
0
                let other = &arg_tokens[0];
887
0
                Ok(quote! { [#obj_tokens, #other].concat() })
888
            }
889
0
            "flatten" => {
890
                // vec.flatten() -> vec.into_iter().flatten().collect()
891
0
                if !arg_tokens.is_empty() {
892
0
                    bail!("flatten requires no arguments");
893
0
                }
894
0
                Ok(quote! { #obj_tokens.into_iter().flatten().collect::<Vec<_>>() })
895
            }
896
0
            "unique" => {
897
                // vec.unique() -> vec.into_iter().collect::<HashSet<_>>().into_iter().collect()
898
0
                if !arg_tokens.is_empty() {
899
0
                    bail!("unique requires no arguments");
900
0
                }
901
0
                Ok(quote! { 
902
0
                    {
903
0
                        use std::collections::HashSet;
904
0
                        #obj_tokens.into_iter().collect::<HashSet<_>>().into_iter().collect::<Vec<_>>()
905
0
                    }
906
0
                })
907
            }
908
0
            "join" => {
909
                // vec.join(separator) -> vec.join(separator) (for Vec<String>)
910
0
                if arg_tokens.len() != 1 {
911
0
                    bail!("join requires exactly 1 argument");
912
0
                }
913
0
                let separator = &arg_tokens[0];
914
0
                Ok(quote! { #obj_tokens.join(&#separator) })
915
            }
916
0
            _ => unreachable!("Non-advanced-collection method passed to transpile_advanced_collection_methods"),
917
        }
918
0
    }
919
920
    /// Transpiles blocks
921
26
    pub fn transpile_block(&self, exprs: &[Expr]) -> Result<TokenStream> {
922
26
        if exprs.is_empty() {
923
2
            return Ok(quote! { {} });
924
24
        }
925
926
24
        let mut statements = Vec::new();
927
928
30
        for (i, expr) in 
exprs24
.
iter24
().
enumerate24
() {
929
30
            let expr_tokens = self.transpile_expr(expr)
?0
;
930
931
            // HOTFIX: Never add semicolon to the last expression in a block (it should be the return value)  
932
30
            if i < exprs.len() - 1 {
933
6
                statements.push(quote! { #expr_tokens; });
934
24
            } else {
935
24
                statements.push(expr_tokens);
936
24
            }
937
        }
938
939
24
        Ok(quote! {
940
            {
941
                #(#statements)*
942
            }
943
        })
944
26
    }
945
946
947
    /// Transpiles pipeline expressions
948
1
    pub fn transpile_pipeline(&self, expr: &Expr, stages: &[PipelineStage]) -> Result<TokenStream> {
949
1
        let mut result = self.transpile_expr(expr)
?0
;
950
951
3
        for 
stage2
in stages {
952
            // Each stage contains an expression to apply
953
2
            let stage_expr = &stage.op;
954
955
            // Apply the stage - check what kind of expression it is
956
2
            match &stage_expr.kind {
957
0
                ExprKind::Call { func, args } => {
958
0
                    let func_tokens = self.transpile_expr(func)?;
959
0
                    let arg_tokens: Result<Vec<_>> =
960
0
                        args.iter().map(|a| self.transpile_expr(a)).collect();
961
0
                    let arg_tokens = arg_tokens?;
962
963
                    // Pipeline passes the previous result as the first argument
964
0
                    result = quote! { #func_tokens(#result #(, #arg_tokens)*) };
965
                }
966
0
                ExprKind::MethodCall { method, args, .. } => {
967
0
                    let method_ident = format_ident!("{}", method);
968
0
                    let arg_tokens: Result<Vec<_>> =
969
0
                        args.iter().map(|a| self.transpile_expr(a)).collect();
970
0
                    let arg_tokens = arg_tokens?;
971
972
0
                    result = quote! { #result.#method_ident(#(#arg_tokens),*) };
973
                }
974
                _ => {
975
                    // For other expressions, apply them directly
976
2
                    let stage_tokens = self.transpile_expr(stage_expr)
?0
;
977
2
                    result = quote! { #stage_tokens(#result) };
978
                }
979
            }
980
        }
981
982
1
        Ok(result)
983
1
    }
984
985
    /// Transpiles for loops
986
2
    pub fn transpile_for(&self, var: &str, pattern: Option<&Pattern>, iter: &Expr, body: &Expr) -> Result<TokenStream> {
987
2
        let iter_tokens = self.transpile_expr(iter)
?0
;
988
2
        let body_tokens = self.transpile_expr(body)
?0
;
989
990
        // If we have a pattern, use it for destructuring
991
2
        if let Some(pat) = pattern {
992
2
            let pattern_tokens = self.transpile_pattern(pat)
?0
;
993
2
            Ok(quote! {
994
2
                for #pattern_tokens in #iter_tokens {
995
2
                    #body_tokens
996
2
                }
997
2
            })
998
        } else {
999
            // Fall back to simple variable
1000
0
            let var_ident = format_ident!("{}", var);
1001
0
            Ok(quote! {
1002
0
                for #var_ident in #iter_tokens {
1003
0
                    #body_tokens
1004
0
                }
1005
0
            })
1006
        }
1007
2
    }
1008
1009
    /// Transpiles while loops
1010
2
    pub fn transpile_while(&self, condition: &Expr, body: &Expr) -> Result<TokenStream> {
1011
2
        let cond_tokens = self.transpile_expr(condition)
?0
;
1012
2
        let body_tokens = self.transpile_expr(body)
?0
;
1013
1014
2
        Ok(quote! {
1015
2
            while #cond_tokens {
1016
2
                #body_tokens
1017
2
            }
1018
2
        })
1019
2
    }
1020
1021
    /// Transpile if-let expression (complexity: 5)
1022
0
    pub fn transpile_if_let(
1023
0
        &self,
1024
0
        pattern: &Pattern,
1025
0
        expr: &Expr,
1026
0
        then_branch: &Expr,
1027
0
        else_branch: Option<&Expr>,
1028
0
    ) -> Result<TokenStream> {
1029
0
        let expr_tokens = self.transpile_expr(expr)?;
1030
0
        let pattern_tokens = self.transpile_pattern(pattern)?;
1031
0
        let then_tokens = self.transpile_expr(then_branch)?;
1032
1033
0
        if let Some(else_expr) = else_branch {
1034
0
            let else_tokens = self.transpile_expr(else_expr)?;
1035
0
            Ok(quote! {
1036
0
                if let #pattern_tokens = #expr_tokens {
1037
0
                    #then_tokens
1038
0
                } else {
1039
0
                    #else_tokens
1040
0
                }
1041
0
            })
1042
        } else {
1043
0
            Ok(quote! {
1044
0
                if let #pattern_tokens = #expr_tokens {
1045
0
                    #then_tokens
1046
0
                }
1047
0
            })
1048
        }
1049
0
    }
1050
1051
    /// Transpile while-let expression (complexity: 4)
1052
0
    pub fn transpile_while_let(
1053
0
        &self,
1054
0
        pattern: &Pattern,
1055
0
        expr: &Expr,
1056
0
        body: &Expr,
1057
0
    ) -> Result<TokenStream> {
1058
0
        let expr_tokens = self.transpile_expr(expr)?;
1059
0
        let pattern_tokens = self.transpile_pattern(pattern)?;
1060
0
        let body_tokens = self.transpile_expr(body)?;
1061
1062
0
        Ok(quote! {
1063
0
            while let #pattern_tokens = #expr_tokens {
1064
0
                #body_tokens
1065
0
            }
1066
0
        })
1067
0
    }
1068
1069
0
    pub fn transpile_loop(&self, body: &Expr) -> Result<TokenStream> {
1070
0
        let body_tokens = self.transpile_expr(body)?;
1071
1072
0
        Ok(quote! {
1073
0
            loop {
1074
0
                #body_tokens
1075
0
            }
1076
0
        })
1077
0
    }
1078
1079
    /// Transpiles list comprehensions
1080
3
    pub fn transpile_list_comprehension(
1081
3
        &self,
1082
3
        expr: &Expr,
1083
3
        var: &str,
1084
3
        iter: &Expr,
1085
3
        filter: Option<&Expr>,
1086
3
    ) -> Result<TokenStream> {
1087
3
        let var_ident = format_ident!("{}", var);
1088
3
        let iter_tokens = self.transpile_expr(iter)
?0
;
1089
3
        let expr_tokens = self.transpile_expr(expr)
?0
;
1090
1091
3
        if let Some(
filter_expr2
) = filter {
1092
2
            let filter_tokens = self.transpile_expr(filter_expr)
?0
;
1093
2
            Ok(quote! {
1094
2
                #iter_tokens
1095
2
                    .into_iter()
1096
2
                    .filter(|#var_ident| #filter_tokens)
1097
2
                    .map(|#var_ident| #expr_tokens)
1098
2
                    .collect::<Vec<_>>()
1099
2
            })
1100
        } else {
1101
1
            Ok(quote! {
1102
1
                #iter_tokens
1103
1
                    .into_iter()
1104
1
                    .map(|#var_ident| #expr_tokens)
1105
1
                    .collect::<Vec<_>>()
1106
1
            })
1107
        }
1108
3
    }
1109
1110
1111
    /// Transpiles module declarations
1112
0
    pub fn transpile_module(&self, name: &str, body: &Expr) -> Result<TokenStream> {
1113
0
        let module_name = format_ident!("{}", name);
1114
0
        let body_tokens = self.transpile_expr(body)?;
1115
1116
0
        Ok(quote! {
1117
0
            mod #module_name {
1118
0
                #body_tokens
1119
0
            }
1120
0
        })
1121
0
    }
1122
1123
    
1124
    /// Static method for transpiling inline imports (backward compatibility)
1125
1
    pub fn transpile_import(path: &str, items: &[crate::frontend::ast::ImportItem]) -> TokenStream {
1126
        
1127
        
1128
        // All imports should have module-level scope, not be wrapped in blocks
1129
        // This includes both std library imports and local module imports
1130
1
        Self::transpile_import_inline(path, items)
1131
1
    }
1132
    
1133
    /// Handle `std::fs` imports and generate file operation functions
1134
0
    fn transpile_std_fs_import(items: &[crate::frontend::ast::ImportItem]) -> TokenStream {
1135
        use crate::frontend::ast::ImportItem;
1136
        
1137
0
        let mut tokens = TokenStream::new();
1138
        
1139
        // Always include std::fs for file operations
1140
0
        tokens.extend(quote! { use std::fs; });
1141
        
1142
0
        if items.is_empty() || items.iter().any(|i| matches!(i, ImportItem::Wildcard)) {
1143
0
            // Import all file operations
1144
0
            tokens.extend(Self::generate_all_file_operations());
1145
0
        } else {
1146
            // Import specific operations
1147
0
            for item in items {
1148
0
                match item {
1149
0
                    ImportItem::Named(name) => {
1150
0
                        match name.as_str() {
1151
0
                            "read_file" => tokens.extend(Self::generate_read_file_function()),
1152
0
                            "write_file" => tokens.extend(Self::generate_write_file_function()),
1153
0
                            _ => {
1154
0
                                // Unknown std::fs function, generate stub or error
1155
0
                                let func_name = format_ident!("{}", name);
1156
0
                                tokens.extend(quote! {
1157
0
                                    fn #func_name() -> ! {
1158
0
                                        panic!("std::fs::{} not yet implemented", #name);
1159
0
                                    }
1160
0
                                });
1161
0
                            }
1162
                        }
1163
                    }
1164
0
                    ImportItem::Aliased { name, alias } => {
1165
0
                        let alias_ident = format_ident!("{}", alias);
1166
0
                        match name.as_str() {
1167
0
                            "read_file" => {
1168
0
                                tokens.extend(quote! {
1169
0
                                    fn #alias_ident(filename: String) -> String {
1170
0
                                        fs::read_to_string(filename).unwrap_or_else(|e| panic!("Failed to read file: {}", e))
1171
0
                                    }
1172
0
                                });
1173
0
                            }
1174
0
                            "write_file" => {
1175
0
                                tokens.extend(quote! {
1176
0
                                    fn #alias_ident(filename: String, content: String) {
1177
0
                                        fs::write(filename, content).unwrap_or_else(|e| panic!("Failed to write file: {}", e));
1178
0
                                    }
1179
0
                                });
1180
0
                            }
1181
0
                            _ => {
1182
0
                                tokens.extend(quote! {
1183
0
                                    fn #alias_ident() -> ! {
1184
0
                                        panic!("std::fs::{} not yet implemented", #name);
1185
0
                                    }
1186
0
                                });
1187
0
                            }
1188
                        }
1189
                    }
1190
0
                    ImportItem::Wildcard => {
1191
0
                        tokens.extend(Self::generate_all_file_operations());
1192
0
                    }
1193
                }
1194
            }
1195
        }
1196
        
1197
0
        tokens
1198
0
    }
1199
    
1200
    /// Generate `read_file` function
1201
0
    fn generate_read_file_function() -> TokenStream {
1202
0
        quote! {
1203
            fn read_file(filename: String) -> String {
1204
                fs::read_to_string(filename).unwrap_or_else(|e| panic!("Failed to read file: {}", e))
1205
            }
1206
        }
1207
0
    }
1208
    
1209
    /// Generate `write_file` function  
1210
0
    fn generate_write_file_function() -> TokenStream {
1211
0
        quote! {
1212
            fn write_file(filename: String, content: String) {
1213
                fs::write(filename, content).unwrap_or_else(|e| panic!("Failed to write file: {}", e));
1214
            }
1215
        }
1216
0
    }
1217
    
1218
    /// Generate all file operation functions
1219
0
    fn generate_all_file_operations() -> TokenStream {
1220
0
        let read_func = Self::generate_read_file_function();
1221
0
        let write_func = Self::generate_write_file_function();
1222
        
1223
0
        quote! {
1224
            #read_func
1225
            #write_func
1226
        }
1227
0
    }
1228
    
1229
    /// Handle `std::fs` imports with path-based syntax (import `std::fs::read_file`)
1230
0
    fn transpile_std_fs_import_with_path(path: &str, items: &[crate::frontend::ast::ImportItem]) -> TokenStream {
1231
        use crate::frontend::ast::ImportItem;
1232
        
1233
        
1234
0
        let mut tokens = TokenStream::new();
1235
        
1236
        // Always include std::fs for file operations
1237
0
        tokens.extend(quote! { use std::fs; });
1238
        
1239
0
        if path == "std::fs" {
1240
            // Wildcard import or specific items from std::fs
1241
            // Special case: if path is "std::fs" and items contain Named("fs"), treat as wildcard
1242
0
            let is_wildcard_import = items.is_empty() 
1243
0
                || items.iter().any(|i| matches!(i, ImportItem::Wildcard))
1244
0
                || (items.len() == 1 && matches!(&items[0], ImportItem::Named(name) if name == "fs"));
1245
                
1246
0
            if is_wildcard_import {
1247
0
                // Import all file operations for wildcard or empty imports
1248
0
                tokens.extend(Self::generate_all_file_operations());
1249
0
            } else {
1250
                // Import specific operations
1251
0
                for item in items {
1252
0
                    match item {
1253
0
                        ImportItem::Named(name) => {
1254
0
                            match name.as_str() {
1255
0
                                "read_file" => tokens.extend(Self::generate_read_file_function()),
1256
0
                                "write_file" => tokens.extend(Self::generate_write_file_function()),
1257
0
                                _ => {} // Ignore unknown functions
1258
                            }
1259
                        }
1260
                        ImportItem::Wildcard => {
1261
0
                            tokens.extend(Self::generate_all_file_operations());
1262
0
                            break;
1263
                        }
1264
0
                        ImportItem::Aliased { name, alias: _ } => {
1265
                            // Handle aliased imports like "read_file as rf"
1266
0
                            match name.as_str() {
1267
0
                                "read_file" => tokens.extend(Self::generate_read_file_function()),
1268
0
                                "write_file" => tokens.extend(Self::generate_write_file_function()),
1269
0
                                _ => {} // Ignore unknown functions
1270
                            }
1271
                        }
1272
                    }
1273
                }
1274
            }
1275
0
        } else if path.starts_with("std::fs::") {
1276
            // Path-based import like std::fs::read_file
1277
0
            let function_name = path.strip_prefix("std::fs::").unwrap_or("");
1278
0
            match function_name {
1279
0
                "read_file" => tokens.extend(Self::generate_read_file_function()),
1280
0
                "write_file" => tokens.extend(Self::generate_write_file_function()),
1281
0
                _ => {} // Ignore unknown functions
1282
            }
1283
0
        }
1284
        
1285
0
        tokens
1286
0
    }
1287
1288
    /// Handle `std::process` imports with process management functions
1289
0
    fn transpile_std_process_import(_path: &str, _items: &[crate::frontend::ast::ImportItem]) -> TokenStream {
1290
        // Generate process functions
1291
0
        quote! {
1292
            mod process {
1293
                pub fn current_pid() -> i32 {
1294
                    std::process::id() as i32
1295
                }
1296
                
1297
                pub fn exit(code: i32) {
1298
                    std::process::exit(code);
1299
                }
1300
                
1301
                pub fn spawn(command: &str) -> Result<i32, String> {
1302
                    match std::process::Command::new(command).spawn() {
1303
                        Ok(child) => Ok(child.id() as i32),
1304
                        Err(e) => Err(e.to_string()),
1305
                    }
1306
                }
1307
            }
1308
        }
1309
0
    }
1310
    
1311
    /// Handle `std::system` imports with system information functions
1312
0
    fn transpile_std_system_import(_path: &str, _items: &[crate::frontend::ast::ImportItem]) -> TokenStream {
1313
        // Generate system functions
1314
0
        quote! {
1315
            mod system {
1316
                pub fn get_env(key: &str) -> Option<String> {
1317
                    std::env::var(key).ok()
1318
                }
1319
                
1320
                pub fn set_env(key: &str, value: &str) {
1321
                    std::env::set_var(key, value);
1322
                }
1323
                
1324
                pub fn os_name() -> String {
1325
                    std::env::consts::OS.to_string()
1326
                }
1327
                
1328
                pub fn arch() -> String {
1329
                    std::env::consts::ARCH.to_string()
1330
                }
1331
            }
1332
        }
1333
0
    }
1334
    
1335
    /// Handle `std::signal` imports with signal handling functions
1336
0
    fn transpile_std_signal_import(_path: &str, _items: &[crate::frontend::ast::ImportItem]) -> TokenStream {
1337
        // For now, just provide stubs as signal handling is complex and platform-specific
1338
0
        quote! {
1339
            // Import signal constants at top level
1340
            const SIGINT: i32 = 2;
1341
            const SIGTERM: i32 = 15;
1342
            const SIGKILL: i32 = 9;
1343
            
1344
            // Also import exit function for signal handlers
1345
            fn exit(code: i32) {
1346
                std::process::exit(code);
1347
            }
1348
            
1349
            mod signal {
1350
                pub const SIGINT: i32 = 2;
1351
                pub const SIGTERM: i32 = 15;
1352
                pub const SIGKILL: i32 = 9;
1353
                
1354
                pub fn on(_signal: i32, _handler: impl Fn()) {
1355
                    // Signal handling would require unsafe code and platform-specific logic
1356
                    // For now, this is a stub
1357
                }
1358
            }
1359
        }
1360
0
    }
1361
    
1362
    /// Handle `std::net` imports with networking functions
1363
0
    fn transpile_std_net_import(_path: &str, _items: &[crate::frontend::ast::ImportItem]) -> TokenStream {
1364
        // Generate networking functions and re-export std types
1365
0
        quote! {
1366
            mod net {
1367
                pub use std::net::*;
1368
                
1369
                pub struct TcpListener;
1370
                
1371
                impl TcpListener {
1372
                    pub fn bind(addr: String) -> Result<Self, String> {
1373
                        println!("Would bind TCP listener to: {}", addr);
1374
                        Ok(TcpListener)
1375
                    }
1376
                    
1377
                    pub fn accept(&self) -> Result<TcpStream, String> {
1378
                        println!("Would accept connection");
1379
                        Ok(TcpStream)
1380
                    }
1381
                }
1382
                
1383
                pub struct TcpStream;
1384
                
1385
                impl TcpStream {
1386
                    pub fn connect(addr: String) -> Result<Self, String> {
1387
                        println!("Would connect to: {}", addr);
1388
                        Ok(TcpStream)
1389
                    }
1390
                }
1391
            }
1392
            
1393
            // Also make available as module for http submodules
1394
            mod http {
1395
                pub struct Server {
1396
                    addr: String,
1397
                }
1398
                
1399
                impl Server {
1400
                    pub fn new(addr: String) -> Self {
1401
                        println!("Creating HTTP server on: {}", addr);
1402
                        Server { addr }
1403
                    }
1404
                    
1405
                    pub fn listen(&self) {
1406
                        println!("HTTP server listening on: {}", self.addr);
1407
                    }
1408
                }
1409
            }
1410
        }
1411
0
    }
1412
1413
0
    fn transpile_std_mem_import(_path: &str, _items: &[crate::frontend::ast::ImportItem]) -> TokenStream {
1414
        // Generate memory management functions
1415
0
        quote! {
1416
            mod mem {
1417
                pub struct Array<T> {
1418
                    data: Vec<T>,
1419
                }
1420
                
1421
                impl<T: Clone> Array<T> {
1422
                    pub fn new(size: usize, default_value: T) -> Self {
1423
                        Array {
1424
                            data: vec![default_value; size],
1425
                        }
1426
                    }
1427
                }
1428
                
1429
                pub struct MemoryInfo {
1430
                    pub allocated: usize,
1431
                    pub peak: usize,
1432
                }
1433
                
1434
                impl std::fmt::Display for MemoryInfo {
1435
                    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1436
                        write!(f, "allocated: {}KB, peak: {}KB", self.allocated / 1024, self.peak / 1024)
1437
                    }
1438
                }
1439
                
1440
                pub fn usage() -> MemoryInfo {
1441
                    MemoryInfo {
1442
                        allocated: 1024 * 100, // 100KB stub
1443
                        peak: 1024 * 150,      // 150KB stub
1444
                    }
1445
                }
1446
            }
1447
        }
1448
0
    }
1449
1450
0
    fn transpile_std_parallel_import(_path: &str, _items: &[crate::frontend::ast::ImportItem]) -> TokenStream {
1451
        // Generate parallel processing functions
1452
0
        quote! {
1453
            mod parallel {
1454
                pub fn map<T, U, F>(data: Vec<T>, func: F) -> Vec<U>
1455
                where
1456
                    T: Send,
1457
                    U: Send,
1458
                    F: Fn(T) -> U + Send + Sync,
1459
                {
1460
                    // Simple sequential implementation for now (stub)
1461
                    data.into_iter().map(func).collect()
1462
                }
1463
                
1464
                pub fn filter<T, F>(data: Vec<T>, predicate: F) -> Vec<T>
1465
                where
1466
                    T: Send,
1467
                    F: Fn(&T) -> bool + Send + Sync,
1468
                {
1469
                    data.into_iter().filter(|x| predicate(x)).collect()
1470
                }
1471
                
1472
                pub fn reduce<T, F>(data: Vec<T>, func: F) -> Option<T>
1473
                where
1474
                    T: Send,
1475
                    F: Fn(T, T) -> T + Send + Sync,
1476
                {
1477
                    data.into_iter().reduce(func)
1478
                }
1479
            }
1480
        }
1481
0
    }
1482
1483
0
    fn transpile_std_simd_import(_path: &str, _items: &[crate::frontend::ast::ImportItem]) -> TokenStream {
1484
        // Generate SIMD vectorization functions
1485
0
        quote! {
1486
            mod simd {
1487
                use std::ops::Add;
1488
                
1489
                pub struct SimdVec<T> {
1490
                    data: Vec<T>,
1491
                }
1492
                
1493
                impl<T> SimdVec<T> {
1494
                    pub fn from_slice(slice: &[T]) -> Self
1495
                    where
1496
                        T: Clone,
1497
                    {
1498
                        SimdVec {
1499
                            data: slice.to_vec(),
1500
                        }
1501
                    }
1502
                }
1503
                
1504
                impl<T> Add for SimdVec<T>
1505
                where
1506
                    T: Add<Output = T> + Copy,
1507
                {
1508
                    type Output = SimdVec<T>;
1509
                    
1510
                    fn add(self, other: SimdVec<T>) -> SimdVec<T> {
1511
                        let result: Vec<T> = self.data.iter()
1512
                            .zip(other.data.iter())
1513
                            .map(|(&a, &b)| a + b)
1514
                            .collect();
1515
                        SimdVec { data: result }
1516
                    }
1517
                }
1518
                
1519
                impl<T> std::fmt::Display for SimdVec<T>
1520
                where
1521
                    T: std::fmt::Display,
1522
                {
1523
                    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1524
                        write!(f, "[{}]", self.data.iter().map(|x| format!("{}", x)).collect::<Vec<_>>().join(", "))
1525
                    }
1526
                }
1527
                
1528
                pub fn from_slice<T: Clone>(slice: &[T]) -> SimdVec<T> {
1529
                    SimdVec::from_slice(slice)
1530
                }
1531
            }
1532
        }
1533
0
    }
1534
1535
0
    fn transpile_std_cache_import(_path: &str, _items: &[crate::frontend::ast::ImportItem]) -> TokenStream {
1536
        // Generate caching functions - placeholder for @memoize attribute support
1537
0
        quote! {
1538
            mod cache {
1539
                use std::collections::HashMap;
1540
                
1541
                pub struct Cache<K, V> {
1542
                    data: HashMap<K, V>,
1543
                }
1544
                
1545
                impl<K, V> Cache<K, V>
1546
                where
1547
                    K: std::hash::Hash + Eq,
1548
                {
1549
                    pub fn new() -> Self {
1550
                        Cache {
1551
                            data: HashMap::new(),
1552
                        }
1553
                    }
1554
                    
1555
                    pub fn get(&self, key: &K) -> Option<&V> {
1556
                        self.data.get(key)
1557
                    }
1558
                    
1559
                    pub fn insert(&mut self, key: K, value: V) -> Option<V> {
1560
                        self.data.insert(key, value)
1561
                    }
1562
                }
1563
            }
1564
        }
1565
0
    }
1566
1567
0
    fn transpile_std_bench_import(_path: &str, _items: &[crate::frontend::ast::ImportItem]) -> TokenStream {
1568
        // Generate benchmarking functions
1569
0
        quote! {
1570
            mod bench {
1571
                use std::time::{Duration, Instant};
1572
                
1573
                pub struct BenchmarkResult {
1574
                    pub elapsed: u128,
1575
                }
1576
                
1577
                impl BenchmarkResult {
1578
                    pub fn new(elapsed: Duration) -> Self {
1579
                        BenchmarkResult {
1580
                            elapsed: elapsed.as_millis(),
1581
                        }
1582
                    }
1583
                }
1584
                
1585
                impl std::fmt::Display for BenchmarkResult {
1586
                    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1587
                        write!(f, "{}ms", self.elapsed)
1588
                    }
1589
                }
1590
                
1591
                pub fn time<F, T>(mut func: F) -> BenchmarkResult
1592
                where
1593
                    F: FnMut() -> T,
1594
                {
1595
                    let start = Instant::now();
1596
                    let _ = func();
1597
                    let elapsed = start.elapsed();
1598
                    BenchmarkResult::new(elapsed)
1599
                }
1600
            }
1601
        }
1602
0
    }
1603
1604
0
    fn transpile_std_profile_import(_path: &str, _items: &[crate::frontend::ast::ImportItem]) -> TokenStream {
1605
        // Generate profiling functions - placeholder for @hot_path attribute support
1606
0
        quote! {
1607
            mod profile {
1608
                pub struct ProfileInfo {
1609
                    pub function_name: String,
1610
                    pub call_count: usize,
1611
                    pub total_time: u128,
1612
                }
1613
                
1614
                impl std::fmt::Display for ProfileInfo {
1615
                    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1616
                        write!(f, "{}: {} calls, {}ms total", 
1617
                               self.function_name, self.call_count, self.total_time)
1618
                    }
1619
                }
1620
                
1621
                pub fn get_stats(function_name: &str) -> ProfileInfo {
1622
                    ProfileInfo {
1623
                        function_name: function_name.to_string(),
1624
                        call_count: 42, // Stub values
1625
                        total_time: 100,
1626
                    }
1627
                }
1628
            }
1629
        }
1630
0
    }
1631
    
1632
    /// Handle `std::system` imports with system information functions
1633
    /// Core inline import transpilation logic - REFACTORED FOR COMPLEXITY REDUCTION
1634
    /// Original: 48 cyclomatic complexity, Target: <20
1635
1
    pub fn transpile_import_inline(path: &str, items: &[crate::frontend::ast::ImportItem]) -> TokenStream {
1636
        // Try std module handlers first (complexity: delegated)
1637
1
        if let Some(
result0
) = Self::handle_std_module_import(path, items) {
1638
0
            return result;
1639
1
        }
1640
        
1641
        // Fall back to generic import handling (complexity: delegated)
1642
1
        Self::handle_generic_import(path, items)
1643
1
    }
1644
    
1645
    /// Extract std module dispatcher (complexity ~12)
1646
1
    fn handle_std_module_import(path: &str, items: &[crate::frontend::ast::ImportItem]) -> Option<TokenStream> {
1647
1
        if path.starts_with("std::fs") {
1648
0
            return Some(Self::transpile_std_fs_import_with_path(path, items));
1649
1
        }
1650
1
        if path.starts_with("std::process") {
1651
0
            return Some(Self::transpile_std_process_import(path, items));
1652
1
        }
1653
1
        if path.starts_with("std::system") {
1654
0
            return Some(Self::transpile_std_system_import(path, items));
1655
1
        }
1656
1
        if path.starts_with("std::signal") {
1657
0
            return Some(Self::transpile_std_signal_import(path, items));
1658
1
        }
1659
1
        if path.starts_with("std::net") {
1660
0
            return Some(Self::transpile_std_net_import(path, items));
1661
1
        }
1662
1
        if path.starts_with("std::mem") {
1663
0
            return Some(Self::transpile_std_mem_import(path, items));
1664
1
        }
1665
1
        if path.starts_with("std::parallel") {
1666
0
            return Some(Self::transpile_std_parallel_import(path, items));
1667
1
        }
1668
1
        if path.starts_with("std::simd") {
1669
0
            return Some(Self::transpile_std_simd_import(path, items));
1670
1
        }
1671
1
        if path.starts_with("std::cache") {
1672
0
            return Some(Self::transpile_std_cache_import(path, items));
1673
1
        }
1674
1
        if path.starts_with("std::bench") {
1675
0
            return Some(Self::transpile_std_bench_import(path, items));
1676
1
        }
1677
1
        if path.starts_with("std::profile") {
1678
0
            return Some(Self::transpile_std_profile_import(path, items));
1679
1
        }
1680
1
        None
1681
1
    }
1682
    
1683
    /// Extract generic import handling (complexity ~8)
1684
1
    fn handle_generic_import(path: &str, items: &[crate::frontend::ast::ImportItem]) -> TokenStream {
1685
        
1686
1
        let path_tokens = Self::path_to_tokens(path);
1687
        
1688
1
        if items.is_empty() {
1689
1
            quote! { use #path_tokens::*; }
1690
0
        } else if items.len() == 1 {
1691
0
            Self::handle_single_import_item(&path_tokens, path, &items[0])
1692
        } else {
1693
0
            Self::handle_multiple_import_items(&path_tokens, items)
1694
        }
1695
1
    }
1696
    
1697
    /// Extract path tokenization (complexity ~4)
1698
1
    fn path_to_tokens(path: &str) -> TokenStream {
1699
1
        let mut path_tokens = TokenStream::new();
1700
1
        let segments: Vec<_> = path.split("::").collect();
1701
        
1702
1
        for (i, segment) in segments.iter().enumerate() {
1703
1
            if i > 0 {
1704
0
                path_tokens.extend(quote! { :: });
1705
1
            }
1706
1
            if !segment.is_empty() {
1707
1
                let seg_ident = format_ident!("{}", segment);
1708
1
                path_tokens.extend(quote! { #seg_ident });
1709
1
            
}0
1710
        }
1711
        
1712
1
        path_tokens
1713
1
    }
1714
    
1715
    /// Extract single item handling (complexity ~5)
1716
0
    fn handle_single_import_item(
1717
0
        path_tokens: &TokenStream, 
1718
0
        path: &str, 
1719
0
        item: &crate::frontend::ast::ImportItem
1720
0
    ) -> TokenStream {
1721
        use crate::frontend::ast::ImportItem;
1722
        
1723
0
        match item {
1724
0
            ImportItem::Named(name) => {
1725
0
                if path.ends_with(&format!("::{name}")) {
1726
0
                    quote! { use #path_tokens; }
1727
                } else {
1728
0
                    let item_ident = format_ident!("{}", name);
1729
0
                    quote! { use #path_tokens::#item_ident; }
1730
                }
1731
            }
1732
0
            ImportItem::Aliased { name, alias } => {
1733
0
                let name_ident = format_ident!("{}", name);
1734
0
                let alias_ident = format_ident!("{}", alias);
1735
0
                quote! { use #path_tokens::#name_ident as #alias_ident; }
1736
            }
1737
0
            ImportItem::Wildcard => quote! { use #path_tokens::*; },
1738
        }
1739
0
    }
1740
    
1741
    /// Extract multiple items handling (complexity ~3)
1742
0
    fn handle_multiple_import_items(
1743
0
        path_tokens: &TokenStream, 
1744
0
        items: &[crate::frontend::ast::ImportItem]
1745
0
    ) -> TokenStream {
1746
0
        let item_tokens = Self::process_import_items(items);
1747
0
        quote! { use #path_tokens::{#(#item_tokens),*}; }
1748
0
    }
1749
    
1750
    /// Extract import items processing (complexity ~3)
1751
0
    fn process_import_items(items: &[crate::frontend::ast::ImportItem]) -> Vec<TokenStream> {
1752
        use crate::frontend::ast::ImportItem;
1753
        
1754
0
        items.iter().map(|item| match item {
1755
0
            ImportItem::Named(name) => {
1756
0
                let name_ident = format_ident!("{}", name);
1757
0
                quote! { #name_ident }
1758
            }
1759
0
            ImportItem::Aliased { name, alias } => {
1760
0
                let name_ident = format_ident!("{}", name);
1761
0
                let alias_ident = format_ident!("{}", alias);
1762
0
                quote! { #name_ident as #alias_ident }
1763
            }
1764
0
            ImportItem::Wildcard => quote! { * },
1765
0
        }).collect()
1766
0
    }
1767
1768
    /// Transpiles export statements
1769
0
    pub fn transpile_export(items: &[String]) -> TokenStream {
1770
0
        let item_idents: Vec<_> = items.iter().map(|s| format_ident!("{}", s)).collect();
1771
1772
0
        if items.len() == 1 {
1773
0
            let item = &item_idents[0];
1774
0
            quote! { pub use #item; }
1775
        } else {
1776
0
            quote! { pub use {#(#item_idents),*}; }
1777
        }
1778
0
    }
1779
1780
    /// Handle print/debug macros (println, print, dbg, panic)
1781
    /// 
1782
    /// # Examples
1783
    /// 
1784
    /// ```
1785
    /// use ruchy::{Transpiler, Parser};
1786
    /// 
1787
    /// // Test println macro handling
1788
    /// let transpiler = Transpiler::new();
1789
    /// let mut parser = Parser::new("println(42)");
1790
    /// let ast = parser.parse().unwrap();
1791
    /// let result = transpiler.transpile(&ast).unwrap().to_string();
1792
    /// assert!(result.contains("println !"));
1793
    /// assert!(result.contains("{}"));
1794
    /// ```
1795
34
    fn try_transpile_print_macro(
1796
34
        &self, 
1797
34
        func_tokens: &TokenStream, 
1798
34
        base_name: &str, 
1799
34
        args: &[Expr]
1800
34
    ) -> Result<Option<TokenStream>> {
1801
34
        if !(base_name == "println" || 
base_name == "print"31
||
base_name == "dbg"30
||
base_name == "panic"30
) {
1802
30
            return Ok(None);
1803
4
        }
1804
        
1805
        // Handle single argument with string interpolation
1806
4
        if (base_name == "println" || 
base_name == "print"1
) && args.len() == 1 {
1807
4
            if let ExprKind::StringInterpolation { 
parts0
} = &args[0].kind {
1808
0
                return Ok(Some(self.transpile_print_with_interpolation(base_name, parts)?));
1809
4
            }
1810
            // For single non-string arguments, add smart format string
1811
4
            if !
matches!1
(&args[0].kind, ExprKind::Literal(Literal::String(_))) {
1812
1
                let arg_tokens = self.transpile_expr(&args[0])
?0
;
1813
                // Use Debug formatting for safety - works with all types including Vec, tuples, etc.
1814
1
                let format_str = "{:?}";
1815
1
                return Ok(Some(quote! { #func_tokens!(#format_str, #arg_tokens) }));
1816
3
            }
1817
0
        }
1818
        
1819
        // Handle multiple arguments
1820
3
        if args.len() > 1 {
1821
0
            return self.transpile_print_multiple_args(func_tokens, args);
1822
3
        }
1823
        
1824
        // Single string literal or simple case
1825
3
        let arg_tokens: Result<Vec<_>> = args.iter().map(|a| self.transpile_expr(a)).collect();
1826
3
        let arg_tokens = arg_tokens
?0
;
1827
3
        Ok(Some(quote! { #func_tokens!(#(#arg_tokens),*) }))
1828
34
    }
1829
    
1830
    /// Handle multiple arguments for print macros
1831
0
    fn transpile_print_multiple_args(
1832
0
        &self,
1833
0
        func_tokens: &TokenStream,
1834
0
        args: &[Expr]
1835
0
    ) -> Result<Option<TokenStream>> {
1836
        // FIXED: Don't treat first string argument as format string
1837
        // Instead, treat all arguments as values to print with spaces
1838
0
        if args.is_empty() {
1839
0
            return Ok(Some(quote! { #func_tokens!() }));
1840
0
        }
1841
        
1842
0
        let all_args: Result<Vec<_>> = args.iter().map(|a| self.transpile_expr(a)).collect();
1843
0
        let all_args = all_args?;
1844
        
1845
0
        if args.len() == 1 {
1846
            // Single argument - check if it's a string-like expression
1847
0
            match &args[0].kind {
1848
                ExprKind::Literal(Literal::String(_)) | 
1849
                ExprKind::StringInterpolation { .. } => {
1850
                    // String literal or interpolation - use Display format
1851
0
                    Ok(Some(quote! { #func_tokens!("{}", #(#all_args)*) }))
1852
                }
1853
                ExprKind::Identifier(_) => {
1854
                    // For identifiers, we can't know the type at compile time
1855
                    // Use a runtime check to decide format
1856
0
                    let arg = &all_args[0];
1857
0
                    let printing_logic = self.generate_value_printing_tokens(quote! { #arg }, quote! { #func_tokens });
1858
0
                    Ok(Some(printing_logic))
1859
                }
1860
                _ => {
1861
                    // Other types - use Debug format for complex types
1862
0
                    Ok(Some(quote! { #func_tokens!("{:?}", #(#all_args)*) }))
1863
                }
1864
            }
1865
        } else {
1866
            // Multiple arguments - use appropriate format for each
1867
0
            let format_parts: Vec<_> = args.iter().map(|arg| {
1868
0
                match &arg.kind {
1869
0
                    ExprKind::Literal(Literal::String(_)) => "{}",
1870
0
                    _ => "{:?}"
1871
                }
1872
0
            }).collect();
1873
0
            let format_str = format_parts.join(" ");
1874
0
            Ok(Some(quote! { #func_tokens!(#format_str, #(#all_args),*) }))
1875
        }
1876
0
    }
1877
    
1878
    /// Handle math functions (sqrt, pow, abs, min, max, floor, ceil, round)
1879
    /// 
1880
    /// # Examples
1881
    /// 
1882
    /// ```
1883
    /// use ruchy::{Transpiler, Parser};
1884
    /// 
1885
    /// let transpiler = Transpiler::new();
1886
    /// let mut parser = Parser::new("sqrt(4.0)");
1887
    /// let ast = parser.parse().unwrap();
1888
    /// let result = transpiler.transpile(&ast).unwrap().to_string();
1889
    /// assert!(result.contains("sqrt"));
1890
    /// ```
1891
30
    fn try_transpile_math_function(&self, base_name: &str, args: &[Expr]) -> Result<Option<TokenStream>> {
1892
30
        match (base_name, args.len()) {
1893
30
            ("sqrt", 1) => 
self0
.
transpile_sqrt0
(
&args[0]0
).
map0
(Some),
1894
30
            ("pow", 2) => 
self0
.
transpile_pow0
(
&args[0]0
,
&args[1]0
).
map0
(Some),
1895
30
            ("abs", 1) => 
self0
.
transpile_abs0
(
&args[0]0
).
map0
(Some),
1896
30
            ("min", 2) => 
self0
.
transpile_min0
(
&args[0]0
,
&args[1]0
).
map0
(Some),
1897
30
            ("max", 2) => 
self0
.
transpile_max0
(
&args[0]0
,
&args[1]0
).
map0
(Some),
1898
30
            ("floor", 1) => 
self0
.
transpile_floor0
(
&args[0]0
).
map0
(Some),
1899
30
            ("ceil", 1) => 
self0
.
transpile_ceil0
(
&args[0]0
).
map0
(Some),
1900
30
            ("round", 1) => 
self0
.
transpile_round0
(
&args[0]0
).
map0
(Some),
1901
30
            _ => Ok(None)
1902
        }
1903
30
    }
1904
1905
0
    fn transpile_sqrt(&self, arg: &Expr) -> Result<TokenStream> {
1906
0
        let arg_tokens = self.transpile_expr(arg)?;
1907
0
        Ok(quote! { (#arg_tokens as f64).sqrt() })
1908
0
    }
1909
1910
0
    fn transpile_pow(&self, base: &Expr, exp: &Expr) -> Result<TokenStream> {
1911
0
        let base_tokens = self.transpile_expr(base)?;
1912
0
        let exp_tokens = self.transpile_expr(exp)?;
1913
0
        Ok(quote! { (#base_tokens as f64).powf(#exp_tokens as f64) })
1914
0
    }
1915
1916
0
    fn transpile_abs(&self, arg: &Expr) -> Result<TokenStream> {
1917
0
        let arg_tokens = self.transpile_expr(arg)?;
1918
        // Check if arg is negative literal to handle type
1919
0
        if let ExprKind::Unary { op: UnaryOp::Negate, operand } = &arg.kind {
1920
0
            if matches!(&operand.kind, ExprKind::Literal(Literal::Float(_))) {
1921
0
                return Ok(quote! { (#arg_tokens).abs() });
1922
0
            }
1923
0
        }
1924
        // For all other cases, use standard abs
1925
0
        Ok(quote! { #arg_tokens.abs() })
1926
0
    }
1927
1928
0
    fn transpile_min(&self, a: &Expr, b: &Expr) -> Result<TokenStream> {
1929
0
        let a_tokens = self.transpile_expr(a)?;
1930
0
        let b_tokens = self.transpile_expr(b)?;
1931
        // Check if args are float literals to determine type
1932
0
        let is_float = matches!(&a.kind, ExprKind::Literal(Literal::Float(_))) 
1933
0
            || matches!(&b.kind, ExprKind::Literal(Literal::Float(_)));
1934
0
        if is_float {
1935
0
            Ok(quote! { (#a_tokens as f64).min(#b_tokens as f64) })
1936
        } else {
1937
0
            Ok(quote! { std::cmp::min(#a_tokens, #b_tokens) })
1938
        }
1939
0
    }
1940
1941
0
    fn transpile_max(&self, a: &Expr, b: &Expr) -> Result<TokenStream> {
1942
0
        let a_tokens = self.transpile_expr(a)?;
1943
0
        let b_tokens = self.transpile_expr(b)?;
1944
        // Check if args are float literals to determine type
1945
0
        let is_float = matches!(&a.kind, ExprKind::Literal(Literal::Float(_))) 
1946
0
            || matches!(&b.kind, ExprKind::Literal(Literal::Float(_)));
1947
0
        if is_float {
1948
0
            Ok(quote! { (#a_tokens as f64).max(#b_tokens as f64) })
1949
        } else {
1950
0
            Ok(quote! { std::cmp::max(#a_tokens, #b_tokens) })
1951
        }
1952
0
    }
1953
1954
0
    fn transpile_floor(&self, arg: &Expr) -> Result<TokenStream> {
1955
0
        let arg_tokens = self.transpile_expr(arg)?;
1956
0
        Ok(quote! { (#arg_tokens as f64).floor() })
1957
0
    }
1958
1959
0
    fn transpile_ceil(&self, arg: &Expr) -> Result<TokenStream> {
1960
0
        let arg_tokens = self.transpile_expr(arg)?;
1961
0
        Ok(quote! { (#arg_tokens as f64).ceil() })
1962
0
    }
1963
1964
0
    fn transpile_round(&self, arg: &Expr) -> Result<TokenStream> {
1965
0
        let arg_tokens = self.transpile_expr(arg)?;
1966
0
        Ok(quote! { (#arg_tokens as f64).round() })
1967
0
    }
1968
    
1969
    /// Handle input functions (input, readline)
1970
    /// 
1971
    /// # Examples
1972
    /// 
1973
    /// ```
1974
    /// use ruchy::{Transpiler, Parser};
1975
    /// 
1976
    /// let transpiler = Transpiler::new();
1977
    /// let mut parser = Parser::new("input()");
1978
    /// let ast = parser.parse().unwrap();
1979
    /// let result = transpiler.transpile(&ast).unwrap().to_string();
1980
    /// assert!(result.contains("read_line"));
1981
    /// ```
1982
30
    fn try_transpile_input_function(&self, base_name: &str, args: &[Expr]) -> Result<Option<TokenStream>> {
1983
0
        match base_name {
1984
30
            "input" => {
1985
0
                if args.len() > 1 {
1986
0
                    bail!("input expects 0 or 1 arguments (optional prompt)");
1987
0
                }
1988
0
                if args.is_empty() {
1989
0
                    Ok(Some(self.generate_input_without_prompt()))
1990
                } else {
1991
0
                    let prompt = self.transpile_expr(&args[0])?;
1992
0
                    Ok(Some(self.generate_input_with_prompt(prompt)))
1993
                }
1994
            }
1995
30
            "readline" if 
args0
.
is_empty0
(
)0
=> {
1996
0
                Ok(Some(self.generate_input_without_prompt()))
1997
            }
1998
30
            _ => Ok(None)
1999
        }
2000
30
    }
2001
    
2002
    /// Generate input reading code without prompt
2003
0
    fn generate_input_without_prompt(&self) -> TokenStream {
2004
0
        quote! { 
2005
            {
2006
                let mut input = String::new();
2007
                std::io::stdin().read_line(&mut input).expect("Failed to read input");
2008
                if input.ends_with('\n') {
2009
                    input.pop();
2010
                    if input.ends_with('\r') {
2011
                        input.pop();
2012
                    }
2013
                }
2014
                input
2015
            }
2016
        }
2017
0
    }
2018
    
2019
    /// Generate input reading code with prompt
2020
0
    fn generate_input_with_prompt(&self, prompt: TokenStream) -> TokenStream {
2021
0
        quote! { 
2022
            {
2023
                print!("{}", #prompt);
2024
                std::io::Write::flush(&mut std::io::stdout()).unwrap();
2025
                let mut input = String::new();
2026
                std::io::stdin().read_line(&mut input).expect("Failed to read input");
2027
                if input.ends_with('\n') {
2028
                    input.pop();
2029
                    if input.ends_with('\r') {
2030
                        input.pop();
2031
                    }
2032
                }
2033
                input
2034
            }
2035
        }
2036
0
    }
2037
    
2038
    /// Try to transpile type conversion functions (str, int, float, bool)
2039
    /// 
2040
    /// # Examples
2041
    /// 
2042
    /// ```rust
2043
    /// # use ruchy::backend::transpiler::Transpiler;
2044
    /// let transpiler = Transpiler::new();
2045
    /// // str(42) -> 42.to_string()
2046
    /// // int("42") -> "42".parse::<i64>().unwrap()
2047
    /// // float(42) -> 42 as f64
2048
    /// // bool(1) -> 1 != 0
2049
    /// ```
2050
30
    fn try_transpile_type_conversion(&self, base_name: &str, args: &[Expr]) -> Result<Option<TokenStream>> {
2051
        // Delegate to refactored version with reduced complexity
2052
        // Original complexity: 62, New complexity: <20 per function
2053
30
        self.try_transpile_type_conversion_refactored(base_name, args)
2054
30
    }
2055
    
2056
    // Old implementation kept for reference (will be removed after verification)
2057
    #[allow(dead_code)]
2058
0
    pub fn try_transpile_type_conversion_old(&self, base_name: &str, args: &[Expr]) -> Result<Option<TokenStream>> {
2059
0
        match base_name {
2060
0
            "str" => self.transpile_str_conversion(args).map(Some),
2061
0
            "int" => self.transpile_int_conversion(args).map(Some), 
2062
0
            "float" => self.transpile_float_conversion(args).map(Some),
2063
0
            "bool" => self.transpile_bool_conversion(args).map(Some),
2064
0
            _ => Ok(None)
2065
        }
2066
0
    }
2067
    
2068
    /// Handle `str()` type conversion - extract string representation
2069
0
    fn transpile_str_conversion(&self, args: &[Expr]) -> Result<TokenStream> {
2070
0
        if args.len() != 1 {
2071
0
            bail!("str() expects exactly 1 argument");
2072
0
        }
2073
0
        let value = self.transpile_expr(&args[0])?;
2074
0
        Ok(quote! { format!("{}", #value) })
2075
0
    }
2076
    
2077
    /// Handle `int()` type conversion with literal-specific optimizations
2078
0
    fn transpile_int_conversion(&self, args: &[Expr]) -> Result<TokenStream> {
2079
0
        if args.len() != 1 {
2080
0
            bail!("int() expects exactly 1 argument");
2081
0
        }
2082
        
2083
        // Check if the argument is a literal for compile-time optimizations
2084
0
        match &args[0].kind {
2085
            ExprKind::Literal(Literal::String(_)) => {
2086
0
                let value = self.transpile_expr(&args[0])?;
2087
0
                Ok(quote! { #value.parse::<i64>().expect("Failed to parse integer") })
2088
            }
2089
0
            ExprKind::StringInterpolation { parts } if parts.len() == 1 => {
2090
0
                if let crate::frontend::ast::StringPart::Text(_) = &parts[0] {
2091
0
                    let value = self.transpile_expr(&args[0])?;
2092
0
                    Ok(quote! { #value.parse::<i64>().expect("Failed to parse integer") })
2093
                } else {
2094
0
                    self.transpile_int_generic(&args[0])
2095
                }
2096
            }
2097
            ExprKind::Literal(Literal::Float(_)) => {
2098
0
                let value = self.transpile_expr(&args[0])?;
2099
0
                Ok(quote! { (#value as i64) })
2100
            }
2101
            ExprKind::Literal(Literal::Bool(_)) => {
2102
0
                let value = self.transpile_expr(&args[0])?;
2103
0
                Ok(quote! { if #value { 1i64 } else { 0i64 } })
2104
            }
2105
0
            _ => self.transpile_int_generic(&args[0])
2106
        }
2107
0
    }
2108
    
2109
    /// Generic int conversion for non-literal expressions
2110
0
    fn transpile_int_generic(&self, expr: &Expr) -> Result<TokenStream> {
2111
0
        let value = self.transpile_expr(expr)?;
2112
0
        Ok(quote! { (#value as i64) })
2113
0
    }
2114
    
2115
    /// Handle `float()` type conversion with literal-specific optimizations
2116
0
    fn transpile_float_conversion(&self, args: &[Expr]) -> Result<TokenStream> {
2117
0
        if args.len() != 1 {
2118
0
            bail!("float() expects exactly 1 argument");
2119
0
        }
2120
        
2121
        // Check if the argument is a literal for compile-time optimizations
2122
0
        match &args[0].kind {
2123
            ExprKind::Literal(Literal::String(_)) => {
2124
0
                let value = self.transpile_expr(&args[0])?;
2125
0
                Ok(quote! { #value.parse::<f64>().expect("Failed to parse float") })
2126
            }
2127
0
            ExprKind::StringInterpolation { parts } if parts.len() == 1 => {
2128
0
                if let crate::frontend::ast::StringPart::Text(_) = &parts[0] {
2129
0
                    let value = self.transpile_expr(&args[0])?;
2130
0
                    Ok(quote! { #value.parse::<f64>().expect("Failed to parse float") })
2131
                } else {
2132
0
                    self.transpile_float_generic(&args[0])
2133
                }
2134
            }
2135
            ExprKind::Literal(Literal::Integer(_)) => {
2136
0
                let value = self.transpile_expr(&args[0])?;
2137
0
                Ok(quote! { (#value as f64) })
2138
            }
2139
0
            _ => self.transpile_float_generic(&args[0])
2140
        }
2141
0
    }
2142
    
2143
    /// Generic float conversion for non-literal expressions
2144
0
    fn transpile_float_generic(&self, expr: &Expr) -> Result<TokenStream> {
2145
0
        let value = self.transpile_expr(expr)?;
2146
0
        Ok(quote! { (#value as f64) })
2147
0
    }
2148
    
2149
    /// Handle `bool()` type conversion with type-specific logic
2150
0
    fn transpile_bool_conversion(&self, args: &[Expr]) -> Result<TokenStream> {
2151
0
        if args.len() != 1 {
2152
0
            bail!("bool() expects exactly 1 argument");
2153
0
        }
2154
        
2155
        // Check the type of the argument to generate appropriate conversion
2156
0
        match &args[0].kind {
2157
            ExprKind::Literal(Literal::Integer(_)) => {
2158
0
                let value = self.transpile_expr(&args[0])?;
2159
0
                Ok(quote! { (#value != 0) })
2160
            }
2161
            ExprKind::Literal(Literal::String(_)) => {
2162
0
                let value = self.transpile_expr(&args[0])?;
2163
0
                Ok(quote! { !#value.is_empty() })
2164
            }
2165
0
            ExprKind::StringInterpolation { parts } if parts.len() == 1 => {
2166
0
                let value = self.transpile_expr(&args[0])?;
2167
0
                Ok(quote! { !#value.is_empty() })
2168
            }
2169
            ExprKind::Literal(Literal::Bool(_)) => {
2170
                // Boolean already, just pass through
2171
0
                let value = self.transpile_expr(&args[0])?;
2172
0
                Ok(value)
2173
            }
2174
            _ => {
2175
                // Generic case - for numbers check != 0
2176
0
                let value = self.transpile_expr(&args[0])?;
2177
0
                Ok(quote! { (#value != 0) })
2178
            }
2179
        }
2180
0
    }
2181
    
2182
    /// Try to transpile advanced math functions (sin, cos, tan, log, log10, random)
2183
    /// 
2184
    /// # Examples
2185
    /// 
2186
    /// ```rust
2187
    /// # use ruchy::backend::transpiler::Transpiler;
2188
    /// let transpiler = Transpiler::new();
2189
    /// // sin(x) -> x.sin()
2190
    /// // cos(x) -> x.cos()
2191
    /// // log(x) -> x.ln()
2192
    /// // random() -> rand::random::<f64>()
2193
    /// ```
2194
16
    fn try_transpile_math_functions(&self, base_name: &str, args: &[Expr]) -> Result<Option<TokenStream>> {
2195
16
        match base_name {
2196
16
            "sin" | "cos" | "tan" => {
2197
0
                if args.len() != 1 {
2198
0
                    bail!("{}() expects exactly 1 argument", base_name);
2199
0
                }
2200
0
                let value = self.transpile_expr(&args[0])?;
2201
0
                let method = proc_macro2::Ident::new(base_name, proc_macro2::Span::call_site());
2202
0
                Ok(Some(quote! { ((#value as f64).#method()) }))
2203
            }
2204
16
            "log" => {
2205
0
                if args.len() != 1 {
2206
0
                    bail!("log() expects exactly 1 argument");
2207
0
                }
2208
0
                let value = self.transpile_expr(&args[0])?;
2209
0
                Ok(Some(quote! { ((#value as f64).ln()) }))
2210
            }
2211
16
            "log10" => {
2212
0
                if args.len() != 1 {
2213
0
                    bail!("log10() expects exactly 1 argument");
2214
0
                }
2215
0
                let value = self.transpile_expr(&args[0])?;
2216
0
                Ok(Some(quote! { ((#value as f64).log10()) }))
2217
            }
2218
16
            "random" => {
2219
0
                if !args.is_empty() {
2220
0
                    bail!("random() expects no arguments");
2221
0
                }
2222
                // Use a simple pseudo-random generator
2223
0
                Ok(Some(quote! {
2224
0
                    {
2225
0
                        use std::time::{SystemTime, UNIX_EPOCH};
2226
0
                        let seed = SystemTime::now()
2227
0
                            .duration_since(UNIX_EPOCH)
2228
0
                            .unwrap()
2229
0
                            .as_nanos() as u64;
2230
0
                        // Use a safe LCG that won't overflow
2231
0
                        let a = 1664525u64;
2232
0
                        let c = 1013904223u64;
2233
0
                        let m = 1u64 << 32;
2234
0
                        ((seed.wrapping_mul(a).wrapping_add(c)) % m) as f64 / m as f64
2235
0
                    }
2236
0
                }))
2237
            }
2238
16
            _ => Ok(None)
2239
        }
2240
16
    }
2241
    
2242
    /// Handle assert functions (assert, `assert_eq`, `assert_ne`)
2243
    /// 
2244
    /// # Examples
2245
    /// 
2246
    /// ```
2247
    /// use ruchy::{Transpiler, Parser};
2248
    /// 
2249
    /// let transpiler = Transpiler::new();
2250
    /// let mut parser = Parser::new("assert(true)");
2251
    /// let ast = parser.parse().unwrap();
2252
    /// let result = transpiler.transpile(&ast).unwrap().to_string();
2253
    /// assert!(result.contains("assert !"));
2254
    /// ```
2255
30
    fn try_transpile_assert_function(
2256
30
        &self,
2257
30
        _func_tokens: &TokenStream,
2258
30
        base_name: &str,
2259
30
        args: &[Expr]
2260
30
    ) -> Result<Option<TokenStream>> {
2261
30
        match base_name {
2262
30
            "assert" => {
2263
0
                if args.is_empty() || args.len() > 2 {
2264
0
                    bail!("assert expects 1 or 2 arguments (condition, optional message)");
2265
0
                }
2266
0
                let condition = self.transpile_expr(&args[0])?;
2267
0
                if args.len() == 1 {
2268
0
                    Ok(Some(quote! { assert!(#condition) }))
2269
                } else {
2270
0
                    let message = self.transpile_expr(&args[1])?;
2271
0
                    Ok(Some(quote! { assert!(#condition, "{}", #message) }))
2272
                }
2273
            }
2274
30
            "assert_eq" => {
2275
0
                if args.len() < 2 || args.len() > 3 {
2276
0
                    bail!("assert_eq expects 2 or 3 arguments (left, right, optional message)");
2277
0
                }
2278
0
                let left = self.transpile_expr(&args[0])?;
2279
0
                let right = self.transpile_expr(&args[1])?;
2280
0
                if args.len() == 2 {
2281
0
                    Ok(Some(quote! { assert_eq!(#left, #right) }))
2282
                } else {
2283
0
                    let message = self.transpile_expr(&args[2])?;
2284
0
                    Ok(Some(quote! { assert_eq!(#left, #right, "{}", #message) }))
2285
                }
2286
            }
2287
30
            "assert_ne" => {
2288
0
                if args.len() < 2 || args.len() > 3 {
2289
0
                    bail!("assert_ne expects 2 or 3 arguments (left, right, optional message)");
2290
0
                }
2291
0
                let left = self.transpile_expr(&args[0])?;
2292
0
                let right = self.transpile_expr(&args[1])?;
2293
0
                if args.len() == 2 {
2294
0
                    Ok(Some(quote! { assert_ne!(#left, #right) }))
2295
                } else {
2296
0
                    let message = self.transpile_expr(&args[2])?;
2297
0
                    Ok(Some(quote! { assert_ne!(#left, #right, "{}", #message) }))
2298
                }
2299
            }
2300
30
            _ => Ok(None)
2301
        }
2302
30
    }
2303
    
2304
    /// Handle collection constructors (`HashMap`, `HashSet`)
2305
    /// 
2306
    /// # Examples
2307
    /// 
2308
    /// ```
2309
    /// use ruchy::{Transpiler, Parser};
2310
    /// 
2311
    /// let transpiler = Transpiler::new();
2312
    /// let mut parser = Parser::new("HashMap()");
2313
    /// let ast = parser.parse().unwrap();
2314
    /// let result = transpiler.transpile(&ast).unwrap().to_string();
2315
    /// assert!(result.contains("HashMap"));
2316
    /// ```
2317
16
    fn try_transpile_collection_constructor(&self, base_name: &str, args: &[Expr]) -> Result<Option<TokenStream>> {
2318
16
        match (base_name, args.len()) {
2319
16
            ("HashMap", 0) => 
Ok(Some(quote! { std::collections::HashMap::new() }))0
,
2320
16
            ("HashSet", 0) => 
Ok(Some(quote! { std::collections::HashSet::new() }))0
,
2321
16
            _ => Ok(None)
2322
        }
2323
16
    }
2324
    
2325
    /// Handle `DataFrame` functions (col)
2326
    /// 
2327
    /// # Examples
2328
    /// 
2329
    /// ```
2330
    /// use ruchy::{Transpiler, Parser};
2331
    /// 
2332
    /// let transpiler = Transpiler::new();
2333
    /// let mut parser = Parser::new(r#"col("name")"#);
2334
    /// let ast = parser.parse().unwrap();
2335
    /// let result = transpiler.transpile(&ast).unwrap().to_string();
2336
    /// assert!(result.contains("polars"));
2337
    /// ```
2338
16
    fn try_transpile_dataframe_function(&self, base_name: &str, args: &[Expr]) -> Result<Option<TokenStream>> {
2339
16
        if base_name == "col" && 
args.len() == 11
{
2340
1
            if let ExprKind::Literal(Literal::String(col_name)) = &args[0].kind {
2341
1
                return Ok(Some(quote! { polars::prelude::col(#col_name) }));
2342
0
            }
2343
15
        }
2344
15
        Ok(None)
2345
16
    }
2346
    
2347
    /// Handle regular function calls with string literal conversion
2348
    /// 
2349
    /// # Examples
2350
    /// 
2351
    /// ```
2352
    /// use ruchy::{Transpiler, Parser};
2353
    /// 
2354
    /// let transpiler = Transpiler::new();
2355
    /// let mut parser = Parser::new(r#"my_func("test")"#);
2356
    /// let ast = parser.parse().unwrap();
2357
    /// let result = transpiler.transpile(&ast).unwrap().to_string();
2358
    /// assert!(result.contains("my_func"));
2359
    /// ```
2360
15
    fn transpile_regular_function_call(
2361
15
        &self,
2362
15
        func_tokens: &TokenStream,
2363
15
        args: &[Expr]
2364
15
    ) -> Result<TokenStream> {
2365
        // Get function name for signature lookup
2366
15
        let func_name = func_tokens.to_string().trim().to_string();
2367
        
2368
        // Apply type coercion based on function signature
2369
15
        let arg_tokens: Result<Vec<_>> = if let Some(
signature5
) = self.function_signatures.get(&func_name) {
2370
5
            args.iter().enumerate().map(|(i, arg)| {
2371
5
                let base_tokens = self.transpile_expr(arg)
?0
;
2372
                
2373
                // Apply String/&str coercion if needed
2374
5
                if let Some(expected_type) = signature.param_types.get(i) {
2375
5
                    self.apply_string_coercion(arg, &base_tokens, expected_type)
2376
                } else {
2377
0
                    Ok(base_tokens)
2378
                }
2379
5
            }).collect()
2380
        } else {
2381
            // No signature info - transpile as-is
2382
13
            
args10
.
iter10
().
map10
(|a| self.transpile_expr(a)).
collect10
()
2383
        };
2384
        
2385
15
        let arg_tokens = arg_tokens
?0
;
2386
15
        Ok(quote! { #func_tokens(#(#arg_tokens),*) })
2387
15
    }
2388
    
2389
    /// Apply String/&str coercion based on expected type
2390
5
    fn apply_string_coercion(
2391
5
        &self,
2392
5
        arg: &Expr,
2393
5
        tokens: &TokenStream,
2394
5
        expected_type: &str
2395
5
    ) -> Result<TokenStream> {
2396
        use crate::frontend::ast::{ExprKind, Literal};
2397
        
2398
5
        match (&arg.kind, expected_type) {
2399
            // String literal to String parameter: add .to_string()
2400
0
            (ExprKind::Literal(Literal::String(_)), "String") => {
2401
0
                Ok(quote! { #tokens.to_string() })
2402
            }
2403
            // String literal to &str parameter: keep as-is
2404
0
            (ExprKind::Literal(Literal::String(_)), expected) if expected.starts_with('&') => {
2405
0
                Ok(tokens.clone())
2406
            }
2407
            // Variable that might be &str to String parameter
2408
2
            (ExprKind::Identifier(_), "String") => {
2409
                // For now, assume string variables are String type from auto-conversion
2410
                // This matches the existing behavior in transpile_let
2411
0
                Ok(tokens.clone())
2412
            }
2413
            // No coercion needed
2414
5
            _ => Ok(tokens.clone())
2415
        }
2416
5
    }
2417
}
2418
2419
#[cfg(test)]
2420
#[allow(clippy::single_char_pattern)]
2421
mod tests {
2422
    use super::*;
2423
    use crate::Parser;
2424
2425
21
    fn create_transpiler() -> Transpiler {
2426
21
        Transpiler::new()
2427
21
    }
2428
2429
    #[test]
2430
1
    fn test_transpile_if_with_else() {
2431
1
        let transpiler = create_transpiler();
2432
1
        let code = "if true { 1 } else { 2 }";
2433
1
        let mut parser = Parser::new(code);
2434
1
        let ast = parser.parse().unwrap();
2435
        
2436
1
        let result = transpiler.transpile(&ast).unwrap();
2437
1
        let rust_str = result.to_string();
2438
        
2439
1
        assert!(rust_str.contains("if"));
2440
1
        assert!(rust_str.contains("else"));
2441
1
    }
2442
2443
    #[test]
2444
1
    fn test_transpile_if_without_else() {
2445
1
        let transpiler = create_transpiler();
2446
1
        let code = "if true { 1 }";
2447
1
        let mut parser = Parser::new(code);
2448
1
        let ast = parser.parse().unwrap();
2449
        
2450
1
        let result = transpiler.transpile(&ast).unwrap();
2451
1
        let rust_str = result.to_string();
2452
        
2453
1
        assert!(rust_str.contains("if"));
2454
1
        assert!(!rust_str.contains("else"));
2455
1
    }
2456
2457
    #[test]
2458
1
    fn test_transpile_let_binding() {
2459
1
        let transpiler = create_transpiler();
2460
1
        let code = "let x = 5; x";
2461
1
        let mut parser = Parser::new(code);
2462
1
        let ast = parser.parse().unwrap();
2463
        
2464
1
        let result = transpiler.transpile(&ast).unwrap();
2465
1
        let rust_str = result.to_string();
2466
        
2467
1
        assert!(rust_str.contains("let"));
2468
1
        assert!(rust_str.contains("x"));
2469
1
        assert!(rust_str.contains("5"));
2470
1
    }
2471
2472
    #[test]
2473
1
    fn test_transpile_mutable_let() {
2474
1
        let transpiler = create_transpiler();
2475
1
        let code = "let mut x = 5; x";
2476
1
        let mut parser = Parser::new(code);
2477
1
        let ast = parser.parse().unwrap();
2478
        
2479
1
        let result = transpiler.transpile(&ast).unwrap();
2480
1
        let rust_str = result.to_string();
2481
        
2482
1
        assert!(rust_str.contains("mut"));
2483
1
    }
2484
2485
    #[test]
2486
1
    fn test_transpile_for_loop() {
2487
1
        let transpiler = create_transpiler();
2488
1
        let code = "for x in [1, 2, 3] { x }";
2489
1
        let mut parser = Parser::new(code);
2490
1
        let ast = parser.parse().unwrap();
2491
        
2492
1
        let result = transpiler.transpile(&ast).unwrap();
2493
1
        let rust_str = result.to_string();
2494
        
2495
1
        assert!(rust_str.contains("for"));
2496
1
        assert!(rust_str.contains("in"));
2497
1
    }
2498
2499
    #[test]
2500
1
    fn test_transpile_while_loop() {
2501
1
        let transpiler = create_transpiler();
2502
1
        let code = "while true { }";
2503
1
        let mut parser = Parser::new(code);
2504
1
        let ast = parser.parse().unwrap();
2505
        
2506
1
        let result = transpiler.transpile(&ast).unwrap();
2507
1
        let rust_str = result.to_string();
2508
        
2509
1
        assert!(rust_str.contains("while"));
2510
1
    }
2511
2512
    #[test]
2513
1
    fn test_function_with_parameters() {
2514
1
        let transpiler = create_transpiler();
2515
1
        let code = "fun add(x, y) { x + y }";
2516
1
        let mut parser = Parser::new(code);
2517
1
        let ast = parser.parse().unwrap();
2518
        
2519
1
        let result = transpiler.transpile(&ast).unwrap();
2520
1
        let rust_str = result.to_string();
2521
        
2522
1
        assert!(rust_str.contains("fn add"));
2523
1
        assert!(rust_str.contains("x"));
2524
1
        assert!(rust_str.contains("y"));
2525
1
    }
2526
2527
    #[test]
2528
1
    fn test_function_without_parameters() {
2529
1
        let transpiler = create_transpiler();
2530
1
        let code = "fun hello() { \"world\" }";
2531
1
        let mut parser = Parser::new(code);
2532
1
        let ast = parser.parse().unwrap();
2533
        
2534
1
        let result = transpiler.transpile(&ast).unwrap();
2535
1
        let rust_str = result.to_string();
2536
        
2537
1
        assert!(rust_str.contains("fn hello"));
2538
1
        assert!(rust_str.contains("()"));
2539
1
    }
2540
2541
    #[test]
2542
1
    fn test_looks_like_numeric_function() {
2543
1
        let transpiler = create_transpiler();
2544
        
2545
        // Test known numeric function names
2546
1
        assert!(transpiler.looks_like_numeric_function("double"));
2547
1
        assert!(transpiler.looks_like_numeric_function("add"));
2548
1
        assert!(transpiler.looks_like_numeric_function("square"));
2549
        
2550
        // Test non-numeric function names
2551
1
        assert!(!transpiler.looks_like_numeric_function("hello"));
2552
1
        assert!(!transpiler.looks_like_numeric_function("main"));
2553
1
        assert!(!transpiler.looks_like_numeric_function("test"));
2554
1
    }
2555
2556
    #[test]
2557
1
    fn test_match_expression() {
2558
1
        let transpiler = create_transpiler();
2559
1
        let code = "match x { 1 => \"one\", _ => \"other\" }";
2560
1
        let mut parser = Parser::new(code);
2561
1
        let ast = parser.parse().unwrap();
2562
        
2563
1
        let result = transpiler.transpile(&ast).unwrap();
2564
1
        let rust_str = result.to_string();
2565
        
2566
1
        assert!(rust_str.contains("match"));
2567
1
    }
2568
2569
    #[test]
2570
1
    fn test_lambda_expression() {
2571
1
        let transpiler = create_transpiler();
2572
1
        let code = "(x) => x + 1";
2573
1
        let mut parser = Parser::new(code);
2574
1
        let ast = parser.parse().unwrap();
2575
        
2576
1
        let result = transpiler.transpile(&ast).unwrap();
2577
1
        let rust_str = result.to_string();
2578
        
2579
        // Lambda should be transpiled to closure
2580
1
        assert!(rust_str.contains("|") || 
rust_str.contains("move")0
);
2581
1
    }
2582
2583
    #[test]
2584
1
    fn test_reserved_keyword_handling() {
2585
1
        let transpiler = create_transpiler();
2586
1
        let code = "let final = 5; final";  // Use regular keyword, not r# syntax
2587
1
        let mut parser = Parser::new(code);
2588
1
        let ast = parser.parse().unwrap();
2589
        
2590
1
        let result = transpiler.transpile(&ast).unwrap();
2591
1
        let rust_str = result.to_string();
2592
        
2593
        // Should handle Rust reserved keywords by prefixing with r#
2594
1
        assert!(rust_str.contains("r#final") || 
rust_str.contains("final")0
);
2595
1
    }
2596
2597
    #[test]
2598
1
    fn test_generic_function() {
2599
1
        let transpiler = create_transpiler();
2600
1
        let code = "fun identity<T>(x: T) -> T { x }";
2601
1
        let mut parser = Parser::new(code);
2602
1
        let ast = parser.parse().unwrap();
2603
        
2604
1
        let result = transpiler.transpile(&ast).unwrap();
2605
1
        let rust_str = result.to_string();
2606
        
2607
1
        assert!(rust_str.contains("fn identity"));
2608
1
    }
2609
2610
    #[test]
2611
1
    fn test_main_function_special_case() {
2612
1
        let transpiler = create_transpiler();
2613
1
        let code = "fun main() { println(\"Hello\") }";
2614
1
        let mut parser = Parser::new(code);
2615
1
        let ast = parser.parse().unwrap();
2616
        
2617
1
        let result = transpiler.transpile(&ast).unwrap();
2618
1
        let rust_str = result.to_string();
2619
        
2620
        // main should not have explicit return type
2621
1
        assert!(!rust_str.contains("fn main() ->"));
2622
1
        assert!(!rust_str.contains("fn main () ->"));
2623
1
    }
2624
2625
    #[test]
2626
1
    fn test_dataframe_function_call() {
2627
1
        let transpiler = create_transpiler();
2628
1
        let code = "col(\"name\")";
2629
1
        let mut parser = Parser::new(code);
2630
1
        let ast = parser.parse().unwrap();
2631
        
2632
1
        let result = transpiler.transpile(&ast).unwrap();
2633
1
        let rust_str = result.to_string();
2634
        
2635
        // Should transpile DataFrame column access
2636
1
        assert!(rust_str.contains("polars") || 
rust_str.contains("col")0
);
2637
1
    }
2638
2639
    #[test]
2640
1
    fn test_regular_function_call_string_conversion() {
2641
1
        let transpiler = create_transpiler();
2642
1
        let code = "my_func(\"test\")";
2643
1
        let mut parser = Parser::new(code);
2644
1
        let ast = parser.parse().unwrap();
2645
        
2646
1
        let result = transpiler.transpile(&ast).unwrap();
2647
1
        let rust_str = result.to_string();
2648
        
2649
        // Regular function calls should convert string literals
2650
1
        assert!(rust_str.contains("my_func"));
2651
1
        assert!(rust_str.contains("to_string") || rust_str.contains("\"test\""));
2652
1
    }
2653
2654
    #[test]
2655
1
    fn test_nested_expressions() {
2656
1
        let transpiler = create_transpiler();
2657
1
        let code = "if true { let x = 5; x + 1 } else { 0 }";
2658
1
        let mut parser = Parser::new(code);
2659
1
        let ast = parser.parse().unwrap();
2660
        
2661
1
        let result = transpiler.transpile(&ast).unwrap();
2662
1
        let rust_str = result.to_string();
2663
        
2664
        // Should handle nested let inside if
2665
1
        assert!(rust_str.contains("if"));
2666
1
        assert!(rust_str.contains("let"));
2667
1
        assert!(rust_str.contains("else"));
2668
1
    }
2669
2670
    #[test]
2671
1
    fn test_type_inference_integration() {
2672
1
        let transpiler = create_transpiler();
2673
        
2674
        // Test function parameter as function
2675
1
        let code1 = "fun apply(f, x) { f(x) }";
2676
1
        let mut parser1 = Parser::new(code1);
2677
1
        let ast1 = parser1.parse().unwrap();
2678
1
        let result1 = transpiler.transpile(&ast1).unwrap();
2679
1
        let rust_str1 = result1.to_string();
2680
1
        assert!(rust_str1.contains("impl Fn"));
2681
        
2682
        // Test numeric parameter
2683
1
        let code2 = "fun double(n) { n * 2 }";
2684
1
        let mut parser2 = Parser::new(code2);
2685
1
        let ast2 = parser2.parse().unwrap();
2686
1
        let result2 = transpiler.transpile(&ast2).unwrap();
2687
1
        let rust_str2 = result2.to_string();
2688
1
        assert!(rust_str2.contains("n : i32") || 
rust_str2.contains("n: i32")0
);
2689
        
2690
        // Test string parameter
2691
1
        let code3 = "fun greet(name) { \"Hello \" + name }";
2692
1
        let mut parser3 = Parser::new(code3);
2693
1
        let ast3 = parser3.parse().unwrap();
2694
1
        let result3 = transpiler.transpile(&ast3).unwrap();
2695
1
        let rust_str3 = result3.to_string();
2696
1
        assert!(rust_str3.contains("name : String") || 
rust_str3.contains("name: String")0
);
2697
1
    }
2698
2699
    #[test]
2700
1
    fn test_return_type_inference() {
2701
1
        let transpiler = create_transpiler();
2702
        
2703
        // Test numeric function gets return type
2704
1
        let code = "fun double(n) { n * 2 }";
2705
1
        let mut parser = Parser::new(code);
2706
1
        let ast = parser.parse().unwrap();
2707
1
        let result = transpiler.transpile(&ast).unwrap();
2708
1
        let rust_str = result.to_string();
2709
1
        assert!(rust_str.contains("-> i32"));
2710
1
    }
2711
2712
    #[test]
2713
1
    fn test_void_function_no_return_type() {
2714
1
        let transpiler = create_transpiler();
2715
1
        let code = "fun print_hello() { println(\"Hello\") }";
2716
1
        let mut parser = Parser::new(code);
2717
1
        let ast = parser.parse().unwrap();
2718
1
        let result = transpiler.transpile(&ast).unwrap();
2719
1
        let rust_str = result.to_string();
2720
        
2721
        // Should not have explicit return type for void functions
2722
1
        assert!(!rust_str.contains("-> "));
2723
1
    }
2724
2725
    #[test]
2726
1
    fn test_complex_function_combinations() {
2727
1
        let transpiler = create_transpiler();
2728
1
        let code = "fun transform(f, n, m) { f(n + m) * 2 }";
2729
1
        let mut parser = Parser::new(code);
2730
1
        let ast = parser.parse().unwrap();
2731
1
        let result = transpiler.transpile(&ast).unwrap();
2732
1
        let rust_str = result.to_string();
2733
        
2734
        // f should be function, n and m should be i32
2735
1
        assert!(rust_str.contains("impl Fn"));
2736
1
        assert!(rust_str.contains("n : i32") || 
rust_str.contains("n: i32")0
);
2737
1
        assert!(rust_str.contains("m : i32") || 
rust_str.contains("m: i32")0
);
2738
1
    }
2739
}