aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def/src/trace.rs
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2019-11-22 18:43:36 +0000
committerAleksey Kladov <[email protected]>2019-11-22 20:09:17 +0000
commit0f415dd4b30289117fe76d071293e9bdd3556336 (patch)
tree908faccf9e77fcb1d2804da3289ebc4d026ce339 /crates/ra_hir_def/src/trace.rs
parent5b19202e00fffe62a1a9c07f4b974f0affdd0c66 (diff)
More principled sources for enums and fields
Diffstat (limited to 'crates/ra_hir_def/src/trace.rs')
-rw-r--r--crates/ra_hir_def/src/trace.rs49
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.
12use ra_arena::{map::ArenaMap, Arena, ArenaId, RawId};
13
14pub(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
21impl<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}