Skip to main content

normalize_surface_syntax/ir/
pat.rs

1//! Pattern types for the IR.
2//!
3//! Patterns appear in destructuring bindings (`let { a, b } = obj`) and
4//! in function parameters (`function f({ name }) {}`).
5
6use super::Expr;
7use serde::{Deserialize, Serialize};
8
9/// A binding pattern.
10///
11/// Patterns appear on the left-hand side of destructuring declarations and
12/// in destructuring function parameters.
13#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
14pub enum Pat {
15    /// Simple identifier binding: `x`.
16    Ident(String),
17
18    /// Object destructuring pattern: `{ x, y: z, ...rest }`.
19    Object(Vec<PatField>),
20
21    /// Array/tuple destructuring pattern: `[x, y, ...rest]`.
22    ///
23    /// Elements are `None` for holes (e.g. `[, y]` skips the first element).
24    /// `rest` is the name of the rest element (e.g. `"rest"` for `[...rest]`).
25    Array(Vec<Option<Pat>>, Option<String>),
26
27    /// Rest pattern: `...rest` (used inside object/array patterns).
28    Rest(Box<Pat>),
29}
30
31/// A field in an object destructuring pattern.
32///
33/// Represents one entry in `{ key: pat = default }`.
34#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
35pub struct PatField {
36    /// The source property key (e.g. `"b"` in `{ b: c }`).
37    pub key: String,
38    /// The binding target pattern (e.g. `Pat::Ident("c")` in `{ b: c }`).
39    pub pat: Pat,
40    /// Optional default value (e.g. `"foo"` in `{ a = "foo" }`).
41    #[serde(skip_serializing_if = "Option::is_none")]
42    pub default: Option<Expr>,
43}
44
45impl Pat {
46    /// Create a simple identifier pattern.
47    pub fn ident(name: impl Into<String>) -> Self {
48        Pat::Ident(name.into())
49    }
50
51    /// Create an object pattern from a list of fields.
52    pub fn object(fields: Vec<PatField>) -> Self {
53        Pat::Object(fields)
54    }
55
56    /// Create an array pattern from elements and an optional rest name.
57    pub fn array(elements: Vec<Option<Pat>>, rest: Option<String>) -> Self {
58        Pat::Array(elements, rest)
59    }
60}
61
62impl PatField {
63    /// Create a shorthand field: `{ key }` binds `key` to `Pat::Ident(key)`.
64    pub fn shorthand(key: impl Into<String>) -> Self {
65        let k = key.into();
66        Self {
67            pat: Pat::Ident(k.clone()),
68            key: k,
69            default: None,
70        }
71    }
72
73    /// Create a renamed field: `{ key: name }`.
74    pub fn renamed(key: impl Into<String>, name: impl Into<String>) -> Self {
75        Self {
76            key: key.into(),
77            pat: Pat::Ident(name.into()),
78            default: None,
79        }
80    }
81
82    /// Create a field with a nested pattern: `{ key: pat }`.
83    pub fn nested(key: impl Into<String>, pat: Pat) -> Self {
84        Self {
85            key: key.into(),
86            pat,
87            default: None,
88        }
89    }
90
91    /// Attach a default value to this field.
92    pub fn with_default(mut self, default: Expr) -> Self {
93        self.default = Some(default);
94        self
95    }
96}