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 la_arena::{Arena, ArenaMap, Idx, RawIdx}; 13 14 pub(crate) struct Trace<T, V> { 15 arena: Option<Arena<T>>, 16 map: Option<ArenaMap<Idx<T>, V>>, 17 len: u32, 18 } 19 20 impl<T, V> Trace<T, V> { new_for_arena() -> Trace<T, V>21 pub(crate) fn new_for_arena() -> Trace<T, V> { 22 Trace { arena: Some(Arena::default()), map: None, len: 0 } 23 } 24 new_for_map() -> Trace<T, V>25 pub(crate) fn new_for_map() -> Trace<T, V> { 26 Trace { arena: None, map: Some(ArenaMap::default()), len: 0 } 27 } 28 alloc(&mut self, value: impl FnOnce() -> V, data: impl FnOnce() -> T) -> Idx<T>29 pub(crate) fn alloc(&mut self, value: impl FnOnce() -> V, data: impl FnOnce() -> T) -> Idx<T> { 30 let id = if let Some(arena) = &mut self.arena { 31 arena.alloc(data()) 32 } else { 33 let id = Idx::<T>::from_raw(RawIdx::from(self.len)); 34 self.len += 1; 35 id 36 }; 37 38 if let Some(map) = &mut self.map { 39 map.insert(id, value()); 40 } 41 id 42 } 43 into_arena(mut self) -> Arena<T>44 pub(crate) fn into_arena(mut self) -> Arena<T> { 45 self.arena.take().unwrap() 46 } 47 into_map(mut self) -> ArenaMap<Idx<T>, V>48 pub(crate) fn into_map(mut self) -> ArenaMap<Idx<T>, V> { 49 self.map.take().unwrap() 50 } 51 } 52