## Coverage Report

#### Created: 2025-09-08 21:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)

    /home/noah/src/ruchy/src/backend/transpiler/mod.rs

    Line
    Count
    Source
    1
    //! Modular transpiler for Ruchy language
    2
    //!
    3
    //! This module is responsible for converting Ruchy AST into Rust code using `proc_macro2` `TokenStream`.
    4
    5
    #![allow(clippy::missing_errors_doc)]
    6
    #![allow(clippy::too_many_lines)]
    7
    8
    mod actors;
    9
    mod dataframe;
    10
    mod dataframe_builder;
    11
    mod dataframe_helpers;
    12
    mod dispatcher;
    13
    mod expressions;
    14
    mod method_call_refactored;
    15
    mod patterns;
    16
    mod result_type;
    17
    mod statements;
    18
    mod type_conversion_refactored;
    19
    mod type_inference;
    20
    mod types;
    21
    pub mod codegen_minimal;
    22
    23
    use crate::frontend::ast::{Attribute, Expr, ExprKind, Span, Type};
    24
    use crate::backend::module_resolver::ModuleResolver;
    25
    use anyhow::Result;
    26
    use proc_macro2::TokenStream;
    27
    use quote::{format_ident, quote};
    28
    29
    // Module exports are handled by the impl blocks in each module
    30
    31
    /// Block categorization result: (functions, statements, modules, `has_main`, `main_expr`)
    32
    type BlockCategorization<'a> = (Vec<TokenStream>, Vec<TokenStream>, Vec<TokenStream>, bool, Option<&'a Expr>);
    33
    34
    /// Function signature information for type coercion
    35
    #[derive(Debug, Clone)]
    36
    pub struct FunctionSignature {
    37
        pub name: String,
    38
        pub param_types: Vec<String>,  // Simplified: just the type name as string
    39
    }
    40
    41
    /// The main transpiler struct
    42
    pub struct Transpiler {
    43
        /// Track whether we're in an async context
    44
        pub in_async_context: bool,
    45
        /// Track variables that need to be mutable (for auto-mutability)
    46
        pub mutable_vars: std::collections::HashSet<String>,
    47
        /// Track function signatures for type coercion
    48
        pub function_signatures: std::collections::HashMap<String, FunctionSignature>,
    49
    }
    50
    51
    impl Default for Transpiler {
    52
    0
        fn default() -> Self {
    53
    0
            Self::new()
    54
    0
        }
    55
    }
    56
    57
    impl Transpiler {
    58
        /// Creates a new transpiler instance without module loader
    59
        ///
    60
        /// # Examples
    61
        ///
    62
        /// ```
    63
        /// use ruchy::Transpiler;
    64
        ///
    65
        /// let transpiler = Transpiler::new();
    66
        /// assert!(!transpiler.in_async_context);
    67
        /// ```
    68
    0
        pub fn new() -> Self {
    69
    0
            Self {
    70
    0
                in_async_context: false,
    71
    0
                mutable_vars: std::collections::HashSet::new(),
    72
    0
                function_signatures: std::collections::HashMap::new(),
    73
    0
            }
    74
    0
        }
    75
    76
        /// Centralized result printing logic - ONE PLACE FOR ALL RESULT PRINTING
    77
        /// This eliminates code duplication and ensures consistent Unit type handling
    78
    0
        fn generate_result_printing_tokens(&self) -> TokenStream {
    79
    0
            quote! {
    80
                // Check the type name first to avoid Unit type Display error
    81
                if std::any::type_name_of_val(&result) == "()" {
    82
                    // Don't print Unit type
    83
                } else if std::any::type_name_of_val(&result).contains("String") ||
    84
                          std::any::type_name_of_val(&result).contains("&str") {
    85
                    println!("{}", result);
    86
                } else {
    87
                    println!("{:?}", result);
    88
                }
    89
            }
    90
    0
        }
    91
    92
        /// Centralized value printing logic for functions like println
    93
    0
        fn generate_value_printing_tokens(&self, value_expr: TokenStream, func_tokens: TokenStream) -> TokenStream {
    94
    0
            quote! {
    95
                {
    96
                    use std::any::Any;
    97
                    let value = #value_expr;
    98
                    // Special handling for String and &str types to avoid quotes
    99
                    if let Some(s) = (&value as &dyn Any).downcast_ref::<String>() {
    100
                        #func_tokens!("{}", s)
    101
                    } else if let Some(s) = (&value as &dyn Any).downcast_ref::<&str>() {
    102
                        #func_tokens!("{}", s)
    103
                    } else {
    104
                        #func_tokens!("{:?}", value)
    105
                    }
    106
                }
    107
            }
    108
    0
        }
    109
    110
        /// Analyze expressions to determine which variables need to be mutable
    111
    0
        pub fn analyze_mutability(&mut self, exprs: &[Expr]) {
    112
    0
            for expr in exprs {
    113
    0
                self.analyze_expr_mutability(expr);
    114
    0
            }
    115
    0
        }
    116
    117
        /// Collect function signatures for type coercion
    118
    0
        pub fn collect_function_signatures(&mut self, exprs: &[Expr]) {
    119
    0
            for expr in exprs {
    120
    0
                self.collect_signatures_from_expr(expr);
    121
    0
            }
    122
    0
        }
    123
    124
    0
        fn collect_signatures_from_expr(&mut self, expr: &Expr) {
    125
            use crate::frontend::ast::ExprKind;
    126
    127
    0
            match &expr.kind {
    128
    0
                ExprKind::Function { name, params, .. } => {
    129
    0
                    let param_types: Vec<String> = params.iter()
    130
    0
                        .map(|param| self.type_to_string(&param.ty))
    131
    0
                        .collect();
    132
    133
    0
                    let signature = FunctionSignature {
    134
    0
                        name: name.clone(),
    135
    0
                        param_types,
    136
    0
                    };
    137
    138
    0
                    self.function_signatures.insert(name.clone(), signature);
    139
                }
    140
    0
                ExprKind::Block(exprs) => {
    141
    0
                    for e in exprs {
    142
    0
                        self.collect_signatures_from_expr(e);
    143
    0
                    }
    144
                }
    145
    0
                ExprKind::Let { body, .. } => {
    146
    0
                    self.collect_signatures_from_expr(body);
    147
    0
                }
    148
    0
                _ => {}
    149
            }
    150
    0
        }
    151
    152
    0
        fn type_to_string(&self, ty: &crate::frontend::ast::Type) -> String {
    153
            use crate::frontend::ast::TypeKind;
    154
    155
    0
            match &ty.kind {
    156
    0
                TypeKind::Named(name) => name.clone(),
    157
    0
                TypeKind::Reference { inner, .. } => format!("&{}", self.type_to_string(inner)),
    158
    0
                _ => "Unknown".to_string(),
    159
            }
    160
    0
        }
    161
    162
    0
        fn analyze_expr_mutability(&mut self, expr: &Expr) {
    163
            use crate::frontend::ast::ExprKind;
    164
    165
    0
            match &expr.kind {
    166
                // Direct assignment marks the target as mutable
    167
    0
                ExprKind::Assign { target, value } => {
    168
    0
                    if let ExprKind::Identifier(name) = &target.kind {
    169
    0
                        self.mutable_vars.insert(name.clone());
    170
    0
                    }
    171
    0
                    self.analyze_expr_mutability(value);
    172
                }
    173
                // Compound assignment marks the target as mutable
    174
    0
                ExprKind::CompoundAssign { target, value, .. } => {
    175
    0
                    if let ExprKind::Identifier(name) = &target.kind {
    176
    0
                        self.mutable_vars.insert(name.clone());
    177
    0
                    }
    178
    0
                    self.analyze_expr_mutability(value);
    179
                }
    180
                // Pre/Post increment/decrement mark the target as mutable
    181
    0
                ExprKind::PreIncrement { target } |
    182
    0
                ExprKind::PostIncrement { target } |
    183
    0
                ExprKind::PreDecrement { target } |
    184
    0
                ExprKind::PostDecrement { target } => {
    185
    0
                    if let ExprKind::Identifier(name) = &target.kind {
    186
    0
                        self.mutable_vars.insert(name.clone());
    187
    0
                    }
    188
                }
    189
                // Recursively analyze blocks
    190
    0
                ExprKind::Block(exprs) => {
    191
    0
                    for e in exprs {
    192
    0
                        self.analyze_expr_mutability(e);
    193
    0
                    }
    194
                }
    195
                // Analyze control flow
    196
    0
                ExprKind::If { condition, then_branch, else_branch } => {
    197
    0
                    self.analyze_expr_mutability(condition);
    198
    0
                    self.analyze_expr_mutability(then_branch);
    199
    0
                    if let Some(else_expr) = else_branch {
    200
    0
                        self.analyze_expr_mutability(else_expr);
    201
    0
                    }
    202
                }
    203
    0
                ExprKind::While { condition, body } => {
    204
    0
                    self.analyze_expr_mutability(condition);
    205
    0
                    self.analyze_expr_mutability(body);
    206
    0
                }
    207
    0
                ExprKind::For { body, iter, .. } => {
    208
    0
                    self.analyze_expr_mutability(iter);
    209
    0
                    self.analyze_expr_mutability(body);
    210
    0
                }
    211
                // Analyze match arms
    212
    0
                ExprKind::Match { expr, arms } => {
    213
    0
                    self.analyze_expr_mutability(expr);
    214
    0
                    for arm in arms {
    215
    0
                        self.analyze_expr_mutability(&arm.body);
    216
    0
                    }
    217
                }
    218
                // Analyze let bodies
    219
    0
                ExprKind::Let { body, value, .. } | ExprKind::LetPattern { body, value, .. } => {
    220
    0
                    self.analyze_expr_mutability(value);
    221
    0
                    self.analyze_expr_mutability(body);
    222
    0
                }
    223
                // Analyze function bodies
    224
    0
                ExprKind::Function { body, .. } => {
    225
    0
                    self.analyze_expr_mutability(body);
    226
    0
                }
    227
    0
                ExprKind::Lambda { body, .. } => {
    228
    0
                    self.analyze_expr_mutability(body);
    229
    0
                }
    230
                // Analyze binary/unary operations
    231
    0
                ExprKind::Binary { left, right, .. } => {
    232
    0
                    self.analyze_expr_mutability(left);
    233
    0
                    self.analyze_expr_mutability(right);
    234
    0
                }
    235
    0
                ExprKind::Unary { operand, .. } => {
    236
    0
                    self.analyze_expr_mutability(operand);
    237
    0
                }
    238
                // Analyze calls
    239
    0
                ExprKind::Call { func, args } => {
    240
    0
                    self.analyze_expr_mutability(func);
    241
    0
                    for arg in args {
    242
    0
                        self.analyze_expr_mutability(arg);
    243
    0
                    }
    244
                }
    245
    0
                ExprKind::MethodCall { receiver, args, .. } => {
    246
    0
                    self.analyze_expr_mutability(receiver);
    247
    0
                    for arg in args {
    248
    0
                        self.analyze_expr_mutability(arg);
    249
    0
                    }
    250
                }
    251
    0
                _ => {}
    252
            }
    253
    0
        }
    254
    255
        /// Resolves file imports in the AST using `ModuleResolver`
    256
        #[allow(dead_code)]
    257
    0
        fn resolve_imports(&self, expr: &Expr) -> Result<Expr> {
    258
            // For now, just use default search paths since we don't have file context here
    259
    0
            let mut resolver = ModuleResolver::new();
    260
    0
            resolver.resolve_imports(expr.clone())
    261
    0
        }
    262
    263
        /// Resolves file imports with a specific file context for search paths
    264
    0
        fn resolve_imports_with_context(&self, expr: &Expr, file_path: Option<&std::path::Path>) -> Result<Expr> {
    265
    0
            let mut resolver = ModuleResolver::new();
    266
    267
            // Add the file's directory to search paths if provided
    268
    0
            if let Some(path) = file_path {
    269
    0
                if let Some(dir) = path.parent() {
    270
    0
                    resolver.add_search_path(dir);
    271
    0
                }
    272
    0
            }
    273
    274
    0
            resolver.resolve_imports(expr.clone())
    275
    0
        }
    276
    277
        /// Transpiles an expression to a `TokenStream`
    278
        ///
    279
        /// # Examples
    280
        ///
    281
        /// ```
    282
        /// use ruchy::{Transpiler, Parser};
    283
        ///
    284
        /// let mut parser = Parser::new("42");
    285
        /// let ast = parser.parse().unwrap();
    286
        ///
    287
        /// let transpiler = Transpiler::new();
    288
        /// let result = transpiler.transpile(&ast);
    289
        /// assert!(result.is_ok());
    290
        /// ```
    291
        ///
    292
        /// # Errors
    293
        ///
    294
        /// Returns an error if the AST cannot be transpiled to valid Rust code.
    295
    0
        pub fn transpile(&self, expr: &Expr) -> Result<TokenStream> {
    296
    0
            self.transpile_expr(expr)
    297
    0
        }
    298
    299
        /// Check if AST contains `HashMap` operations requiring `std::collections::HashMap` import
    300
    0
        fn contains_hashmap(expr: &Expr) -> bool {
    301
            use crate::frontend::ast::{ExprKind, Literal};
    302
    303
    0
            match &expr.kind {
    304
    0
                ExprKind::ObjectLiteral { .. } => true,
    305
    0
                ExprKind::Call { func, .. } => {
    306
                    // Check for HashMap methods like .get(), .insert(), etc.
    307
    0
                    if let ExprKind::FieldAccess { field, .. } = &func.kind {
    308
    0
                        matches!(field.as_str(), "get" | "insert" | "remove" | "contains_key" | "keys" | "values")
    309
                    } else {
    310
    0
                        false
    311
                    }
    312
                }
    313
    0
                ExprKind::IndexAccess { object: _, index } => {
    314
                    // String literal index access suggests HashMap
    315
    0
                    matches!(&index.kind, ExprKind::Literal(Literal::String(_)))
    316
                }
    317
    0
                ExprKind::Block(exprs) => exprs.iter().any(Self::contains_hashmap),
    318
    0
                ExprKind::Function { body, .. } => Self::contains_hashmap(body),
    319
    0
                ExprKind::If { condition, then_branch, else_branch } => {
    320
    0
                    Self::contains_hashmap(condition) ||
    321
    0
                    Self::contains_hashmap(then_branch) ||
    322
    0
                    else_branch.as_ref().is_some_and(|e| Self::contains_hashmap(e))
    323
                }
    324
    0
                ExprKind::Binary { left, right, .. } => {
    325
    0
                    Self::contains_hashmap(left) || Self::contains_hashmap(right)
    326
                }
    327
    0
                _ => false,
    328
            }
    329
    0
        }
    330
    331
        /// Checks if an expression contains `DataFrame` operations (simplified for complexity)
    332
    0
        fn contains_dataframe(expr: &Expr) -> bool {
    333
    0
            matches!(
    334
    0
                expr.kind,
    335
                ExprKind::DataFrame { .. } | ExprKind::DataFrameOperation { .. }
    336
            )
    337
    0
        }
    338
    339
        /// Wraps transpiled code in a complete Rust program with necessary imports
    340
        ///
    341
        /// # Examples
    342
        ///
    343
        /// ```
    344
        /// use ruchy::{Transpiler, Parser};
    345
        ///
    346
        /// let mut parser = Parser::new("42");
    347
        /// let ast = parser.parse().unwrap();
    348
        ///
    349
        /// let transpiler = Transpiler::new();
    350
        /// let result = transpiler.transpile_to_program(&ast);
    351
        /// assert!(result.is_ok());
    352
        ///
    353
        /// let code = result.unwrap().to_string();
    354
        /// assert!(code.contains("fn main"));
    355
        /// assert!(code.contains("42"));
    356
        /// ```
    357
        ///
    358
        /// # Errors
    359
        ///
    360
        /// Returns an error if the AST cannot be transpiled to a valid Rust program.
    361
    0
        pub fn transpile_to_program(&mut self, expr: &Expr) -> Result<TokenStream> {
    362
            // First analyze the entire program to detect mutable variables and function signatures
    363
    0
            if let ExprKind::Block(exprs) = &expr.kind {
    364
    0
                self.analyze_mutability(exprs);
    365
    0
                self.collect_function_signatures(exprs);
    366
    0
            } else {
    367
    0
                self.analyze_expr_mutability(expr);
    368
    0
                self.collect_signatures_from_expr(expr);
    369
    0
            }
    370
    371
    0
            let result = self.transpile_to_program_with_context(expr, None);
    372
    0
            if let Ok(ref token_stream) = result {
    373
    0
                // Debug: Write the generated Rust code to a debug file
    374
    0
                let rust_code = token_stream.to_string();
    375
    0
                std::fs::write("/tmp/debug_transpiler_output.rs", &rust_code).ok();
    376
    0
            }
    377
    0
            result
    378
    0
        }
    379
    380
        /// Transpile with file context for module resolution
    381
    0
        pub fn transpile_to_program_with_context(&self, expr: &Expr, file_path: Option<&std::path::Path>) -> Result<TokenStream> {
    382
            // First, resolve any file imports using the module resolver
    383
    0
            let resolved_expr = self.resolve_imports_with_context(expr, file_path)?;
    384
    0
            let needs_polars = Self::contains_dataframe(&resolved_expr);
    385
    0
            let needs_hashmap = Self::contains_hashmap(&resolved_expr);
    386
    387
    0
            match &resolved_expr.kind {
    388
    0
                ExprKind::Function { name, .. } => {
    389
    0
                    self.transpile_single_function(&resolved_expr, name, needs_polars, needs_hashmap)
    390
                }
    391
    0
                ExprKind::Block(exprs) => {
    392
    0
                    self.transpile_program_block(exprs, needs_polars, needs_hashmap)
    393
                }
    394
                _ => {
    395
    0
                    self.transpile_expression_program(&resolved_expr, needs_polars, needs_hashmap)
    396
                }
    397
            }
    398
    0
        }
    399
    400
    0
        fn transpile_single_function(&self, expr: &Expr, name: &str, needs_polars: bool, needs_hashmap: bool) -> Result<TokenStream> {
    401
            // Use the proper function expression transpiler to handle attributes correctly
    402
    0
            let func = match &expr.kind {
    403
    0
                crate::frontend::ast::ExprKind::Function { .. } => self.transpile_function_expr(expr)?,
    404
    0
                _ => self.transpile_expr(expr)?,
    405
            };
    406
    0
            let needs_main = name != "main";
    407
    408
    0
            match (needs_polars, needs_hashmap, needs_main) {
    409
    0
                (true, true, true) => Ok(quote! {
    410
    0
                    use polars::prelude::*;
    411
    0
                    use std::collections::HashMap;
    412
    0
                    #func
    413
    0
                    fn main() { /* Function defined but not called */ }
    414
    0
                }),
    415
    0
                (true, true, false) => Ok(quote! {
    416
    0
                    use polars::prelude::*;
    417
    0
                    use std::collections::HashMap;
    418
    0
                    #func
    419
    0
                }),
    420
    0
                (true, false, true) => Ok(quote! {
    421
    0
                    use polars::prelude::*;
    422
    0
                    #func
    423
    0
                    fn main() { /* Function defined but not called */ }
    424
    0
                }),
    425
    0
                (true, false, false) => Ok(quote! {
    426
    0
                    use polars::prelude::*;
    427
    0
                    #func
    428
    0
                }),
    429
    0
                (false, true, true) => Ok(quote! {
    430
    0
                    use std::collections::HashMap;
    431
    0
                    #func
    432
    0
                    fn main() { /* Function defined but not called */ }
    433
    0
                }),
    434
    0
                (false, true, false) => Ok(quote! {
    435
    0
                    use std::collections::HashMap;
    436
    0
                    #func
    437
    0
                }),
    438
    0
                (false, false, true) => Ok(quote! {
    439
    0
                    #func
    440
    0
                    fn main() { /* Function defined but not called */ }
    441
    0
                }),
    442
    0
                (false, false, false) => Ok(quote! {
    443
    0
                    #func
    444
    0
                })
    445
            }
    446
    0
        }
    447
    448
    0
        fn transpile_program_block(&self, exprs: &[Expr], needs_polars: bool, needs_hashmap: bool) -> Result<TokenStream> {
    449
    0
            let (functions, statements, modules, has_main, main_expr) = self.categorize_block_expressions(exprs)?;
    450
    451
    0
            if functions.is_empty() && !has_main && modules.is_empty() {
    452
    0
                self.transpile_statement_only_block(exprs, needs_polars, needs_hashmap)
    453
    0
            } else if has_main || !modules.is_empty() {
    454
    0
                self.transpile_block_with_main_function(&functions, &statements, &modules, main_expr, needs_polars, needs_hashmap)
    455
            } else {
    456
    0
                self.transpile_block_with_functions(&functions, &statements, needs_polars, needs_hashmap)
    457
            }
    458
    0
        }
    459
    460
    0
        fn categorize_block_expressions<'a>(&self, exprs: &'a [Expr]) -> Result<BlockCategorization<'a>> {
    461
    0
            let mut functions = Vec::new();
    462
    0
            let mut statements = Vec::new();
    463
    0
            let mut modules = Vec::new();
    464
    0
            let mut has_main_function = false;
    465
    0
            let mut main_function_expr = None;
    466
    467
    468
    0
            for expr in exprs {
    469
    0
                match &expr.kind {
    470
    0
                    ExprKind::Function { name, .. } => {
    471
    0
                        if name == "main" {
    472
    0
                            has_main_function = true;
    473
    0
                            main_function_expr = Some(expr);
    474
    0
                        } else {
    475
                            // Use proper function transpiler to handle attributes correctly
    476
    0
                            functions.push(self.transpile_function_expr(expr)?);
    477
                        }
    478
                    },
    479
    0
                    ExprKind::Module { name, body } => {
    480
                        // Extract module declarations for top-level placement
    481
    0
                        modules.push(self.transpile_module_declaration(name, body)?);
    482
                    },
    483
    0
                    ExprKind::Block(block_exprs) => {
    484
                        // Check if this is a module-containing block from the resolver
    485
    0
                        if block_exprs.len() == 2
    486
    0
                            && matches!(block_exprs[0].kind, ExprKind::Module { .. })
    487
    0
                            && matches!(block_exprs[1].kind, ExprKind::Import { .. }) {
    488
                            // This is a module resolver block: extract the module and keep the import as statement
    489
    0
                            if let ExprKind::Module { name, body } = &block_exprs[0].kind {
    490
    0
                                modules.push(self.transpile_module_declaration(name, body)?);
    491
    0
                            }
    492
    0
                            statements.push(self.transpile_expr(&block_exprs[1])?);
    493
                        } else {
    494
                            // Regular block, treat as statement
    495
    0
                            statements.push(self.transpile_expr(expr)?);
    496
                        }
    497
                    },
    498
                    _ => {
    499
    0
                        let stmt = self.transpile_expr(expr)?;
    500
                        // Ensure statements have semicolons for proper separation
    501
    0
                        let stmt_str = stmt.to_string();
    502
    0
                        if !stmt_str.trim().ends_with(';') && !stmt_str.trim().ends_with('}') {
    503
    0
                            statements.push(quote! { #stmt; });
    504
    0
                        } else {
    505
    0
                            statements.push(stmt);
    506
    0
                        }
    507
                    }
    508
                }
    509
            }
    510
    511
    0
            Ok((functions, statements, modules, has_main_function, main_function_expr))
    512
    0
        }
    513
    514
    0
        fn transpile_module_declaration(&self, name: &str, body: &Expr) -> Result<TokenStream> {
    515
    0
            let module_name = format_ident!("{}", name);
    516
    517
            // Handle module body - if it's a block, transpile its contents as module items
    518
    0
            let body_tokens = if let ExprKind::Block(exprs) = &body.kind {
    519
                // Separate functions from other items in the module
    520
    0
                let mut module_items = Vec::new();
    521
    522
    0
                for expr in exprs {
    523
    0
                    match &expr.kind {
    524
                        ExprKind::Function { .. } => {
    525
                            // Transpile functions as module items
    526
    0
                            module_items.push(self.transpile_function_expr(expr)?);
    527
                        }
    528
                        _ => {
    529
                            // Other items (constants, etc.)
    530
    0
                            module_items.push(self.transpile_expr(expr)?);
    531
                        }
    532
                    }
    533
                }
    534
    535
    0
                quote! { #(#module_items)* }
    536
            } else {
    537
                // Single expression - transpile normally
    538
    0
                self.transpile_expr(body)?
    539
            };
    540
    541
    0
            Ok(quote! {
    542
    0
                mod #module_name {
    543
    0
                    #body_tokens
    544
    0
                }
    545
    0
            })
    546
    0
        }
    547
    548
    0
        fn transpile_statement_only_block(&self, exprs: &[Expr], needs_polars: bool, needs_hashmap: bool) -> Result<TokenStream> {
    549
            // Check if this is a statement sequence (contains let, assignments, etc.) or an expression sequence
    550
    0
            let has_statements = exprs.iter().any(|expr| self.is_statement_expr(expr));
    551
    552
    0
            if has_statements {
    553
                // Split into statements and possible final expression
    554
    0
                let (statements, final_expr) = if !exprs.is_empty() && !self.is_statement_expr(exprs.last().unwrap()) {
    555
                    // Last item is an expression, not a statement
    556
    0
                    (&exprs[..exprs.len() - 1], Some(exprs.last().unwrap()))
    557
                } else {
    558
                    // All are statements
    559
    0
                    (exprs, None)
    560
                };
    561
    562
                // Transpile all statements and add semicolons intelligently
    563
    0
                let statement_results: Result<Vec<_>> = statements.iter().map(|expr| {
    564
    0
                    let tokens = self.transpile_expr(expr)?;
    565
    0
                    let tokens_str = tokens.to_string();
    566
                    // If the statement already ends with a semicolon, don't add another
    567
    0
                    if tokens_str.trim().ends_with(';') {
    568
    0
                        Ok(tokens)
    569
                    } else {
    570
                        // Add semicolon for statements that need them
    571
    0
                        Ok(quote! { #tokens; })
    572
                    }
    573
    0
                }).collect();
    574
    0
                let statement_tokens = statement_results?;
    575
    576
                // Handle final expression if present
    577
    0
                let main_body = if let Some(final_expr) = final_expr {
    578
    0
                    let final_tokens = self.transpile_expr(final_expr)?;
    579
    0
                    let result_printing_logic = self.generate_result_printing_tokens();
    580
    0
                    quote! {
    581
                        #(#statement_tokens)*
    582
                        let result = #final_tokens;
    583
                        #result_printing_logic
    584
                    }
    585
                } else {
    586
    0
                    quote! {
    587
                        #(#statement_tokens)*
    588
                    }
    589
                };
    590
    591
    0
                match (needs_polars, needs_hashmap) {
    592
    0
                    (true, true) => Ok(quote! {
    593
    0
                        use polars::prelude::*;
    594
    0
                        use std::collections::HashMap;
    595
    0
                        fn main() {
    596
    0
                            #main_body
    597
    0
                        }
    598
    0
                    }),
    599
    0
                    (true, false) => Ok(quote! {
    600
    0
                        use polars::prelude::*;
    601
    0
                        fn main() {
    602
    0
                            #main_body
    603
    0
                        }
    604
    0
                    }),
    605
    0
                    (false, true) => Ok(quote! {
    606
    0
                        use std::collections::HashMap;
    607
    0
                        fn main() {
    608
    0
                            #main_body
    609
    0
                        }
    610
    0
                    }),
    611
    0
                    (false, false) => Ok(quote! {
    612
    0
                        fn main() {
    613
    0
                            #main_body
    614
    0
                        }
    615
    0
                    })
    616
                }
    617
            } else {
    618
                // Pure expression sequence - use existing result printing approach
    619
    0
                let block_expr = Expr::new(ExprKind::Block(exprs.to_vec()), Span::new(0, 0));
    620
    0
                let body = self.transpile_expr(&block_expr)?;
    621
    0
                self.wrap_in_main_with_result_printing(body, needs_polars, needs_hashmap)
    622
            }
    623
    0
        }
    624
    625
    0
        fn is_statement_expr(&self, expr: &Expr) -> bool {
    626
    0
            match &expr.kind {
    627
                // Let bindings are statements
    628
    0
                ExprKind::Let { .. } | ExprKind::LetPattern { .. } => true,
    629
                // Assignment operations are statements
    630
    0
                ExprKind::Assign { .. } | ExprKind::CompoundAssign { .. } => true,
    631
                // Loops are statements (void/unit type)
    632
    0
                ExprKind::While { .. } | ExprKind::For { .. } | ExprKind::Loop { .. } => true,
    633
                // Function calls that don't return meaningful values (like println)
    634
    0
                ExprKind::Call { func, .. } => {
    635
    0
                    if let ExprKind::Identifier(name) = &func.kind {
    636
    0
                        matches!(name.as_str(), "println" | "print" | "dbg")
    637
                    } else {
    638
    0
                        false
    639
                    }
    640
                }
    641
                // Blocks containing statements
    642
    0
                ExprKind::Block(exprs) => exprs.iter().any(|e| self.is_statement_expr(e)),
    643
                // Most other expressions are not statements
    644
    0
                _ => false,
    645
            }
    646
    0
        }
    647
    648
    0
        fn transpile_block_with_main_function(&self, functions: &[TokenStream], statements: &[TokenStream], modules: &[TokenStream], main_expr: Option<&Expr>, needs_polars: bool, needs_hashmap: bool) -> Result<TokenStream> {
    649
    0
            if statements.is_empty() && main_expr.is_some() {
    650
                // Only functions, just emit them normally (includes user's main)
    651
    0
                let main_tokens = if let Some(main) = main_expr {
    652
    0
                    self.transpile_expr(main)?
    653
                } else {
    654
    0
                    return Err(anyhow::anyhow!("Expected main function expression"));
    655
                };
    656
    657
    0
                match (needs_polars, needs_hashmap) {
    658
    0
                    (true, true) => Ok(quote! {
    659
                        use polars::prelude::*;
    660
                        use std::collections::HashMap;
    661
                        #(#modules)*
    662
                        #(#functions)*
    663
                        #main_tokens
    664
                    }),
    665
    0
                    (true, false) => Ok(quote! {
    666
                        use polars::prelude::*;
    667
                        #(#modules)*
    668
                        #(#functions)*
    669
                        #main_tokens
    670
                    }),
    671
    0
                    (false, true) => Ok(quote! {
    672
                        use std::collections::HashMap;
    673
                        #(#modules)*
    674
                        #(#functions)*
    675
                        #main_tokens
    676
                    }),
    677
    0
                    (false, false) => Ok(quote! {
    678
                        #(#modules)*
    679
                        #(#functions)*
    680
                        #main_tokens
    681
                    })
    682
                }
    683
            } else {
    684
                // TOP-LEVEL STATEMENTS: Extract main body and combine with statements
    685
    0
                let main_body = if let Some(main) = main_expr {
    686
    0
                    self.extract_main_function_body(main)?
    687
                } else {
    688
                    // No user main function, just use empty body
    689
    0
                    quote! {}
    690
                };
    691
    692
    0
                match (needs_polars, needs_hashmap) {
    693
    0
                    (true, true) => Ok(quote! {
    694
                        use polars::prelude::*;
    695
                        use std::collections::HashMap;
    696
                        #(#modules)*
    697
                        #(#functions)*
    698
                        fn main() {
    699
                            // Top-level statements execute first
    700
                            #(#statements)*
    701
    702
                            // Then user's main function body
    703
                            #main_body
    704
                        }
    705
                    }),
    706
    0
                    (true, false) => Ok(quote! {
    707
                        use polars::prelude::*;
    708
                        #(#modules)*
    709
                        #(#functions)*
    710
                        fn main() {
    711
                            // Top-level statements execute first
    712
                            #(#statements)*
    713
    714
                            // Then user's main function body
    715
                            #main_body
    716
                        }
    717
                    }),
    718
    0
                    (false, true) => Ok(quote! {
    719
                        use std::collections::HashMap;
    720
                        #(#modules)*
    721
                        #(#functions)*
    722
                        fn main() {
    723
                            // Top-level statements execute first
    724
                            #(#statements)*
    725
    726
                            // Then user's main function body
    727
                            #main_body
    728
                        }
    729
                    }),
    730
    0
                    (false, false) => Ok(quote! {
    731
                        #(#modules)*
    732
                        #(#functions)*
    733
                        fn main() {
    734
                            // Top-level statements execute first
    735
                            #(#statements)*
    736
    737
                            // Then user's main function body
    738
                            #main_body
    739
                        }
    740
                    })
    741
                }
    742
            }
    743
    0
        }
    744
    745
        /// Extracts the body of a main function for inlining with top-level statements
    746
    0
        fn extract_main_function_body(&self, main_expr: &Expr) -> Result<TokenStream> {
    747
    0
            if let ExprKind::Function { body, .. } = &main_expr.kind {
    748
                // Transpile just the body, not the entire function definition
    749
    0
                self.transpile_expr(body)
    750
            } else {
    751
    0
                Err(anyhow::anyhow!("Expected function expression for main body extraction"))
    752
            }
    753
    0
        }
    754
    755
    0
        fn transpile_block_with_functions(&self, functions: &[TokenStream], statements: &[TokenStream], needs_polars: bool, needs_hashmap: bool) -> Result<TokenStream> {
    756
            // No main function among extracted functions - create one for statements
    757
    0
            match (needs_polars, needs_hashmap) {
    758
    0
                (true, true) => Ok(quote! {
    759
                    use polars::prelude::*;
    760
                    use std::collections::HashMap;
    761
                    #(#functions)*
    762
                    fn main() { #(#statements)* }
    763
                }),
    764
    0
                (true, false) => Ok(quote! {
    765
                    use polars::prelude::*;
    766
                    #(#functions)*
    767
                    fn main() { #(#statements)* }
    768
                }),
    769
    0
                (false, true) => Ok(quote! {
    770
                    use std::collections::HashMap;
    771
                    #(#functions)*
    772
                    fn main() { #(#statements)* }
    773
                }),
    774
    0
                (false, false) => Ok(quote! {
    775
                    #(#functions)*
    776
                    fn main() { #(#statements)* }
    777
                })
    778
            }
    779
    0
        }
    780
    781
    782
    0
        fn transpile_expression_program(&self, expr: &Expr, needs_polars: bool, needs_hashmap: bool) -> Result<TokenStream> {
    783
    0
            let body = self.transpile_expr(expr)?;
    784
    785
            // Check if this is a statement vs expression
    786
    0
            if self.is_statement_expr(expr) {
    787
                // For statements, execute directly without result wrapping
    788
    0
                self.wrap_statement_in_main(body, needs_polars, needs_hashmap)
    789
            } else {
    790
                // For expressions, wrap with result printing
    791
    0
                self.wrap_in_main_with_result_printing(body, needs_polars, needs_hashmap)
    792
            }
    793
    0
        }
    794
    795
    0
        fn wrap_statement_in_main(&self, body: TokenStream, needs_polars: bool, needs_hashmap: bool) -> Result<TokenStream> {
    796
            // For statements, execute directly without result capture
    797
    0
            match (needs_polars, needs_hashmap) {
    798
    0
                (true, true) => Ok(quote! {
    799
    0
                    use polars::prelude::*;
    800
    0
                    use std::collections::HashMap;
    801
    0
                    fn main() {
    802
    0
                        #body;
    803
    0
                    }
    804
    0
                }),
    805
    0
                (true, false) => Ok(quote! {
    806
    0
                    use polars::prelude::*;
    807
    0
                    fn main() {
    808
    0
                        #body;
    809
    0
                    }
    810
    0
                }),
    811
    0
                (false, true) => Ok(quote! {
    812
    0
                    use std::collections::HashMap;
    813
    0
                    fn main() {
    814
    0
                        #body;
    815
    0
                    }
    816
    0
                }),
    817
    0
                (false, false) => Ok(quote! {
    818
    0
                    fn main() {
    819
    0
                        #body;
    820
    0
                    }
    821
    0
                })
    822
            }
    823
    0
        }
    824
    825
    0
        fn wrap_in_main_with_result_printing(&self, body: TokenStream, needs_polars: bool, needs_hashmap: bool) -> Result<TokenStream> {
    826
    0
            let result_printing_logic = self.generate_result_printing_tokens();
    827
    0
            match (needs_polars, needs_hashmap) {
    828
    0
                (true, true) => Ok(quote! {
    829
    0
                    use polars::prelude::*;
    830
    0
                    use std::collections::HashMap;
    831
    0
                    fn main() {
    832
    0
                        let result = #body;
    833
    0
                        #result_printing_logic
    834
    0
                    }
    835
    0
                }),
    836
    0
                (true, false) => Ok(quote! {
    837
    0
                    use polars::prelude::*;
    838
    0
                    fn main() {
    839
    0
                        let result = #body;
    840
    0
                        #result_printing_logic
    841
    0
                    }
    842
    0
                }),
    843
                (false, true) => {
    844
    0
                    Ok(quote! {
    845
    0
                        use std::collections::HashMap;
    846
    0
                        fn main() {
    847
    0
                            let result = #body;
    848
    0
                            #result_printing_logic
    849
    0
                        }
    850
    0
                    })
    851
                },
    852
                (false, false) => {
    853
    0
                    Ok(quote! {
    854
    0
                        fn main() {
    855
    0
                            let result = #body;
    856
    0
                            #result_printing_logic
    857
    0
                        }
    858
    0
                    })
    859
                }
    860
            }
    861
    0
        }
    862
    863
        /// Transpiles an expression to a String
    864
    0
        pub fn transpile_to_string(&self, expr: &Expr) -> Result<String> {
    865
    0
            let tokens = self.transpile(expr)?;
    866
    867
            // Format the tokens with rustfmt-like style
    868
    0
            let mut result = String::new();
    869
    0
            let token_str = tokens.to_string();
    870
    871
            // Basic formatting: add newlines after semicolons and braces
    872
    0
            for ch in token_str.chars() {
    873
    0
                result.push(ch);
    874
    0
                if ch == ';' || ch == '{' {
    875
    0
                    result.push('\n');
    876
    0
                }
    877
            }
    878
    879
    0
            Ok(result)
    880
    0
        }
    881
    882
        /// Generate minimal code for self-hosting (direct Rust mapping, no optimization)
    883
    0
        pub fn transpile_minimal(&self, expr: &Expr) -> Result<String> {
    884
    0
            codegen_minimal::MinimalCodeGen::gen_program(expr)
    885
    0
        }
    886
    887
        /// Check if a name is a Rust reserved keyword
    888
    0
        pub(crate) fn is_rust_reserved_keyword(name: &str) -> bool {
    889
            // List of Rust reserved keywords that would conflict
    890
    0
            matches!(name,
    891
    0
                "as" | "break" | "const" | "continue" | "crate" | "else" | "enum" | "extern" |
    892
    0
                "false" | "fn" | "for" | "if" | "impl" | "in" | "let" | "loop" | "match" |
    893
    0
                "mod" | "move" | "mut" | "pub" | "ref" | "return" | "self" | "Self" |
    894
    0
                "static" | "struct" | "super" | "trait" | "true" | "type" | "unsafe" |
    895
    0
                "use" | "where" | "while" | "async" | "await" | "dyn" | "final" | "try" |
    896
    0
                "abstract" | "become" | "box" | "do" | "override" | "priv" | "typeof" |
    897
    0
                "unsized" | "virtual" | "yield"
    898
            )
    899
    0
        }
    900
    901
        /// Main expression transpilation dispatcher
    902
        ///
    903
        /// # Panics
    904
        ///
    905
        /// Panics if label names cannot be parsed as valid Rust tokens
    906
    0
        pub fn transpile_expr(&self, expr: &Expr) -> Result<TokenStream> {
    907
            use ExprKind::{
    908
                Actor, ActorQuery, ActorSend, Ask, Assign, AsyncBlock, Await, Binary, Call, Command, CompoundAssign, DataFrame,
    909
                DataFrameOperation, Err, FieldAccess, For, Function, Identifier, If, IfLet, IndexAccess, Lambda,
    910
                List, ListComprehension, Literal, Loop, Macro, Match, MethodCall, None, ObjectLiteral, Ok, QualifiedName,
    911
                Range, Send, Slice, Some, StringInterpolation, Struct, StructLiteral, Throw, Try, TryCatch, TypeCast,
    912
                Tuple, Unary, While, WhileLet,
    913
            };
    914
    915
            // Dispatch to specialized handlers to keep complexity below 10
    916
    0
            match &expr.kind {
    917
                // Basic expressions
    918
                Literal(_) | Identifier(_) | QualifiedName { .. } | StringInterpolation { .. } | TypeCast { .. } => {
    919
    0
                    self.transpile_basic_expr(expr)
    920
                }
    921
    922
                // Operators and control flow
    923
                Binary { .. }
    924
                | Unary { .. }
    925
                | Assign { .. }
    926
                | CompoundAssign { .. }
    927
                | Await { .. }
    928
                | AsyncBlock { .. }
    929
                | If { .. }
    930
                | IfLet { .. }
    931
                | Match { .. }
    932
                | For { .. }
    933
                | While { .. }
    934
                | WhileLet { .. }
    935
                | Loop { .. }
    936
    0
                | TryCatch { .. } => self.transpile_operator_control_expr(expr),
    937
    938
                // Functions
    939
                Function { .. } | Lambda { .. } | Call { .. } | MethodCall { .. } | Macro { .. } => {
    940
    0
                    self.transpile_function_expr(expr)
    941
                }
    942
    943
                // Structures
    944
                Struct { .. } | StructLiteral { .. } | ObjectLiteral { .. } | FieldAccess { .. }
    945
                | IndexAccess { .. } | Slice { .. } => {
    946
    0
                    self.transpile_struct_expr(expr)
    947
                }
    948
    949
                // Data and error handling
    950
                DataFrame { .. }
    951
                | DataFrameOperation { .. }
    952
                | List(_)
    953
                | Tuple(_)
    954
                | ListComprehension { .. }
    955
                | Range { .. }
    956
                | Throw { .. }
    957
                | Ok { .. }
    958
                | Err { .. }
    959
                | Some { .. }
    960
                | None
    961
    0
                | Try { .. } => self.transpile_data_error_expr(expr),
    962
    963
                // Actor system and process execution
    964
    0
                Actor { .. } | Send { .. } | Ask { .. } | ActorSend { .. } | ActorQuery { .. } | Command { .. } => self.transpile_actor_expr(expr),
    965
    966
                // Everything else
    967
    0
                _ => self.transpile_misc_expr(expr),
    968
            }
    969
    0
        }
    970
    }