From 3c3730425f0a9a4241c4f57cb7f4d00b71db201e Mon Sep 17 00:00:00 2001 From: Laurenz Date: Wed, 30 Sep 2020 14:38:46 +0200 Subject: [PATCH] =?UTF-8?q?SpanWith=20trait=20=E2=86=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/compute/value.rs | 17 ++++++++--------- src/layout/tree.rs | 10 +++++----- src/parse/parser.rs | 32 ++++++++++++++++---------------- src/parse/tests.rs | 2 +- src/parse/tokenizer.rs | 4 ++-- src/syntax/span.rs | 10 ++++++++++ src/syntax/tree.rs | 8 ++++---- 7 files changed, 46 insertions(+), 37 deletions(-) diff --git a/src/compute/value.rs b/src/compute/value.rs index 95219a5c6..ef36e5d8a 100644 --- a/src/compute/value.rs +++ b/src/compute/value.rs @@ -11,7 +11,7 @@ use crate::color::RgbaColor; use crate::layout::{Command, Commands, Dir, LayoutContext, SpecAlign}; use crate::length::{Length, ScaleLength}; use crate::paper::Paper; -use crate::syntax::{Ident, Span, Spanned, SyntaxNode, SyntaxTree}; +use crate::syntax::{Ident, Span, SpanWith, Spanned, SyntaxNode, SyntaxTree}; use crate::{DynFuture, Feedback, Pass}; /// A computational value. @@ -76,10 +76,8 @@ impl Spanned { for entry in table.into_values() { if let Some(last_end) = end { let span = Span::new(last_end, entry.key.start); - commands.push(Command::LayoutSyntaxTree(vec![Spanned::new( - SyntaxNode::Spacing, - span, - )])); + let tree = vec![SyntaxNode::Spacing.span_with(span)]; + commands.push(Command::LayoutSyntaxTree(tree)); } end = Some(entry.val.span.end); @@ -89,10 +87,11 @@ impl Spanned { } // Format with debug. - val => vec![Command::LayoutSyntaxTree(vec![Spanned::new( - SyntaxNode::Text(format!("{:?}", val)), - self.span, - )])], + val => { + let fmt = format!("{:?}", val); + let tree = vec![SyntaxNode::Text(fmt).span_with(self.span)]; + vec![Command::LayoutSyntaxTree(tree)] + } } } } diff --git a/src/layout/tree.rs b/src/layout/tree.rs index 19bff091a..82a91131a 100644 --- a/src/layout/tree.rs +++ b/src/layout/tree.rs @@ -5,7 +5,7 @@ use super::text::{layout_text, TextContext}; use super::*; use crate::style::LayoutStyle; use crate::syntax::{ - CallExpr, Code, Decoration, Heading, Span, Spanned, SyntaxNode, SyntaxTree, + CallExpr, Code, Decoration, Heading, Span, SpanWith, Spanned, SyntaxNode, SyntaxTree, }; use crate::{DynFuture, Feedback, Pass}; @@ -53,8 +53,8 @@ impl<'a> TreeLayouter<'a> { } async fn layout_node(&mut self, node: &Spanned) { - let decorate = |this: &mut Self, deco| { - this.feedback.decorations.push(Spanned::new(deco, node.span)); + let decorate = |this: &mut Self, deco: Decoration| { + this.feedback.decorations.push(deco.span_with(node.span)); }; match &node.v { @@ -87,7 +87,7 @@ impl<'a> TreeLayouter<'a> { SyntaxNode::Code(block) => self.layout_code(block).await, SyntaxNode::Call(call) => { - self.layout_call(Spanned::new(call, node.span)).await; + self.layout_call(call.span_with(node.span)).await; } } } @@ -167,7 +167,7 @@ impl<'a> TreeLayouter<'a> { }; let val = call.v.eval(&ctx, &mut self.feedback).await; - let commands = Spanned::new(val, call.span).into_commands(); + let commands = val.span_with(call.span).into_commands(); for command in commands { self.execute_command(command, call.span).await; diff --git a/src/parse/parser.rs b/src/parse/parser.rs index 2ff30397d..bbd7ee1d2 100644 --- a/src/parse/parser.rs +++ b/src/parse/parser.rs @@ -113,7 +113,7 @@ impl Parser<'_> { let lang = lang.and_then(|lang| { if let Some(ident) = Ident::new(lang.v) { - Some(Spanned::new(ident, lang.span)) + Some(ident.span_with(lang.span)) } else { error!(@self.feedback, lang.span, "invalid identifier"); None @@ -166,7 +166,7 @@ impl Parser<'_> { } let span = Span::new(start, self.pos()); - let level = Spanned::new(level, span); + let level = level.span_with(span); if level.v > 5 { warning!( @@ -185,7 +185,7 @@ impl Parser<'_> { } let span = Span::new(start, self.pos()); - Spanned::new(Heading { level, tree }, span) + Heading { level, tree }.span_with(span) } } @@ -203,7 +203,7 @@ impl Parser<'_> { self.skip_ws(); let name = self.parse_ident().unwrap_or_else(|| { self.expected_found_or_at("function name", before_name); - Spanned::new(Ident(String::new()), Span::at(before_name)) + Ident(String::new()).span_with(Span::at(before_name)) }); self.skip_ws(); @@ -224,7 +224,7 @@ impl Parser<'_> { let item = self.parse_bracket_call(true); let span = item.span; let t = vec![item.map(SyntaxNode::Call)]; - args.push(SpannedEntry::val(Spanned::new(Expr::Tree(t), span))); + args.push(SpannedEntry::val(Expr::Tree(t).span_with(span))); (true, span.end) } else { self.tokens.pop_mode(); @@ -244,11 +244,11 @@ impl Parser<'_> { let body_span = self.end_group(); let expr = Expr::Tree(body); - args.push(SpannedEntry::val(Spanned::new(expr, body_span))); + args.push(SpannedEntry::val(expr.span_with(body_span))); span.expand(body_span); } - Spanned::new(CallExpr { name, args }, span) + CallExpr { name, args }.span_with(span) } fn parse_paren_call(&mut self, name: Spanned) -> Spanned { @@ -256,7 +256,7 @@ impl Parser<'_> { let args = self.parse_table_contents().0; let args_span = self.end_group(); let span = Span::merge(name.span, args_span); - Spanned::new(CallExpr { name, args }, span) + CallExpr { name, args }.span_with(span) } } @@ -305,7 +305,7 @@ impl Parser<'_> { table.insert(key.v.0, SpannedEntry::new(key.span, val)); self.feedback .decorations - .push(Spanned::new(Decoration::TableKey, key.span)); + .push(Decoration::TableKey.span_with(key.span)); } else { table.push(SpannedEntry::val(val)); } @@ -364,7 +364,7 @@ impl Parser<'_> { if let Some(right) = parse_operand(self) { let span = Span::merge(left.span, right.span); let v = op(Box::new(left), Box::new(right)); - left = Spanned::new(v, span); + left = v.span_with(span); self.skip_ws(); continue; } @@ -385,7 +385,7 @@ impl Parser<'_> { self.skip_ws(); if let Some(factor) = self.parse_factor() { let span = Span::merge(hyph.span, factor.span); - Some(Spanned::new(Expr::Neg(Box::new(factor)), span)) + Some(Expr::Neg(Box::new(factor)).span_with(span)) } else { error!(@self.feedback, hyph.span, "dangling minus"); None @@ -400,7 +400,7 @@ impl Parser<'_> { Some(match token { // This could be a function call or an identifier. Token::Ident(id) => { - let name = Spanned::new(Ident(id.to_string()), span); + let name = Ident(id.to_string()).span_with(span); self.eat(); self.skip_ws(); if self.check(Token::LeftParen) { @@ -445,7 +445,7 @@ impl Parser<'_> { Expr::Table(table) }; - Spanned::new(expr, span) + expr.span_with(span) } // This is a content expression. @@ -457,14 +457,14 @@ impl Parser<'_> { self.tokens.pop_mode(); let span = self.end_group(); - Spanned::new(Expr::Tree(tree), span) + Expr::Tree(tree).span_with(span) } // This is a bracketed function call. Token::LeftBracket => { let call = self.parse_bracket_call(false); let tree = vec![call.map(SyntaxNode::Call)]; - Spanned::new(Expr::Tree(tree), span) + Expr::Tree(tree).span_with(span) } _ => return None, @@ -587,7 +587,7 @@ impl<'s> Parser<'s> { fn with_span(&mut self, v: T) -> Spanned { let span = self.eat().expect("expected token").span; - Spanned::new(v, span) + v.span_with(span) } fn eof(&mut self) -> bool { diff --git a/src/parse/tests.rs b/src/parse/tests.rs index 70517bd82..209717f9e 100644 --- a/src/parse/tests.rs +++ b/src/parse/tests.rs @@ -187,7 +187,7 @@ where } pub fn s(sl: usize, sc: usize, el: usize, ec: usize, v: T) -> Spanned { - Spanned::new(v, Span::new(Pos::new(sl, sc), Pos::new(el, ec))) + v.span_with(Span::new(Pos::new(sl, sc), Pos::new(el, ec))) } // Enables tests to optionally specify spans. diff --git a/src/parse/tokenizer.rs b/src/parse/tokenizer.rs index a251d9605..d36053091 100644 --- a/src/parse/tokenizer.rs +++ b/src/parse/tokenizer.rs @@ -5,7 +5,7 @@ use std::str::Chars; use unicode_xid::UnicodeXID; use crate::length::Length; -use crate::syntax::{Pos, Span, Spanned, Token}; +use crate::syntax::{Pos, Span, SpanWith, Spanned, Token}; use Token::*; use TokenMode::*; @@ -236,7 +236,7 @@ impl<'s> Tokens<'s> { let end = self.pos(); let lang = if !lang.is_empty() { - Some(Spanned::new(lang, Span::new(start, end))) + Some(lang.span_with(Span::new(start, end))) } else { None }; diff --git a/src/syntax/span.rs b/src/syntax/span.rs index 6f5420d44..cda35ec0b 100644 --- a/src/syntax/span.rs +++ b/src/syntax/span.rs @@ -17,6 +17,16 @@ pub trait Offset { fn offset(self, by: Pos) -> Self; } +/// Annotate a value with a span. +pub trait SpanWith: Sized { + /// Wraps `self` in a `Spanned` with the given span. + fn span_with(self, span: Span) -> Spanned { + Spanned::new(self, span) + } +} + +impl SpanWith for T {} + /// A vector of spanned values of type `T`. pub type SpanVec = Vec>; diff --git a/src/syntax/tree.rs b/src/syntax/tree.rs index 8c4270e2f..5327bfa44 100644 --- a/src/syntax/tree.rs +++ b/src/syntax/tree.rs @@ -2,7 +2,7 @@ use std::fmt::{self, Debug, Formatter}; -use super::span::{SpanVec, Spanned}; +use super::span::{SpanVec, SpanWith, Spanned}; use super::Decoration; use crate::color::RgbaColor; use crate::compute::table::{SpannedEntry, Table}; @@ -203,7 +203,7 @@ impl TableExpr { for (key, entry) in self.iter() { let val = entry.val.v.eval(ctx, f).await; - let spanned = Spanned::new(val, entry.val.span); + let spanned = val.span_with(entry.val.span); let entry = SpannedEntry::new(entry.key, spanned); table.insert(key, entry); } @@ -230,12 +230,12 @@ impl CallExpr { if let Some(func) = ctx.scope.func(name) { let pass = func(span, args, ctx.clone()).await; f.extend(pass.feedback); - f.decorations.push(Spanned::new(Decoration::Resolved, span)); + f.decorations.push(Decoration::Resolved.span_with(span)); pass.output } else { if !name.is_empty() { error!(@f, span, "unknown function"); - f.decorations.push(Spanned::new(Decoration::Unresolved, span)); + f.decorations.push(Decoration::Unresolved.span_with(span)); } Value::Table(args) }