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