Skip to main content

miden_debug_types/
span.rs

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