diff options
Diffstat (limited to 'crates/ra_hir_def/src/trace.rs')
-rw-r--r-- | crates/ra_hir_def/src/trace.rs | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/crates/ra_hir_def/src/trace.rs b/crates/ra_hir_def/src/trace.rs new file mode 100644 index 000000000..fc26f5a48 --- /dev/null +++ b/crates/ra_hir_def/src/trace.rs | |||
@@ -0,0 +1,49 @@ | |||
1 | //! Trace is a pretty niche data structure which is used when lowering a CST | ||
2 | //! into HIR. | ||
3 | //! | ||
4 | //! Lowering process calculates two bits of information: | ||
5 | //! * the lowered syntax itself | ||
6 | //! * a mapping between lowered syntax and original syntax | ||
7 | //! | ||
8 | //! Due to the way salsa works, the mapping is usually hot lava, as it contains | ||
9 | //! absolute offsets. The `Trace` structure (inspired, at least in name, by | ||
10 | //! Kotlin's `BindingTrace`) allows use the same code to compute both | ||
11 | //! projections. | ||
12 | use ra_arena::{map::ArenaMap, Arena, ArenaId, RawId}; | ||
13 | |||
14 | pub(crate) struct Trace<ID: ArenaId, T, V> { | ||
15 | for_arena: bool, | ||
16 | arena: Arena<ID, T>, | ||
17 | map: ArenaMap<ID, V>, | ||
18 | len: u32, | ||
19 | } | ||
20 | |||
21 | impl<ID: ra_arena::ArenaId, T, V> Trace<ID, T, V> { | ||
22 | pub(crate) fn new_for_arena() -> Trace<ID, T, V> { | ||
23 | Trace { for_arena: true, arena: Arena::default(), map: ArenaMap::default(), len: 0 } | ||
24 | } | ||
25 | |||
26 | pub(crate) fn new_for_map() -> Trace<ID, T, V> { | ||
27 | Trace { for_arena: false, arena: Arena::default(), map: ArenaMap::default(), len: 0 } | ||
28 | } | ||
29 | |||
30 | pub(crate) fn alloc(&mut self, value: impl Fn() -> V, data: impl Fn() -> T) { | ||
31 | if self.for_arena { | ||
32 | self.arena.alloc(data()); | ||
33 | } else { | ||
34 | let id = ID::from_raw(RawId::from(self.len)); | ||
35 | self.len += 1; | ||
36 | self.map.insert(id, value()); | ||
37 | } | ||
38 | } | ||
39 | |||
40 | pub(crate) fn into_arena(self) -> Arena<ID, T> { | ||
41 | assert!(self.for_arena); | ||
42 | self.arena | ||
43 | } | ||
44 | |||
45 | pub(crate) fn into_map(self) -> ArenaMap<ID, V> { | ||
46 | assert!(!self.for_arena); | ||
47 | self.map | ||
48 | } | ||
49 | } | ||