rune/compile/
location.rs

1use core::fmt;
2
3use crate as rune;
4use crate::alloc::prelude::*;
5use crate::ast::{Span, Spanned};
6use crate::SourceId;
7
8/// A fully descriptive location which is a combination of a [SourceId] and a
9/// [Span].
10#[derive(Default, TryClone, Clone, Copy)]
11#[try_clone(copy)]
12#[non_exhaustive]
13pub struct Location {
14    /// The source id of the file of the location.
15    pub source_id: SourceId,
16    /// The span of the location.
17    pub span: Span,
18}
19
20impl Location {
21    /// Construct a new location.
22    pub(crate) const fn new(source_id: SourceId, span: Span) -> Self {
23        Self { source_id, span }
24    }
25}
26
27impl Spanned for Location {
28    #[inline]
29    fn span(&self) -> Span {
30        self.span
31    }
32}
33
34impl Located for Location {
35    #[inline]
36    fn location(&self) -> Location {
37        *self
38    }
39
40    #[inline]
41    fn as_spanned(&self) -> &dyn Spanned {
42        self
43    }
44}
45
46impl Spanned for dyn Located {
47    #[inline]
48    fn span(&self) -> Span {
49        self.as_spanned().span()
50    }
51}
52
53/// Trait for things that have a [Location].
54pub trait Located {
55    /// Get the assocaited location.
56    fn location(&self) -> Location;
57
58    /// Get located item as spanned.
59    fn as_spanned(&self) -> &dyn Spanned;
60}
61
62pub(crate) struct DynLocation<S> {
63    source_id: SourceId,
64    span: S,
65}
66
67impl<S> DynLocation<S> {
68    #[inline(always)]
69    pub(crate) const fn new(source_id: SourceId, span: S) -> Self {
70        Self { source_id, span }
71    }
72}
73
74impl<S> Spanned for DynLocation<S>
75where
76    S: Spanned,
77{
78    #[inline]
79    fn span(&self) -> Span {
80        self.span.span()
81    }
82}
83
84impl<S> Located for DynLocation<S>
85where
86    S: Spanned,
87{
88    #[inline]
89    fn location(&self) -> Location {
90        Location {
91            source_id: self.source_id,
92            span: self.span.span(),
93        }
94    }
95
96    #[inline]
97    fn as_spanned(&self) -> &dyn Spanned {
98        self
99    }
100}
101
102impl fmt::Debug for Location {
103    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
104        f.debug_tuple("Location")
105            .field(&self.source_id)
106            .field(&self.span)
107            .finish()
108    }
109}