diff options
Diffstat (limited to 'tvix/eval/src/source.rs')
-rw-r--r-- | tvix/eval/src/source.rs | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/tvix/eval/src/source.rs b/tvix/eval/src/source.rs new file mode 100644 index 000000000000..5a7f10abb8da --- /dev/null +++ b/tvix/eval/src/source.rs @@ -0,0 +1,65 @@ +//! 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()))) + } +} |