mago_syntax/ast/
sequence.rs1use std::slice::Iter;
2use std::vec::IntoIter;
3
4use mago_database::file::FileId;
5use serde::Deserialize;
6use serde::Serialize;
7
8use mago_span::HasSpan;
9use mago_span::Position;
10use mago_span::Span;
11
12use crate::token::Token;
13
14#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
20#[repr(transparent)]
21pub struct Sequence<T> {
22 pub nodes: Vec<T>,
23}
24
25#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
31pub struct TokenSeparatedSequence<T> {
32 pub nodes: Vec<T>,
33 pub tokens: Vec<Token>,
34}
35
36impl<T: HasSpan> Sequence<T> {
37 #[inline]
38 pub const fn new(inner: Vec<T>) -> Self {
39 Self { nodes: inner }
40 }
41
42 #[inline]
43 pub const fn empty() -> Self {
44 Self { nodes: vec![] }
45 }
46
47 #[inline]
48 pub fn len(&self) -> usize {
49 self.nodes.len()
50 }
51
52 #[inline]
53 pub fn is_empty(&self) -> bool {
54 self.nodes.is_empty()
55 }
56
57 #[inline]
58 #[must_use]
59 pub fn get(&self, index: usize) -> Option<&T> {
60 self.nodes.get(index)
61 }
62
63 #[inline]
64 #[must_use]
65 pub fn first(&self) -> Option<&T> {
66 self.nodes.first()
67 }
68
69 #[inline]
70 #[must_use]
71 pub fn first_span(&self) -> Option<Span> {
72 self.nodes.first().map(|node| node.span())
73 }
74
75 #[inline]
76 #[must_use]
77 pub fn last(&self) -> Option<&T> {
78 self.nodes.last()
79 }
80
81 #[inline]
82 #[must_use]
83 pub fn last_span(&self) -> Option<Span> {
84 self.nodes.last().map(|node| node.span())
85 }
86
87 #[inline]
88 #[must_use]
89 pub fn span(&self, file_id: FileId, from: Position) -> Span {
90 self.last_span().map_or(Span::new(file_id, from, from), |span| Span::new(file_id, from, span.end))
91 }
92
93 #[inline]
94 pub fn iter(&self) -> Iter<'_, T> {
95 self.nodes.iter()
96 }
97
98 #[inline]
99 #[must_use]
100 pub fn as_slice(&self) -> &[T] {
101 self.nodes.as_slice()
102 }
103
104 #[inline]
105 pub fn to_vec(&self) -> Vec<&T> {
106 self.nodes.iter().collect()
107 }
108}
109
110impl<T: HasSpan> TokenSeparatedSequence<T> {
111 #[inline]
112 #[must_use]
113 pub const fn new(inner: Vec<T>, tokens: Vec<Token>) -> Self {
114 Self { nodes: inner, tokens }
115 }
116
117 #[inline]
118 #[must_use]
119 pub const fn empty() -> Self {
120 Self { nodes: vec![], tokens: vec![] }
121 }
122
123 #[inline]
124 pub fn len(&self) -> usize {
125 self.nodes.len()
126 }
127
128 #[inline]
129 pub fn is_empty(&self) -> bool {
130 self.nodes.is_empty()
131 }
132
133 #[inline]
134 pub fn get(&self, index: usize) -> Option<&T> {
135 self.nodes.get(index)
136 }
137
138 #[inline]
139 #[must_use]
140 pub fn first(&self) -> Option<&T> {
141 self.nodes.first()
142 }
143
144 #[inline]
145 pub fn first_span(&self) -> Option<Span> {
146 match (self.tokens.first(), self.nodes.first()) {
147 (Some(token), Some(node)) => {
148 if token.span.end <= node.span().start { Some(token.span) } else { Some(node.span()) }
150 }
151 (Some(token), None) => Some(token.span),
152 (None, Some(node)) => Some(node.span()),
153 (None, None) => None,
154 }
155 }
156
157 #[inline]
158 pub fn last(&self) -> Option<&T> {
159 self.nodes.last()
160 }
161
162 #[inline]
163 pub fn last_span(&self) -> Option<Span> {
164 match (self.tokens.last(), self.nodes.last()) {
165 (Some(token), Some(node)) => {
166 if token.span.start >= node.span().end { Some(token.span) } else { Some(node.span()) }
168 }
169 (Some(token), None) => Some(token.span),
170 (None, Some(node)) => Some(node.span()),
171 (None, None) => None,
172 }
173 }
174
175 #[inline]
176 pub fn span(&self, file_id: FileId, from: Position) -> Span {
177 match (self.first_span(), self.last_span()) {
178 (Some(first), Some(last)) => Span::new(file_id, first.start, last.end),
179 _ => Span::new(file_id, from, from),
180 }
181 }
182
183 #[inline]
184 pub fn has_trailing_token(&self) -> bool {
185 self.tokens
186 .last()
187 .is_some_and(|token| token.span.start.offset >= self.nodes.last().map_or(0, |node| node.span().end.offset))
188 }
189
190 #[inline]
191 pub fn get_trailing_token(&self) -> Option<&Token> {
192 self.tokens
193 .last()
194 .filter(|token| token.span.start.offset >= self.nodes.last().map_or(0, |node| node.span().end.offset))
195 }
196
197 #[inline]
198 pub fn iter(&self) -> Iter<'_, T> {
199 self.nodes.iter()
200 }
201
202 #[inline]
206 pub fn iter_with_tokens(&self) -> impl Iterator<Item = (usize, &T, Option<&Token>)> {
207 self.nodes.iter().enumerate().map(move |(i, item)| {
208 let token = self.tokens.get(i);
209
210 (i, item, token)
211 })
212 }
213
214 #[inline]
215 pub fn as_slice(&self) -> &[T] {
216 self.nodes.as_slice()
217 }
218
219 #[inline]
220 pub fn to_vec(&self) -> Vec<&T> {
221 self.nodes.iter().collect()
222 }
223}
224
225impl<T: HasSpan> FromIterator<T> for Sequence<T> {
226 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
227 Self { nodes: iter.into_iter().collect() }
228 }
229}
230
231impl<T: HasSpan> IntoIterator for Sequence<T> {
232 type Item = T;
233 type IntoIter = IntoIter<Self::Item>;
234
235 fn into_iter(self) -> Self::IntoIter {
236 self.nodes.into_iter()
237 }
238}
239
240impl<T: HasSpan> IntoIterator for TokenSeparatedSequence<T> {
241 type Item = T;
242 type IntoIter = IntoIter<Self::Item>;
243
244 fn into_iter(self) -> Self::IntoIter {
245 self.nodes.into_iter()
246 }
247}
248
249impl<T: HasSpan> std::default::Default for Sequence<T> {
250 fn default() -> Self {
251 Sequence::new(Default::default())
252 }
253}
254
255impl<T: HasSpan> std::default::Default for TokenSeparatedSequence<T> {
256 fn default() -> Self {
257 TokenSeparatedSequence::new(Default::default(), Default::default())
258 }
259}