mirror of
https://github.com/typst/typst
synced 2025-05-14 17:15:28 +08:00
SpanWith trait ↔
This commit is contained in:
parent
7143e10afc
commit
3c3730425f
@ -11,7 +11,7 @@ use crate::color::RgbaColor;
|
|||||||
use crate::layout::{Command, Commands, Dir, LayoutContext, SpecAlign};
|
use crate::layout::{Command, Commands, Dir, LayoutContext, SpecAlign};
|
||||||
use crate::length::{Length, ScaleLength};
|
use crate::length::{Length, ScaleLength};
|
||||||
use crate::paper::Paper;
|
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};
|
use crate::{DynFuture, Feedback, Pass};
|
||||||
|
|
||||||
/// A computational value.
|
/// A computational value.
|
||||||
@ -76,10 +76,8 @@ impl Spanned<Value> {
|
|||||||
for entry in table.into_values() {
|
for entry in table.into_values() {
|
||||||
if let Some(last_end) = end {
|
if let Some(last_end) = end {
|
||||||
let span = Span::new(last_end, entry.key.start);
|
let span = Span::new(last_end, entry.key.start);
|
||||||
commands.push(Command::LayoutSyntaxTree(vec![Spanned::new(
|
let tree = vec![SyntaxNode::Spacing.span_with(span)];
|
||||||
SyntaxNode::Spacing,
|
commands.push(Command::LayoutSyntaxTree(tree));
|
||||||
span,
|
|
||||||
)]));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
end = Some(entry.val.span.end);
|
end = Some(entry.val.span.end);
|
||||||
@ -89,10 +87,11 @@ impl Spanned<Value> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Format with debug.
|
// Format with debug.
|
||||||
val => vec![Command::LayoutSyntaxTree(vec![Spanned::new(
|
val => {
|
||||||
SyntaxNode::Text(format!("{:?}", val)),
|
let fmt = format!("{:?}", val);
|
||||||
self.span,
|
let tree = vec![SyntaxNode::Text(fmt).span_with(self.span)];
|
||||||
)])],
|
vec![Command::LayoutSyntaxTree(tree)]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ use super::text::{layout_text, TextContext};
|
|||||||
use super::*;
|
use super::*;
|
||||||
use crate::style::LayoutStyle;
|
use crate::style::LayoutStyle;
|
||||||
use crate::syntax::{
|
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};
|
use crate::{DynFuture, Feedback, Pass};
|
||||||
|
|
||||||
@ -53,8 +53,8 @@ impl<'a> TreeLayouter<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn layout_node(&mut self, node: &Spanned<SyntaxNode>) {
|
async fn layout_node(&mut self, node: &Spanned<SyntaxNode>) {
|
||||||
let decorate = |this: &mut Self, deco| {
|
let decorate = |this: &mut Self, deco: Decoration| {
|
||||||
this.feedback.decorations.push(Spanned::new(deco, node.span));
|
this.feedback.decorations.push(deco.span_with(node.span));
|
||||||
};
|
};
|
||||||
|
|
||||||
match &node.v {
|
match &node.v {
|
||||||
@ -87,7 +87,7 @@ impl<'a> TreeLayouter<'a> {
|
|||||||
SyntaxNode::Code(block) => self.layout_code(block).await,
|
SyntaxNode::Code(block) => self.layout_code(block).await,
|
||||||
|
|
||||||
SyntaxNode::Call(call) => {
|
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 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 {
|
for command in commands {
|
||||||
self.execute_command(command, call.span).await;
|
self.execute_command(command, call.span).await;
|
||||||
|
@ -113,7 +113,7 @@ impl Parser<'_> {
|
|||||||
|
|
||||||
let lang = lang.and_then(|lang| {
|
let lang = lang.and_then(|lang| {
|
||||||
if let Some(ident) = Ident::new(lang.v) {
|
if let Some(ident) = Ident::new(lang.v) {
|
||||||
Some(Spanned::new(ident, lang.span))
|
Some(ident.span_with(lang.span))
|
||||||
} else {
|
} else {
|
||||||
error!(@self.feedback, lang.span, "invalid identifier");
|
error!(@self.feedback, lang.span, "invalid identifier");
|
||||||
None
|
None
|
||||||
@ -166,7 +166,7 @@ impl Parser<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let span = Span::new(start, self.pos());
|
let span = Span::new(start, self.pos());
|
||||||
let level = Spanned::new(level, span);
|
let level = level.span_with(span);
|
||||||
|
|
||||||
if level.v > 5 {
|
if level.v > 5 {
|
||||||
warning!(
|
warning!(
|
||||||
@ -185,7 +185,7 @@ impl Parser<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let span = Span::new(start, self.pos());
|
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();
|
self.skip_ws();
|
||||||
let name = self.parse_ident().unwrap_or_else(|| {
|
let name = self.parse_ident().unwrap_or_else(|| {
|
||||||
self.expected_found_or_at("function name", before_name);
|
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();
|
self.skip_ws();
|
||||||
@ -224,7 +224,7 @@ impl Parser<'_> {
|
|||||||
let item = self.parse_bracket_call(true);
|
let item = self.parse_bracket_call(true);
|
||||||
let span = item.span;
|
let span = item.span;
|
||||||
let t = vec![item.map(SyntaxNode::Call)];
|
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)
|
(true, span.end)
|
||||||
} else {
|
} else {
|
||||||
self.tokens.pop_mode();
|
self.tokens.pop_mode();
|
||||||
@ -244,11 +244,11 @@ impl Parser<'_> {
|
|||||||
let body_span = self.end_group();
|
let body_span = self.end_group();
|
||||||
|
|
||||||
let expr = Expr::Tree(body);
|
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);
|
span.expand(body_span);
|
||||||
}
|
}
|
||||||
|
|
||||||
Spanned::new(CallExpr { name, args }, span)
|
CallExpr { name, args }.span_with(span)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_paren_call(&mut self, name: Spanned<Ident>) -> Spanned<CallExpr> {
|
fn parse_paren_call(&mut self, name: Spanned<Ident>) -> Spanned<CallExpr> {
|
||||||
@ -256,7 +256,7 @@ impl Parser<'_> {
|
|||||||
let args = self.parse_table_contents().0;
|
let args = self.parse_table_contents().0;
|
||||||
let args_span = self.end_group();
|
let args_span = self.end_group();
|
||||||
let span = Span::merge(name.span, args_span);
|
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));
|
table.insert(key.v.0, SpannedEntry::new(key.span, val));
|
||||||
self.feedback
|
self.feedback
|
||||||
.decorations
|
.decorations
|
||||||
.push(Spanned::new(Decoration::TableKey, key.span));
|
.push(Decoration::TableKey.span_with(key.span));
|
||||||
} else {
|
} else {
|
||||||
table.push(SpannedEntry::val(val));
|
table.push(SpannedEntry::val(val));
|
||||||
}
|
}
|
||||||
@ -364,7 +364,7 @@ impl Parser<'_> {
|
|||||||
if let Some(right) = parse_operand(self) {
|
if let Some(right) = parse_operand(self) {
|
||||||
let span = Span::merge(left.span, right.span);
|
let span = Span::merge(left.span, right.span);
|
||||||
let v = op(Box::new(left), Box::new(right));
|
let v = op(Box::new(left), Box::new(right));
|
||||||
left = Spanned::new(v, span);
|
left = v.span_with(span);
|
||||||
self.skip_ws();
|
self.skip_ws();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -385,7 +385,7 @@ impl Parser<'_> {
|
|||||||
self.skip_ws();
|
self.skip_ws();
|
||||||
if let Some(factor) = self.parse_factor() {
|
if let Some(factor) = self.parse_factor() {
|
||||||
let span = Span::merge(hyph.span, factor.span);
|
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 {
|
} else {
|
||||||
error!(@self.feedback, hyph.span, "dangling minus");
|
error!(@self.feedback, hyph.span, "dangling minus");
|
||||||
None
|
None
|
||||||
@ -400,7 +400,7 @@ impl Parser<'_> {
|
|||||||
Some(match token {
|
Some(match token {
|
||||||
// This could be a function call or an identifier.
|
// This could be a function call or an identifier.
|
||||||
Token::Ident(id) => {
|
Token::Ident(id) => {
|
||||||
let name = Spanned::new(Ident(id.to_string()), span);
|
let name = Ident(id.to_string()).span_with(span);
|
||||||
self.eat();
|
self.eat();
|
||||||
self.skip_ws();
|
self.skip_ws();
|
||||||
if self.check(Token::LeftParen) {
|
if self.check(Token::LeftParen) {
|
||||||
@ -445,7 +445,7 @@ impl Parser<'_> {
|
|||||||
Expr::Table(table)
|
Expr::Table(table)
|
||||||
};
|
};
|
||||||
|
|
||||||
Spanned::new(expr, span)
|
expr.span_with(span)
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is a content expression.
|
// This is a content expression.
|
||||||
@ -457,14 +457,14 @@ impl Parser<'_> {
|
|||||||
|
|
||||||
self.tokens.pop_mode();
|
self.tokens.pop_mode();
|
||||||
let span = self.end_group();
|
let span = self.end_group();
|
||||||
Spanned::new(Expr::Tree(tree), span)
|
Expr::Tree(tree).span_with(span)
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is a bracketed function call.
|
// This is a bracketed function call.
|
||||||
Token::LeftBracket => {
|
Token::LeftBracket => {
|
||||||
let call = self.parse_bracket_call(false);
|
let call = self.parse_bracket_call(false);
|
||||||
let tree = vec![call.map(SyntaxNode::Call)];
|
let tree = vec![call.map(SyntaxNode::Call)];
|
||||||
Spanned::new(Expr::Tree(tree), span)
|
Expr::Tree(tree).span_with(span)
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => return None,
|
_ => return None,
|
||||||
@ -587,7 +587,7 @@ impl<'s> Parser<'s> {
|
|||||||
|
|
||||||
fn with_span<T>(&mut self, v: T) -> Spanned<T> {
|
fn with_span<T>(&mut self, v: T) -> Spanned<T> {
|
||||||
let span = self.eat().expect("expected token").span;
|
let span = self.eat().expect("expected token").span;
|
||||||
Spanned::new(v, span)
|
v.span_with(span)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eof(&mut self) -> bool {
|
fn eof(&mut self) -> bool {
|
||||||
|
@ -187,7 +187,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn s<T>(sl: usize, sc: usize, el: usize, ec: usize, v: T) -> Spanned<T> {
|
pub fn s<T>(sl: usize, sc: usize, el: usize, ec: usize, v: T) -> Spanned<T> {
|
||||||
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.
|
// Enables tests to optionally specify spans.
|
||||||
|
@ -5,7 +5,7 @@ use std::str::Chars;
|
|||||||
use unicode_xid::UnicodeXID;
|
use unicode_xid::UnicodeXID;
|
||||||
|
|
||||||
use crate::length::Length;
|
use crate::length::Length;
|
||||||
use crate::syntax::{Pos, Span, Spanned, Token};
|
use crate::syntax::{Pos, Span, SpanWith, Spanned, Token};
|
||||||
|
|
||||||
use Token::*;
|
use Token::*;
|
||||||
use TokenMode::*;
|
use TokenMode::*;
|
||||||
@ -236,7 +236,7 @@ impl<'s> Tokens<'s> {
|
|||||||
let end = self.pos();
|
let end = self.pos();
|
||||||
|
|
||||||
let lang = if !lang.is_empty() {
|
let lang = if !lang.is_empty() {
|
||||||
Some(Spanned::new(lang, Span::new(start, end)))
|
Some(lang.span_with(Span::new(start, end)))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
@ -17,6 +17,16 @@ pub trait Offset {
|
|||||||
fn offset(self, by: Pos) -> Self;
|
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<Self> {
|
||||||
|
Spanned::new(self, span)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> SpanWith for T {}
|
||||||
|
|
||||||
/// A vector of spanned values of type `T`.
|
/// A vector of spanned values of type `T`.
|
||||||
pub type SpanVec<T> = Vec<Spanned<T>>;
|
pub type SpanVec<T> = Vec<Spanned<T>>;
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
use std::fmt::{self, Debug, Formatter};
|
use std::fmt::{self, Debug, Formatter};
|
||||||
|
|
||||||
use super::span::{SpanVec, Spanned};
|
use super::span::{SpanVec, SpanWith, Spanned};
|
||||||
use super::Decoration;
|
use super::Decoration;
|
||||||
use crate::color::RgbaColor;
|
use crate::color::RgbaColor;
|
||||||
use crate::compute::table::{SpannedEntry, Table};
|
use crate::compute::table::{SpannedEntry, Table};
|
||||||
@ -203,7 +203,7 @@ impl TableExpr {
|
|||||||
|
|
||||||
for (key, entry) in self.iter() {
|
for (key, entry) in self.iter() {
|
||||||
let val = entry.val.v.eval(ctx, f).await;
|
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);
|
let entry = SpannedEntry::new(entry.key, spanned);
|
||||||
table.insert(key, entry);
|
table.insert(key, entry);
|
||||||
}
|
}
|
||||||
@ -230,12 +230,12 @@ impl CallExpr {
|
|||||||
if let Some(func) = ctx.scope.func(name) {
|
if let Some(func) = ctx.scope.func(name) {
|
||||||
let pass = func(span, args, ctx.clone()).await;
|
let pass = func(span, args, ctx.clone()).await;
|
||||||
f.extend(pass.feedback);
|
f.extend(pass.feedback);
|
||||||
f.decorations.push(Spanned::new(Decoration::Resolved, span));
|
f.decorations.push(Decoration::Resolved.span_with(span));
|
||||||
pass.output
|
pass.output
|
||||||
} else {
|
} else {
|
||||||
if !name.is_empty() {
|
if !name.is_empty() {
|
||||||
error!(@f, span, "unknown function");
|
error!(@f, span, "unknown function");
|
||||||
f.decorations.push(Spanned::new(Decoration::Unresolved, span));
|
f.decorations.push(Decoration::Unresolved.span_with(span));
|
||||||
}
|
}
|
||||||
Value::Table(args)
|
Value::Table(args)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user