## 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/frontend/ast.rs

    Line
    Count
    Source
    1
    //! Abstract Syntax Tree definitions for Ruchy
    2
    3
    use serde::{Deserialize, Serialize};
    4
    use std::fmt;
    5
    6
    /// Source location tracking for error reporting
    7
    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
    8
    pub struct Span {
    9
        pub start: usize,
    10
        pub end: usize,
    11
    }
    12
    13
    impl Span {
    14
        #[must_use]
    15
    0
        pub fn new(start: usize, end: usize) -> Self {
    16
    0
            Self { start, end }
    17
    0
        }
    18
    19
        #[must_use]
    20
    0
        pub fn merge(self, other: Self) -> Self {
    21
    0
            Self {
    22
    0
                start: self.start.min(other.start),
    23
    0
                end: self.end.max(other.end),
    24
    0
            }
    25
    0
        }
    26
    }
    27
    28
    /// Catch clause in try-catch blocks
    29
    #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
    30
    pub struct CatchClause {
    31
        pub pattern: Pattern,  // The error pattern to match
    32
        pub body: Box<Expr>,    // The catch block body
    33
    }
    34
    35
    /// The main AST node type for expressions
    36
    #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
    37
    pub struct Expr {
    38
        pub kind: ExprKind,
    39
        pub span: Span,
    40
        pub attributes: Vec<Attribute>,
    41
    }
    42
    43
    impl Expr {
    44
        #[must_use]
    45
    0
        pub fn new(kind: ExprKind, span: Span) -> Self {
    46
    0
            Self {
    47
    0
                kind,
    48
    0
                span,
    49
    0
                attributes: Vec::new(),
    50
    0
            }
    51
    0
        }
    52
    53
        #[must_use]
    54
    0
        pub fn with_attributes(kind: ExprKind, span: Span, attributes: Vec<Attribute>) -> Self {
    55
    0
            Self {
    56
    0
                kind,
    57
    0
                span,
    58
    0
                attributes,
    59
    0
            }
    60
    0
        }
    61
    }
    62
    63
    #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
    64
    pub enum ExprKind {
    65
        Literal(Literal),
    66
        Identifier(String),
    67
        QualifiedName {
    68
            module: String,
    69
            name: String,
    70
        },
    71
        StringInterpolation {
    72
            parts: Vec<StringPart>,
    73
        },
    74
        Binary {
    75
            left: Box<Expr>,
    76
            op: BinaryOp,
    77
            right: Box<Expr>,
    78
        },
    79
        Unary {
    80
            op: UnaryOp,
    81
            operand: Box<Expr>,
    82
        },
    83
        Throw {
    84
            expr: Box<Expr>,
    85
        },
    86
        TryCatch {
    87
            try_block: Box<Expr>,
    88
            catch_clauses: Vec<CatchClause>,
    89
            finally_block: Option<Box<Expr>>,
    90
        },
    91
        Ok {
    92
            value: Box<Expr>,
    93
        },
    94
        Err {
    95
            error: Box<Expr>,
    96
        },
    97
        Some {
    98
            value: Box<Expr>,
    99
        },
    100
        None,
    101
        TypeCast {
    102
            expr: Box<Expr>,
    103
            target_type: String,
    104
        },
    105
        Try {
    106
            expr: Box<Expr>,
    107
        },
    108
        Await {
    109
            expr: Box<Expr>,
    110
        },
    111
        AsyncBlock {
    112
            body: Box<Expr>,
    113
        },
    114
        If {
    115
            condition: Box<Expr>,
    116
            then_branch: Box<Expr>,
    117
            else_branch: Option<Box<Expr>>,
    118
        },
    119
        IfLet {
    120
            pattern: Pattern,
    121
            expr: Box<Expr>,
    122
            then_branch: Box<Expr>,
    123
            else_branch: Option<Box<Expr>>,
    124
        },
    125
        Let {
    126
            name: String,
    127
            type_annotation: Option<Type>,
    128
            value: Box<Expr>,
    129
            body: Box<Expr>,
    130
            is_mutable: bool,
    131
        },
    132
        LetPattern {
    133
            pattern: Pattern,
    134
            type_annotation: Option<Type>,
    135
            value: Box<Expr>,
    136
            body: Box<Expr>,
    137
            is_mutable: bool,
    138
        },
    139
        Function {
    140
            name: String,
    141
            type_params: Vec<String>,
    142
            params: Vec<Param>,
    143
            return_type: Option<Type>,
    144
            body: Box<Expr>,
    145
            is_async: bool,
    146
            is_pub: bool,
    147
        },
    148
        Lambda {
    149
            params: Vec<Param>,
    150
            body: Box<Expr>,
    151
        },
    152
        Struct {
    153
            name: String,
    154
            type_params: Vec<String>,
    155
            fields: Vec<StructField>,
    156
            is_pub: bool,
    157
        },
    158
        Enum {
    159
            name: String,
    160
            type_params: Vec<String>,
    161
            variants: Vec<EnumVariant>,
    162
            is_pub: bool,
    163
        },
    164
        StructLiteral {
    165
            name: String,
    166
            fields: Vec<(String, Expr)>,
    167
        },
    168
        ObjectLiteral {
    169
            fields: Vec<ObjectField>,
    170
        },
    171
        FieldAccess {
    172
            object: Box<Expr>,
    173
            field: String,
    174
        },
    175
        OptionalFieldAccess {
    176
            object: Box<Expr>,
    177
            field: String,
    178
        },
    179
        IndexAccess {
    180
            object: Box<Expr>,
    181
            index: Box<Expr>,
    182
        },
    183
        Slice {
    184
            object: Box<Expr>,
    185
            start: Option<Box<Expr>>,
    186
            end: Option<Box<Expr>>,
    187
        },
    188
        Trait {
    189
            name: String,
    190
            type_params: Vec<String>,
    191
            methods: Vec<TraitMethod>,
    192
            is_pub: bool,
    193
        },
    194
        Impl {
    195
            type_params: Vec<String>,
    196
            trait_name: Option<String>,
    197
            for_type: String,
    198
            methods: Vec<ImplMethod>,
    199
            is_pub: bool,
    200
        },
    201
        Actor {
    202
            name: String,
    203
            state: Vec<StructField>,
    204
            handlers: Vec<ActorHandler>,
    205
        },
    206
        Send {
    207
            actor: Box<Expr>,
    208
            message: Box<Expr>,
    209
        },
    210
        Command {
    211
            program: String,
    212
            args: Vec<String>,
    213
            env: Vec<(String, String)>,
    214
            working_dir: Option<String>,
    215
        },
    216
        Ask {
    217
            actor: Box<Expr>,
    218
            message: Box<Expr>,
    219
            timeout: Option<Box<Expr>>,
    220
        },
    221
        /// Fire-and-forget actor send (left <- right)
    222
        ActorSend {
    223
            actor: Box<Expr>,
    224
            message: Box<Expr>,
    225
        },
    226
        /// Actor query with reply (left <? right)
    227
        ActorQuery {
    228
            actor: Box<Expr>,
    229
            message: Box<Expr>,
    230
        },
    231
        Call {
    232
            func: Box<Expr>,
    233
            args: Vec<Expr>,
    234
        },
    235
        Macro {
    236
            name: String,
    237
            args: Vec<Expr>,
    238
        },
    239
        MethodCall {
    240
            receiver: Box<Expr>,
    241
            method: String,
    242
            args: Vec<Expr>,
    243
        },
    244
        OptionalMethodCall {
    245
            receiver: Box<Expr>,
    246
            method: String,
    247
            args: Vec<Expr>,
    248
        },
    249
        Block(Vec<Expr>),
    250
        Pipeline {
    251
            expr: Box<Expr>,
    252
            stages: Vec<PipelineStage>,
    253
        },
    254
        Match {
    255
            expr: Box<Expr>,
    256
            arms: Vec<MatchArm>,
    257
        },
    258
        List(Vec<Expr>),
    259
        Tuple(Vec<Expr>),
    260
        Spread {
    261
            expr: Box<Expr>,
    262
        },
    263
        ListComprehension {
    264
            element: Box<Expr>,
    265
            variable: String,
    266
            iterable: Box<Expr>,
    267
            condition: Option<Box<Expr>>,
    268
        },
    269
        DataFrame {
    270
            columns: Vec<DataFrameColumn>,
    271
        },
    272
        DataFrameOperation {
    273
            source: Box<Expr>,
    274
            operation: DataFrameOp,
    275
        },
    276
        For {
    277
            var: String,  // Keep for backward compatibility
    278
            pattern: Option<Pattern>,  // New: Support destructuring patterns
    279
            iter: Box<Expr>,
    280
            body: Box<Expr>,
    281
        },
    282
        While {
    283
            condition: Box<Expr>,
    284
            body: Box<Expr>,
    285
        },
    286
        WhileLet {
    287
            pattern: Pattern,
    288
            expr: Box<Expr>,
    289
            body: Box<Expr>,
    290
        },
    291
        Loop {
    292
            body: Box<Expr>,
    293
        },
    294
        Range {
    295
            start: Box<Expr>,
    296
            end: Box<Expr>,
    297
            inclusive: bool,
    298
        },
    299
        Import {
    300
            path: String,
    301
            items: Vec<ImportItem>,
    302
        },
    303
        Module {
    304
            name: String,
    305
            body: Box<Expr>,
    306
        },
    307
        Export {
    308
            items: Vec<String>,
    309
        },
    310
        Break {
    311
            label: Option<String>,
    312
        },
    313
        Continue {
    314
            label: Option<String>,
    315
        },
    316
        Return {
    317
            value: Option<Box<Expr>>,
    318
        },
    319
        Assign {
    320
            target: Box<Expr>,
    321
            value: Box<Expr>,
    322
        },
    323
        CompoundAssign {
    324
            target: Box<Expr>,
    325
            op: BinaryOp,
    326
            value: Box<Expr>,
    327
        },
    328
        PreIncrement {
    329
            target: Box<Expr>,
    330
        },
    331
        PostIncrement {
    332
            target: Box<Expr>,
    333
        },
    334
        PreDecrement {
    335
            target: Box<Expr>,
    336
        },
    337
        PostDecrement {
    338
            target: Box<Expr>,
    339
        },
    340
        Extension {
    341
            target_type: String,
    342
            methods: Vec<ImplMethod>,
    343
        },
    344
    }
    345
    346
    #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
    347
    pub enum Literal {
    348
        Integer(i64),
    349
        Float(f64),
    350
        String(String),
    351
        Bool(bool),
    352
        Char(char),
    353
        Unit,
    354
    }
    355
    356
    impl Literal {
    357
        /// Convert a REPL Value to a Literal (for synthetic expressions)
    358
    0
        pub fn from_value(value: &crate::runtime::repl::Value) -> Self {
    359
            use crate::runtime::repl::Value;
    360
    0
            match value {
    361
    0
                Value::Int(i) => Literal::Integer(*i),
    362
    0
                Value::Float(f) => Literal::Float(*f),
    363
    0
                Value::String(s) => Literal::String(s.clone()),
    364
    0
                Value::Bool(b) => Literal::Bool(*b),
    365
    0
                Value::Char(c) => Literal::Char(*c),
    366
    0
                Value::Unit => Literal::Unit,
    367
    0
                _ => Literal::Unit, // Fallback for complex types
    368
            }
    369
    0
        }
    370
    }
    371
    372
    /// String interpolation parts - either literal text or an expression
    373
    #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
    374
    pub enum StringPart {
    375
        /// Literal text portion of the string
    376
        Text(String),
    377
        /// Expression to be interpolated without format specifier
    378
        Expr(Box<Expr>),
    379
        /// Expression with format specifier (e.g., {value:.2})
    380
        ExprWithFormat {
    381
            expr: Box<Expr>,
    382
            format_spec: String,
    383
        },
    384
    }
    385
    386
    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
    387
    pub enum BinaryOp {
    388
        // Arithmetic
    389
        Add,
    390
        Subtract,
    391
        Multiply,
    392
        Divide,
    393
        Modulo,
    394
        Power,
    395
    396
        // Comparison
    397
        Equal,
    398
        NotEqual,
    399
        Less,
    400
        LessEqual,
    401
        Greater,
    402
        GreaterEqual,
    403
    404
        // Logical
    405
        And,
    406
        Or,
    407
        NullCoalesce,
    408
    409
        // Bitwise
    410
        BitwiseAnd,
    411
        BitwiseOr,
    412
        BitwiseXor,
    413
        LeftShift,
    414
    }
    415
    416
    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
    417
    pub enum UnaryOp {
    418
        Not,
    419
        Negate,
    420
        BitwiseNot,
    421
        Reference,
    422
    }
    423
    424
    #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
    425
    pub struct Param {
    426
        pub pattern: Pattern,
    427
        pub ty: Type,
    428
        pub span: Span,
    429
        pub is_mutable: bool,
    430
        pub default_value: Option<Box<Expr>>,
    431
    }
    432
    433
    impl Param {
    434
        /// Get the primary name from this parameter pattern.
    435
        /// For complex patterns, this returns the first/primary identifier.
    436
        /// For simple patterns, this returns the identifier itself.
    437
        #[must_use]
    438
    0
        pub fn name(&self) -> String {
    439
    0
            self.pattern.primary_name()
    440
    0
        }
    441
    }
    442
    443
    #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
    444
    pub struct StructField {
    445
        pub name: String,
    446
        pub ty: Type,
    447
        pub is_pub: bool,
    448
    }
    449
    450
    #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
    451
    pub struct EnumVariant {
    452
        pub name: String,
    453
        pub fields: Option<Vec<Type>>, // None for unit variant, Some for tuple variant
    454
        pub discriminant: Option<i64>, // Explicit discriminant value for TypeScript compatibility
    455
    }
    456
    457
    #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
    458
    pub enum ObjectField {
    459
        KeyValue { key: String, value: Expr },
    460
        Spread { expr: Expr },
    461
    }
    462
    463
    #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
    464
    pub struct TraitMethod {
    465
        pub name: String,
    466
        pub params: Vec<Param>,
    467
        pub return_type: Option<Type>,
    468
        pub body: Option<Box<Expr>>, // None for method signatures, Some for default implementations
    469
        pub is_pub: bool,
    470
    }
    471
    472
    #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
    473
    pub struct ImplMethod {
    474
        pub name: String,
    475
        pub params: Vec<Param>,
    476
        pub return_type: Option<Type>,
    477
        pub body: Box<Expr>,
    478
        pub is_pub: bool,
    479
    }
    480
    481
    #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
    482
    pub struct ActorHandler {
    483
        pub message_type: String,
    484
        pub params: Vec<Param>,
    485
        pub body: Box<Expr>,
    486
    }
    487
    488
    #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
    489
    pub struct Type {
    490
        pub kind: TypeKind,
    491
        pub span: Span,
    492
    }
    493
    494
    #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
    495
    pub enum TypeKind {
    496
        Named(String),
    497
        Generic { base: String, params: Vec<Type> },
    498
        Optional(Box<Type>),
    499
        List(Box<Type>),
    500
        Tuple(Vec<Type>),
    501
        Function { params: Vec<Type>, ret: Box<Type> },
    502
        DataFrame { columns: Vec<(String, Type)> },
    503
        Series { dtype: Box<Type> },
    504
        Reference { is_mut: bool, inner: Box<Type> },
    505
    }
    506
    507
    #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
    508
    pub struct PipelineStage {
    509
        pub op: Box<Expr>,
    510
        pub span: Span,
    511
    }
    512
    513
    #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
    514
    pub struct MatchArm {
    515
        pub pattern: Pattern,
    516
        pub guard: Option<Box<Expr>>,  // Pattern guard: if condition
    517
        pub body: Box<Expr>,
    518
        pub span: Span,
    519
    }
    520
    521
    #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
    522
    pub enum Pattern {
    523
        Wildcard,
    524
        Literal(Literal),
    525
        Identifier(String),
    526
        QualifiedName(Vec<String>), // For patterns like Ordering::Less
    527
        Tuple(Vec<Pattern>),
    528
        List(Vec<Pattern>),
    529
        Struct {
    530
            name: String,
    531
            fields: Vec<StructPatternField>,
    532
            has_rest: bool,
    533
        },
    534
        Range {
    535
            start: Box<Pattern>,
    536
            end: Box<Pattern>,
    537
            inclusive: bool,
    538
        },
    539
        Or(Vec<Pattern>),
    540
        Rest, // For ... patterns
    541
        RestNamed(String), // For ..name patterns
    542
        WithDefault {
    543
            pattern: Box<Pattern>,
    544
            default: Box<Expr>,
    545
        }, // For patterns with default values like a = 10
    546
        Ok(Box<Pattern>),
    547
        Err(Box<Pattern>),
    548
        Some(Box<Pattern>),
    549
        None,
    550
    }
    551
    552
    impl Pattern {
    553
        /// Get the primary identifier name from this pattern.
    554
        /// For complex patterns, returns the first/most significant identifier.
    555
        #[must_use]
    556
    0
        pub fn primary_name(&self) -> String {
    557
    0
            match self {
    558
    0
                Pattern::Identifier(name) => name.clone(),
    559
    0
                Pattern::QualifiedName(path) => path.join("::"),
    560
    0
                Pattern::Tuple(patterns) => {
    561
                    // Return the name of the first pattern
    562
    0
                    patterns
    563
    0
                        .first()
    564
    0
                        .map_or_else(|| "_tuple".to_string(), Pattern::primary_name)
    565
                }
    566
    0
                Pattern::List(patterns) => {
    567
                    // Return the name of the first pattern
    568
    0
                    patterns
    569
    0
                        .first()
    570
    0
                        .map_or_else(|| "_list".to_string(), Pattern::primary_name)
    571
                }
    572
    0
                Pattern::Struct { name, fields, .. } => {
    573
                    // Return the struct type name, or first field name if anonymous
    574
    0
                    if name.is_empty() {
    575
    0
                        fields.first().map_or_else(|| "_struct".to_string(), |f| f.name.clone())
    576
                    } else {
    577
    0
                        name.clone()
    578
                    }
    579
                }
    580
    0
                Pattern::Ok(inner) | Pattern::Err(inner) | Pattern::Some(inner) => inner.primary_name(),
    581
    0
                Pattern::None => "_none".to_string(),
    582
    0
                Pattern::Or(patterns) => {
    583
                    // Return the name of the first pattern
    584
    0
                    patterns
    585
    0
                        .first()
    586
    0
                        .map_or_else(|| "_or".to_string(), Pattern::primary_name)
    587
                }
    588
    0
                Pattern::Wildcard => "_".to_string(),
    589
    0
                Pattern::Rest => "_rest".to_string(),
    590
    0
                Pattern::RestNamed(name) => name.clone(),
    591
    0
                Pattern::WithDefault { pattern, .. } => pattern.primary_name(),
    592
    0
                Pattern::Literal(lit) => format!("_literal_{lit:?}"),
    593
    0
                Pattern::Range { .. } => "_range".to_string(),
    594
            }
    595
    0
        }
    596
    }
    597
    598
    #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
    599
    pub struct StructPatternField {
    600
        pub name: String,
    601
        pub pattern: Option<Pattern>, // None for shorthand like { x } instead of { x: x }
    602
    }
    603
    604
    605
    /// Custom error type definition
    606
    #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
    607
    pub struct ErrorTypeDef {
    608
        pub name: String,
    609
        pub fields: Vec<StructField>,
    610
        pub extends: Option<String>, // Parent error type
    611
    }
    612
    613
    /// Attribute for annotating expressions (e.g., `#[property]`)
    614
    #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
    615
    pub struct Attribute {
    616
        pub name: String,
    617
        pub args: Vec<String>,
    618
        pub span: Span,
    619
    }
    620
    621
    #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
    622
    pub struct DataFrameColumn {
    623
        pub name: String,
    624
        pub values: Vec<Expr>,
    625
    }
    626
    627
    #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
    628
    pub enum DataFrameOp {
    629
        Filter(Box<Expr>),
    630
        Select(Vec<String>),
    631
        GroupBy(Vec<String>),
    632
        Sort(Vec<String>),
    633
        Join {
    634
            other: Box<Expr>,
    635
            on: Vec<String>,
    636
            how: JoinType,
    637
        },
    638
        Aggregate(Vec<AggregateOp>),
    639
        Limit(usize),
    640
        Head(usize),
    641
        Tail(usize),
    642
    }
    643
    644
    #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
    645
    pub enum JoinType {
    646
        Inner,
    647
        Left,
    648
        Right,
    649
        Outer,
    650
    }
    651
    652
    #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
    653
    pub enum ImportItem {
    654
        /// Import a specific name: `use std::collections::HashMap`
    655
        Named(String),
    656
        /// Import with alias: `use std::collections::HashMap as Map`
    657
        Aliased { name: String, alias: String },
    658
        /// Import all: `use std::collections::*`
    659
        Wildcard,
    660
    }
    661
    662
    impl ImportItem {
    663
        /// Check if this import is for a URL module
    664
    0
        pub fn is_url_import(path: &str) -> bool {
    665
    0
            path.starts_with("https://") || path.starts_with("http://")
    666
    0
        }
    667
    }
    668
    669
    #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
    670
    pub enum AggregateOp {
    671
        Sum(String),
    672
        Mean(String),
    673
        Min(String),
    674
        Max(String),
    675
        Count(String),
    676
        Std(String),
    677
        Var(String),
    678
    }
    679
    680
    impl fmt::Display for BinaryOp {
    681
    0
        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    682
    0
            match self {
    683
    0
                Self::Add => write!(f, "+"),
    684
    0
                Self::Subtract => write!(f, "-"),
    685
    0
                Self::Multiply => write!(f, "*"),
    686
    0
                Self::Divide => write!(f, "/"),
    687
    0
                Self::Modulo => write!(f, "%"),
    688
    0
                Self::Power => write!(f, "**"),
    689
    0
                Self::Equal => write!(f, "=="),
    690
    0
                Self::NotEqual => write!(f, "!="),
    691
    0
                Self::Less => write!(f, "<"),
    692
    0
                Self::LessEqual => write!(f, "<="),
    693
    0
                Self::Greater => write!(f, ">"),
    694
    0
                Self::GreaterEqual => write!(f, ">="),
    695
    0
                Self::And => write!(f, "&&"),
    696
    0
                Self::Or => write!(f, "||"),
    697
    0
                Self::NullCoalesce => write!(f, "??"),
    698
    0
                Self::BitwiseAnd => write!(f, "&"),
    699
    0
                Self::BitwiseOr => write!(f, "|"),
    700
    0
                Self::BitwiseXor => write!(f, "^"),
    701
    0
                Self::LeftShift => write!(f, "<<"),
    702
            }
    703
    0
        }
    704
    }
    705
    706
    impl fmt::Display for UnaryOp {
    707
    0
        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    708
    0
            match self {
    709
    0
                Self::Not => write!(f, "!"),
    710
    0
                Self::Negate => write!(f, "-"),
    711
    0
                Self::BitwiseNot => write!(f, "~"),
    712
    0
                Self::Reference => write!(f, "&"),
    713
            }
    714
    0
        }
    715
    }
    716
    717
    #[cfg(test)]
    718
    #[allow(clippy::unwrap_used, clippy::panic, clippy::expect_used)]
    719
    #[allow(clippy::unwrap_used)]
    720
    #[allow(clippy::panic)]
    721
    mod tests {
    722
        use super::*;
    723
        use proptest::prelude::*;
    724
    725
        proptest! {
    726
            #[test]
    727
            fn test_span_merge(start1 in 0usize..1000, end1 in 0usize..1000,
    728
                              start2 in 0usize..1000, end2 in 0usize..1000) {
    729
                let span1 = Span::new(start1, end1);
    730
                let span2 = Span::new(start2, end2);
    731
                let merged = span1.merge(span2);
    732
    733
                prop_assert!(merged.start <= span1.start);
    734
                prop_assert!(merged.start <= span2.start);
    735
                prop_assert!(merged.end >= span1.end);
    736
                prop_assert!(merged.end >= span2.end);
    737
            }
    738
        }
    739
    740
        #[test]
    741
        fn test_ast_size() {
    742
            // Track AST node sizes for optimization
    743
            let expr_size = std::mem::size_of::<Expr>();
    744
            let kind_size = std::mem::size_of::<ExprKind>();
    745
            // Current sizes are larger than ideal but acceptable for MVP
    746
            // Future optimization: Use arena allocation and indices
    747
            assert!(expr_size <= 192, "Expr too large: {expr_size} bytes");
    748
            assert!(kind_size <= 152, "ExprKind too large: {kind_size} bytes");
    749
        }
    750
    751
        #[test]
    752
        fn test_span_creation() {
    753
            let span = Span::new(10, 20);
    754
            assert_eq!(span.start, 10);
    755
            assert_eq!(span.end, 20);
    756
        }
    757
    758
        #[test]
    759
        fn test_span_merge_simple() {
    760
            let span1 = Span::new(5, 10);
    761
            let span2 = Span::new(8, 15);
    762
            let merged = span1.merge(span2);
    763
            assert_eq!(merged.start, 5);
    764
            assert_eq!(merged.end, 15);
    765
        }
    766
    767
        #[test]
    768
        fn test_span_merge_disjoint() {
    769
            let span1 = Span::new(0, 5);
    770
            let span2 = Span::new(10, 15);
    771
            let merged = span1.merge(span2);
    772
            assert_eq!(merged.start, 0);
    773
            assert_eq!(merged.end, 15);
    774
        }
    775
    776
        #[test]
    777
        fn test_expr_creation() {
    778
            let span = Span::new(0, 10);
    779
            let expr = Expr::new(ExprKind::Literal(Literal::Integer(42)), span);
    780
            assert_eq!(expr.span.start, 0);
    781
            assert_eq!(expr.span.end, 10);
    782
            match expr.kind {
    783
                ExprKind::Literal(Literal::Integer(n)) => assert_eq!(n, 42),
    784
                _ => panic!("Wrong expression kind"),
    785
            }
    786
        }
    787
    788
        #[test]
    789
        fn test_literal_variants() {
    790
            let literals = vec![
    791
                Literal::Integer(42),
    792
                #[allow(clippy::approx_constant)]
    793
                Literal::Float(3.14), // Not PI, just a test value
    794
                Literal::String("hello".to_string()),
    795
                Literal::Bool(true),
    796
                Literal::Unit,
    797
            ];
    798
    799
            for lit in literals {
    800
                let expr = Expr::new(ExprKind::Literal(lit.clone()), Span::new(0, 0));
    801
                match expr.kind {
    802
                    ExprKind::Literal(l) => assert_eq!(l, lit),
    803
                    _ => panic!("Expected literal"),
    804
                }
    805
            }
    806
        }
    807
    808
        #[test]
    809
        fn test_binary_op_display() {
    810
            assert_eq!(BinaryOp::Add.to_string(), "+");
    811
            assert_eq!(BinaryOp::Subtract.to_string(), "-");
    812
            assert_eq!(BinaryOp::Multiply.to_string(), "*");
    813
            assert_eq!(BinaryOp::Divide.to_string(), "/");
    814
            assert_eq!(BinaryOp::Modulo.to_string(), "%");
    815
            assert_eq!(BinaryOp::Power.to_string(), "**");
    816
            assert_eq!(BinaryOp::Equal.to_string(), "==");
    817
            assert_eq!(BinaryOp::NotEqual.to_string(), "!=");
    818
            assert_eq!(BinaryOp::Less.to_string(), "<");
    819
            assert_eq!(BinaryOp::LessEqual.to_string(), "<=");
    820
            assert_eq!(BinaryOp::Greater.to_string(), ">");
    821
            assert_eq!(BinaryOp::GreaterEqual.to_string(), ">=");
    822
            assert_eq!(BinaryOp::And.to_string(), "&&");
    823
            assert_eq!(BinaryOp::Or.to_string(), "||");
    824
            assert_eq!(BinaryOp::BitwiseAnd.to_string(), "&");
    825
            assert_eq!(BinaryOp::BitwiseOr.to_string(), "|");
    826
            assert_eq!(BinaryOp::BitwiseXor.to_string(), "^");
    827
            assert_eq!(BinaryOp::LeftShift.to_string(), "<<");
    828
        }
    829
    830
        #[test]
    831
        fn test_unary_op_display() {
    832
            assert_eq!(UnaryOp::Not.to_string(), "!");
    833
            assert_eq!(UnaryOp::Negate.to_string(), "-");
    834
            assert_eq!(UnaryOp::BitwiseNot.to_string(), "~");
    835
            assert_eq!(UnaryOp::Reference.to_string(), "&");
    836
        }
    837
    838
        #[test]
    839
        fn test_binary_expression() {
    840
            let left = Box::new(Expr::new(
    841
                ExprKind::Literal(Literal::Integer(1)),
    842
                Span::new(0, 1),
    843
            ));
    844
            let right = Box::new(Expr::new(
    845
                ExprKind::Literal(Literal::Integer(2)),
    846
                Span::new(4, 5),
    847
            ));
    848
            let expr = Expr::new(
    849
                ExprKind::Binary {
    850
                    left,
    851
                    op: BinaryOp::Add,
    852
                    right,
    853
                },
    854
                Span::new(0, 5),
    855
            );
    856
    857
            match expr.kind {
    858
                ExprKind::Binary {
    859
                    left: l,
    860
                    op,
    861
                    right: r,
    862
                } => {
    863
                    assert_eq!(op, BinaryOp::Add);
    864
                    match l.kind {
    865
                        ExprKind::Literal(Literal::Integer(n)) => assert_eq!(n, 1),
    866
                        _ => panic!("Wrong left operand"),
    867
                    }
    868
                    match r.kind {
    869
                        ExprKind::Literal(Literal::Integer(n)) => assert_eq!(n, 2),
    870
                        _ => panic!("Wrong right operand"),
    871
                    }
    872
                }
    873
                _ => panic!("Expected binary expression"),
    874
            }
    875
        }
    876
    877
        #[test]
    878
        fn test_unary_expression() {
    879
            let operand = Box::new(Expr::new(
    880
                ExprKind::Literal(Literal::Bool(true)),
    881
                Span::new(1, 5),
    882
            ));
    883
            let expr = Expr::new(
    884
                ExprKind::Unary {
    885
                    op: UnaryOp::Not,
    886
                    operand,
    887
                },
    888
                Span::new(0, 5),
    889
            );
    890
    891
            match expr.kind {
    892
                ExprKind::Unary { op, operand } => {
    893
                    assert_eq!(op, UnaryOp::Not);
    894
                    match operand.kind {
    895
                        ExprKind::Literal(Literal::Bool(b)) => assert!(b),
    896
                        _ => panic!("Wrong operand"),
    897
                    }
    898
                }
    899
                _ => panic!("Expected unary expression"),
    900
            }
    901
        }
    902
    903
        #[test]
    904
        fn test_if_expression() {
    905
            let condition = Box::new(Expr::new(
    906
                ExprKind::Literal(Literal::Bool(true)),
    907
                Span::new(3, 7),
    908
            ));
    909
            let then_branch = Box::new(Expr::new(
    910
                ExprKind::Literal(Literal::Integer(1)),
    911
                Span::new(10, 11),
    912
            ));
    913
            let else_branch = Some(Box::new(Expr::new(
    914
                ExprKind::Literal(Literal::Integer(2)),
    915
                Span::new(17, 18),
    916
            )));
    917
    918
            let expr = Expr::new(
    919
                ExprKind::If {
    920
                    condition,
    921
                    then_branch,
    922
                    else_branch,
    923
                },
    924
                Span::new(0, 18),
    925
            );
    926
    927
            match expr.kind {
    928
                ExprKind::If {
    929
                    condition: c,
    930
                    then_branch: t,
    931
                    else_branch: e,
    932
                } => {
    933
                    match c.kind {
    934
                        ExprKind::Literal(Literal::Bool(b)) => assert!(b),
    935
                        _ => panic!("Wrong condition"),
    936
                    }
    937
                    match t.kind {
    938
                        ExprKind::Literal(Literal::Integer(n)) => assert_eq!(n, 1),
    939
                        _ => panic!("Wrong then branch"),
    940
                    }
    941
                    assert!(e.is_some());
    942
                    if let Some(else_expr) = e {
    943
                        match else_expr.kind {
    944
                            ExprKind::Literal(Literal::Integer(n)) => assert_eq!(n, 2),
    945
                            _ => panic!("Wrong else branch"),
    946
                        }
    947
                    }
    948
                }
    949
                _ => panic!("Expected if expression"),
    950
            }
    951
        }
    952
    953
        #[test]
    954
        fn test_let_expression() {
    955
            let value = Box::new(Expr::new(
    956
                ExprKind::Literal(Literal::Integer(42)),
    957
                Span::new(8, 10),
    958
            ));
    959
            let body = Box::new(Expr::new(
    960
                ExprKind::Identifier("x".to_string()),
    961
                Span::new(14, 15),
    962
            ));
    963
    964
            let expr = Expr::new(
    965
                ExprKind::Let {
    966
                    name: "x".to_string(),
    967
                    type_annotation: None,
    968
                    value,
    969
                    body,
    970
                    is_mutable: false,
    971
                },
    972
                Span::new(0, 15),
    973
            );
    974
    975
            match expr.kind {
    976
                ExprKind::Let {
    977
                    name,
    978
                    value: v,
    979
                    body: b,
    980
                    ..
    981
                } => {
    982
                    assert_eq!(name, "x");
    983
                    match v.kind {
    984
                        ExprKind::Literal(Literal::Integer(n)) => assert_eq!(n, 42),
    985
                        _ => panic!("Wrong value"),
    986
                    }
    987
                    match b.kind {
    988
                        ExprKind::Identifier(id) => assert_eq!(id, "x"),
    989
                        _ => panic!("Wrong body"),
    990
                    }
    991
                }
    992
                _ => panic!("Expected let expression"),
    993
            }
    994
        }
    995
    996
        #[test]
    997
        fn test_function_expression() {
    998
            let params = vec![Param {
    999
                pattern: Pattern::Identifier("x".to_string()),
    1000
                ty: Type {
    1001
                    kind: TypeKind::Named("i32".to_string()),
    1002
                    span: Span::new(10, 13),
    1003
                },
    1004
                span: Span::new(8, 13),
    1005
                is_mutable: false,
    1006
                default_value: None,
    1007
            }];
    1008
            let body = Box::new(Expr::new(
    1009
                ExprKind::Identifier("x".to_string()),
    1010
                Span::new(20, 21),
    1011
            ));
    1012
    1013
            let expr = Expr::new(
    1014
                ExprKind::Function {
    1015
                    name: "identity".to_string(),
    1016
                    type_params: vec![],
    1017
                    params,
    1018
                    return_type: Some(Type {
    1019
                        kind: TypeKind::Named("i32".to_string()),
    1020
                        span: Span::new(16, 19),
    1021
                    }),
    1022
                    body,
    1023
                    is_async: false,
    1024
                    is_pub: false,
    1025
                },
    1026
                Span::new(0, 22),
    1027
            );
    1028
    1029
            match expr.kind {
    1030
                ExprKind::Function {
    1031
                    name,
    1032
                    params: p,
    1033
                    return_type,
    1034
                    body: b,
    1035
                    ..
    1036
                } => {
    1037
                    assert_eq!(name, "identity");
    1038
                    assert_eq!(p.len(), 1);
    1039
                    assert_eq!(p[0].name(), "x");
    1040
                    assert!(return_type.is_some());
    1041
                    match b.kind {
    1042
                        ExprKind::Identifier(id) => assert_eq!(id, "x"),
    1043
                        _ => panic!("Wrong body"),
    1044
                    }
    1045
                }
    1046
                _ => panic!("Expected function expression"),
    1047
            }
    1048
        }
    1049
    1050
        #[test]
    1051
        fn test_call_expression() {
    1052
            let func = Box::new(Expr::new(
    1053
                ExprKind::Identifier("add".to_string()),
    1054
                Span::new(0, 3),
    1055
            ));
    1056
            let args = vec![
    1057
                Expr::new(ExprKind::Literal(Literal::Integer(1)), Span::new(4, 5)),
    1058
                Expr::new(ExprKind::Literal(Literal::Integer(2)), Span::new(7, 8)),
    1059
            ];
    1060
    1061
            let expr = Expr::new(ExprKind::Call { func, args }, Span::new(0, 9));
    1062
    1063
            match expr.kind {
    1064
                ExprKind::Call { func: f, args: a } => {
    1065
                    match f.kind {
    1066
                        ExprKind::Identifier(name) => assert_eq!(name, "add"),
    1067
                        _ => panic!("Wrong function"),
    1068
                    }
    1069
                    assert_eq!(a.len(), 2);
    1070
                }
    1071
                _ => panic!("Expected call expression"),
    1072
            }
    1073
        }
    1074
    1075
        #[test]
    1076
        fn test_block_expression() {
    1077
            let exprs = vec![
    1078
                Expr::new(ExprKind::Literal(Literal::Integer(1)), Span::new(2, 3)),
    1079
                Expr::new(ExprKind::Literal(Literal::Integer(2)), Span::new(5, 6)),
    1080
            ];
    1081
    1082
            let expr = Expr::new(ExprKind::Block(exprs), Span::new(0, 8));
    1083
    1084
            match expr.kind {
    1085
                ExprKind::Block(block) => {
    1086
                    assert_eq!(block.len(), 2);
    1087
                }
    1088
                _ => panic!("Expected block expression"),
    1089
            }
    1090
        }
    1091
    1092
        #[test]
    1093
        fn test_list_expression() {
    1094
            let items = vec![
    1095
                Expr::new(ExprKind::Literal(Literal::Integer(1)), Span::new(1, 2)),
    1096
                Expr::new(ExprKind::Literal(Literal::Integer(2)), Span::new(4, 5)),
    1097
                Expr::new(ExprKind::Literal(Literal::Integer(3)), Span::new(7, 8)),
    1098
            ];
    1099
    1100
            let expr = Expr::new(ExprKind::List(items), Span::new(0, 9));
    1101
    1102
            match expr.kind {
    1103
                ExprKind::List(list) => {
    1104
                    assert_eq!(list.len(), 3);
    1105
                }
    1106
                _ => panic!("Expected list expression"),
    1107
            }
    1108
        }
    1109
    1110
        #[test]
    1111
        fn test_for_expression() {
    1112
            let iter = Box::new(Expr::new(
    1113
                ExprKind::Range {
    1114
                    start: Box::new(Expr::new(
    1115
                        ExprKind::Literal(Literal::Integer(0)),
    1116
                        Span::new(10, 11),
    1117
                    )),
    1118
                    end: Box::new(Expr::new(
    1119
                        ExprKind::Literal(Literal::Integer(10)),
    1120
                        Span::new(13, 15),
    1121
                    )),
    1122
                    inclusive: false,
    1123
                },
    1124
                Span::new(10, 15),
    1125
            ));
    1126
            let body = Box::new(Expr::new(
    1127
                ExprKind::Identifier("i".to_string()),
    1128
                Span::new(20, 21),
    1129
            ));
    1130
    1131
            let expr = Expr::new(
    1132
                ExprKind::For {
    1133
                    var: "i".to_string(),
    1134
                    pattern: None,
    1135
                    iter,
    1136
                    body,
    1137
                },
    1138
                Span::new(0, 22),
    1139
            );
    1140
    1141
            match expr.kind {
    1142
                ExprKind::For {
    1143
                    var,
    1144
                    iter: it,
    1145
                    body: b,
    1146
                    ..
    1147
                } => {
    1148
                    assert_eq!(var, "i");
    1149
                    match it.kind {
    1150
                        ExprKind::Range { .. } => {}
    1151
                        _ => panic!("Wrong iterator"),
    1152
                    }
    1153
                    match b.kind {
    1154
                        ExprKind::Identifier(id) => assert_eq!(id, "i"),
    1155
                        _ => panic!("Wrong body"),
    1156
                    }
    1157
                }
    1158
                _ => panic!("Expected for expression"),
    1159
            }
    1160
        }
    1161
    1162
        #[test]
    1163
        fn test_range_expression() {
    1164
            let start = Box::new(Expr::new(
    1165
                ExprKind::Literal(Literal::Integer(1)),
    1166
                Span::new(0, 1),
    1167
            ));
    1168
            let end = Box::new(Expr::new(
    1169
                ExprKind::Literal(Literal::Integer(10)),
    1170
                Span::new(3, 5),
    1171
            ));
    1172
    1173
            let expr = Expr::new(
    1174
                ExprKind::Range {
    1175
                    start,
    1176
                    end,
    1177
                    inclusive: false,
    1178
                },
    1179
                Span::new(0, 5),
    1180
            );
    1181
    1182
            match expr.kind {
    1183
                ExprKind::Range {
    1184
                    start: s,
    1185
                    end: e,
    1186
                    inclusive,
    1187
                } => {
    1188
                    assert!(!inclusive);
    1189
                    match s.kind {
    1190
                        ExprKind::Literal(Literal::Integer(n)) => assert_eq!(n, 1),
    1191
                        _ => panic!("Wrong start"),
    1192
                    }
    1193
                    match e.kind {
    1194
                        ExprKind::Literal(Literal::Integer(n)) => assert_eq!(n, 10),
    1195
                        _ => panic!("Wrong end"),
    1196
                    }
    1197
                }
    1198
                _ => panic!("Expected range expression"),
    1199
            }
    1200
        }
    1201
    1202
        #[test]
    1203
        fn test_import_expression() {
    1204
            let expr = Expr::new(
    1205
                ExprKind::Import {
    1206
                    path: "std::collections".to_string(),
    1207
                    items: vec![
    1208
                        ImportItem::Named("HashMap".to_string()),
    1209
                        ImportItem::Named("HashSet".to_string()),
    1210
                    ],
    1211
                },
    1212
                Span::new(0, 30),
    1213
            );
    1214
    1215
            match expr.kind {
    1216
                ExprKind::Import { path, items } => {
    1217
                    assert_eq!(path, "std::collections");
    1218
                    assert_eq!(items.len(), 2);
    1219
                    assert_eq!(items[0], ImportItem::Named("HashMap".to_string()));
    1220
                    assert_eq!(items[1], ImportItem::Named("HashSet".to_string()));
    1221
                }
    1222
                _ => panic!("Expected import expression"),
    1223
            }
    1224
        }
    1225
    1226
        #[test]
    1227
        fn test_pipeline_expression() {
    1228
            let expr_start = Box::new(Expr::new(
    1229
                ExprKind::List(vec![
    1230
                    Expr::new(ExprKind::Literal(Literal::Integer(1)), Span::new(1, 2)),
    1231
                    Expr::new(ExprKind::Literal(Literal::Integer(2)), Span::new(4, 5)),
    1232
                ]),
    1233
                Span::new(0, 6),
    1234
            ));
    1235
            let stages = vec![PipelineStage {
    1236
                op: Box::new(Expr::new(
    1237
                    ExprKind::Identifier("filter".to_string()),
    1238
                    Span::new(10, 16),
    1239
                )),
    1240
                span: Span::new(10, 16),
    1241
            }];
    1242
    1243
            let expr = Expr::new(
    1244
                ExprKind::Pipeline {
    1245
                    expr: expr_start,
    1246
                    stages,
    1247
                },
    1248
                Span::new(0, 16),
    1249
            );
    1250
    1251
            match expr.kind {
    1252
                ExprKind::Pipeline { expr: e, stages: s } => {
    1253
                    assert_eq!(s.len(), 1);
    1254
                    match e.kind {
    1255
                        ExprKind::List(list) => assert_eq!(list.len(), 2),
    1256
                        _ => panic!("Wrong pipeline start"),
    1257
                    }
    1258
                }
    1259
                _ => panic!("Expected pipeline expression"),
    1260
            }
    1261
        }
    1262
    1263
        #[test]
    1264
        fn test_match_expression() {
    1265
            let expr_to_match = Box::new(Expr::new(
    1266
                ExprKind::Identifier("x".to_string()),
    1267
                Span::new(6, 7),
    1268
            ));
    1269
            let arms = vec![
    1270
                MatchArm {
    1271
                    pattern: Pattern::Literal(Literal::Integer(1)),
    1272
                    guard: None,
    1273
                    body: Box::new(Expr::new(
    1274
                        ExprKind::Literal(Literal::String("one".to_string())),
    1275
                        Span::new(15, 20),
    1276
                    )),
    1277
                    span: Span::new(10, 20),
    1278
                },
    1279
                MatchArm {
    1280
                    pattern: Pattern::Wildcard,
    1281
                    guard: None,
    1282
                    body: Box::new(Expr::new(
    1283
                        ExprKind::Literal(Literal::String("other".to_string())),
    1284
                        Span::new(28, 35),
    1285
                    )),
    1286
                    span: Span::new(25, 35),
    1287
                },
    1288
            ];
    1289
    1290
            let expr = Expr::new(
    1291
                ExprKind::Match {
    1292
                    expr: expr_to_match,
    1293
                    arms,
    1294
                },
    1295
                Span::new(0, 36),
    1296
            );
    1297
    1298
            match expr.kind {
    1299
                ExprKind::Match { expr: e, arms: a } => {
    1300
                    assert_eq!(a.len(), 2);
    1301
                    match e.kind {
    1302
                        ExprKind::Identifier(id) => assert_eq!(id, "x"),
    1303
                        _ => panic!("Wrong match expression"),
    1304
                    }
    1305
                }
    1306
                _ => panic!("Expected match expression"),
    1307
            }
    1308
        }
    1309
    1310
        #[test]
    1311
        fn test_pattern_variants() {
    1312
            let patterns = vec![
    1313
                Pattern::Wildcard,
    1314
                Pattern::Literal(Literal::Integer(42)),
    1315
                Pattern::Identifier("x".to_string()),
    1316
                Pattern::Tuple(vec![
    1317
                    Pattern::Literal(Literal::Integer(1)),
    1318
                    Pattern::Identifier("x".to_string()),
    1319
                ]),
    1320
                Pattern::List(vec![
    1321
                    Pattern::Literal(Literal::Integer(1)),
    1322
                    Pattern::Literal(Literal::Integer(2)),
    1323
                ]),
    1324
                Pattern::Struct {
    1325
                    name: "Point".to_string(),
    1326
                    fields: vec![StructPatternField {
    1327
                        name: "x".to_string(),
    1328
                        pattern: Some(Pattern::Identifier("x".to_string())),
    1329
                    }],
    1330
                    has_rest: false,
    1331
                },
    1332
                Pattern::Range {
    1333
                    start: Box::new(Pattern::Literal(Literal::Integer(1))),
    1334
                    end: Box::new(Pattern::Literal(Literal::Integer(10))),
    1335
                    inclusive: true,
    1336
                },
    1337
                Pattern::Or(vec![
    1338
                    Pattern::Literal(Literal::Integer(1)),
    1339
                    Pattern::Literal(Literal::Integer(2)),
    1340
                ]),
    1341
                Pattern::Rest,
    1342
            ];
    1343
    1344
            for pattern in patterns {
    1345
                match pattern {
    1346
                    Pattern::Tuple(list) | Pattern::List(list) => assert!(!list.is_empty()),
    1347
                    Pattern::Struct { fields, .. } => assert!(!fields.is_empty()),
    1348
                    Pattern::Or(patterns) => assert!(!patterns.is_empty()),
    1349
                    Pattern::Range { .. }
    1350
                    | Pattern::Wildcard
    1351
                    | Pattern::Literal(_)
    1352
                    | Pattern::Identifier(_)
    1353
                    | Pattern::Rest
    1354
                    | Pattern::RestNamed(_)
    1355
                    | Pattern::Ok(_)
    1356
                    | Pattern::Err(_)
    1357
                    | Pattern::Some(_)
    1358
                    | Pattern::None
    1359
                    | Pattern::QualifiedName(_)
    1360
                    | Pattern::WithDefault { .. } => {} // Simple patterns
    1361
                }
    1362
            }
    1363
        }
    1364
    1365
        #[test]
    1366
        fn test_type_kinds() {
    1367
            let types = vec![
    1368
                Type {
    1369
                    kind: TypeKind::Named("i32".to_string()),
    1370
                    span: Span::new(0, 3),
    1371
                },
    1372
                Type {
    1373
                    kind: TypeKind::Optional(Box::new(Type {
    1374
                        kind: TypeKind::Named("String".to_string()),
    1375
                        span: Span::new(0, 6),
    1376
                    })),
    1377
                    span: Span::new(0, 7),
    1378
                },
    1379
                Type {
    1380
                    kind: TypeKind::List(Box::new(Type {
    1381
                        kind: TypeKind::Named("f64".to_string()),
    1382
                        span: Span::new(1, 4),
    1383
                    })),
    1384
                    span: Span::new(0, 5),
    1385
                },
    1386
                Type {
    1387
                    kind: TypeKind::Function {
    1388
                        params: vec![Type {
    1389
                            kind: TypeKind::Named("i32".to_string()),
    1390
                            span: Span::new(0, 3),
    1391
                        }],
    1392
                        ret: Box::new(Type {
    1393
                            kind: TypeKind::Named("String".to_string()),
    1394
                            span: Span::new(7, 13),
    1395
                        }),
    1396
                    },
    1397
                    span: Span::new(0, 13),
    1398
                },
    1399
            ];
    1400
    1401
            for ty in types {
    1402
                match ty.kind {
    1403
                    TypeKind::Named(name) => assert!(!name.is_empty()),
    1404
                    TypeKind::Generic { base, params } => {
    1405
                        assert!(!base.is_empty());
    1406
                        assert!(!params.is_empty());
    1407
                    }
    1408
                    TypeKind::Optional(_) | TypeKind::List(_) | TypeKind::Series { .. } => {}
    1409
                    TypeKind::Function { params, .. } => assert!(!params.is_empty()),
    1410
                    TypeKind::DataFrame { columns } => assert!(!columns.is_empty()),
    1411
                    TypeKind::Tuple(ref types) => assert!(!types.is_empty()),
    1412
                    TypeKind::Reference { is_mut: _, ref inner } => {
    1413
                        // Reference types should have a valid inner type
    1414
                        if let TypeKind::Named(ref name) = inner.kind {
    1415
                            assert!(!name.is_empty());
    1416
                        }
    1417
                    }
    1418
                }
    1419
            }
    1420
        }
    1421
    1422
        #[test]
    1423
        fn test_param_creation() {
    1424
            let param = Param {
    1425
                pattern: Pattern::Identifier("count".to_string()),
    1426
                ty: Type {
    1427
                    kind: TypeKind::Named("usize".to_string()),
    1428
                    span: Span::new(6, 11),
    1429
                },
    1430
                span: Span::new(0, 11),
    1431
                is_mutable: false,
    1432
                default_value: None,
    1433
            };
    1434
    1435
            assert_eq!(param.name(), "count");
    1436
            match param.ty.kind {
    1437
                TypeKind::Named(name) => assert_eq!(name, "usize"),
    1438
                _ => panic!("Wrong type kind"),
    1439
            }
    1440
        }
    1441
    }