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