Skip to main content

mago_syntax/ast/ast/
array.rs

1use serde::Serialize;
2
3use mago_span::HasSpan;
4use mago_span::Span;
5
6use crate::ast::ast::expression::Expression;
7use crate::ast::ast::keyword::Keyword;
8use crate::ast::sequence::TokenSeparatedSequence;
9
10#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord)]
11pub struct ArrayAccess<'arena> {
12    pub array: &'arena Expression<'arena>,
13    pub left_bracket: Span,
14    pub index: &'arena Expression<'arena>,
15    pub right_bracket: Span,
16}
17
18#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord)]
19pub struct ArrayAppend<'arena> {
20    pub array: &'arena Expression<'arena>,
21    pub left_bracket: Span,
22    pub right_bracket: Span,
23}
24
25/// Represents a PHP list, defined using `list` keyword and parentheses `()`.
26///
27/// # Example:
28///
29/// ```php
30/// <?php
31///
32/// list($a, 'b' => $c, /* missing */, ...$rest) = $arr;
33/// ```
34#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord)]
35pub struct List<'arena> {
36    pub list: Keyword<'arena>,
37    pub left_parenthesis: Span,
38    pub elements: TokenSeparatedSequence<'arena, ArrayElement<'arena>>,
39    pub right_parenthesis: Span,
40}
41
42/// Represents a standard PHP array, defined using square brackets `[]`.
43///
44/// # Example:
45///
46/// ```php
47/// <?php
48///
49/// $arr = ['apple', 'banana', 3 => 'orange'];
50/// ```
51#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord)]
52pub struct Array<'arena> {
53    pub left_bracket: Span,
54    pub elements: TokenSeparatedSequence<'arena, ArrayElement<'arena>>,
55    pub right_bracket: Span,
56}
57
58/// Represents a legacy PHP array, defined using `array` keyword and parentheses `()`.
59///
60/// # Example:
61///
62/// ```php
63/// <?php
64///
65/// $arr = array('apple', 'banana', 3 => 'orange');
66/// ```
67#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord)]
68pub struct LegacyArray<'arena> {
69    pub array: Keyword<'arena>,
70    pub left_parenthesis: Span,
71    pub elements: TokenSeparatedSequence<'arena, ArrayElement<'arena>>,
72    pub right_parenthesis: Span,
73}
74
75/// Represents an array element.
76#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord)]
77#[serde(tag = "type", content = "value")]
78pub enum ArrayElement<'arena> {
79    KeyValue(KeyValueArrayElement<'arena>),
80    Value(ValueArrayElement<'arena>),
81    Variadic(VariadicArrayElement<'arena>),
82    Missing(MissingArrayElement),
83}
84
85/// Represents a key-value pair in an array.
86///
87/// # Example:
88///
89/// ```php
90/// <?php
91///
92/// $arr = [
93///   1 => 'orange',
94/// ];
95/// ```
96#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord)]
97pub struct KeyValueArrayElement<'arena> {
98    pub key: &'arena Expression<'arena>,
99    pub double_arrow: Span,
100    pub value: &'arena Expression<'arena>,
101}
102
103/// Represents a value in an array.
104///
105/// # Example:
106///
107/// ```php
108/// <?php
109///
110/// $arr = [
111///   'orange',
112/// ];
113/// ```
114#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord)]
115pub struct ValueArrayElement<'arena> {
116    pub value: &'arena Expression<'arena>,
117}
118
119/// Represents a variadic array element.
120///
121/// # Example:
122///
123/// ```php
124/// <?php
125///
126/// $arr = [
127///   ...$other,
128/// ];
129/// ```
130#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord)]
131pub struct VariadicArrayElement<'arena> {
132    pub ellipsis: Span,
133    pub value: &'arena Expression<'arena>,
134}
135
136/// Represents a missing array element.
137///
138/// # Example:
139///
140/// ```php
141/// <?php
142///
143/// $arr = [
144///   'first',
145///   ,
146///   'third',
147/// ];
148#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord)]
149pub struct MissingArrayElement {
150    pub comma: Span,
151}
152
153impl<'arena> ArrayElement<'arena> {
154    #[inline]
155    #[must_use]
156    pub const fn is_variadic(&self) -> bool {
157        matches!(self, ArrayElement::Variadic(_))
158    }
159
160    #[inline]
161    #[must_use]
162    pub const fn is_missing(&self) -> bool {
163        matches!(self, ArrayElement::Missing(_))
164    }
165
166    #[inline]
167    #[must_use]
168    pub const fn is_key_value(&self) -> bool {
169        matches!(self, ArrayElement::KeyValue(_))
170    }
171
172    #[inline]
173    #[must_use]
174    pub const fn is_value(&self) -> bool {
175        matches!(self, ArrayElement::Value(_))
176    }
177
178    #[inline]
179    #[must_use]
180    pub fn get_key(&self) -> Option<&Expression<'arena>> {
181        match self {
182            ArrayElement::KeyValue(element) => Some(element.key),
183            ArrayElement::Value(_) => None,
184            ArrayElement::Variadic(_) => None,
185            ArrayElement::Missing(_) => None,
186        }
187    }
188
189    #[inline]
190    #[must_use]
191    pub fn get_value(&self) -> Option<&Expression<'arena>> {
192        match self {
193            ArrayElement::KeyValue(element) => Some(element.value),
194            ArrayElement::Value(element) => Some(element.value),
195            ArrayElement::Variadic(element) => Some(element.value),
196            ArrayElement::Missing(_) => None,
197        }
198    }
199}
200
201impl HasSpan for ArrayAccess<'_> {
202    fn span(&self) -> Span {
203        self.array.span().join(self.right_bracket)
204    }
205}
206
207impl HasSpan for ArrayAppend<'_> {
208    fn span(&self) -> Span {
209        self.array.span().join(self.right_bracket)
210    }
211}
212
213impl HasSpan for List<'_> {
214    fn span(&self) -> Span {
215        self.list.span().join(self.right_parenthesis)
216    }
217}
218
219impl HasSpan for Array<'_> {
220    fn span(&self) -> Span {
221        self.left_bracket.join(self.right_bracket)
222    }
223}
224
225impl HasSpan for LegacyArray<'_> {
226    fn span(&self) -> Span {
227        self.array.span().join(self.right_parenthesis)
228    }
229}
230
231impl HasSpan for ArrayElement<'_> {
232    fn span(&self) -> Span {
233        match self {
234            ArrayElement::KeyValue(element) => element.span(),
235            ArrayElement::Value(element) => element.span(),
236            ArrayElement::Variadic(element) => element.span(),
237            ArrayElement::Missing(element) => element.span(),
238        }
239    }
240}
241
242impl HasSpan for KeyValueArrayElement<'_> {
243    fn span(&self) -> Span {
244        self.key.span().join(self.value.span())
245    }
246}
247
248impl HasSpan for ValueArrayElement<'_> {
249    fn span(&self) -> Span {
250        self.value.span()
251    }
252}
253
254impl HasSpan for VariadicArrayElement<'_> {
255    fn span(&self) -> Span {
256        self.ellipsis.join(self.value.span())
257    }
258}
259
260impl HasSpan for MissingArrayElement {
261    fn span(&self) -> Span {
262        self.comma
263    }
264}