1use std::slice::Iter;
4
5use mago_allocator::prelude::*;
6
7use mago_span::HasPosition;
8use mago_span::HasSpan;
9use mago_span::Span;
10
11#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord)]
13#[cfg_attr(feature = "serde", derive(serde::Serialize))]
14#[repr(transparent)]
15pub struct Sequence<'arena, T> {
16 pub nodes: &'arena [T],
17}
18
19impl<'arena, T> Sequence<'arena, T> {
20 #[inline]
22 #[must_use]
23 pub fn new<A>(nodes: Vec<'arena, T, A>) -> Self
24 where
25 A: Arena,
26 {
27 Self { nodes: nodes.leak() }
28 }
29
30 #[inline]
32 #[must_use]
33 pub const fn from_slice(nodes: &'arena [T]) -> Self {
34 Self { nodes }
35 }
36
37 #[inline]
38 #[must_use]
39 pub const fn empty() -> Self {
40 Self { nodes: &[] }
41 }
42
43 #[inline]
44 #[must_use]
45 pub fn len(&self) -> usize {
46 self.nodes.len()
47 }
48
49 #[inline]
50 #[must_use]
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 last(&self) -> Option<&T> {
70 self.nodes.last()
71 }
72
73 #[inline]
74 pub fn iter(&self) -> Iter<'_, T> {
75 self.nodes.iter()
76 }
77
78 #[inline]
79 #[must_use]
80 pub fn as_slice(&self) -> &[T] {
81 self.nodes
82 }
83}
84
85impl<T: HasSpan> Sequence<'_, T> {
86 #[inline]
87 #[must_use]
88 pub fn first_span(&self) -> Option<Span> {
89 self.nodes.first().map(HasSpan::span)
90 }
91
92 #[inline]
93 #[must_use]
94 pub fn last_span(&self) -> Option<Span> {
95 self.nodes.last().map(HasSpan::span)
96 }
97
98 #[inline]
102 #[must_use]
103 pub fn span(&self, file_id: mago_database::file::FileId, from: mago_span::Position) -> Span {
104 self.last_span().map_or(Span::new(file_id, from, from), |span| Span::new(file_id, from, span.end))
105 }
106}
107
108impl<T> std::ops::Index<usize> for Sequence<'_, T> {
109 type Output = T;
110
111 #[inline]
112 fn index(&self, index: usize) -> &T {
113 &self.nodes[index]
114 }
115}
116
117impl<T, Tok> std::ops::Index<usize> for TokenSeparatedSequence<'_, T, Tok> {
118 type Output = T;
119
120 #[inline]
121 fn index(&self, index: usize) -> &T {
122 &self.nodes[index]
123 }
124}
125
126impl<'arena, T> IntoIterator for Sequence<'arena, T> {
127 type Item = &'arena T;
128 type IntoIter = Iter<'arena, T>;
129
130 fn into_iter(self) -> Self::IntoIter {
131 self.nodes.iter()
132 }
133}
134
135impl<'seq, T> IntoIterator for &'seq Sequence<'_, T> {
136 type Item = &'seq T;
137 type IntoIter = Iter<'seq, T>;
138
139 fn into_iter(self) -> Self::IntoIter {
140 self.iter()
141 }
142}
143
144#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
155#[cfg_attr(feature = "serde", derive(serde::Serialize))]
156pub struct TokenSeparatedSequence<'arena, T, Tok> {
157 pub nodes: &'arena [T],
158 pub tokens: &'arena [Tok],
159}
160
161impl<'arena, T, Tok> TokenSeparatedSequence<'arena, T, Tok> {
162 #[inline]
164 #[must_use]
165 pub fn new<A>(nodes: Vec<'arena, T, A>, tokens: Vec<'arena, Tok, A>) -> Self
166 where
167 A: Arena,
168 {
169 Self { nodes: nodes.leak(), tokens: tokens.leak() }
170 }
171
172 #[inline]
174 #[must_use]
175 pub const fn from_slices(nodes: &'arena [T], tokens: &'arena [Tok]) -> Self {
176 Self { nodes, tokens }
177 }
178
179 #[inline]
180 #[must_use]
181 pub const fn empty() -> Self {
182 Self { nodes: &[], tokens: &[] }
183 }
184
185 #[inline]
186 #[must_use]
187 pub fn len(&self) -> usize {
188 self.nodes.len()
189 }
190
191 #[inline]
192 #[must_use]
193 pub fn is_empty(&self) -> bool {
194 self.nodes.is_empty()
195 }
196
197 #[inline]
198 #[must_use]
199 pub fn get(&self, index: usize) -> Option<&T> {
200 self.nodes.get(index)
201 }
202
203 #[inline]
204 #[must_use]
205 pub fn first(&self) -> Option<&T> {
206 self.nodes.first()
207 }
208
209 #[inline]
210 #[must_use]
211 pub fn last(&self) -> Option<&T> {
212 self.nodes.last()
213 }
214
215 #[inline]
216 pub fn iter(&self) -> Iter<'_, T> {
217 self.nodes.iter()
218 }
219
220 #[inline]
221 #[must_use]
222 pub fn as_slice(&self) -> &[T] {
223 self.nodes
224 }
225
226 #[inline]
231 pub fn iter_with_tokens(&self) -> impl Iterator<Item = (usize, &T, Option<&Tok>)> {
232 self.nodes.iter().enumerate().map(move |(i, item)| (i, item, self.tokens.get(i)))
233 }
234}
235
236impl<T, Tok> TokenSeparatedSequence<'_, T, Tok>
237where
238 T: HasSpan,
239 Tok: HasPosition,
240{
241 #[inline]
243 #[must_use]
244 pub fn has_trailing_token(&self) -> bool {
245 self.tokens.last().is_some_and(|t| t.offset() >= self.nodes.last().map_or(0, |n| n.span().end.offset))
246 }
247
248 #[inline]
250 #[must_use]
251 pub fn get_trailing_token(&self) -> Option<&Tok> {
252 self.tokens.last().filter(|t| t.offset() >= self.nodes.last().map_or(0, |n| n.span().end.offset))
253 }
254}
255
256impl<'arena, T, Tok> IntoIterator for TokenSeparatedSequence<'arena, T, Tok> {
257 type Item = &'arena T;
258 type IntoIter = Iter<'arena, T>;
259
260 fn into_iter(self) -> Self::IntoIter {
261 self.nodes.iter()
262 }
263}
264
265impl<'seq, T, Tok> IntoIterator for &'seq TokenSeparatedSequence<'_, T, Tok> {
266 type Item = &'seq T;
267 type IntoIter = Iter<'seq, T>;
268
269 fn into_iter(self) -> Self::IntoIter {
270 self.iter()
271 }
272}