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
}