Skip to main content

nu_protocol/ast/
match_pattern.rs

1use super::Expression;
2use crate::{Span, Value, VarId};
3use serde::{Deserialize, Serialize};
4
5/// AST Node for match arm with optional match guard
6#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
7pub struct MatchPattern {
8    pub pattern: Pattern,
9    pub guard: Option<Box<Expression>>,
10    pub span: Span,
11}
12
13impl MatchPattern {
14    pub fn variables(&self) -> Vec<VarId> {
15        self.pattern.variables()
16    }
17
18    pub fn is_wildcard(&self) -> bool {
19        self.guard.is_none() && self.pattern.is_wildcard()
20    }
21}
22
23/// AST Node for pattern matching rules
24#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
25pub enum Pattern {
26    /// Destructuring of records
27    Record(Vec<(String, MatchPattern)>),
28    /// List destructuring
29    List(Vec<MatchPattern>),
30    /// Matching against a literal (from expression result).
31    /// Prefer [`Pattern::Value`] for new patterns; the parser const-evaluates
32    /// literal / parenthesized arms into `Value` when possible.
33    Expression(Box<Expression>),
34    /// Matching against a literal (pure value), including const-evaluated expressions.
35    /// Range values match by containment rather than equality.
36    Value(Value),
37    /// binding to a variable
38    Variable(VarId),
39    /// the `pattern1 \ pattern2` or-pattern
40    Or(Vec<MatchPattern>),
41    /// the `..$foo` pattern
42    Rest(VarId),
43    /// the `..` pattern
44    IgnoreRest,
45    /// the `_` pattern
46    IgnoreValue,
47    /// Failed parsing of a pattern
48    Garbage,
49}
50
51impl Pattern {
52    pub fn variables(&self) -> Vec<VarId> {
53        let mut output = vec![];
54        match self {
55            Pattern::Record(items) => {
56                for item in items {
57                    output.append(&mut item.1.variables());
58                }
59            }
60            Pattern::List(items) => {
61                for item in items {
62                    output.append(&mut item.variables());
63                }
64            }
65            Pattern::Variable(var_id) => output.push(*var_id),
66            Pattern::Or(patterns) => {
67                for pattern in patterns {
68                    output.append(&mut pattern.variables());
69                }
70            }
71            Pattern::Rest(var_id) => output.push(*var_id),
72            Pattern::Expression(_)
73            | Pattern::Value(_)
74            | Pattern::IgnoreValue
75            | Pattern::Garbage
76            | Pattern::IgnoreRest => {}
77        }
78
79        output
80    }
81
82    pub fn is_wildcard(&self) -> bool {
83        match self {
84            Self::Variable(_) | Self::IgnoreValue => true,
85            Self::Or(match_patterns) => match_patterns.iter().any(|x| x.is_wildcard()),
86            _ => false,
87        }
88    }
89}