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}