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}