mago_ast/
sequence.rs

1use std::slice::Iter;
2use std::vec::IntoIter;
3
4use serde::Deserialize;
5use serde::Serialize;
6
7use mago_span::HasSpan;
8use mago_span::Position;
9use mago_span::Span;
10use mago_token::Token;
11
12/// Represents a sequence of nodes.
13///
14/// An example of this is modifiers in a method declaration.
15///
16/// i.e. `public` and `static` in `public static function foo() {}`.
17#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
18#[repr(transparent)]
19pub struct Sequence<T> {
20    pub nodes: Vec<T>,
21}
22
23/// Represents a sequence of nodes separated by a token.
24///
25/// An example of this is arguments in a function call, where the tokens are commas.
26///
27/// i.e. `1`, `2` and `3` in `foo(1, 2, 3)`.
28#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
29pub struct TokenSeparatedSequence<T> {
30    pub nodes: Vec<T>,
31    pub tokens: Vec<Token>,
32}
33
34impl<T: HasSpan> Sequence<T> {
35    #[inline]
36    pub const fn new(inner: Vec<T>) -> Self {
37        Self { nodes: inner }
38    }
39
40    #[inline]
41    pub const fn empty() -> Self {
42        Self { nodes: vec![] }
43    }
44
45    #[inline]
46    pub fn len(&self) -> usize {
47        self.nodes.len()
48    }
49
50    #[inline]
51    pub fn is_empty(&self) -> bool {
52        self.nodes.is_empty()
53    }
54
55    #[inline]
56    #[must_use]
57    pub fn get(&self, index: usize) -> Option<&T> {
58        self.nodes.get(index)
59    }
60
61    #[inline]
62    #[must_use]
63    pub fn first(&self) -> Option<&T> {
64        self.nodes.first()
65    }
66
67    #[inline]
68    #[must_use]
69    pub fn first_span(&self) -> Option<Span> {
70        self.nodes.first().map(|node| node.span())
71    }
72
73    #[inline]
74    #[must_use]
75    pub fn last(&self) -> Option<&T> {
76        self.nodes.last()
77    }
78
79    #[inline]
80    #[must_use]
81    pub fn last_span(&self) -> Option<Span> {
82        self.nodes.last().map(|node| node.span())
83    }
84
85    #[inline]
86    #[must_use]
87    pub fn span(&self, from: Position) -> Span {
88        self.last_span().map_or(Span::new(from, from), |span| Span::new(from, span.end))
89    }
90
91    #[inline]
92    pub fn iter(&self) -> Iter<'_, T> {
93        self.nodes.iter()
94    }
95
96    #[inline]
97    #[must_use]
98    pub fn as_slice(&self) -> &[T] {
99        self.nodes.as_slice()
100    }
101}
102
103impl<T: HasSpan> TokenSeparatedSequence<T> {
104    #[inline]
105    #[must_use]
106    pub const fn new(inner: Vec<T>, tokens: Vec<Token>) -> Self {
107        Self { nodes: inner, tokens }
108    }
109
110    #[inline]
111    #[must_use]
112    pub const fn empty() -> Self {
113        Self { nodes: vec![], tokens: vec![] }
114    }
115
116    #[inline]
117    pub fn len(&self) -> usize {
118        self.nodes.len()
119    }
120
121    #[inline]
122    pub fn is_empty(&self) -> bool {
123        self.nodes.is_empty()
124    }
125
126    #[inline]
127    pub fn get(&self, index: usize) -> Option<&T> {
128        self.nodes.get(index)
129    }
130
131    #[inline]
132    #[must_use]
133    pub fn first(&self) -> Option<&T> {
134        self.nodes.first()
135    }
136
137    #[inline]
138    pub fn first_span(&self) -> Option<Span> {
139        match (self.tokens.first(), self.nodes.first()) {
140            (Some(token), Some(node)) => {
141                // check if the token comes before the node
142                if token.span.end <= node.span().start { Some(token.span) } else { Some(node.span()) }
143            }
144            (Some(token), None) => Some(token.span),
145            (None, Some(node)) => Some(node.span()),
146            (None, None) => None,
147        }
148    }
149
150    #[inline]
151    pub fn last(&self) -> Option<&T> {
152        self.nodes.last()
153    }
154
155    #[inline]
156    pub fn last_span(&self) -> Option<Span> {
157        match (self.tokens.last(), self.nodes.last()) {
158            (Some(token), Some(node)) => {
159                // check if the token comes after the node
160                if token.span.start >= node.span().end { Some(token.span) } else { Some(node.span()) }
161            }
162            (Some(token), None) => Some(token.span),
163            (None, Some(node)) => Some(node.span()),
164            (None, None) => None,
165        }
166    }
167
168    #[inline]
169    pub fn span(&self, from: Position) -> Span {
170        self.last_span().map_or(Span::new(from, from), |span| Span::new(from, span.end))
171    }
172
173    #[inline]
174    pub fn has_trailing_token(&self) -> bool {
175        self.tokens.last().is_some_and(|token| token.span.start >= self.last_span().unwrap().end)
176    }
177
178    #[inline]
179    pub fn get_trailing_token(&self) -> Option<&Token> {
180        self.tokens.last().filter(|token| token.span.start >= self.last_span().unwrap().end)
181    }
182
183    #[inline]
184    pub fn iter(&self) -> Iter<'_, T> {
185        self.nodes.iter()
186    }
187
188    /// Returns an iterator over the sequence, where each item includes
189    /// the index of the element, the element and the token following it.
190    /// The token is `None` only for the last element if it has no trailing token.
191    #[inline]
192    pub fn iter_with_tokens(&self) -> impl Iterator<Item = (usize, &T, Option<&Token>)> {
193        self.nodes.iter().enumerate().map(move |(i, item)| {
194            let token = self.tokens.get(i);
195
196            (i, item, token)
197        })
198    }
199
200    #[inline]
201    pub fn as_slice(&self) -> &[T] {
202        self.nodes.as_slice()
203    }
204}
205
206impl<T: HasSpan> FromIterator<T> for Sequence<T> {
207    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
208        Self { nodes: iter.into_iter().collect() }
209    }
210}
211
212impl<T: HasSpan> IntoIterator for Sequence<T> {
213    type Item = T;
214    type IntoIter = IntoIter<Self::Item>;
215
216    fn into_iter(self) -> Self::IntoIter {
217        self.nodes.into_iter()
218    }
219}
220
221impl<T: HasSpan> IntoIterator for TokenSeparatedSequence<T> {
222    type Item = T;
223    type IntoIter = IntoIter<Self::Item>;
224
225    fn into_iter(self) -> Self::IntoIter {
226        self.nodes.into_iter()
227    }
228}
229
230impl<T: HasSpan> std::default::Default for Sequence<T> {
231    fn default() -> Self {
232        Sequence::new(Default::default())
233    }
234}
235
236impl<T: HasSpan> std::default::Default for TokenSeparatedSequence<T> {
237    fn default() -> Self {
238        TokenSeparatedSequence::new(Default::default(), Default::default())
239    }
240}