//! This module contains utilities for dealing with the codemap that //! needs to be carried across different compiler instantiations in an //! evaluation. //! //! The data type `SourceCode` should be carried through all relevant //! places instead of copying the codemap structures directly. use std::{ cell::{Ref, RefCell, RefMut}, rc::Rc, sync::Arc, }; use codemap::{CodeMap, Span}; /// Tracks all source code in a Tvix evaluation for accurate error /// reporting. #[derive(Clone, Debug)] pub struct SourceCode(Rc<RefCell<CodeMap>>); impl SourceCode { /// Access a read-only reference to the codemap. pub fn codemap(&self) -> Ref<CodeMap> { self.0.borrow() } /// Access a writable reference to the codemap. fn codemap_mut(&self) -> RefMut<CodeMap> { self.0.borrow_mut() } /// Add a file to the codemap. The returned Arc is managed by the /// codemap internally and can be used like a normal reference. pub fn add_file(&self, name: String, code: String) -> Arc<codemap::File> { self.codemap_mut().add_file(name, code) } /// Retrieve the line number of the given span. If it spans /// multiple lines, the first line will be returned. pub fn get_line(&self, span: Span) -> usize { // lines are 0-indexed in the codemap, but users probably want // real line numbers self.codemap().look_up_span(span).begin.line + 1 } /// Returns the literal source slice of the given span. pub fn source_slice(&self, span: Span) -> Ref<str> { Ref::map(self.codemap(), |c| { c.find_file(span.low()).source_slice(span) }) } /// Returns the reference to the file structure that a given span /// is in. pub fn get_file(&self, span: Span) -> Arc<codemap::File> { self.codemap().look_up_span(span).file } } impl Default for SourceCode { /// Create a new SourceCode instance. fn default() -> Self { Self(Rc::new(RefCell::new(CodeMap::new()))) } }