diff options
author | Vincent Ambo <mail@tazj.in> | 2022-09-16T18·51+0300 |
---|---|---|
committer | tazjin <tazjin@tvl.su> | 2022-09-17T14·11+0000 |
commit | 337d670d0c0e47622c23fb5c9681df4e4a7048a1 (patch) | |
tree | 5f3b253fe0854f78ecaaa81954f6c7d60237682b /tvix/eval/src/compiler/spans.rs | |
parent | 3a67a140093335e93cee560c1d2f9873035ffa95 (diff) |
feat(tvix/eval): introduce `ToSpan` trait in compiler module r/4883
This trait can be used to convert most structures from rnix-parser into a codemap::Span. It uses a macro to implement the trait for the various expression types in the rnix AST, as Rust's silly semantic versioning restriction stops us from doing a blanket implementation. This will be used in the next commit to clean up the span handling in the compiler a bit. Change-Id: I0a437034e5fa203b5a49c6f25c45932a9f3b2bca Reviewed-on: https://cl.tvl.fyi/c/depot/+/6615 Tested-by: BuildkiteCI Reviewed-by: sterni <sternenseemann@systemli.org>
Diffstat (limited to 'tvix/eval/src/compiler/spans.rs')
-rw-r--r-- | tvix/eval/src/compiler/spans.rs | 84 |
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) + } +} |