about summary refs log tree commit diff
path: root/tvix/eval/src/compiler/spans.rs
diff options
context:
space:
mode:
Diffstat (limited to 'tvix/eval/src/compiler/spans.rs')
-rw-r--r--tvix/eval/src/compiler/spans.rs84
1 files changed, 84 insertions, 0 deletions
diff --git a/tvix/eval/src/compiler/spans.rs b/tvix/eval/src/compiler/spans.rs
new file mode 100644
index 000000000000..a972a17eddb3
--- /dev/null
+++ b/tvix/eval/src/compiler/spans.rs
@@ -0,0 +1,84 @@
+//! Utilities for dealing with span tracking in the compiler.
+
+use super::*;
+use codemap::{File, Span};
+use rowan::ast::AstNode;
+
+/// Trait implemented by all types from which we can retrieve a span.
+pub(super) trait ToSpan {
+    fn span_for(&self, file: &File) -> Span;
+}
+
+impl ToSpan for Span {
+    fn span_for(&self, _: &File) -> Span {
+        *self
+    }
+}
+
+impl ToSpan for rnix::SyntaxToken {
+    fn span_for(&self, file: &File) -> Span {
+        let rowan_span = self.text_range();
+        file.span.subspan(
+            u32::from(rowan_span.start()) as u64,
+            u32::from(rowan_span.end()) as u64,
+        )
+    }
+}
+
+impl ToSpan for rnix::SyntaxNode {
+    fn span_for(&self, file: &File) -> Span {
+        let rowan_span = self.text_range();
+        file.span.subspan(
+            u32::from(rowan_span.start()) as u64,
+            u32::from(rowan_span.end()) as u64,
+        )
+    }
+}
+
+/// Generates a `ToSpan` implementation for a type implementing
+/// `rowan::AstNode`. This is impossible to do as a blanket
+/// implementation because `rustc` forbids these implementations for
+/// traits from third-party crates due to a belief that semantic
+/// versioning truly could work (it doesn't).
+macro_rules! expr_to_span {
+    ( $type:path ) => {
+        impl ToSpan for $type {
+            fn span_for(&self, file: &File) -> Span {
+                self.syntax().span_for(file)
+            }
+        }
+    };
+}
+
+expr_to_span!(ast::Expr);
+expr_to_span!(ast::Apply);
+expr_to_span!(ast::Assert);
+expr_to_span!(ast::Attr);
+expr_to_span!(ast::AttrSet);
+expr_to_span!(ast::Attrpath);
+expr_to_span!(ast::AttrpathValue);
+expr_to_span!(ast::BinOp);
+expr_to_span!(ast::HasAttr);
+expr_to_span!(ast::Ident);
+expr_to_span!(ast::IdentParam);
+expr_to_span!(ast::IfElse);
+expr_to_span!(ast::Inherit);
+expr_to_span!(ast::Interpol);
+expr_to_span!(ast::Lambda);
+expr_to_span!(ast::LegacyLet);
+expr_to_span!(ast::LetIn);
+expr_to_span!(ast::List);
+expr_to_span!(ast::Literal);
+expr_to_span!(ast::PatBind);
+expr_to_span!(ast::Path);
+expr_to_span!(ast::Pattern);
+expr_to_span!(ast::Select);
+expr_to_span!(ast::Str);
+expr_to_span!(ast::UnaryOp);
+expr_to_span!(ast::With);
+
+impl Compiler<'_, '_> {
+    pub(super) fn span_for<S: ToSpan>(&self, to_span: &S) -> Span {
+        to_span.span_for(self.file)
+    }
+}