## 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/middleend/infer.rs

    Line
    Count
    Source
    1
    //! Type inference engine using Algorithm W
    2
    3
    use crate::frontend::ast::{BinaryOp, Expr, ExprKind, Literal, Param, Pattern, TypeKind, UnaryOp};
    4
    use crate::middleend::environment::TypeEnv;
    5
    use crate::middleend::types::{MonoType, TyVar, TyVarGenerator, TypeScheme};
    6
    use crate::middleend::unify::Unifier;
    7
    use anyhow::{bail, Result};
    8
    9
    /// Type inference context with enhanced constraint solving
    10
    pub struct InferenceContext {
    11
        /// Type variable generator
    12
        gen: TyVarGenerator,
    13
        /// Unification engine
    14
        unifier: Unifier,
    15
        /// Type environment
    16
        env: TypeEnv,
    17
        /// Deferred constraints for later resolution
    18
        constraints: Vec<(TyVar, TyVar)>,
    19
        /// Enhanced constraint queue for complex type relationships
    20
        type_constraints: Vec<TypeConstraint>,
    21
        /// Recursion depth tracker for safety
    22
        recursion_depth: usize,
    23
    }
    24
    25
    /// Enhanced constraint types for self-hosting compiler patterns
    26
    #[derive(Debug, Clone)]
    27
    pub enum TypeConstraint {
    28
        /// Two types must unify
    29
        Unify(MonoType, MonoType),
    30
        /// Type must be a function with specific arity
    31
        FunctionArity(MonoType, usize),
    32
        /// Type must support method call
    33
        MethodCall(MonoType, String, Vec<MonoType>),
    34
        /// Type must be iterable
    35
        Iterable(MonoType, MonoType),
    36
    }
    37
    38
    impl InferenceContext {
    39
        #[must_use]
    40
    0
        pub fn new() -> Self {
    41
    0
            InferenceContext {
    42
    0
                gen: TyVarGenerator::new(),
    43
    0
                unifier: Unifier::new(),
    44
    0
                env: TypeEnv::standard(),
    45
    0
                constraints: Vec::new(),
    46
    0
                type_constraints: Vec::new(),
    47
    0
                recursion_depth: 0,
    48
    0
            }
    49
    0
        }
    50
    51
        #[must_use]
    52
    0
        pub fn with_env(env: TypeEnv) -> Self {
    53
    0
            InferenceContext {
    54
    0
                gen: TyVarGenerator::new(),
    55
    0
                unifier: Unifier::new(),
    56
    0
                env,
    57
    0
                constraints: Vec::new(),
    58
    0
                type_constraints: Vec::new(),
    59
    0
                recursion_depth: 0,
    60
    0
            }
    61
    0
        }
    62
    63
        /// Infer the type of an expression with enhanced constraint solving
    64
        ///
    65
        /// # Errors
    66
        ///
    67
        /// Returns an error if type inference fails (type error, undefined variable, etc.)
    68
    0
        pub fn infer(&mut self, expr: &Expr) -> Result<MonoType> {
    69
            // Check recursion depth to prevent infinite loops
    70
    0
            if self.recursion_depth > 100 {
    71
    0
                bail!("Type inference recursion limit exceeded");
    72
    0
            }
    73
    74
    0
            self.recursion_depth += 1;
    75
    0
            let result = self.infer_expr(expr);
    76
    0
            self.recursion_depth -= 1;
    77
    78
    0
            let inferred_type = result?;
    79
    80
            // Solve all accumulated constraints
    81
    0
            self.solve_all_constraints()?;
    82
    83
            // Apply final substitutions
    84
    0
            Ok(self.unifier.apply(&inferred_type))
    85
    0
        }
    86
    87
        /// Solve all accumulated constraints (enhanced for self-hosting)
    88
    0
        fn solve_all_constraints(&mut self) -> Result<()> {
    89
            // First solve simple variable constraints
    90
    0
            self.solve_constraints();
    91
    92
            // Then solve complex type constraints
    93
    0
            while let Some(constraint) = self.type_constraints.pop() {
    94
    0
                self.solve_type_constraint(constraint)?;
    95
            }
    96
    97
    0
            Ok(())
    98
    0
        }
    99
    100
        /// Solve deferred constraints
    101
    0
        fn solve_constraints(&mut self) {
    102
    0
            while let Some((a, b)) = self.constraints.pop() {
    103
    0
                // Convert TyVar to MonoType for unification
    104
    0
                let ty_a = MonoType::Var(a);
    105
    0
                let ty_b = MonoType::Var(b);
    106
    0
                // Ignore failures for now - this is a simplified implementation
    107
    0
                let _ = self.unifier.unify(&ty_a, &ty_b);
    108
    0
            }
    109
    0
        }
    110
    111
        /// Solve complex type constraints for advanced patterns
    112
    0
        fn solve_type_constraint(&mut self, constraint: TypeConstraint) -> Result<()> {
    113
    0
            match constraint {
    114
    0
                TypeConstraint::Unify(t1, t2) => {
    115
    0
                    self.unifier.unify(&t1, &t2)?;
    116
                }
    117
    0
                TypeConstraint::FunctionArity(func_ty, expected_arity) => {
    118
                    // Verify function has correct number of parameters
    119
    0
                    let mut current_ty = &func_ty;
    120
    0
                    let mut arity = 0;
    121
    122
    0
                    while let MonoType::Function(_, ret) = current_ty {
    123
    0
                        arity += 1;
    124
    0
                        current_ty = ret;
    125
    0
                    }
    126
    127
    0
                    if arity != expected_arity {
    128
    0
                        bail!(
    129
    0
                            "Function arity mismatch: expected {}, found {}",
    130
                            expected_arity,
    131
                            arity
    132
                        );
    133
    0
                    }
    134
                }
    135
    0
                TypeConstraint::MethodCall(receiver_ty, method_name, arg_types) => {
    136
                    // Verify receiver type supports the method call
    137
    0
                    self.check_method_call_constraint(&receiver_ty, &method_name, &arg_types)?;
    138
                }
    139
    0
                TypeConstraint::Iterable(collection_ty, element_ty) => {
    140
                    // Ensure collection_ty is a valid iterable containing element_ty
    141
    0
                    match collection_ty {
    142
    0
                        MonoType::List(inner) => {
    143
    0
                            self.unifier.unify(&inner, &element_ty)?;
    144
                        }
    145
                        MonoType::String => {
    146
                            // String iterates over characters
    147
    0
                            self.unifier.unify(&element_ty, &MonoType::Char)?;
    148
                        }
    149
    0
                        _ => bail!("Type {} is not iterable", collection_ty),
    150
                    }
    151
                }
    152
            }
    153
    0
            Ok(())
    154
    0
        }
    155
    156
        /// Check method call constraints for compiler patterns
    157
    0
        fn check_method_call_constraint(
    158
    0
            &mut self,
    159
    0
            receiver_ty: &MonoType,
    160
    0
            method_name: &str,
    161
    0
            _arg_types: &[MonoType],
    162
    0
        ) -> Result<()> {
    163
    0
            match (method_name, receiver_ty) {
    164
                // List methods
    165
    0
                ("map" | "filter" | "reduce", MonoType::List(_)) => Ok(()),
    166
    0
                ("len" | "length", MonoType::List(_) | MonoType::String) => Ok(()),
    167
    0
                ("push", MonoType::List(_)) => Ok(()),
    168
    169
                // DataFrame methods
    170
    0
                ("filter" | "groupby" | "agg" | "select" | "col", MonoType::DataFrame(_)) => Ok(()),
    171
    0
                ("filter" | "groupby" | "agg" | "select" | "col", MonoType::Named(name))
    172
    0
                    if name == "DataFrame" => Ok(()),
    173
    174
                // Series methods
    175
    0
                ("mean" | "std" | "sum" | "count", MonoType::Series(_) | MonoType::DataFrame(_)) => Ok(()),
    176
    0
                ("mean" | "std" | "sum" | "count", MonoType::Named(name))
    177
    0
                    if name == "Series" || name == "DataFrame" => Ok(()),
    178
    179
                // HashMap methods (for compiler symbol tables)
    180
    0
                ("insert" | "get" | "contains_key", MonoType::Named(name))
    181
    0
                    if name.starts_with("HashMap") => Ok(()),
    182
    183
                // String methods
    184
    0
                ("chars" | "trim" | "to_upper" | "to_lower", MonoType::String) => Ok(()),
    185
    186
                // For testing purposes, be more permissive with unknown methods
    187
                _ => {
    188
                    // In a production implementation, this would be stricter
    189
                    // For self-hosting development, we allow more flexibility
    190
    0
                    Ok(())
    191
                }
    192
            }
    193
    0
        }
    194
    195
        /// Core type inference dispatcher with complexity <10
    196
        ///
    197
        /// Delegates to specialized handlers for each expression category
    198
        ///
    199
        /// # Example Usage
    200
        /// This method infers types for expressions by delegating to specialized handlers.
    201
        /// For example, literals get their type directly, while function calls check argument types.
    202
    0
        fn infer_expr(&mut self, expr: &Expr) -> Result<MonoType> {
    203
    0
            match &expr.kind {
    204
                // Literals and identifiers
    205
    0
                ExprKind::Literal(lit) => Ok(Self::infer_literal(lit)),
    206
    0
                ExprKind::Identifier(name) => self.infer_identifier(name),
    207
    0
                ExprKind::QualifiedName { module: _, name } => self.infer_identifier(name),
    208
    209
                // Control flow and pattern matching
    210
                ExprKind::If { condition: _, then_branch: _, else_branch: _ } => {
    211
    0
                    self.infer_control_flow_expr(expr)
    212
                }
    213
    0
                ExprKind::Match { expr, arms } => self.infer_match(expr, arms),
    214
                ExprKind::IfLet { .. } | ExprKind::WhileLet { .. } => {
    215
    0
                    self.infer_control_flow_expr(expr)
    216
                }
    217
    218
                // Functions and lambdas
    219
                ExprKind::Function { .. } | ExprKind::Lambda { .. } => {
    220
    0
                    self.infer_function_expr(expr)
    221
                }
    222
    223
                // Collections and data structures
    224
                ExprKind::List(..) | ExprKind::Tuple(..) | ExprKind::ListComprehension { .. } => {
    225
    0
                    self.infer_collection_expr(expr)
    226
                }
    227
    228
                // Operations and method calls
    229
                ExprKind::Binary { .. } | ExprKind::Unary { .. } | ExprKind::Call { .. } | ExprKind::MethodCall { .. } => {
    230
    0
                    self.infer_operation_expr(expr)
    231
                }
    232
    233
                // All other expressions
    234
    0
                _ => self.infer_other_expr(expr),
    235
            }
    236
    0
        }
    237
    238
    0
        fn infer_literal(lit: &Literal) -> MonoType {
    239
    0
            match lit {
    240
    0
                Literal::Integer(_) => MonoType::Int,
    241
    0
                Literal::Float(_) => MonoType::Float,
    242
    0
                Literal::String(_) => MonoType::String,
    243
    0
                Literal::Bool(_) => MonoType::Bool,
    244
    0
                Literal::Char(_) => MonoType::Char,
    245
    0
                Literal::Unit => MonoType::Unit,
    246
            }
    247
    0
        }
    248
    249
    0
        fn infer_identifier(&mut self, name: &str) -> Result<MonoType> {
    250
    0
            match self.env.lookup(name) {
    251
    0
                Some(scheme) => Ok(self.env.instantiate(scheme, &mut self.gen)),
    252
    0
                None => bail!("Undefined variable: {}", name),
    253
            }
    254
    0
        }
    255
    256
    0
        fn infer_binary(&mut self, left: &Expr, op: BinaryOp, right: &Expr) -> Result<MonoType> {
    257
    0
            let left_ty = self.infer_expr(left)?;
    258
    0
            let right_ty = self.infer_expr(right)?;
    259
    260
    0
            match op {
    261
                // Arithmetic operators
    262
                BinaryOp::Add
    263
                | BinaryOp::Subtract
    264
                | BinaryOp::Multiply
    265
                | BinaryOp::Divide
    266
                | BinaryOp::Modulo => {
    267
                    // Both operands must be numeric and same type
    268
    0
                    self.unifier.unify(&left_ty, &right_ty)?;
    269
                    // For now, assume Int (could be Float too)
    270
    0
                    self.unifier.unify(&left_ty, &MonoType::Int)?;
    271
    0
                    Ok(MonoType::Int)
    272
                }
    273
                BinaryOp::Power => {
    274
    0
                    self.unifier.unify(&left_ty, &MonoType::Int)?;
    275
    0
                    self.unifier.unify(&right_ty, &MonoType::Int)?;
    276
    0
                    Ok(MonoType::Int)
    277
                }
    278
                // Comparison operators
    279
                BinaryOp::Equal
    280
                | BinaryOp::NotEqual
    281
                | BinaryOp::Less
    282
                | BinaryOp::LessEqual
    283
                | BinaryOp::Greater
    284
                | BinaryOp::GreaterEqual => {
    285
                    // Operands must have same type
    286
    0
                    self.unifier.unify(&left_ty, &right_ty)?;
    287
    0
                    Ok(MonoType::Bool)
    288
                }
    289
                // Boolean operators
    290
                BinaryOp::And | BinaryOp::Or => {
    291
    0
                    self.unifier.unify(&left_ty, &MonoType::Bool)?;
    292
    0
                    self.unifier.unify(&right_ty, &MonoType::Bool)?;
    293
    0
                    Ok(MonoType::Bool)
    294
                }
    295
                // Null coalescing operator: return type is union of operand types
    296
                BinaryOp::NullCoalesce => {
    297
                    // Type is the union of left and right, but return the more specific non-null type
    298
    0
                    Ok(right_ty) // For now, assume right type (could be improved with union types)
    299
                }
    300
                // Bitwise operators
    301
                BinaryOp::BitwiseAnd
    302
                | BinaryOp::BitwiseOr
    303
                | BinaryOp::BitwiseXor
    304
                | BinaryOp::LeftShift => {
    305
    0
                    self.unifier.unify(&left_ty, &MonoType::Int)?;
    306
    0
                    self.unifier.unify(&right_ty, &MonoType::Int)?;
    307
    0
                    Ok(MonoType::Int)
    308
                }
    309
            }
    310
    0
        }
    311
    312
    0
        fn infer_unary(&mut self, op: UnaryOp, operand: &Expr) -> Result<MonoType> {
    313
    0
            let operand_ty = self.infer_expr(operand)?;
    314
    315
    0
            match op {
    316
                UnaryOp::Not => {
    317
    0
                    self.unifier.unify(&operand_ty, &MonoType::Bool)?;
    318
    0
                    Ok(MonoType::Bool)
    319
                }
    320
                UnaryOp::Negate => {
    321
                    // Can negate Int or Float
    322
    0
                    self.unifier.unify(&operand_ty, &MonoType::Int)?;
    323
    0
                    Ok(MonoType::Int)
    324
                }
    325
                UnaryOp::BitwiseNot => {
    326
    0
                    self.unifier.unify(&operand_ty, &MonoType::Int)?;
    327
    0
                    Ok(MonoType::Int)
    328
                }
    329
                UnaryOp::Reference => {
    330
                    // Reference operator &x: T -> &T
    331
    0
                    Ok(MonoType::Reference(Box::new(operand_ty)))
    332
                }
    333
            }
    334
    0
        }
    335
    336
    337
    0
        fn infer_throw(&mut self, expr: &Expr) -> Result<MonoType> {
    338
            // Infer the type of the expression being thrown
    339
    0
            let _expr_ty = self.infer_expr(expr)?;
    340
    341
            // The expression must implement Error trait
    342
            // For now, we'll just ensure it's a valid type
    343
            // In a more complete implementation, we'd check Error trait bounds
    344
    345
            // The throw expression itself has the Never type (!)
    346
            // But we'll represent it as a generic type for now
    347
    0
            Ok(MonoType::Var(self.gen.fresh()))
    348
    0
        }
    349
    350
    0
        fn infer_await(&mut self, expr: &Expr) -> Result<MonoType> {
    351
            // The expression must be a Future<Output = T>
    352
    0
            let expr_ty = self.infer_expr(expr)?;
    353
    354
            // For now, we'll just return the inner type
    355
            // In a full implementation, we'd check for Future trait
    356
    0
            if let MonoType::Named(name) = &expr_ty {
    357
    0
                if name.starts_with("Future") {
    358
                    // Extract the output type
    359
    0
                    return Ok(MonoType::Var(self.gen.fresh()));
    360
    0
                }
    361
    0
            }
    362
    363
            // For now, just return a fresh type variable
    364
    0
            Ok(MonoType::Var(self.gen.fresh()))
    365
    0
        }
    366
    367
    0
        fn infer_if(
    368
    0
            &mut self,
    369
    0
            condition: &Expr,
    370
    0
            then_branch: &Expr,
    371
    0
            else_branch: Option<&Expr>,
    372
    0
        ) -> Result<MonoType> {
    373
            // Condition must be Bool
    374
    0
            let cond_ty = self.infer_expr(condition)?;
    375
    0
            self.unifier.unify(&cond_ty, &MonoType::Bool)?;
    376
    377
    0
            let then_ty = self.infer_expr(then_branch)?;
    378
    379
    0
            if let Some(else_expr) = else_branch {
    380
    0
                let else_ty = self.infer_expr(else_expr)?;
    381
                // Both branches must have same type
    382
    0
                self.unifier.unify(&then_ty, &else_ty)?;
    383
    0
                Ok(self.unifier.apply(&then_ty))
    384
            } else {
    385
                // No else branch means Unit type
    386
    0
                self.unifier.unify(&then_ty, &MonoType::Unit)?;
    387
    0
                Ok(MonoType::Unit)
    388
            }
    389
    0
        }
    390
    391
    0
        fn infer_let(
    392
    0
            &mut self,
    393
    0
            name: &str,
    394
    0
            value: &Expr,
    395
    0
            body: &Expr,
    396
    0
            _is_mutable: bool,
    397
    0
        ) -> Result<MonoType> {
    398
            // Infer type of value
    399
    0
            let value_ty = self.infer_expr(value)?;
    400
    401
            // Generalize the value type
    402
    0
            let scheme = self.env.generalize(value_ty);
    403
    404
            // Extend environment and infer body
    405
    0
            let old_env = self.env.clone();
    406
    0
            self.env = self.env.extend(name, scheme);
    407
    0
            let body_ty = self.infer_expr(body)?;
    408
    0
            self.env = old_env;
    409
    410
    0
            Ok(body_ty)
    411
    0
        }
    412
    413
    0
        fn infer_function(
    414
    0
            &mut self,
    415
    0
            name: &str,
    416
    0
            params: &[Param],
    417
    0
            body: &Expr,
    418
    0
            _return_type: Option<&crate::frontend::ast::Type>,
    419
    0
            _is_async: bool,
    420
    0
        ) -> Result<MonoType> {
    421
            // Create fresh type variables for parameters
    422
    0
            let mut param_types = Vec::new();
    423
    0
            let old_env = self.env.clone();
    424
    425
    0
            for param in params {
    426
    0
                let param_ty =
    427
    0
                    if param.ty.kind == crate::frontend::ast::TypeKind::Named("Any".to_string()) {
    428
                        // Untyped parameter - create fresh type variable
    429
    0
                        MonoType::Var(self.gen.fresh())
    430
                    } else {
    431
                        // Convert AST type to MonoType
    432
    0
                        Self::ast_type_to_mono_static(&param.ty)?
    433
                    };
    434
    0
                param_types.push(param_ty.clone());
    435
    0
                self.env = self.env.extend(param.name(), TypeScheme::mono(param_ty));
    436
            }
    437
    438
            // Add function itself to environment for recursion
    439
    0
            let result_var = MonoType::Var(self.gen.fresh());
    440
    0
            let func_type = param_types
    441
    0
                .iter()
    442
    0
                .rev()
    443
    0
                .fold(result_var.clone(), |acc, param_ty| {
    444
    0
                    MonoType::Function(Box::new(param_ty.clone()), Box::new(acc))
    445
    0
                });
    446
    0
            self.env = self.env.extend(name, TypeScheme::mono(func_type.clone()));
    447
    448
            // Infer body type
    449
    0
            let body_ty = self.infer_expr(body)?;
    450
    0
            self.unifier.unify(&result_var, &body_ty)?;
    451
    452
    0
            self.env = old_env;
    453
    454
    0
            let final_type = self.unifier.apply(&func_type);
    455
    456
            // Always return the function type for type inference
    457
            // The distinction between statements and expressions should be handled at a higher level
    458
    0
            Ok(final_type)
    459
    0
        }
    460
    461
    0
        fn infer_lambda(&mut self, params: &[Param], body: &Expr) -> Result<MonoType> {
    462
    0
            let old_env = self.env.clone();
    463
    464
            // Create type variables for parameters
    465
    0
            let mut param_types = Vec::new();
    466
    0
            for param in params {
    467
    0
                let param_ty = match &param.ty.kind {
    468
    0
                    TypeKind::Named(name) if name == "Any" || name == "_" => {
    469
                        // Untyped parameter - create fresh type variable
    470
    0
                        MonoType::Var(self.gen.fresh())
    471
                    }
    472
                    _ => {
    473
                        // Convert AST type to MonoType
    474
    0
                        Self::ast_type_to_mono_static(&param.ty)?
    475
                    }
    476
                };
    477
    0
                param_types.push(param_ty.clone());
    478
    0
                self.env = self.env.extend(param.name(), TypeScheme::mono(param_ty));
    479
            }
    480
    481
            // Infer body type
    482
    0
            let body_ty = self.infer_expr(body)?;
    483
    484
            // Restore environment
    485
    0
            self.env = old_env;
    486
    487
            // Build function type from parameters and body
    488
    0
            let lambda_type = param_types.iter().rev().fold(body_ty, |acc, param_ty| {
    489
    0
                MonoType::Function(Box::new(param_ty.clone()), Box::new(acc))
    490
    0
            });
    491
    492
    0
            Ok(self.unifier.apply(&lambda_type))
    493
    0
        }
    494
    495
    0
        fn infer_call(&mut self, func: &Expr, args: &[Expr]) -> Result<MonoType> {
    496
    0
            let func_ty = self.infer_expr(func)?;
    497
    498
            // Create type for the function we expect
    499
    0
            let result_ty = MonoType::Var(self.gen.fresh());
    500
    0
            let mut expected_func_ty = result_ty.clone();
    501
    502
    0
            for arg in args.iter().rev() {
    503
    0
                let arg_ty = self.infer_expr(arg)?;
    504
    0
                expected_func_ty = MonoType::Function(Box::new(arg_ty), Box::new(expected_func_ty));
    505
            }
    506
    507
            // Unify with actual function type
    508
    0
            self.unifier.unify(&func_ty, &expected_func_ty)?;
    509
    510
    0
            Ok(self.unifier.apply(&result_ty))
    511
    0
        }
    512
    513
    0
        fn infer_macro(&mut self, name: &str, args: &[Expr]) -> Result<MonoType> {
    514
            // Type check the arguments first
    515
    0
            for arg in args {
    516
    0
                self.infer_expr(arg)?;
    517
            }
    518
    519
            // Determine the return type based on the macro name
    520
    0
            match name {
    521
    0
                "println" => Ok(MonoType::Unit), // println! returns unit
    522
    0
                "vec" => {
    523
                    // vec! returns a vector of the element type
    524
    0
                    if args.is_empty() {
    525
                        // Empty vec! needs type annotation or we use a generic type
    526
    0
                        Ok(MonoType::List(Box::new(MonoType::Var(self.gen.fresh()))))
    527
                    } else {
    528
                        // Infer element type from first argument
    529
    0
                        let elem_ty = self.infer_expr(&args[0])?;
    530
    0
                        Ok(MonoType::List(Box::new(elem_ty)))
    531
                    }
    532
                }
    533
    0
                _ => bail!("Unknown macro: {}", name),
    534
            }
    535
    0
        }
    536
    537
        /// REFACTORED FOR COMPLEXITY REDUCTION
    538
        /// Original: 41 cyclomatic complexity, Target: <20
    539
        /// Strategy: Extract method-category specific handlers
    540
    0
        pub fn infer_method_call(
    541
    0
            &mut self,
    542
    0
            receiver: &Expr,
    543
    0
            method: &str,
    544
    0
            args: &[Expr],
    545
    0
        ) -> Result<MonoType> {
    546
    0
            let receiver_ty = self.infer_expr(receiver)?;
    547
    0
            self.add_method_constraint(&receiver_ty, method, args)?;
    548
    549
            // Dispatch based on receiver type category (complexity: delegated)
    550
    0
            match &receiver_ty {
    551
    0
                MonoType::List(_) => self.infer_list_method(&receiver_ty, method, args),
    552
    0
                MonoType::String => self.infer_string_method(&receiver_ty, method, args),
    553
                MonoType::DataFrame(_) | MonoType::Series(_) => {
    554
    0
                    self.infer_dataframe_method(&receiver_ty, method, args)
    555
                }
    556
    0
                MonoType::Named(name) if name == "DataFrame" || name == "Series" => {
    557
    0
                    self.infer_dataframe_method(&receiver_ty, method, args)
    558
                }
    559
    0
                _ => self.infer_generic_method(&receiver_ty, method, args),
    560
            }
    561
    0
        }
    562
    563
        /// Extract method constraint addition (complexity ~3)
    564
    0
        fn add_method_constraint(
    565
    0
            &mut self,
    566
    0
            receiver_ty: &MonoType,
    567
    0
            method: &str,
    568
    0
            args: &[Expr]
    569
    0
        ) -> Result<()> {
    570
    0
            let arg_types: Result<Vec<_>> = args.iter().map(|arg| self.infer_expr(arg)).collect();
    571
    0
            let arg_types = arg_types?;
    572
    573
    0
            self.type_constraints.push(TypeConstraint::MethodCall(
    574
    0
                receiver_ty.clone(),
    575
    0
                method.to_string(),
    576
    0
                arg_types,
    577
    0
            ));
    578
    0
            Ok(())
    579
    0
        }
    580
    581
        /// Extract list method handling (complexity ~10)
    582
    0
        fn infer_list_method(
    583
    0
            &mut self,
    584
    0
            receiver_ty: &MonoType,
    585
    0
            method: &str,
    586
    0
            args: &[Expr]
    587
    0
        ) -> Result<MonoType> {
    588
    0
            if let MonoType::List(elem_ty) = receiver_ty {
    589
    0
                match method {
    590
    0
                    "len" | "length" => {
    591
    0
                        self.validate_no_args(method, args)?;
    592
    0
                        Ok(MonoType::Int)
    593
                    }
    594
    0
                    "push" => {
    595
    0
                        self.validate_single_arg(method, args)?;
    596
    0
                        let arg_ty = self.infer_expr(&args[0])?;
    597
    0
                        self.unifier.unify(&arg_ty, elem_ty)?;
    598
    0
                        Ok(MonoType::Unit)
    599
                    }
    600
    0
                    "pop" => {
    601
    0
                        self.validate_no_args(method, args)?;
    602
    0
                        Ok(MonoType::Optional(elem_ty.clone()))
    603
                    }
    604
    0
                    "sorted" | "reversed" | "unique" => {
    605
    0
                        self.validate_no_args(method, args)?;
    606
    0
                        Ok(MonoType::List(elem_ty.clone()))
    607
                    }
    608
    0
                    "sum" => {
    609
    0
                        self.validate_no_args(method, args)?;
    610
    0
                        Ok(*elem_ty.clone())
    611
                    }
    612
    0
                    "min" | "max" => {
    613
    0
                        self.validate_no_args(method, args)?;
    614
    0
                        Ok(MonoType::Optional(elem_ty.clone()))
    615
                    }
    616
    0
                    _ => self.infer_generic_method(receiver_ty, method, args),
    617
                }
    618
            } else {
    619
    0
                self.infer_generic_method(receiver_ty, method, args)
    620
            }
    621
    0
        }
    622
    623
        /// Extract string method handling (complexity ~5)
    624
    0
        fn infer_string_method(
    625
    0
            &mut self,
    626
    0
            receiver_ty: &MonoType,
    627
    0
            method: &str,
    628
    0
            args: &[Expr]
    629
    0
        ) -> Result<MonoType> {
    630
    0
            match method {
    631
    0
                "len" | "length" => {
    632
    0
                    self.validate_no_args(method, args)?;
    633
    0
                    Ok(MonoType::Int)
    634
                }
    635
    0
                "chars" => {
    636
    0
                    self.validate_no_args(method, args)?;
    637
    0
                    Ok(MonoType::List(Box::new(MonoType::String)))
    638
                }
    639
    0
                _ => self.infer_generic_method(receiver_ty, method, args),
    640
            }
    641
    0
        }
    642
    643
        /// Extract dataframe method handling (complexity ~8)
    644
    0
        fn infer_dataframe_method(
    645
    0
            &mut self,
    646
    0
            receiver_ty: &MonoType,
    647
    0
            method: &str,
    648
    0
            args: &[Expr]
    649
    0
        ) -> Result<MonoType> {
    650
    0
            match method {
    651
    0
                "filter" | "groupby" | "agg" | "select" => {
    652
    0
                    match receiver_ty {
    653
    0
                        MonoType::DataFrame(columns) => Ok(MonoType::DataFrame(columns.clone())),
    654
    0
                        MonoType::Named(name) if name == "DataFrame" => {
    655
    0
                            Ok(MonoType::Named("DataFrame".to_string()))
    656
                        }
    657
    0
                        _ => Ok(MonoType::Named("DataFrame".to_string())),
    658
                    }
    659
                }
    660
    0
                "mean" | "std" | "sum" | "count" => Ok(MonoType::Float),
    661
    0
                "col" => self.infer_column_selection(receiver_ty, args),
    662
    0
                _ => self.infer_generic_method(receiver_ty, method, args),
    663
            }
    664
    0
        }
    665
    666
        /// Extract column selection logic (complexity ~5)
    667
    0
        fn infer_column_selection(
    668
    0
            &mut self,
    669
    0
            receiver_ty: &MonoType,
    670
    0
            args: &[Expr]
    671
    0
        ) -> Result<MonoType> {
    672
    0
            if let MonoType::DataFrame(columns) = receiver_ty {
    673
    0
                if let Some(arg) = args.first() {
    674
    0
                    if let ExprKind::Literal(Literal::String(col_name)) = &arg.kind {
    675
    0
                        if let Some((_, col_type)) = columns.iter().find(|(name, _)| name == col_name) {
    676
    0
                            return Ok(MonoType::Series(Box::new(col_type.clone())));
    677
    0
                        }
    678
    0
                    }
    679
    0
                }
    680
    0
                Ok(MonoType::Series(Box::new(MonoType::Var(self.gen.fresh()))))
    681
            } else {
    682
    0
                Ok(MonoType::Series(Box::new(MonoType::Var(self.gen.fresh()))))
    683
            }
    684
    0
        }
    685
    686
        /// Extract generic method handling (complexity ~8)
    687
    0
        fn infer_generic_method(
    688
    0
            &mut self,
    689
    0
            receiver_ty: &MonoType,
    690
    0
            method: &str,
    691
    0
            args: &[Expr]
    692
    0
        ) -> Result<MonoType> {
    693
    0
            if let Some(scheme) = self.env.lookup(method) {
    694
    0
                let method_ty = self.env.instantiate(scheme, &mut self.gen);
    695
    0
                let result_ty = MonoType::Var(self.gen.fresh());
    696
    0
                let expected_func_ty = self.build_method_function_type(receiver_ty, args, result_ty.clone())?;
    697
    698
    0
                self.unifier.unify(&method_ty, &expected_func_ty)?;
    699
    0
                Ok(self.unifier.apply(&result_ty))
    700
            } else {
    701
    0
                Ok(MonoType::Var(self.gen.fresh()))
    702
            }
    703
    0
        }
    704
    705
        /// Extract function type construction (complexity ~4)
    706
    0
        fn build_method_function_type(
    707
    0
            &mut self,
    708
    0
            receiver_ty: &MonoType,
    709
    0
            args: &[Expr],
    710
    0
            result_ty: MonoType
    711
    0
        ) -> Result<MonoType> {
    712
    0
            let mut expected_func_ty = result_ty;
    713
    714
    0
            for arg in args.iter().rev() {
    715
    0
                let arg_ty = self.infer_expr(arg)?;
    716
    0
                expected_func_ty = MonoType::Function(Box::new(arg_ty), Box::new(expected_func_ty));
    717
            }
    718
    719
            // Add receiver as first argument
    720
    0
            expected_func_ty = MonoType::Function(Box::new(receiver_ty.clone()), Box::new(expected_func_ty));
    721
    0
            Ok(expected_func_ty)
    722
    0
        }
    723
    724
        /// Helper methods for argument validation (complexity ~3 each)
    725
    0
        fn validate_no_args(&self, method: &str, args: &[Expr]) -> Result<()> {
    726
    0
            if !args.is_empty() {
    727
    0
                bail!("Method {} takes no arguments", method);
    728
    0
            }
    729
    0
            Ok(())
    730
    0
        }
    731
    732
    0
        fn validate_single_arg(&self, method: &str, args: &[Expr]) -> Result<()> {
    733
    0
            if args.len() != 1 {
    734
    0
                bail!("Method {} takes exactly one argument", method);
    735
    0
            }
    736
    0
            Ok(())
    737
    0
        }
    738
    739
    0
        fn infer_block(&mut self, exprs: &[Expr]) -> Result<MonoType> {
    740
    0
            if exprs.is_empty() {
    741
    0
                return Ok(MonoType::Unit);
    742
    0
            }
    743
    744
    0
            let mut last_ty = MonoType::Unit;
    745
    0
            for expr in exprs {
    746
    0
                last_ty = self.infer_expr(expr)?;
    747
            }
    748
    749
    0
            Ok(last_ty)
    750
    0
        }
    751
    752
    0
        fn infer_list(&mut self, elements: &[Expr]) -> Result<MonoType> {
    753
    0
            if elements.is_empty() {
    754
                // Empty list with fresh type variable
    755
    0
                let elem_ty = MonoType::Var(self.gen.fresh());
    756
    0
                return Ok(MonoType::List(Box::new(elem_ty)));
    757
    0
            }
    758
    759
            // All elements must have same type
    760
    0
            let first_ty = self.infer_expr(&elements[0])?;
    761
    0
            for elem in &elements[1..] {
    762
    0
                let elem_ty = self.infer_expr(elem)?;
    763
    0
                self.unifier.unify(&first_ty, &elem_ty)?;
    764
            }
    765
    766
    0
            Ok(MonoType::List(Box::new(self.unifier.apply(&first_ty))))
    767
    0
        }
    768
    769
    0
        fn infer_list_comprehension(
    770
    0
            &mut self,
    771
    0
            element: &Expr,
    772
    0
            variable: &str,
    773
    0
            iterable: &Expr,
    774
    0
            condition: Option<&Expr>,
    775
    0
        ) -> Result<MonoType> {
    776
            // Type check the iterable - must be a list
    777
    0
            let iterable_ty = self.infer_expr(iterable)?;
    778
    0
            let elem_ty = MonoType::Var(self.gen.fresh());
    779
    0
            self.unifier
    780
    0
                .unify(&iterable_ty, &MonoType::List(Box::new(elem_ty.clone())))?;
    781
    782
            // Save the old environment and add the loop variable
    783
    0
            let old_env = self.env.clone();
    784
    0
            self.env = self
    785
    0
                .env
    786
    0
                .extend(variable, TypeScheme::mono(self.unifier.apply(&elem_ty)));
    787
    788
            // Type check the optional condition (must be bool)
    789
    0
            if let Some(cond) = condition {
    790
    0
                let cond_ty = self.infer_expr(cond)?;
    791
    0
                self.unifier.unify(&cond_ty, &MonoType::Bool)?;
    792
    0
            }
    793
    794
            // Type check the element expression
    795
    0
            let result_elem_ty = self.infer_expr(element)?;
    796
    797
            // Restore the environment
    798
    0
            self.env = old_env;
    799
    800
            // Return List<T> where T is the type of the element expression
    801
    0
            Ok(MonoType::List(Box::new(
    802
    0
                self.unifier.apply(&result_elem_ty),
    803
    0
            )))
    804
    0
        }
    805
    806
    0
        fn infer_match(
    807
    0
            &mut self,
    808
    0
            expr: &Expr,
    809
    0
            arms: &[crate::frontend::ast::MatchArm],
    810
    0
        ) -> Result<MonoType> {
    811
    0
            let expr_ty = self.infer_expr(expr)?;
    812
    813
    0
            if arms.is_empty() {
    814
    0
                bail!("Match expression must have at least one arm");
    815
    0
            }
    816
    817
            // All arms must return same type
    818
    0
            let result_ty = MonoType::Var(self.gen.fresh());
    819
    820
    0
            for arm in arms {
    821
                // Infer pattern and bind variables
    822
    0
                let old_env = self.env.clone();
    823
    0
                self.infer_pattern(&arm.pattern, &expr_ty)?;
    824
    825
                // Guards have been removed from the grammar
    826
    827
                // Infer body type
    828
    0
                let body_ty = self.infer_expr(&arm.body)?;
    829
    0
                self.unifier.unify(&result_ty, &body_ty)?;
    830
    831
    0
                self.env = old_env;
    832
            }
    833
    834
    0
            Ok(self.unifier.apply(&result_ty))
    835
    0
        }
    836
    837
    0
        fn infer_pattern(&mut self, pattern: &Pattern, expected_ty: &MonoType) -> Result<()> {
    838
    0
            match pattern {
    839
    0
                Pattern::Wildcard => Ok(()),
    840
    0
                Pattern::Literal(lit) => {
    841
    0
                    let lit_ty = Self::infer_literal(lit);
    842
    0
                    self.unifier.unify(expected_ty, &lit_ty)
    843
                }
    844
    0
                Pattern::Identifier(name) => {
    845
                    // Bind the identifier to the expected type
    846
    0
                    self.env = self.env.extend(name, TypeScheme::mono(expected_ty.clone()));
    847
    0
                    Ok(())
    848
                }
    849
    0
                Pattern::QualifiedName(_path) => {
    850
                    // Qualified names in patterns should match against specific enum variants
    851
                    // For now, assume it's valid
    852
    0
                    Ok(())
    853
                }
    854
    0
                Pattern::List(patterns) => {
    855
    0
                    let elem_ty = MonoType::Var(self.gen.fresh());
    856
    0
                    self.unifier
    857
    0
                        .unify(expected_ty, &MonoType::List(Box::new(elem_ty.clone())))?;
    858
    859
    0
                    for pat in patterns {
    860
    0
                        self.infer_pattern(pat, &elem_ty)?;
    861
                    }
    862
    0
                    Ok(())
    863
                }
    864
    0
                Pattern::Ok(inner) => {
    865
                    // Expected type should be Result<T, E>, extract T for inner pattern
    866
    0
                    if let MonoType::Result(ok_ty, _) = expected_ty {
    867
    0
                        self.infer_pattern(inner, ok_ty)
    868
                    } else {
    869
                        // Create a fresh Result type
    870
    0
                        let error_ty = MonoType::Var(self.gen.fresh());
    871
    0
                        let inner_ty = MonoType::Var(self.gen.fresh());
    872
    0
                        let result_ty =
    873
    0
                            MonoType::Result(Box::new(inner_ty.clone()), Box::new(error_ty));
    874
    0
                        self.unifier.unify(expected_ty, &result_ty)?;
    875
    0
                        self.infer_pattern(inner, &inner_ty)
    876
                    }
    877
                }
    878
    0
                Pattern::Err(inner) => {
    879
                    // Expected type should be Result<T, E>, extract E for inner pattern
    880
    0
                    if let MonoType::Result(_, err_ty) = expected_ty {
    881
    0
                        self.infer_pattern(inner, err_ty)
    882
                    } else {
    883
                        // Create a fresh Result type
    884
    0
                        let ok_ty = MonoType::Var(self.gen.fresh());
    885
    0
                        let inner_ty = MonoType::Var(self.gen.fresh());
    886
    0
                        let result_ty = MonoType::Result(Box::new(ok_ty), Box::new(inner_ty.clone()));
    887
    0
                        self.unifier.unify(expected_ty, &result_ty)?;
    888
    0
                        self.infer_pattern(inner, &inner_ty)
    889
                    }
    890
                }
    891
    0
                Pattern::Some(inner) => {
    892
                    // Expected type should be Option<T>, extract T for inner pattern
    893
    0
                    if let MonoType::Optional(inner_ty) = expected_ty {
    894
    0
                        self.infer_pattern(inner, inner_ty)
    895
                    } else {
    896
                        // Create a fresh Option type
    897
    0
                        let inner_ty = MonoType::Var(self.gen.fresh());
    898
    0
                        let option_ty = MonoType::Optional(Box::new(inner_ty.clone()));
    899
    0
                        self.unifier.unify(expected_ty, &option_ty)?;
    900
    0
                        self.infer_pattern(inner, &inner_ty)
    901
                    }
    902
                }
    903
                Pattern::None => {
    904
                    // None pattern matches Option<T> where T can be any type
    905
    0
                    let type_var = MonoType::Var(self.gen.fresh());
    906
    0
                    let option_ty = MonoType::Optional(Box::new(type_var));
    907
    0
                    self.unifier.unify(expected_ty, &option_ty)
    908
                }
    909
    0
                Pattern::Tuple(patterns) => {
    910
                    // Create tuple type with each pattern's inferred type
    911
    0
                    let mut elem_types = Vec::new();
    912
    0
                    for pat in patterns {
    913
    0
                        let elem_ty = MonoType::Var(self.gen.fresh());
    914
    0
                        self.infer_pattern(pat, &elem_ty)?;
    915
    0
                        elem_types.push(elem_ty);
    916
                    }
    917
    0
                    let tuple_ty = MonoType::Tuple(elem_types);
    918
    0
                    self.unifier.unify(expected_ty, &tuple_ty)
    919
                }
    920
    0
                Pattern::Struct { name, fields, has_rest: _ } => {
    921
                    // For now, treat struct patterns as a named type
    922
                    // In a more complete implementation, we'd look up the struct definition
    923
    0
                    let struct_ty = MonoType::Named(name.clone());
    924
    0
                    self.unifier.unify(expected_ty, &struct_ty)?;
    925
    926
                    // Infer field patterns (simplified approach)
    927
    0
                    for field in fields {
    928
    0
                        if let Some(pattern) = &field.pattern {
    929
    0
                            let field_ty = MonoType::Var(self.gen.fresh());
    930
    0
                            self.infer_pattern(pattern, &field_ty)?;
    931
    0
                        }
    932
                    }
    933
    0
                    Ok(())
    934
                }
    935
    0
                Pattern::Range { start, end, .. } => {
    936
                    // Range patterns should match numeric types
    937
    0
                    let start_ty = MonoType::Var(self.gen.fresh());
    938
    0
                    let end_ty = MonoType::Var(self.gen.fresh());
    939
    0
                    self.infer_pattern(start, &start_ty)?;
    940
    0
                    self.infer_pattern(end, &end_ty)?;
    941
    942
                    // Unify start and end types, and with expected type
    943
    0
                    self.unifier.unify(&start_ty, &end_ty)?;
    944
    0
                    self.unifier.unify(expected_ty, &start_ty)
    945
                }
    946
    0
                Pattern::Or(patterns) => {
    947
                    // All patterns in an OR must have the same type
    948
    0
                    for pat in patterns {
    949
    0
                        self.infer_pattern(pat, expected_ty)?;
    950
                    }
    951
    0
                    Ok(())
    952
                }
    953
                Pattern::Rest => {
    954
                    // Rest patterns don't bind to specific types
    955
    0
                    Ok(())
    956
                }
    957
    0
                Pattern::RestNamed(name) => {
    958
                    // Named rest patterns bind the remaining elements to the name
    959
                    // For arrays [first, ..rest], rest should be array type
    960
    0
                    self.env = self.env.extend(name, TypeScheme::mono(expected_ty.clone()));
    961
    0
                    Ok(())
    962
                }
    963
    0
                Pattern::WithDefault { pattern, .. } => {
    964
                    // For default patterns, we check the inner pattern with the expected type
    965
                    // The default value will be used if the actual value doesn't match
    966
    0
                    self.infer_pattern(pattern, expected_ty)
    967
                }
    968
            }
    969
    0
        }
    970
    971
    0
        fn infer_for(&mut self, var: &str, iter: &Expr, body: &Expr) -> Result<MonoType> {
    972
    0
            let iter_ty = self.infer_expr(iter)?;
    973
    974
            // Iterator should be a list
    975
    0
            let elem_ty = MonoType::Var(self.gen.fresh());
    976
    0
            self.unifier
    977
    0
                .unify(&iter_ty, &MonoType::List(Box::new(elem_ty.clone())))?;
    978
    979
            // Bind loop variable and infer body
    980
    0
            let old_env = self.env.clone();
    981
    0
            self.env = self.env.extend(var, TypeScheme::mono(elem_ty));
    982
    0
            let _body_ty = self.infer_expr(body)?;
    983
    0
            self.env = old_env;
    984
    985
            // For loops always return Unit regardless of body type
    986
    0
            Ok(MonoType::Unit)
    987
    0
        }
    988
    989
    0
        fn infer_while(&mut self, condition: &Expr, body: &Expr) -> Result<MonoType> {
    990
            // Condition must be Bool
    991
    0
            let cond_ty = self.infer_expr(condition)?;
    992
    0
            self.unifier.unify(&cond_ty, &MonoType::Bool)?;
    993
    994
            // Type check body
    995
    0
            let body_ty = self.infer_expr(body)?;
    996
    0
            self.unifier.unify(&body_ty, &MonoType::Unit)?;
    997
    998
            // While loops return unit
    999
    0
            Ok(MonoType::Unit)
    1000
    0
        }
    1001
    1002
    0
        fn infer_loop(&mut self, body: &Expr) -> Result<MonoType> {
    1003
            // Type check body
    1004
    0
            let body_ty = self.infer_expr(body)?;
    1005
    0
            self.unifier.unify(&body_ty, &MonoType::Unit)?;
    1006
    1007
            // Loop expressions return unit
    1008
    0
            Ok(MonoType::Unit)
    1009
    0
        }
    1010
    1011
    0
        fn infer_range(&mut self, start: &Expr, end: &Expr) -> Result<MonoType> {
    1012
    0
            let start_ty = self.infer_expr(start)?;
    1013
    0
            let end_ty = self.infer_expr(end)?;
    1014
    1015
            // Both must be integers
    1016
    0
            self.unifier.unify(&start_ty, &MonoType::Int)?;
    1017
    0
            self.unifier.unify(&end_ty, &MonoType::Int)?;
    1018
    1019
            // Range produces a list of integers
    1020
    0
            Ok(MonoType::List(Box::new(MonoType::Int)))
    1021
    0
        }
    1022
    1023
    0
        fn infer_pipeline(
    1024
    0
            &mut self,
    1025
    0
            expr: &Expr,
    1026
    0
            stages: &[crate::frontend::ast::PipelineStage],
    1027
    0
        ) -> Result<MonoType> {
    1028
    0
            let mut current_ty = self.infer_expr(expr)?;
    1029
    1030
    0
            for stage in stages {
    1031
                // Each stage is a function applied to current value
    1032
    0
                let stage_ty = self.infer_expr(&stage.op)?;
    1033
    1034
                // Create expected function type
    1035
    0
                let result_ty = MonoType::Var(self.gen.fresh());
    1036
    0
                let expected_func =
    1037
    0
                    MonoType::Function(Box::new(current_ty.clone()), Box::new(result_ty.clone()));
    1038
    1039
    0
                self.unifier.unify(&stage_ty, &expected_func)?;
    1040
    0
                current_ty = self.unifier.apply(&result_ty);
    1041
            }
    1042
    1043
    0
            Ok(current_ty)
    1044
    0
        }
    1045
    1046
    0
        fn infer_assign(&mut self, target: &Expr, value: &Expr) -> Result<MonoType> {
    1047
            // Infer the type of the value being assigned
    1048
    0
            let value_ty = self.infer_expr(value)?;
    1049
    1050
            // Infer the type of the target (lvalue)
    1051
    0
            let target_ty = self.infer_expr(target)?;
    1052
    1053
            // Target and value must have compatible types
    1054
    0
            self.unifier.unify(&target_ty, &value_ty)?;
    1055
    1056
            // Assignment expressions return Unit
    1057
    0
            Ok(MonoType::Unit)
    1058
    0
        }
    1059
    1060
    0
        fn infer_compound_assign(
    1061
    0
            &mut self,
    1062
    0
            target: &Expr,
    1063
    0
            op: BinaryOp,
    1064
    0
            value: &Expr,
    1065
    0
        ) -> Result<MonoType> {
    1066
            // Infer the types of target and value
    1067
    0
            let target_ty = self.infer_expr(target)?;
    1068
    0
            let value_ty = self.infer_expr(value)?;
    1069
    1070
            // For compound assignment, we need to ensure the operation is valid
    1071
            // This is equivalent to: target = target op value
    1072
    0
            let result_ty = self.infer_binary_op_type(op, &target_ty, &value_ty)?;
    1073
    1074
            // The result type must be compatible with the target type
    1075
    0
            self.unifier.unify(&target_ty, &result_ty)?;
    1076
    1077
            // Compound assignment expressions return Unit
    1078
    0
            Ok(MonoType::Unit)
    1079
    0
        }
    1080
    1081
    0
        fn infer_binary_op_type(
    1082
    0
            &mut self,
    1083
    0
            op: BinaryOp,
    1084
    0
            left_ty: &MonoType,
    1085
    0
            right_ty: &MonoType,
    1086
    0
        ) -> Result<MonoType> {
    1087
    0
            match op {
    1088
                BinaryOp::Add
    1089
                | BinaryOp::Subtract
    1090
                | BinaryOp::Multiply
    1091
                | BinaryOp::Divide
    1092
                | BinaryOp::Modulo => {
    1093
                    // Arithmetic operations: both operands should be numbers, result is same type
    1094
                    // Try Int first, then Float
    1095
    0
                    if let Ok(()) = self.unifier.unify(left_ty, &MonoType::Int) {
    1096
    0
                        if let Ok(()) = self.unifier.unify(right_ty, &MonoType::Int) {
    1097
    0
                            return Ok(MonoType::Int);
    1098
    0
                        }
    1099
    0
                    }
    1100
                    // Fall back to Float
    1101
    0
                    self.unifier.unify(left_ty, &MonoType::Float)?;
    1102
    0
                    self.unifier.unify(right_ty, &MonoType::Float)?;
    1103
    0
                    Ok(MonoType::Float)
    1104
                }
    1105
                BinaryOp::Power => {
    1106
                    // Power operation: base and exponent are numbers, result is same as base
    1107
    0
                    self.unifier.unify(left_ty, right_ty)?;
    1108
    0
                    if let Ok(()) = self.unifier.unify(left_ty, &MonoType::Int) {
    1109
    0
                        Ok(MonoType::Int)
    1110
                    } else {
    1111
    0
                        self.unifier.unify(left_ty, &MonoType::Float)?;
    1112
    0
                        Ok(MonoType::Float)
    1113
                    }
    1114
                }
    1115
                BinaryOp::Equal
    1116
                | BinaryOp::NotEqual
    1117
                | BinaryOp::Less
    1118
                | BinaryOp::LessEqual
    1119
                | BinaryOp::Greater
    1120
                | BinaryOp::GreaterEqual => {
    1121
                    // Comparison operations: operands must be same type, result is Bool
    1122
    0
                    self.unifier.unify(left_ty, right_ty)?;
    1123
    0
                    Ok(MonoType::Bool)
    1124
                }
    1125
                BinaryOp::And | BinaryOp::Or => {
    1126
                    // Logical operations: both operands must be Bool, result is Bool
    1127
    0
                    self.unifier.unify(left_ty, &MonoType::Bool)?;
    1128
    0
                    self.unifier.unify(right_ty, &MonoType::Bool)?;
    1129
    0
                    Ok(MonoType::Bool)
    1130
                }
    1131
                BinaryOp::NullCoalesce => {
    1132
                    // Null coalescing: return type should be the non-null operand type
    1133
                    // For now, return right_ty (could be improved with proper union types)
    1134
    0
                    Ok(right_ty.clone())
    1135
                }
    1136
                BinaryOp::BitwiseAnd
    1137
                | BinaryOp::BitwiseOr
    1138
                | BinaryOp::BitwiseXor
    1139
                | BinaryOp::LeftShift => {
    1140
                    // Bitwise operations: both operands must be Int, result is Int
    1141
    0
                    self.unifier.unify(left_ty, &MonoType::Int)?;
    1142
    0
                    self.unifier.unify(right_ty, &MonoType::Int)?;
    1143
    0
                    Ok(MonoType::Int)
    1144
                }
    1145
            }
    1146
    0
        }
    1147
    1148
    0
        fn infer_increment_decrement(&mut self, target: &Expr) -> Result<MonoType> {
    1149
            // Infer the type of the target
    1150
    0
            let target_ty = self.infer_expr(target)?;
    1151
    1152
            // Target must be a numeric type (Int or Float)
    1153
            // Try Int first, then Float
    1154
    0
            if let Ok(()) = self.unifier.unify(&target_ty, &MonoType::Int) {
    1155
    0
                Ok(MonoType::Int)
    1156
            } else {
    1157
    0
                self.unifier.unify(&target_ty, &MonoType::Float)?;
    1158
    0
                Ok(MonoType::Float)
    1159
            }
    1160
    0
        }
    1161
    1162
    0
        fn ast_type_to_mono_static(ty: &crate::frontend::ast::Type) -> Result<MonoType> {
    1163
            use crate::frontend::ast::TypeKind;
    1164
    1165
    0
            Ok(match &ty.kind {
    1166
    0
                TypeKind::Named(name) => match name.as_str() {
    1167
    0
                    "i32" | "i64" => MonoType::Int,
    1168
    0
                    "f32" | "f64" => MonoType::Float,
    1169
    0
                    "bool" => MonoType::Bool,
    1170
    0
                    "String" | "str" => MonoType::String,
    1171
    0
                    "Any" => MonoType::Var(TyVarGenerator::new().fresh()),
    1172
    0
                    _ => MonoType::Named(name.clone()),
    1173
                },
    1174
    0
                TypeKind::Generic { base, params } => {
    1175
                    // For now, treat generic types as their base type
    1176
                    // Full generic inference will be implemented later
    1177
    0
                    match base.as_str() {
    1178
    0
                        "Vec" | "List" => {
    1179
    0
                            if let Some(first_param) = params.first() {
    1180
    0
                                MonoType::List(Box::new(Self::ast_type_to_mono_static(first_param)?))
    1181
                            } else {
    1182
    0
                                MonoType::List(Box::new(MonoType::Var(TyVarGenerator::new().fresh())))
    1183
                            }
    1184
                        }
    1185
    0
                        "Option" => {
    1186
    0
                            if let Some(first_param) = params.first() {
    1187
    0
                                MonoType::Optional(Box::new(Self::ast_type_to_mono_static(
    1188
    0
                                    first_param,
    1189
    0
                                )?))
    1190
                            } else {
    1191
    0
                                MonoType::Optional(Box::new(MonoType::Var(
    1192
    0
                                    TyVarGenerator::new().fresh(),
    1193
    0
                                )))
    1194
                            }
    1195
                        }
    1196
    0
                        _ => MonoType::Named(base.clone()),
    1197
                    }
    1198
                }
    1199
    0
                TypeKind::Optional(inner) => {
    1200
    0
                    MonoType::Optional(Box::new(Self::ast_type_to_mono_static(inner)?))
    1201
                }
    1202
    0
                TypeKind::List(inner) => {
    1203
    0
                    MonoType::List(Box::new(Self::ast_type_to_mono_static(inner)?))
    1204
                }
    1205
    0
                TypeKind::Function { params, ret } => {
    1206
    0
                    let ret_ty = Self::ast_type_to_mono_static(ret)?;
    1207
    0
                    let result: Result<MonoType> =
    1208
    0
                        params.iter().rev().try_fold(ret_ty, |acc, param| {
    1209
                            Ok(MonoType::Function(
    1210
    0
                                Box::new(Self::ast_type_to_mono_static(param)?),
    1211
    0
                                Box::new(acc),
    1212
                            ))
    1213
    0
                        });
    1214
    0
                    result?
    1215
                }
    1216
    0
                TypeKind::DataFrame { columns } => {
    1217
    0
                    let mut col_types = Vec::new();
    1218
    0
                    for (name, ty) in columns {
    1219
    0
                        col_types.push((name.clone(), Self::ast_type_to_mono_static(ty)?));
    1220
                    }
    1221
    0
                    MonoType::DataFrame(col_types)
    1222
                }
    1223
    0
                TypeKind::Series { dtype } => {
    1224
    0
                    MonoType::Series(Box::new(Self::ast_type_to_mono_static(dtype)?))
    1225
                }
    1226
    0
                TypeKind::Tuple(types) => {
    1227
    0
                    let mono_types: Result<Vec<_>> = types
    1228
    0
                        .iter()
    1229
    0
                        .map(Self::ast_type_to_mono_static)
    1230
    0
                        .collect();
    1231
    0
                    MonoType::Tuple(mono_types?)
    1232
                }
    1233
    0
                TypeKind::Reference { inner, .. } => {
    1234
                    // For type inference, treat references the same as the inner type
    1235
    0
                    Self::ast_type_to_mono_static(inner)?
    1236
                }
    1237
            })
    1238
    0
        }
    1239
    1240
        /// Get the final inferred type for a type variable
    1241
        #[must_use]
    1242
    0
        pub fn solve(&self, var: &crate::middleend::types::TyVar) -> MonoType {
    1243
    0
            self.unifier.solve(var)
    1244
    0
        }
    1245
    1246
        /// Apply current substitution to a type
    1247
        #[must_use]
    1248
    0
        pub fn apply(&self, ty: &MonoType) -> MonoType {
    1249
    0
            self.unifier.apply(ty)
    1250
    0
        }
    1251
    1252
        /// Infer types for control flow expressions (if, match, loops)
    1253
        ///
    1254
        /// # Example Usage
    1255
        /// Handles type inference for control flow constructs.
    1256
        /// For if expressions, ensures both branches have compatible types.
    1257
        /// For match expressions, checks pattern compatibility and branch types.
    1258
    0
        fn infer_control_flow_expr(&mut self, expr: &Expr) -> Result<MonoType> {
    1259
    0
            match &expr.kind {
    1260
    0
                ExprKind::If { condition, then_branch, else_branch } => {
    1261
    0
                    self.infer_if(condition, then_branch, else_branch.as_deref())
    1262
                }
    1263
    0
                ExprKind::For { var, iter, body, .. } => self.infer_for(var, iter, body),
    1264
    0
                ExprKind::While { condition, body } => self.infer_while(condition, body),
    1265
    0
                ExprKind::Loop { body } => self.infer_loop(body),
    1266
    0
                ExprKind::IfLet { pattern: _, expr, then_branch, else_branch } => {
    1267
    0
                    let _expr_ty = self.infer_expr(expr)?;
    1268
    0
                    let then_ty = self.infer_expr(then_branch)?;
    1269
    0
                    let else_ty = if let Some(else_expr) = else_branch {
    1270
    0
                        self.infer_expr(else_expr)?
    1271
                    } else {
    1272
    0
                        MonoType::Unit
    1273
                    };
    1274
    0
                    self.unifier.unify(&then_ty, &else_ty)?;
    1275
    0
                    Ok(then_ty)
    1276
                }
    1277
    0
                ExprKind::WhileLet { pattern: _, expr, body } => {
    1278
    0
                    let _expr_ty = self.infer_expr(expr)?;
    1279
    0
                    let _body_ty = self.infer_expr(body)?;
    1280
    0
                    Ok(MonoType::Unit)
    1281
                }
    1282
    0
                _ => bail!("Unexpected expression type in control flow handler"),
    1283
            }
    1284
    0
        }
    1285
    1286
        /// Infer types for function and lambda expressions
    1287
    0
        fn infer_function_expr(&mut self, expr: &Expr) -> Result<MonoType> {
    1288
    0
            match &expr.kind {
    1289
    0
                ExprKind::Function { name, params, body, return_type, is_async, .. } => {
    1290
    0
                    self.infer_function(name, params, body, return_type.as_ref(), *is_async)
    1291
                }
    1292
    0
                ExprKind::Lambda { params, body } => self.infer_lambda(params, body),
    1293
    0
                _ => bail!("Unexpected expression type in function handler"),
    1294
            }
    1295
    0
        }
    1296
    1297
        /// Infer types for collection expressions (lists, tuples, comprehensions)
    1298
    0
        fn infer_collection_expr(&mut self, expr: &Expr) -> Result<MonoType> {
    1299
    0
            match &expr.kind {
    1300
    0
                ExprKind::List(elements) => self.infer_list(elements),
    1301
    0
                ExprKind::Tuple(elements) => {
    1302
    0
                    let element_types: Result<Vec<_>> = elements.iter().map(|e| self.infer_expr(e)).collect();
    1303
    0
                    Ok(MonoType::Tuple(element_types?))
    1304
                }
    1305
    0
                ExprKind::ListComprehension { element, variable, iterable, condition } => {
    1306
    0
                    self.infer_list_comprehension(element, variable, iterable, condition.as_deref())
    1307
                }
    1308
    0
                _ => bail!("Unexpected expression type in collection handler"),
    1309
            }
    1310
    0
        }
    1311
    1312
        /// Infer types for operations and method calls
    1313
    0
        fn infer_operation_expr(&mut self, expr: &Expr) -> Result<MonoType> {
    1314
    0
            match &expr.kind {
    1315
    0
                ExprKind::Binary { left, op, right } => self.infer_binary(left, *op, right),
    1316
    0
                ExprKind::Unary { op, operand } => self.infer_unary(*op, operand),
    1317
    0
                ExprKind::Call { func, args } => self.infer_call(func, args),
    1318
    0
                ExprKind::MethodCall { receiver, method, args } => {
    1319
    0
                    self.infer_method_call(receiver, method, args)
    1320
                }
    1321
    0
                _ => bail!("Unexpected expression type in operation handler"),
    1322
            }
    1323
    0
        }
    1324
    1325
        /// REFACTORED FOR COMPLEXITY REDUCTION
    1326
        /// Original: 38 cyclomatic complexity, Target: <20
    1327
        /// Strategy: Group related expression types into category handlers
    1328
    0
        pub fn infer_other_expr(&mut self, expr: &Expr) -> Result<MonoType> {
    1329
    0
            match &expr.kind {
    1330
                // Special cases that need specific handling
    1331
    0
                ExprKind::StringInterpolation { parts } => self.infer_string_interpolation(parts),
    1332
    0
                ExprKind::Throw { expr } => self.infer_throw(expr),
    1333
    0
                ExprKind::Ok { value } => self.infer_result_ok(value),
    1334
    0
                ExprKind::Err { error } => self.infer_result_err(error),
    1335
    1336
                // Control flow expressions (all return Unit)
    1337
                ExprKind::Break { .. } | ExprKind::Continue { .. } | ExprKind::Return { .. } => {
    1338
    0
                    self.infer_other_control_flow_expr(expr)
    1339
                }
    1340
    1341
                // Definition expressions (all return Unit)
    1342
                ExprKind::Struct { .. } | ExprKind::Enum { .. } | ExprKind::Trait { .. } |
    1343
                ExprKind::Impl { .. } | ExprKind::Extension { .. } | ExprKind::Actor { .. } |
    1344
                ExprKind::Import { .. } | ExprKind::Export { .. } => {
    1345
    0
                    self.infer_other_definition_expr(expr)
    1346
                }
    1347
    1348
                // Literal and access expressions
    1349
                ExprKind::StructLiteral { .. } | ExprKind::ObjectLiteral { .. } |
    1350
                ExprKind::FieldAccess { .. } | ExprKind::IndexAccess { .. } | ExprKind::Slice { .. } => {
    1351
    0
                    self.infer_other_literal_access_expr(expr)
    1352
                }
    1353
    1354
                // Option expressions
    1355
    0
                ExprKind::Some { .. } | ExprKind::None => self.infer_other_option_expr(expr),
    1356
    1357
                // Async expressions
    1358
                ExprKind::Await { .. } | ExprKind::AsyncBlock { .. } | ExprKind::Try { .. } => {
    1359
    0
                    self.infer_other_async_expr(expr)
    1360
                }
    1361
    1362
                // Actor expressions
    1363
                ExprKind::Send { .. } | ExprKind::ActorSend { .. } | ExprKind::Ask { .. } |
    1364
                ExprKind::ActorQuery { .. } => {
    1365
    0
                    self.infer_other_actor_expr(expr)
    1366
                }
    1367
    1368
                // Assignment expressions
    1369
                ExprKind::Assign { .. } | ExprKind::CompoundAssign { .. } |
    1370
                ExprKind::PreIncrement { .. } | ExprKind::PostIncrement { .. } |
    1371
                ExprKind::PreDecrement { .. } | ExprKind::PostDecrement { .. } => {
    1372
    0
                    self.infer_other_assignment_expr(expr)
    1373
                }
    1374
    1375
                // Remaining expressions
    1376
    0
                _ => self.infer_remaining_expr(expr),
    1377
            }
    1378
    0
        }
    1379
    1380
        /// Extract control flow handling (complexity ~1)
    1381
    0
        fn infer_other_control_flow_expr(&mut self, _expr: &Expr) -> Result<MonoType> {
    1382
    0
            Ok(MonoType::Unit)  // All control flow returns Unit
    1383
    0
        }
    1384
    1385
        /// Extract definition handling (complexity ~1)
    1386
    0
        fn infer_other_definition_expr(&mut self, _expr: &Expr) -> Result<MonoType> {
    1387
    0
            Ok(MonoType::Unit)  // All definitions return Unit
    1388
    0
        }
    1389
    1390
        /// Extract literal/access handling (complexity ~8)
    1391
    0
        fn infer_other_literal_access_expr(&mut self, expr: &Expr) -> Result<MonoType> {
    1392
    0
            match &expr.kind {
    1393
    0
                ExprKind::StructLiteral { name, .. } => Ok(MonoType::Named(name.clone())),
    1394
    0
                ExprKind::ObjectLiteral { fields } => self.infer_object_literal(fields),
    1395
    0
                ExprKind::FieldAccess { object, .. } => self.infer_field_access(object),
    1396
    0
                ExprKind::IndexAccess { object, index } => self.infer_index_access(object, index),
    1397
    0
                ExprKind::Slice { object, .. } => self.infer_slice(object),
    1398
    0
                _ => bail!("Unexpected literal/access expression"),
    1399
            }
    1400
    0
        }
    1401
    1402
        /// Extract option handling (complexity ~5)
    1403
    0
        fn infer_other_option_expr(&mut self, expr: &Expr) -> Result<MonoType> {
    1404
    0
            match &expr.kind {
    1405
    0
                ExprKind::Some { value } => {
    1406
    0
                    let inner_type = self.infer_expr(value)?;
    1407
    0
                    Ok(MonoType::Optional(Box::new(inner_type)))
    1408
                }
    1409
                ExprKind::None => {
    1410
    0
                    let type_var = MonoType::Var(self.gen.fresh());
    1411
    0
                    Ok(MonoType::Optional(Box::new(type_var)))
    1412
                }
    1413
    0
                _ => bail!("Unexpected option expression"),
    1414
            }
    1415
    0
        }
    1416
    1417
        /// Extract async handling (complexity ~5)
    1418
    0
        fn infer_other_async_expr(&mut self, expr: &Expr) -> Result<MonoType> {
    1419
    0
            match &expr.kind {
    1420
    0
                ExprKind::Await { expr } => self.infer_await(expr),
    1421
    0
                ExprKind::AsyncBlock { body } => self.infer_async_block(body),
    1422
    0
                ExprKind::Try { expr } => {
    1423
    0
                    let expr_type = self.infer(expr)?;
    1424
    0
                    Ok(expr_type)
    1425
                }
    1426
    0
                _ => bail!("Unexpected async expression"),
    1427
            }
    1428
    0
        }
    1429
    1430
        /// Extract actor handling (complexity ~6)
    1431
    0
        fn infer_other_actor_expr(&mut self, expr: &Expr) -> Result<MonoType> {
    1432
    0
            match &expr.kind {
    1433
    0
                ExprKind::Send { actor, message } | ExprKind::ActorSend { actor, message } => {
    1434
    0
                    self.infer_send(actor, message)
    1435
                }
    1436
    0
                ExprKind::Ask { actor, message, timeout } => {
    1437
    0
                    self.infer_ask(actor, message, timeout.as_deref())
    1438
                }
    1439
    0
                ExprKind::ActorQuery { actor, message } => self.infer_ask(actor, message, None),
    1440
    0
                _ => bail!("Unexpected actor expression"),
    1441
            }
    1442
    0
        }
    1443
    1444
        /// Extract assignment handling (complexity ~6)
    1445
    0
        fn infer_other_assignment_expr(&mut self, expr: &Expr) -> Result<MonoType> {
    1446
    0
            match &expr.kind {
    1447
    0
                ExprKind::Assign { target, value } => self.infer_assign(target, value),
    1448
    0
                ExprKind::CompoundAssign { target, op, value } => {
    1449
    0
                    self.infer_compound_assign(target, *op, value)
    1450
                }
    1451
    0
                ExprKind::PreIncrement { target } | ExprKind::PostIncrement { target } |
    1452
    0
                ExprKind::PreDecrement { target } | ExprKind::PostDecrement { target } => {
    1453
    0
                    self.infer_increment_decrement(target)
    1454
                }
    1455
    0
                _ => bail!("Unexpected assignment expression"),
    1456
            }
    1457
    0
        }
    1458
    1459
        /// Extract remaining expressions (complexity ~8)
    1460
    0
        fn infer_remaining_expr(&mut self, expr: &Expr) -> Result<MonoType> {
    1461
    0
            match &expr.kind {
    1462
    0
                ExprKind::Let { name, value, body, is_mutable, .. } => {
    1463
    0
                    self.infer_let(name, value, body, *is_mutable)
    1464
                }
    1465
    0
                ExprKind::Block(exprs) => self.infer_block(exprs),
    1466
    0
                ExprKind::Range { start, end, .. } => self.infer_range(start, end),
    1467
    0
                ExprKind::Pipeline { expr, stages } => self.infer_pipeline(expr, stages),
    1468
    0
                ExprKind::Module { body, .. } => self.infer_expr(body),
    1469
    0
                ExprKind::DataFrame { columns } => self.infer_dataframe(columns),
    1470
    0
                ExprKind::Command { .. } => Ok(MonoType::String),
    1471
    0
                ExprKind::Macro { name, args } => self.infer_macro(name, args),
    1472
    0
                ExprKind::DataFrameOperation { source, operation } => {
    1473
    0
                    self.infer_dataframe_operation(source, operation)
    1474
                }
    1475
    0
                _ => bail!("Unknown expression type in inference"),
    1476
            }
    1477
    0
        }
    1478
    1479
        /// Helper methods for complex expression groups
    1480
    0
        fn infer_string_interpolation(
    1481
    0
            &mut self,
    1482
    0
            parts: &[crate::frontend::ast::StringPart],
    1483
    0
        ) -> Result<MonoType> {
    1484
    0
            for part in parts {
    1485
    0
                if let crate::frontend::ast::StringPart::Expr(expr) = part {
    1486
    0
                    let _ = self.infer_expr(expr)?;
    1487
    0
                }
    1488
            }
    1489
    0
            Ok(MonoType::Named("String".to_string()))
    1490
    0
        }
    1491
    1492
    0
        fn infer_result_ok(&mut self, value: &Expr) -> Result<MonoType> {
    1493
    0
            let value_type = self.infer_expr(value)?;
    1494
    0
            let error_type = MonoType::Var(self.gen.fresh());
    1495
    0
            Ok(MonoType::Result(Box::new(value_type), Box::new(error_type)))
    1496
    0
        }
    1497
    1498
    0
        fn infer_result_err(&mut self, error: &Expr) -> Result<MonoType> {
    1499
    0
            let error_type = self.infer_expr(error)?;
    1500
    0
            let value_type = MonoType::Var(self.gen.fresh());
    1501
    0
            Ok(MonoType::Result(Box::new(value_type), Box::new(error_type)))
    1502
    0
        }
    1503
    1504
    0
        fn infer_object_literal(
    1505
    0
            &mut self,
    1506
    0
            fields: &[crate::frontend::ast::ObjectField],
    1507
    0
        ) -> Result<MonoType> {
    1508
    0
            for field in fields {
    1509
    0
                match field {
    1510
    0
                    crate::frontend::ast::ObjectField::KeyValue { value, .. } => {
    1511
    0
                        let _ = self.infer_expr(value)?;
    1512
                    }
    1513
    0
                    crate::frontend::ast::ObjectField::Spread { expr } => {
    1514
    0
                        let _ = self.infer_expr(expr)?;
    1515
                    }
    1516
                }
    1517
            }
    1518
    0
            Ok(MonoType::Named("Object".to_string()))
    1519
    0
        }
    1520
    1521
    0
        fn infer_field_access(&mut self, object: &Expr) -> Result<MonoType> {
    1522
    0
            let _object_ty = self.infer_expr(object)?;
    1523
    0
            Ok(MonoType::Var(self.gen.fresh()))
    1524
    0
        }
    1525
    1526
    0
        fn infer_index_access(&mut self, object: &Expr, index: &Expr) -> Result<MonoType> {
    1527
    0
            let object_ty = self.infer_expr(object)?;
    1528
    0
            let index_ty = self.infer_expr(index)?;
    1529
    1530
            // Check if the index is a range (which results in slicing)
    1531
    0
            if let MonoType::List(inner_ty) = &index_ty {
    1532
    0
                if matches!(**inner_ty, MonoType::Int) {
    1533
                    // This is a range (List of integers), so return the same collection type
    1534
    0
                    return Ok(object_ty);
    1535
    0
                }
    1536
    0
            }
    1537
    1538
            // Regular integer indexing - return the element type
    1539
    0
            match object_ty {
    1540
    0
                MonoType::List(element_ty) => {
    1541
                    // Ensure index is an integer
    1542
    0
                    self.unifier.unify(&index_ty, &MonoType::Int)?;
    1543
    0
                    Ok(*element_ty)
    1544
                }
    1545
                MonoType::String => {
    1546
                    // Ensure index is an integer
    1547
    0
                    self.unifier.unify(&index_ty, &MonoType::Int)?;
    1548
    0
                    Ok(MonoType::String)
    1549
                }
    1550
    0
                _ => Ok(MonoType::Var(self.gen.fresh())),
    1551
            }
    1552
    0
        }
    1553
    1554
    0
        fn infer_slice(&mut self, object: &Expr) -> Result<MonoType> {
    1555
    0
            let object_ty = self.infer_expr(object)?;
    1556
            // Slicing returns the same type as the original collection
    1557
            // (a slice of a list is still a list, a slice of a string is still a string)
    1558
    0
            Ok(object_ty)
    1559
    0
        }
    1560
    1561
    0
        fn infer_send(&mut self, actor: &Expr, message: &Expr) -> Result<MonoType> {
    1562
    0
            let _actor_ty = self.infer_expr(actor)?;
    1563
    0
            let _message_ty = self.infer_expr(message)?;
    1564
    0
            Ok(MonoType::Unit)
    1565
    0
        }
    1566
    1567
    0
        fn infer_ask(
    1568
    0
            &mut self,
    1569
    0
            actor: &Expr,
    1570
    0
            message: &Expr,
    1571
    0
            timeout: Option<&Expr>,
    1572
    0
        ) -> Result<MonoType> {
    1573
    0
            let _actor_ty = self.infer_expr(actor)?;
    1574
    0
            let _message_ty = self.infer_expr(message)?;
    1575
    0
            if let Some(t) = timeout {
    1576
    0
                let timeout_ty = self.infer_expr(t)?;
    1577
    0
                self.unifier.unify(&timeout_ty, &MonoType::Int)?;
    1578
    0
            }
    1579
    0
            Ok(MonoType::Var(self.gen.fresh()))
    1580
    0
        }
    1581
    1582
    0
        fn infer_dataframe(
    1583
    0
            &mut self,
    1584
    0
            columns: &[crate::frontend::ast::DataFrameColumn],
    1585
    0
        ) -> Result<MonoType> {
    1586
    0
            let mut column_types = Vec::new();
    1587
    1588
    0
            for col in columns {
    1589
                // Infer the type of the first value to determine column type
    1590
    0
                let col_type = if col.values.is_empty() {
    1591
    0
                    MonoType::Var(self.gen.fresh())
    1592
                } else {
    1593
    0
                    let first_ty = self.infer_expr(&col.values[0])?;
    1594
                    // Verify all values in the column have the same type
    1595
    0
                    for value in &col.values[1..] {
    1596
    0
                        let value_ty = self.infer_expr(value)?;
    1597
    0
                        self.unifier.unify(&first_ty, &value_ty)?;
    1598
                    }
    1599
    0
                    first_ty
    1600
                };
    1601
    0
                column_types.push((col.name.clone(), col_type));
    1602
            }
    1603
    1604
    0
            Ok(MonoType::DataFrame(column_types))
    1605
    0
        }
    1606
    1607
    0
        fn infer_dataframe_operation(
    1608
    0
            &mut self,
    1609
    0
            source: &Expr,
    1610
    0
            operation: &crate::frontend::ast::DataFrameOp,
    1611
    0
        ) -> Result<MonoType> {
    1612
            use crate::frontend::ast::DataFrameOp;
    1613
    1614
    0
            let source_ty = self.infer_expr(source)?;
    1615
    1616
            // Ensure source is a DataFrame
    1617
    0
            match &source_ty {
    1618
    0
                MonoType::DataFrame(columns) => {
    1619
    0
                    match operation {
    1620
                        DataFrameOp::Filter(_) => {
    1621
                            // Filter preserves the DataFrame structure
    1622
    0
                            Ok(source_ty.clone())
    1623
                        }
    1624
    0
                        DataFrameOp::Select(selected_cols) => {
    1625
                            // Select creates a new DataFrame with only the selected columns
    1626
    0
                            let mut new_columns = Vec::new();
    1627
    0
                            for col_name in selected_cols {
    1628
    0
                                if let Some((_, ty)) = columns.iter().find(|(name, _)| name == col_name)
    1629
    0
                                {
    1630
    0
                                    new_columns.push((col_name.clone(), ty.clone()));
    1631
    0
                                }
    1632
                            }
    1633
    0
                            Ok(MonoType::DataFrame(new_columns))
    1634
                        }
    1635
                        DataFrameOp::GroupBy(_) => {
    1636
                            // GroupBy returns a grouped DataFrame (for now, same type)
    1637
    0
                            Ok(source_ty.clone())
    1638
                        }
    1639
                        DataFrameOp::Aggregate(_) => {
    1640
                            // Aggregation returns a DataFrame with aggregated values
    1641
    0
                            Ok(source_ty.clone())
    1642
                        }
    1643
                        DataFrameOp::Join { .. } => {
    1644
                            // Join returns a DataFrame (simplified for now)
    1645
    0
                            Ok(source_ty.clone())
    1646
                        }
    1647
                        DataFrameOp::Sort { .. } => {
    1648
                            // Sort preserves the DataFrame structure
    1649
    0
                            Ok(source_ty.clone())
    1650
                        }
    1651
                        DataFrameOp::Limit(_) | DataFrameOp::Head(_) | DataFrameOp::Tail(_) => {
    1652
                            // These operations preserve the DataFrame structure
    1653
    0
                            Ok(source_ty.clone())
    1654
                        }
    1655
                    }
    1656
                }
    1657
    0
                MonoType::Named(name) if name == "DataFrame" => {
    1658
                    // Fallback for untyped DataFrames
    1659
    0
                    Ok(MonoType::Named("DataFrame".to_string()))
    1660
                }
    1661
    0
                _ => bail!("DataFrame operation on non-DataFrame type: {}", source_ty),
    1662
            }
    1663
    0
        }
    1664
    1665
    0
        fn infer_async_block(&mut self, body: &Expr) -> Result<MonoType> {
    1666
            // Infer the body type
    1667
    0
            let body_ty = self.infer_expr(body)?;
    1668
    1669
            // Async blocks return Future<Output = body_type>
    1670
    0
            Ok(MonoType::Named(format!("Future<{body_ty}>")))
    1671
    0
        }
    1672
    }
    1673
    1674
    impl Default for InferenceContext {
    1675
    0
        fn default() -> Self {
    1676
    0
            Self::new()
    1677
    0
        }
    1678
    }
    1679
    1680
    #[cfg(test)]
    1681
    #[allow(clippy::unwrap_used)]
    1682
    #[allow(clippy::panic)]
    1683
    mod tests {
    1684
        use super::*;
    1685
        use crate::frontend::parser::Parser;
    1686
    1687
        fn infer_str(input: &str) -> Result<MonoType> {
    1688
            let mut parser = Parser::new(input);
    1689
            let expr = parser.parse()?;
    1690
            let mut ctx = InferenceContext::new();
    1691
            ctx.infer(&expr)
    1692
        }
    1693
    1694
        #[test]
    1695
        fn test_infer_literals() {
    1696
            assert_eq!(infer_str("42").unwrap(), MonoType::Int);
    1697
            assert_eq!(infer_str("3.14").unwrap(), MonoType::Float);
    1698
            assert_eq!(infer_str("true").unwrap(), MonoType::Bool);
    1699
            assert_eq!(infer_str("\"hello\"").unwrap(), MonoType::String);
    1700
        }
    1701
    1702
        #[test]
    1703
        fn test_infer_arithmetic() {
    1704
            assert_eq!(infer_str("1 + 2").unwrap(), MonoType::Int);
    1705
            assert_eq!(infer_str("3 * 4").unwrap(), MonoType::Int);
    1706
            assert_eq!(infer_str("5 - 2").unwrap(), MonoType::Int);
    1707
        }
    1708
    1709
        #[test]
    1710
        fn test_infer_comparison() {
    1711
            assert_eq!(infer_str("1 < 2").unwrap(), MonoType::Bool);
    1712
            assert_eq!(infer_str("3 == 3").unwrap(), MonoType::Bool);
    1713
            assert_eq!(infer_str("true != false").unwrap(), MonoType::Bool);
    1714
        }
    1715
    1716
        #[test]
    1717
        fn test_infer_if() {
    1718
            assert_eq!(
    1719
                infer_str("if true { 1 } else { 2 }").unwrap(),
    1720
                MonoType::Int
    1721
            );
    1722
            assert_eq!(
    1723
                infer_str("if false { \"yes\" } else { \"no\" }").unwrap(),
    1724
                MonoType::String
    1725
            );
    1726
        }
    1727
    1728
        #[test]
    1729
        fn test_infer_let() {
    1730
            assert_eq!(infer_str("let x = 42 in x + 1").unwrap(), MonoType::Int);
    1731
            assert_eq!(
    1732
                infer_str("let f = 3.14 in let g = 2.71 in f").unwrap(),
    1733
                MonoType::Float
    1734
            );
    1735
        }
    1736
    1737
        #[test]
    1738
        fn test_infer_list() {
    1739
            assert_eq!(
    1740
                infer_str("[1, 2, 3]").unwrap(),
    1741
                MonoType::List(Box::new(MonoType::Int))
    1742
            );
    1743
            assert_eq!(
    1744
                infer_str("[true, false]").unwrap(),
    1745
                MonoType::List(Box::new(MonoType::Bool))
    1746
            );
    1747
        }
    1748
    1749
        #[test]
    1750
        #[ignore = "DataFrame syntax changed - needs update"]
    1751
        fn test_infer_dataframe() {
    1752
            let df_str = r#"DataFrame::new()
    1753
                .column("age", [25, 30, 35])
    1754
                .column("name", ["Alice", "Bob", "Charlie"])
    1755
                .build()"#;
    1756
    1757
            let result = infer_str(df_str).unwrap_or(MonoType::DataFrame(vec![]));
    1758
            match result {
    1759
                MonoType::DataFrame(columns) => {
    1760
                    assert_eq!(columns.len(), 2);
    1761
                    assert_eq!(columns[0].0, "age");
    1762
                    assert!(matches!(columns[0].1, MonoType::Int));
    1763
                    assert_eq!(columns[1].0, "name");
    1764
                    assert!(matches!(columns[1].1, MonoType::String));
    1765
                }
    1766
                _ => panic!("Expected DataFrame type, got {result:?}"),
    1767
            }
    1768
        }
    1769
    1770
        #[test]
    1771
        #[ignore = "DataFrame syntax changed - needs update"]
    1772
        fn test_infer_dataframe_operations() {
    1773
            // Test filter operation with simpler pattern
    1774
            let filter_str = r"let df = DataFrame::new(); df.filter(|x| x > 25)";
    1775
            let result = infer_str(filter_str).unwrap_or(MonoType::DataFrame(vec![]));
    1776
            assert!(matches!(result, MonoType::DataFrame(_)));
    1777
    1778
            // Test select operation
    1779
            let select_str = r#"let df = DataFrame::new(); df.select(["age"])"#;
    1780
            let result = infer_str(select_str).unwrap_or(MonoType::DataFrame(vec![]));
    1781
            match result {
    1782
                MonoType::DataFrame(columns) => {
    1783
                    assert_eq!(columns.len(), 1);
    1784
                    assert_eq!(columns[0].0, "age");
    1785
                }
    1786
                _ => panic!("Expected DataFrame type, got {result:?}"),
    1787
            }
    1788
        }
    1789
    1790
        #[test]
    1791
        #[ignore = "DataFrame syntax changed - needs update"]
    1792
        fn test_infer_series() {
    1793
            // Test column selection returns Series
    1794
            let col_str = r#"let df = DataFrame::new(); df.col("age")"#;
    1795
            let result = infer_str(col_str).unwrap_or(MonoType::DataFrame(vec![]));
    1796
            assert!(matches!(result, MonoType::Series(_)) || matches!(result, MonoType::DataFrame(_)));
    1797
    1798
            // Test aggregation on Series
    1799
            let mean_str = r#"let df = DataFrame::new(); df.col("age").mean()"#;
    1800
            let result = infer_str(mean_str).unwrap_or(MonoType::Float);
    1801
            assert_eq!(result, MonoType::Float);
    1802
        }
    1803
    1804
        #[test]
    1805
        fn test_infer_function() {
    1806
            let result = infer_str("fun add(x: i32, y: i32) -> i32 { x + y }").unwrap();
    1807
            match result {
    1808
                MonoType::Function(first_arg, remaining) => {
    1809
                    assert!(matches!(first_arg.as_ref(), MonoType::Int));
    1810
                    match remaining.as_ref() {
    1811
                        MonoType::Function(second_arg, return_type) => {
    1812
                            assert!(matches!(second_arg.as_ref(), MonoType::Int));
    1813
                            assert!(matches!(return_type.as_ref(), MonoType::Int));
    1814
                        }
    1815
                        _ => panic!("Expected function type"),
    1816
                    }
    1817
                }
    1818
                _ => panic!("Expected function type"),
    1819
            }
    1820
        }
    1821
    1822
        #[test]
    1823
        fn test_type_errors() {
    1824
            assert!(infer_str("1 + true").is_err());
    1825
            assert!(infer_str("if 42 { 1 } else { 2 }").is_err());
    1826
            assert!(infer_str("[1, true, 3]").is_err());
    1827
        }
    1828
    1829
        #[test]
    1830
        fn test_infer_lambda() {
    1831
            // Simple lambda: |x| x + 1
    1832
            let result = infer_str("|x| x + 1").unwrap();
    1833
            match result {
    1834
                MonoType::Function(arg, ret) => {
    1835
                    assert!(matches!(arg.as_ref(), MonoType::Int));
    1836
                    assert!(matches!(ret.as_ref(), MonoType::Int));
    1837
                }
    1838
                _ => panic!("Expected function type for lambda"),
    1839
            }
    1840
    1841
            // Lambda with multiple params: |x, y| x * y
    1842
            let result = infer_str("|x, y| x * y").unwrap();
    1843
            match result {
    1844
                MonoType::Function(first_arg, remaining) => {
    1845
                    assert!(matches!(first_arg.as_ref(), MonoType::Int));
    1846
                    match remaining.as_ref() {
    1847
                        MonoType::Function(second_arg, return_type) => {
    1848
                            assert!(matches!(second_arg.as_ref(), MonoType::Int));
    1849
                            assert!(matches!(return_type.as_ref(), MonoType::Int));
    1850
                        }
    1851
                        _ => panic!("Expected function type"),
    1852
                    }
    1853
                }
    1854
                _ => panic!("Expected function type for lambda"),
    1855
            }
    1856
    1857
            // Lambda with no params: || 42
    1858
            let result = infer_str("|| 42").unwrap();
    1859
            assert_eq!(result, MonoType::Int);
    1860
    1861
            // Lambda used in let binding
    1862
            let result = infer_str("let f = |x| x + 1 in f(5)").unwrap();
    1863
            assert_eq!(result, MonoType::Int);
    1864
        }
    1865
    1866
        #[test]
    1867
        fn test_self_hosting_patterns() {
    1868
            // Test fat arrow lambda syntax inference
    1869
            let result = infer_str("x => x * 2").unwrap();
    1870
            match result {
    1871
                MonoType::Function(arg, ret) => {
    1872
                    assert!(matches!(arg.as_ref(), MonoType::Int));
    1873
                    assert!(matches!(ret.as_ref(), MonoType::Int));
    1874
                }
    1875
                _ => panic!("Expected function type for fat arrow lambda"),
    1876
            }
    1877
    1878
            // Test higher-order function patterns (compiler combinators)
    1879
            let result = infer_str("let map = |f, xs| xs in let double = |x| x * 2 in map(double, [1, 2, 3])").unwrap();
    1880
            assert!(matches!(result, MonoType::List(_)));
    1881
    1882
            // Test recursive function inference (needed for recursive descent parser)
    1883
            let result = infer_str("fun factorial(n: i32) -> i32 { if n <= 1 { 1 } else { n * factorial(n - 1) } }").unwrap();
    1884
            match result {
    1885
                MonoType::Function(arg, ret) => {
    1886
                    assert!(matches!(arg.as_ref(), MonoType::Int));
    1887
                    assert!(matches!(ret.as_ref(), MonoType::Int));
    1888
                }
    1889
                _ => panic!("Expected function type for recursive function"),
    1890
            }
    1891
        }
    1892
    1893
        #[test]
    1894
        fn test_compiler_data_structures() {
    1895
            // Test struct type inference for compiler data structures
    1896
            let result = infer_str("struct Token { kind: String, value: String }").unwrap();
    1897
            assert_eq!(result, MonoType::Unit);
    1898
    1899
            // Test enum for AST nodes
    1900
            let result = infer_str("enum Expr { Literal, Binary, Function }").unwrap();
    1901
            assert_eq!(result, MonoType::Unit);
    1902
    1903
            // Test Vec operations for token streams - basic list inference
    1904
            let result = infer_str("[1, 2, 3]").unwrap();
    1905
            assert!(matches!(result, MonoType::List(_)));
    1906
    1907
            // Test list length method
    1908
            let result = infer_str("[1, 2, 3].len()").unwrap();
    1909
            assert_eq!(result, MonoType::Int);
    1910
        }
    1911
    1912
        #[test]
    1913
        fn test_constraint_solving() {
    1914
            // Test basic list operations
    1915
            let result = infer_str("[1, 2, 3].len()").unwrap();
    1916
            assert_eq!(result, MonoType::Int);
    1917
    1918
            // Test polymorphic function inference
    1919
            let result = infer_str("let id = |x| x in let n = id(42) in let s = id(\"hello\") in n").unwrap();
    1920
            assert_eq!(result, MonoType::Int);
    1921
    1922
            // Test simple constraint solving
    1923
            let result = infer_str("let f = |x| x + 1 in f").unwrap();
    1924
            assert!(matches!(result, MonoType::Function(_, _)));
    1925
    1926
            // Test function composition
    1927
            let result = infer_str("let compose = |f, g, x| f(g(x)) in compose").unwrap();
    1928
            assert!(matches!(result, MonoType::Function(_, _)));
    1929
        }
    1930
    }