Coverage Report

Created: 2025-09-05 15:26

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