kind_span/
lib.rs

1/// Position in a syntax context.
2#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
3pub struct Pos {
4    pub index: u32,
5}
6
7/// A syntax context index.
8#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
9pub struct SyntaxCtxIndex(pub usize);
10
11impl SyntaxCtxIndex {
12    pub fn new(size: usize) -> SyntaxCtxIndex {
13        SyntaxCtxIndex(size)
14    }
15
16    /// WARNING: Probably ghost ranges cause problems with it
17    pub fn is_root(&self) -> bool {
18        self.0 == 0
19    }
20}
21
22/// A span in the encoded format that is required by
23/// kind2.
24#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
25pub struct EncodedRange(pub u64);
26
27/// Describes a position in a source code (syntax context). It's useful
28/// to generate error messages.
29#[derive(Clone, Debug, Copy, Hash, PartialEq, Eq)]
30pub struct Range {
31    pub start: Pos,
32    pub end: Pos,
33    pub ctx: SyntaxCtxIndex,
34}
35
36pub trait Locatable {
37    fn locate(&self) -> Range;
38}
39
40impl Range {
41    #[inline]
42    pub fn new(start: Pos, end: Pos, ctx: SyntaxCtxIndex) -> Range {
43        Range { start, end, ctx }
44    }
45
46    pub fn ghost_range() -> Range {
47        Range::new(Pos { index: 0 }, Pos { index: 0 }, SyntaxCtxIndex(0))
48    }
49
50    /// Joins two ranges. It keeps the syntax context
51    /// of the first one.
52    #[inline]
53    pub fn mix(&self, next: Range) -> Range {
54        Range {
55            start: self.start,
56            end: next.end,
57            ctx: self.ctx,
58        }
59    }
60
61    /// Sets the context of the range,
62    #[inline]
63    pub fn set_ctx(&self, ctx: SyntaxCtxIndex) -> Range {
64        Range {
65            start: self.start,
66            end: self.end,
67            ctx,
68        }
69    }
70
71    #[inline]
72    pub fn encode(&self) -> EncodedRange {
73        EncodedRange(
74            ((self.ctx.0 as u64) << 48)
75                | ((self.start.index as u64) & 0xFFFFFF)
76                | (((self.end.index as u64) & 0xFFFFFF) << 24),
77        )
78    }
79}
80
81impl EncodedRange {
82    /// Transforms a encoded span back into a range.
83    pub fn to_range(&self) -> Range {
84        Range {
85            ctx: SyntaxCtxIndex((self.0 >> 48) as usize),
86            start: Pos {
87                index: (self.0 & 0xFFFFFF) as u32,
88            },
89            end: Pos {
90                index: ((self.0 >> 24) & 0xFFFFFF) as u32,
91            },
92        }
93    }
94}