snix_eval/
source.rs

1//! This module contains utilities for dealing with the codemap that
2//! needs to be carried across different compiler instantiations in an
3//! evaluation.
4//!
5//! The data type `SourceCode` should be carried through all relevant
6//! places instead of copying the codemap structures directly.
7
8use std::{
9    cell::{Ref, RefCell, RefMut},
10    rc::Rc,
11    sync::Arc,
12};
13
14use codemap::{CodeMap, Span};
15
16/// Tracks all source code in a Snix evaluation for accurate error
17/// reporting.
18#[derive(Clone, Debug)]
19pub struct SourceCode(Rc<RefCell<CodeMap>>);
20
21impl SourceCode {
22    /// Access a read-only reference to the codemap.
23    pub fn codemap(&self) -> Ref<CodeMap> {
24        self.0.borrow()
25    }
26
27    /// Access a writable reference to the codemap.
28    fn codemap_mut(&self) -> RefMut<CodeMap> {
29        self.0.borrow_mut()
30    }
31
32    /// Add a file to the codemap. The returned Arc is managed by the
33    /// codemap internally and can be used like a normal reference.
34    pub fn add_file(&self, name: String, code: String) -> Arc<codemap::File> {
35        self.codemap_mut().add_file(name, code)
36    }
37
38    /// Retrieve the line number of the given span. If it spans
39    /// multiple lines, the first line will be returned.
40    pub fn get_line(&self, span: Span) -> usize {
41        // lines are 0-indexed in the codemap, but users probably want
42        // real line numbers
43        self.codemap().look_up_span(span).begin.line + 1
44    }
45
46    /// Returns the literal source slice of the given span.
47    pub fn source_slice(&self, span: Span) -> Ref<str> {
48        Ref::map(self.codemap(), |c| {
49            c.find_file(span.low()).source_slice(span)
50        })
51    }
52
53    /// Returns the reference to the file structure that a given span
54    /// is in.
55    pub fn get_file(&self, span: Span) -> Arc<codemap::File> {
56        self.codemap().look_up_span(span).file
57    }
58}
59
60impl Default for SourceCode {
61    /// Create a new SourceCode instance.
62    fn default() -> Self {
63        Self(Rc::new(RefCell::new(CodeMap::new())))
64    }
65}