miden_core/debuginfo/
span.rs

1use core::{
2    borrow::Borrow,
3    fmt,
4    hash::{Hash, Hasher},
5    ops::{Bound, Deref, DerefMut, Index, Range, RangeBounds},
6};
7
8use super::{ByteIndex, ByteOffset, SourceId};
9use crate::utils::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable};
10
11/// This trait should be implemented for any type that has an associated [SourceSpan].
12pub trait Spanned {
13    fn span(&self) -> SourceSpan;
14}
15
16impl Spanned for SourceSpan {
17    #[inline(always)]
18    fn span(&self) -> SourceSpan {
19        *self
20    }
21}
22
23impl<T: ?Sized + Spanned> Spanned for alloc::boxed::Box<T> {
24    fn span(&self) -> SourceSpan {
25        (**self).span()
26    }
27}
28
29impl<T: ?Sized + Spanned> Spanned for alloc::rc::Rc<T> {
30    fn span(&self) -> SourceSpan {
31        (**self).span()
32    }
33}
34
35impl<T: ?Sized + Spanned> Spanned for alloc::sync::Arc<T> {
36    fn span(&self) -> SourceSpan {
37        (**self).span()
38    }
39}
40
41// SPAN
42// ================================================================================================
43
44/// This type is used to wrap any `T` with a [SourceSpan], and is typically used when it is not
45/// convenient to add a [SourceSpan] to the type - most commonly because we don't control the type.
46pub struct Span<T> {
47    span: SourceSpan,
48    spanned: T,
49}
50
51impl<T> Spanned for Span<T> {
52    fn span(&self) -> SourceSpan {
53        self.span
54    }
55}
56
57impl<T: Copy> Copy for Span<T> {}
58
59impl<T: Clone> Clone for Span<T> {
60    fn clone(&self) -> Self {
61        Self {
62            span: self.span,
63            spanned: self.spanned.clone(),
64        }
65    }
66}
67
68impl<T> Span<T> {
69    /// Creates a span for `spanned` with `span`.
70    #[inline]
71    pub fn new(span: impl Into<SourceSpan>, spanned: T) -> Self {
72        Self { span: span.into(), spanned }
73    }
74
75    /// Creates a span for `spanned` representing a single location, `offset`.
76    #[inline]
77    pub fn at(source_id: SourceId, offset: usize, spanned: T) -> Self {
78        let offset = u32::try_from(offset).expect("invalid source offset: too large");
79        Self {
80            span: SourceSpan::at(source_id, offset),
81            spanned,
82        }
83    }
84
85    /// Creates a [Span] from a value with an unknown/default location.
86    pub fn unknown(spanned: T) -> Self {
87        Self { span: Default::default(), spanned }
88    }
89
90    /// Gets the associated [SourceSpan] for this spanned item.
91    #[inline(always)]
92    pub const fn span(&self) -> SourceSpan {
93        self.span
94    }
95
96    /// Gets a reference to the spanned item.
97    #[inline(always)]
98    pub const fn inner(&self) -> &T {
99        &self.spanned
100    }
101
102    /// Applies a transformation to the spanned value while retaining the same [SourceSpan].
103    #[inline]
104    pub fn map<U, F>(self, mut f: F) -> Span<U>
105    where
106        F: FnMut(T) -> U,
107    {
108        Span {
109            span: self.span,
110            spanned: f(self.spanned),
111        }
112    }
113
114    /// Like [`Option<T>::as_deref`], this constructs a [`Span<U>`] wrapping the result of
115    /// dereferencing the inner value of type `T` as a value of type `U`.
116    pub fn as_deref<U>(&self) -> Span<&U>
117    where
118        U: ?Sized,
119        T: Deref<Target = U>,
120    {
121        Span {
122            span: self.span,
123            spanned: self.spanned.deref(),
124        }
125    }
126
127    /// Gets a new [Span] that borrows the inner value.
128    pub fn as_ref(&self) -> Span<&T> {
129        Span { span: self.span, spanned: &self.spanned }
130    }
131
132    /// Shifts the span right by `count` units
133    #[inline]
134    pub fn shift(&mut self, count: ByteOffset) {
135        self.span.start += count;
136        self.span.end += count;
137    }
138
139    /// Extends the end of the span by `count` units.
140    #[inline]
141    pub fn extend(&mut self, count: ByteOffset) {
142        self.span.end += count;
143    }
144
145    /// Consumes this span, returning the component parts, i.e. the [SourceSpan] and value of type
146    /// `T`.
147    #[inline]
148    pub fn into_parts(self) -> (SourceSpan, T) {
149        (self.span, self.spanned)
150    }
151
152    /// Unwraps the spanned value of type `T`.
153    #[inline]
154    pub fn into_inner(self) -> T {
155        self.spanned
156    }
157}
158
159impl<T: Borrow<str>, S: Borrow<T>> Borrow<T> for Span<S> {
160    fn borrow(&self) -> &T {
161        self.spanned.borrow()
162    }
163}
164
165impl<T> Deref for Span<T> {
166    type Target = T;
167
168    #[inline(always)]
169    fn deref(&self) -> &Self::Target {
170        &self.spanned
171    }
172}
173
174impl<T> DerefMut for Span<T> {
175    #[inline(always)]
176    fn deref_mut(&mut self) -> &mut Self::Target {
177        &mut self.spanned
178    }
179}
180
181impl<T: ?Sized, U: AsRef<T>> AsRef<T> for Span<U> {
182    fn as_ref(&self) -> &T {
183        self.spanned.as_ref()
184    }
185}
186
187impl<T: ?Sized, U: AsMut<T>> AsMut<T> for Span<U> {
188    fn as_mut(&mut self) -> &mut T {
189        self.spanned.as_mut()
190    }
191}
192
193impl<T: fmt::Debug> fmt::Debug for Span<T> {
194    #[inline]
195    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
196        fmt::Debug::fmt(&self.spanned, f)
197    }
198}
199
200impl<T: fmt::Display> fmt::Display for Span<T> {
201    #[inline]
202    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
203        fmt::Display::fmt(&self.spanned, f)
204    }
205}
206
207impl<T: crate::prettier::PrettyPrint> crate::prettier::PrettyPrint for Span<T> {
208    fn render(&self) -> crate::prettier::Document {
209        self.spanned.render()
210    }
211}
212
213impl<T: Eq> Eq for Span<T> {}
214
215impl<T: PartialEq> PartialEq for Span<T> {
216    #[inline]
217    fn eq(&self, other: &Self) -> bool {
218        self.spanned.eq(&other.spanned)
219    }
220}
221
222impl<T: PartialEq> PartialEq<T> for Span<T> {
223    #[inline]
224    fn eq(&self, other: &T) -> bool {
225        self.spanned.eq(other)
226    }
227}
228
229impl<T: Ord> Ord for Span<T> {
230    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
231        self.spanned.cmp(&other.spanned)
232    }
233}
234
235impl<T: PartialOrd> PartialOrd for Span<T> {
236    #[inline]
237    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
238        self.spanned.partial_cmp(&other.spanned)
239    }
240}
241
242impl<T: Hash> Hash for Span<T> {
243    fn hash<H: Hasher>(&self, state: &mut H) {
244        self.spanned.hash(state);
245    }
246}
247
248impl<T: Serializable> Span<T> {
249    pub fn write_into_with_options<W: ByteWriter>(&self, target: &mut W, debug: bool) {
250        if debug {
251            self.span.write_into(target);
252        }
253        self.spanned.write_into(target);
254    }
255}
256
257impl<T: Serializable> Serializable for Span<T> {
258    fn write_into<W: ByteWriter>(&self, target: &mut W) {
259        self.span.write_into(target);
260        self.spanned.write_into(target);
261    }
262}
263
264impl<T: Deserializable> Span<T> {
265    pub fn read_from_with_options<R: ByteReader>(
266        source: &mut R,
267        debug: bool,
268    ) -> Result<Self, DeserializationError> {
269        let span = if debug {
270            SourceSpan::read_from(source)?
271        } else {
272            SourceSpan::default()
273        };
274        let spanned = T::read_from(source)?;
275        Ok(Self { span, spanned })
276    }
277}
278
279impl<T: Deserializable> Deserializable for Span<T> {
280    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
281        let span = SourceSpan::read_from(source)?;
282        let spanned = T::read_from(source)?;
283        Ok(Self { span, spanned })
284    }
285}
286
287// SOURCE SPAN
288// ================================================================================================
289
290/// This represents a span of bytes in a Miden Assembly source file.
291///
292/// It is compact, using only 8 bytes to represent the full span. This does, however, come at the
293/// tradeoff of only supporting source files of up to 2^32 bytes.
294///
295/// This type is produced by the lexer and carried through parsing. It can be converted into a
296/// line/column range as well, if needed.
297///
298/// This representation is more convenient to produce, and allows showing source spans in error
299/// messages, whereas line/column information is useful at a glance in debug output, it is harder
300/// to produce nice errors with it compared to this representation.
301#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
302pub struct SourceSpan {
303    source_id: SourceId,
304    start: ByteIndex,
305    end: ByteIndex,
306}
307
308#[derive(Debug, thiserror::Error)]
309#[error("invalid byte index range: maximum supported byte index is 2^32")]
310pub struct InvalidByteIndexRange;
311
312impl SourceSpan {
313    /// A sentinel [SourceSpan] that indicates the span is unknown/invalid
314    pub const UNKNOWN: Self = Self {
315        source_id: SourceId::UNKNOWN,
316        start: ByteIndex::new(0),
317        end: ByteIndex::new(0),
318    };
319
320    /// Creates a new [SourceSpan] from the given range.
321    pub fn new<B>(source_id: SourceId, range: Range<B>) -> Self
322    where
323        B: Into<ByteIndex>,
324    {
325        Self {
326            source_id,
327            start: range.start.into(),
328            end: range.end.into(),
329        }
330    }
331
332    /// Creates a new [SourceSpan] for a specific offset.
333    pub fn at(source_id: SourceId, offset: impl Into<ByteIndex>) -> Self {
334        let offset = offset.into();
335        Self { source_id, start: offset, end: offset }
336    }
337
338    /// Try to create a new [SourceSpan] from the given range with `usize` bounds.
339    pub fn try_from_range(
340        source_id: SourceId,
341        range: Range<usize>,
342    ) -> Result<Self, InvalidByteIndexRange> {
343        const MAX: usize = u32::MAX as usize;
344        if range.start > MAX || range.end > MAX {
345            return Err(InvalidByteIndexRange);
346        }
347
348        Ok(SourceSpan {
349            source_id,
350            start: ByteIndex::from(range.start as u32),
351            end: ByteIndex::from(range.end as u32),
352        })
353    }
354
355    /// Returns `true` if this [SourceSpan] represents the unknown span
356    pub const fn is_unknown(&self) -> bool {
357        self.source_id.is_unknown()
358    }
359
360    /// Get the [SourceId] associated with this source span
361    #[inline(always)]
362    pub fn source_id(&self) -> SourceId {
363        self.source_id
364    }
365
366    /// Gets the offset in bytes corresponding to the start of this span (inclusive).
367    #[inline(always)]
368    pub fn start(&self) -> ByteIndex {
369        self.start
370    }
371
372    /// Gets the offset in bytes corresponding to the end of this span (exclusive).
373    #[inline(always)]
374    pub fn end(&self) -> ByteIndex {
375        self.end
376    }
377
378    /// Gets the length of this span in bytes.
379    #[inline(always)]
380    pub fn len(&self) -> usize {
381        self.end.to_usize() - self.start.to_usize()
382    }
383
384    /// Returns true if this span is empty.
385    pub fn is_empty(&self) -> bool {
386        self.len() == 0
387    }
388
389    /// Converts this span into a [`Range<u32>`].
390    #[inline]
391    pub fn into_range(self) -> Range<u32> {
392        self.start.to_u32()..self.end.to_u32()
393    }
394
395    /// Converts this span into a [`Range<usize>`].
396    #[inline]
397    pub fn into_slice_index(self) -> Range<usize> {
398        self.start.to_usize()..self.end.to_usize()
399    }
400}
401
402#[cfg(feature = "diagnostics")]
403impl From<SourceSpan> for miette::SourceSpan {
404    fn from(span: SourceSpan) -> Self {
405        Self::new(miette::SourceOffset::from(span.start().to_usize()), span.len())
406    }
407}
408
409impl Serializable for SourceSpan {
410    fn write_into<W: ByteWriter>(&self, target: &mut W) {
411        target.write_u32(self.source_id.to_u32());
412        target.write_u32(self.start.into());
413        target.write_u32(self.end.into())
414    }
415}
416
417impl Deserializable for SourceSpan {
418    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
419        let source_id = SourceId::new_unchecked(source.read_u32()?);
420        let start = ByteIndex::from(source.read_u32()?);
421        let end = ByteIndex::from(source.read_u32()?);
422        Ok(Self { source_id, start, end })
423    }
424}
425
426impl From<SourceSpan> for Range<u32> {
427    #[inline(always)]
428    fn from(span: SourceSpan) -> Self {
429        span.into_range()
430    }
431}
432
433impl From<SourceSpan> for Range<usize> {
434    #[inline(always)]
435    fn from(span: SourceSpan) -> Self {
436        span.into_slice_index()
437    }
438}
439
440impl Index<SourceSpan> for [u8] {
441    type Output = [u8];
442
443    #[inline]
444    fn index(&self, index: SourceSpan) -> &Self::Output {
445        &self[index.start().to_usize()..index.end().to_usize()]
446    }
447}
448
449impl RangeBounds<ByteIndex> for SourceSpan {
450    #[inline(always)]
451    fn start_bound(&self) -> Bound<&ByteIndex> {
452        Bound::Included(&self.start)
453    }
454
455    #[inline(always)]
456    fn end_bound(&self) -> Bound<&ByteIndex> {
457        Bound::Excluded(&self.end)
458    }
459}