summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2023-08-19 19:44:08 +0200
committerLaurenz <laurmaedje@gmail.com>2023-08-19 19:44:08 +0200
commit5fb5854ed80c48660b51ee163b3ff77f7e44ab94 (patch)
treeecf71b837a52c4d6ecded46efe0d029dec5f55ba
parent16855121b666df46c897017dd065f9f3ce567f3b (diff)
Make AST borrowed
-rw-r--r--crates/typst-syntax/src/ast.rs789
-rw-r--r--crates/typst-syntax/src/node.rs23
-rw-r--r--crates/typst/src/eval/func.rs100
-rw-r--r--crates/typst/src/eval/mod.rs394
-rw-r--r--crates/typst/src/ide/complete.rs69
5 files changed, 703 insertions, 672 deletions
diff --git a/crates/typst-syntax/src/ast.rs b/crates/typst-syntax/src/ast.rs
index 65a91629..7cf0cbd5 100644
--- a/crates/typst-syntax/src/ast.rs
+++ b/crates/typst-syntax/src/ast.rs
@@ -13,37 +13,52 @@ use super::{
};
/// A typed AST node.
-pub trait AstNode: Sized {
+pub trait AstNode<'a>: Sized {
/// Convert a node into its typed variant.
- fn from_untyped(node: &SyntaxNode) -> Option<Self>;
+ fn from_untyped(node: &'a SyntaxNode) -> Option<Self>;
/// A reference to the underlying syntax node.
- fn as_untyped(&self) -> &SyntaxNode;
+ fn to_untyped(self) -> &'a SyntaxNode;
/// The source code location.
- fn span(&self) -> Span {
- self.as_untyped().span()
+ fn span(self) -> Span {
+ self.to_untyped().span()
}
}
+/// A static syntax node used as a fallback value. This is returned instead of
+/// panicking when the syntactical structure isn't valid. In a normal
+/// compilation, evaluation isn't attempted on a broken file, but for IDE
+/// functionality, it is.
+static ARBITRARY: SyntaxNode = SyntaxNode::arbitrary();
+
macro_rules! node {
($(#[$attr:meta])* $name:ident) => {
- #[derive(Debug, Default, Clone, Hash)]
+ #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
#[repr(transparent)]
$(#[$attr])*
- pub struct $name(SyntaxNode);
+ pub struct $name<'a>(&'a SyntaxNode);
- impl AstNode for $name {
- fn from_untyped(node: &SyntaxNode) -> Option<Self> {
+ impl<'a> AstNode<'a> for $name<'a> {
+ #[inline]
+ fn from_untyped(node: &'a SyntaxNode) -> Option<Self> {
if matches!(node.kind(), SyntaxKind::$name) {
- Some(Self(node.clone()))
+ Some(Self(node))
} else {
Option::None
}
}
- fn as_untyped(&self) -> &SyntaxNode {
- &self.0
+ #[inline]
+ fn to_untyped(self) -> &'a SyntaxNode {
+ self.0
+ }
+ }
+
+ impl Default for $name<'_> {
+ #[inline]
+ fn default() -> Self {
+ Self(&ARBITRARY)
}
}
};
@@ -54,9 +69,9 @@ node! {
Markup
}
-impl Markup {
+impl<'a> Markup<'a> {
/// The expressions.
- pub fn exprs(&self) -> impl DoubleEndedIterator<Item = Expr> + '_ {
+ pub fn exprs(self) -> impl DoubleEndedIterator<Item = Expr<'a>> {
let mut was_stmt = false;
self.0
.children()
@@ -72,126 +87,126 @@ impl Markup {
}
/// An expression in markup, math or code.
-#[derive(Debug, Clone, Hash)]
-pub enum Expr {
+#[derive(Debug, Copy, Clone, Hash)]
+pub enum Expr<'a> {
/// Plain text without markup.
- Text(Text),
+ Text(Text<'a>),
/// Whitespace in markup or math. Has at most one newline in markup, as more
/// indicate a paragraph break.
- Space(Space),
+ Space(Space<'a>),
/// A forced line break: `\`.
- Linebreak(Linebreak),
+ Linebreak(Linebreak<'a>),
/// A paragraph break, indicated by one or multiple blank lines.
- Parbreak(Parbreak),
+ Parbreak(Parbreak<'a>),
/// An escape sequence: `\#`, `\u{1F5FA}`.
- Escape(Escape),
+ Escape(Escape<'a>),
/// A shorthand for a unicode codepoint. For example, `~` for non-breaking
/// space or `-?` for a soft hyphen.
- Shorthand(Shorthand),
+ Shorthand(Shorthand<'a>),
/// A smart quote: `'` or `"`.
- SmartQuote(SmartQuote),
+ SmartQuote(SmartQuote<'a>),
/// Strong content: `*Strong*`.
- Strong(Strong),
+ Strong(Strong<'a>),
/// Emphasized content: `_Emphasized_`.
- Emph(Emph),
+ Emph(Emph<'a>),
/// Raw text with optional syntax highlighting: `` `...` ``.
- Raw(Raw),
+ Raw(Raw<'a>),
/// A hyperlink: `https://typst.org`.
- Link(Link),
+ Link(Link<'a>),
/// A label: `<intro>`.
- Label(Label),
+ Label(Label<'a>),
/// A reference: `@target`, `@target[..]`.
- Ref(Ref),
+ Ref(Ref<'a>),
/// A section heading: `= Introduction`.
- Heading(Heading),
+ Heading(Heading<'a>),
/// An item in a bullet list: `- ...`.
- List(ListItem),
+ List(ListItem<'a>),
/// An item in an enumeration (numbered list): `+ ...` or `1. ...`.
- Enum(EnumItem),
+ Enum(EnumItem<'a>),
/// An item in a term list: `/ Term: Details`.
- Term(TermItem),
+ Term(TermItem<'a>),
/// A mathematical equation: `$x$`, `$ x^2 $`.
- Equation(Equation),
+ Equation(Equation<'a>),
/// The contents of a mathematical equation: `x^2 + 1`.
- Math(Math),
+ Math(Math<'a>),
/// An identifier in math: `pi`.
- MathIdent(MathIdent),
+ MathIdent(MathIdent<'a>),
/// An alignment point in math: `&`.
- MathAlignPoint(MathAlignPoint),
+ MathAlignPoint(MathAlignPoint<'a>),
/// Matched delimiters in math: `[x + y]`.
- MathDelimited(MathDelimited),
+ MathDelimited(MathDelimited<'a>),
/// A base with optional attachments in math: `a_1^2`.
- MathAttach(MathAttach),
+ MathAttach(MathAttach<'a>),
/// Grouped math primes
- MathPrimes(MathPrimes),
+ MathPrimes(MathPrimes<'a>),
/// A fraction in math: `x/2`.
- MathFrac(MathFrac),
+ MathFrac(MathFrac<'a>),
/// A root in math: `√x`, `∛x` or `∜x`.
- MathRoot(MathRoot),
+ MathRoot(MathRoot<'a>),
/// An identifier: `left`.
- Ident(Ident),
+ Ident(Ident<'a>),
/// The `none` literal.
- None(None),
+ None(None<'a>),
/// The `auto` literal.
- Auto(Auto),
+ Auto(Auto<'a>),
/// A boolean: `true`, `false`.
- Bool(Bool),
+ Bool(Bool<'a>),
/// An integer: `120`.
- Int(Int),
+ Int(Int<'a>),
/// A floating-point number: `1.2`, `10e-4`.
- Float(Float),
+ Float(Float<'a>),
/// A numeric value with a unit: `12pt`, `3cm`, `2em`, `90deg`, `50%`.
- Numeric(Numeric),
+ Numeric(Numeric<'a>),
/// A quoted string: `"..."`.
- Str(Str),
+ Str(Str<'a>),
/// A code block: `{ let x = 1; x + 2 }`.
- Code(CodeBlock),
+ Code(CodeBlock<'a>),
/// A content block: `[*Hi* there!]`.
- Content(ContentBlock),
+ Content(ContentBlock<'a>),
/// A grouped expression: `(1 + 2)`.
- Parenthesized(Parenthesized),
+ Parenthesized(Parenthesized<'a>),
/// An array: `(1, "hi", 12cm)`.
- Array(Array),
+ Array(Array<'a>),
/// A dictionary: `(thickness: 3pt, pattern: dashed)`.
- Dict(Dict),
+ Dict(Dict<'a>),
/// A unary operation: `-x`.
- Unary(Unary),
+ Unary(Unary<'a>),
/// A binary operation: `a + b`.
- Binary(Binary),
+ Binary(Binary<'a>),
/// A field access: `properties.age`.
- FieldAccess(FieldAccess),
+ FieldAccess(FieldAccess<'a>),
/// An invocation of a function or method: `f(x, y)`.
- FuncCall(FuncCall),
+ FuncCall(FuncCall<'a>),
/// A closure: `(x, y) => z`.
- Closure(Closure),
+ Closure(Closure<'a>),
/// A let binding: `let x = 1`.
- Let(LetBinding),
+ Let(LetBinding<'a>),
//// A destructuring assignment: `(x, y) = (1, 2)`.
- DestructAssign(DestructAssignment),
+ DestructAssign(DestructAssignment<'a>),
/// A set rule: `set text(...)`.
- Set(SetRule),
+ Set(SetRule<'a>),
/// A show rule: `show heading: it => emph(it.body)`.
- Show(ShowRule),
+ Show(ShowRule<'a>),
/// An if-else conditional: `if x { y } else { z }`.
- Conditional(Conditional),
+ Conditional(Conditional<'a>),
/// A while loop: `while x { y }`.
- While(WhileLoop),
+ While(WhileLoop<'a>),
/// A for loop: `for x in y { z }`.
- For(ForLoop),
+ For(ForLoop<'a>),
/// A module import: `import "utils.typ": a, b, c`.
- Import(ModuleImport),
+ Import(ModuleImport<'a>),
/// A module include: `include "chapter1.typ"`.
- Include(ModuleInclude),
+ Include(ModuleInclude<'a>),
/// A break from a loop: `break`.
- Break(LoopBreak),
+ Break(LoopBreak<'a>),
/// A continue in a loop: `continue`.
- Continue(LoopContinue),
+ Continue(LoopContinue<'a>),
/// A return from a function: `return`, `return x + 1`.
- Return(FuncReturn),
+ Return(FuncReturn<'a>),
}
-impl Expr {
- fn cast_with_space(node: &SyntaxNode) -> Option<Self> {
+impl<'a> Expr<'a> {
+ fn cast_with_space(node: &'a SyntaxNode) -> Option<Self> {
match node.kind() {
SyntaxKind::Space => node.cast().map(Self::Space),
_ => Self::from_untyped(node),
@@ -199,8 +214,8 @@ impl Expr {
}
}
-impl AstNode for Expr {
- fn from_untyped(node: &SyntaxNode) -> Option<Self> {
+impl<'a> AstNode<'a> for Expr<'a> {
+ fn from_untyped(node: &'a SyntaxNode) -> Option<Self> {
match node.kind() {
SyntaxKind::Linebreak => node.cast().map(Self::Linebreak),
SyntaxKind::Parbreak => node.cast().map(Self::Parbreak),
@@ -261,71 +276,71 @@ impl AstNode for Expr {
}
}
- fn as_untyped(&self) -> &SyntaxNode {
+ fn to_untyped(self) -> &'a SyntaxNode {
match self {
- Self::Text(v) => v.as_untyped(),
- Self::Space(v) => v.as_untyped(),
- Self::Linebreak(v) => v.as_untyped(),
- Self::Parbreak(v) => v.as_untyped(),
- Self::Escape(v) => v.as_untyped(),
- Self::Shorthand(v) => v.as_untyped(),
- Self::SmartQuote(v) => v.as_untyped(),
- Self::Strong(v) => v.as_untyped(),
- Self::Emph(v) => v.as_untyped(),
- Self::Raw(v) => v.as_untyped(),
- Self::Link(v) => v.as_untyped(),
- Self::Label(v) => v.as_untyped(),
- Self::Ref(v) => v.as_untyped(),
- Self::Heading(v) => v.as_untyped(),
- Self::List(v) => v.as_untyped(),
- Self::Enum(v) => v.as_untyped(),
- Self::Term(v) => v.as_untyped(),
- Self::Equation(v) => v.as_untyped(),
- Self::Math(v) => v.as_untyped(),
- Self::MathIdent(v) => v.as_untyped(),
- Self::MathAlignPoint(v) => v.as_untyped(),
- Self::MathDelimited(v) => v.as_untyped(),
- Self::MathAttach(v) => v.as_untyped(),
- Self::MathPrimes(v) => v.as_untyped(),
- Self::MathFrac(v) => v.as_untyped(),
- Self::MathRoot(v) => v.as_untyped(),
- Self::Ident(v) => v.as_untyped(),
- Self::None(v) => v.as_untyped(),
- Self::Auto(v) => v.as_untyped(),
- Self::Bool(v) => v.as_untyped(),
- Self::Int(v) => v.as_untyped(),
- Self::Float(v) => v.as_untyped(),
- Self::Numeric(v) => v.as_untyped(),
- Self::Str(v) => v.as_untyped(),
- Self::Code(v) => v.as_untyped(),
- Self::Content(v) => v.as_untyped(),
- Self::Array(v) => v.as_untyped(),
- Self::Dict(v) => v.as_untyped(),
- Self::Parenthesized(v) => v.as_untyped(),
- Self::Unary(v) => v.as_untyped(),
- Self::Binary(v) => v.as_untyped(),
- Self::FieldAccess(v) => v.as_untyped(),
- Self::FuncCall(v) => v.as_untyped(),
- Self::Closure(v) => v.as_untyped(),
- Self::Let(v) => v.as_untyped(),
- Self::DestructAssign(v) => v.as_untyped(),
- Self::Set(v) => v.as_untyped(),
- Self::Show(v) => v.as_untyped(),
- Self::Conditional(v) => v.as_untyped(),
- Self::While(v) => v.as_untyped(),
- Self::For(v) => v.as_untyped(),
- Self::Import(v) => v.as_untyped(),
- Self::Include(v) => v.as_untyped(),
- Self::Break(v) => v.as_untyped(),
- Self::Continue(v) => v.as_untyped(),
- Self::Return(v) => v.as_untyped(),
+ Self::Text(v) => v.to_untyped(),
+ Self::Space(v) => v.to_untyped(),
+ Self::Linebreak(v) => v.to_untyped(),
+ Self::Parbreak(v) => v.to_untyped(),
+ Self::Escape(v) => v.to_untyped(),
+ Self::Shorthand(v) => v.to_untyped(),
+ Self::SmartQuote(v) => v.to_untyped(),
+ Self::Strong(v) => v.to_untyped(),
+ Self::Emph(v) => v.to_untyped(),
+ Self::Raw(v) => v.to_untyped(),
+ Self::Link(v) => v.to_untyped(),
+ Self::Label(v) => v.to_untyped(),
+ Self::Ref(v) => v.to_untyped(),
+ Self::Heading(v) => v.to_untyped(),
+ Self::List(v) => v.to_untyped(),
+ Self::Enum(v) => v.to_untyped(),
+ Self::Term(v) => v.to_untyped(),
+ Self::Equation(v) => v.to_untyped(),
+ Self::Math(v) => v.to_untyped(),
+ Self::MathIdent(v) => v.to_untyped(),
+ Self::MathAlignPoint(v) => v.to_untyped(),
+ Self::MathDelimited(v) => v.to_untyped(),
+ Self::MathAttach(v) => v.to_untyped(),
+ Self::MathPrimes(v) => v.to_untyped(),
+ Self::MathFrac(v) => v.to_untyped(),
+ Self::MathRoot(v) => v.to_untyped(),
+ Self::Ident(v) => v.to_untyped(),
+ Self::None(v) => v.to_untyped(),
+ Self::Auto(v) => v.to_untyped(),
+ Self::Bool(v) => v.to_untyped(),
+ Self::Int(v) => v.to_untyped(),
+ Self::Float(v) => v.to_untyped(),
+ Self::Numeric(v) => v.to_untyped(),
+ Self::Str(v) => v.to_untyped(),
+ Self::Code(v) => v.to_untyped(),
+ Self::Content(v) => v.to_untyped(),
+ Self::Array(v) => v.to_untyped(),
+ Self::Dict(v) => v.to_untyped(),
+ Self::Parenthesized(v) => v.to_untyped(),
+ Self::Unary(v) => v.to_untyped(),
+ Self::Binary(v) => v.to_untyped(),
+ Self::FieldAccess(v) => v.to_untyped(),
+ Self::FuncCall(v) => v.to_untyped(),
+ Self::Closure(v) => v.to_untyped(),
+ Self::Let(v) => v.to_untyped(),
+ Self::DestructAssign(v) => v.to_untyped(),
+ Self::Set(v) => v.to_untyped(),
+ Self::Show(v) => v.to_untyped(),
+ Self::Conditional(v) => v.to_untyped(),
+ Self::While(v) => v.to_untyped(),
+ Self::For(v) => v.to_untyped(),
+ Self::Import(v) => v.to_untyped(),
+ Self::Include(v) => v.to_untyped(),
+ Self::Break(v) => v.to_untyped(),
+ Self::Continue(v) => v.to_untyped(),
+ Self::Return(v) => v.to_untyped(),
}
}
}
-impl Expr {
+impl Expr<'_> {
/// Can this expression be embedded into markup with a hashtag?
- pub fn hashtag(&self) -> bool {
+ pub fn hashtag(self) -> bool {
matches!(
self,
Self::Ident(_)
@@ -358,7 +373,7 @@ impl Expr {
}
/// Is this a literal?
- pub fn is_literal(&self) -> bool {
+ pub fn is_literal(self) -> bool {
matches!(
self,
Self::None(_)
@@ -372,7 +387,7 @@ impl Expr {
}
}
-impl Default for Expr {
+impl Default for Expr<'_> {
fn default() -> Self {
Expr::Space(Space::default())
}
@@ -383,9 +398,9 @@ node! {
Text
}
-impl Text {
+impl<'a> Text<'a> {
/// Get the text.
- pub fn get(&self) -> &EcoString {
+ pub fn get(self) -> &'a EcoString {
self.0.text()
}
}
@@ -411,9 +426,9 @@ node! {
Escape
}
-impl Escape {
+impl Escape<'_> {
/// Get the escaped character.
- pub fn get(&self) -> char {
+ pub fn get(self) -> char {
let mut s = Scanner::new(self.0.text());
s.expect('\\');
if s.eat_if("u{") {
@@ -434,7 +449,7 @@ node! {
Shorthand
}
-impl Shorthand {
+impl Shorthand<'_> {
/// A list of all shorthands in markup mode.
pub const MARKUP_LIST: &[(&'static str, char)] = &[
("...", '…'),
@@ -487,7 +502,7 @@ impl Shorthand {
];
/// Get the shorthanded character.
- pub fn get(&self) -> char {
+ pub fn get(self) -> char {
let text = self.0.text();
(Self::MARKUP_LIST.iter().chain(Self::MATH_LIST))
.find(|&&(s, _)| s == text)
@@ -500,9 +515,9 @@ node! {
SmartQuote
}
-impl SmartQuote {
+impl SmartQuote<'_> {
/// Whether this is a double quote.
- pub fn double(&self) -> bool {
+ pub fn double(self) -> bool {
self.0.text() == "\""
}
}
@@ -512,9 +527,9 @@ node! {
Strong
}
-impl Strong {
+impl<'a> Strong<'a> {
/// The contents of the strong node.
- pub fn body(&self) -> Markup {
+ pub fn body(self) -> Markup<'a> {
self.0.cast_first_match().unwrap_or_default()
}
}
@@ -524,9 +539,9 @@ node! {
Emph
}
-impl Emph {
+impl<'a> Emph<'a> {
/// The contents of the emphasis node.
- pub fn body(&self) -> Markup {
+ pub fn body(self) -> Markup<'a> {
self.0.cast_first_match().unwrap_or_default()
}
}
@@ -536,9 +551,9 @@ node! {
Raw
}
-impl Raw {
+impl<'a> Raw<'a> {
/// The trimmed raw text.
- pub fn text(&self) -> EcoString {
+ pub fn text(self) -> EcoString {
let mut text = self.0.text().as_str();
let blocky = text.starts_with("```");
text = text.trim_matches('`');
@@ -594,7 +609,7 @@ impl Raw {
}
/// An optional identifier specifying the language to syntax-highlight in.
- pub fn lang(&self) -> Option<&str> {
+ pub fn lang(self) -> Option<&'a str> {
let text = self.0.text();
// Only blocky literals are supposed to contain a language.
@@ -611,7 +626,7 @@ impl Raw {
}
/// Whether the raw text should be displayed in a separate block.
- pub fn block(&self) -> bool {
+ pub fn block(self) -> bool {
let text = self.0.text();
text.starts_with("```") && text.chars().any(is_newline)
}
@@ -622,9 +637,9 @@ node! {
Link
}
-impl Link {
+impl<'a> Link<'a> {
/// Get the URL.
- pub fn get(&self) -> &EcoString {
+ pub fn get(self) -> &'a EcoString {
self.0.text()
}
}
@@ -634,9 +649,9 @@ node! {
Label
}
-impl Label {
+impl<'a> Label<'a> {
/// Get the label's text.
- pub fn get(&self) -> &str {
+ pub fn get(self) -> &'a str {
self.0.text().trim_start_matches('<').trim_end_matches('>')
}
}
@@ -646,9 +661,9 @@ node! {
Ref
}
-impl Ref {
+impl<'a> Ref<'a> {
/// Get the target.
- pub fn target(&self) -> &str {
+ pub fn target(self) -> &'a str {
self.0
.children()
.find(|node| node.kind() == SyntaxKind::RefMarker)
@@ -657,7 +672,7 @@ impl Ref {
}
/// Get the supplement.
- pub fn supplement(&self) -> Option<ContentBlock> {
+ pub fn supplement(self) -> Option<ContentBlock<'a>> {
self.0.cast_last_match()
}
}
@@ -667,14 +682,14 @@ node! {
Heading
}
-impl Heading {
+impl<'a> Heading<'a> {
/// The contents of the heading.
- pub fn body(&self) -> Markup {
+ pub fn body(self) -> Markup<'a> {
self.0.cast_first_match().unwrap_or_default()
}
/// The section depth (number of equals signs).
- pub fn level(&self) -> NonZeroUsize {
+ pub fn level(self) -> NonZeroUsize {
self.0
.children()
.find(|node| node.kind() == SyntaxKind::HeadingMarker)
@@ -688,9 +703,9 @@ node! {
ListItem
}
-impl ListItem {
+impl<'a> ListItem<'a> {
/// The contents of the list item.
- pub fn body(&self) -> Markup {
+ pub fn body(self) -> Markup<'a> {
self.0.cast_first_match().unwrap_or_default()
}
}
@@ -700,9 +715,9 @@ node! {
EnumItem
}
-impl EnumItem {
+impl<'a> EnumItem<'a> {
/// The explicit numbering, if any: `23.`.
- pub fn number(&self) -> Option<usize> {
+ pub fn number(self) -> Option<usize> {
self.0.children().find_map(|node| match node.kind() {
SyntaxKind::EnumMarker => node.text().trim_end_matches('.').parse().ok(),
_ => Option::None,
@@ -710,7 +725,7 @@ impl EnumItem {
}
/// The contents of the list item.
- pub fn body(&self) -> Markup {
+ pub fn body(self) -> Markup<'a> {
self.0.cast_first_match().unwrap_or_default()
}
}
@@ -720,14 +735,14 @@ node! {
TermItem
}
-impl TermItem {
+impl<'a> TermItem<'a> {
/// The term described by the item.
- pub fn term(&self) -> Markup {
+ pub fn term(self) -> Markup<'a> {
self.0.cast_first_match().unwrap_or_default()
}
/// The description of the term.
- pub fn description(&self) -> Markup {
+ pub fn description(self) -> Markup<'a> {
self.0.cast_last_match().unwrap_or_default()
}
}
@@ -737,14 +752,14 @@ node! {
Equation
}
-impl Equation {
+impl<'a> Equation<'a> {
/// The contained math.
- pub fn body(&self) -> Math {
+ pub fn body(self) -> Math<'a> {
self.0.cast_first_match().unwrap_or_default()
}
/// Whether the equation should be displayed as a separate block.
- pub fn block(&self) -> bool {
+ pub fn block(self) -> bool {
let is_space = |node: Option<&SyntaxNode>| {
node.map(SyntaxNode::kind) == Some(SyntaxKind::Space)
};
@@ -757,9 +772,9 @@ node! {
Math
}
-impl Math {
+impl<'a> Math<'a> {
/// The expressions the mathematical content consists of.
- pub fn exprs(&self) -> impl DoubleEndedIterator<Item = Expr> + '_ {
+ pub fn exprs(self) -> impl DoubleEndedIterator<Item = Expr<'a>> {
self.0.children().filter_map(Expr::cast_with_space)
}
}
@@ -769,26 +784,23 @@ node! {
MathIdent
}
-impl MathIdent {
+impl<'a> MathIdent<'a> {
/// Get the identifier.
- pub fn get(&self) -> &EcoString {
+ pub fn get(self) -> &'a EcoString {
self.0.text()
}
- /// Take out the contained identifier.
- pub fn take(self) -> EcoString {
- self.0.into_text()
- }
-
/// Get the identifier as a string slice.
- pub fn as_str(&self) -> &str {
+ pub fn as_str(self) -> &'a str {
self.get()
}
}
-impl Deref for MathIdent {
+impl Deref for MathIdent<'_> {
type Target = str;
+ /// Dereference to a string. Note that this shortens the lifetime, so you
+ /// may need to use [`get()`](Self::get) instead in some situations.
fn deref(&self) -> &Self::Target {
self.as_str()
}
@@ -804,19 +816,19 @@ node! {
MathDelimited
}
-impl MathDelimited {
+impl<'a> MathDelimited<'a> {
/// The opening delimiter.
- pub fn open(&self) -> Expr {
+ pub fn open(self) -> Expr<'a> {
self.0.cast_first_match().unwrap_or_default()
}
/// The contents, including the delimiters.
- pub fn body(&self) -> Math {
+ pub fn body(self) -> Math<'a> {
self.0.cast_first_match().unwrap_or_default()
}
/// The closing delimiter.
- pub fn close(&self) -> Expr {
+ pub fn close(self) -> Expr<'a> {
self.0.cast_last_match().unwrap_or_default()
}
}
@@ -826,14 +838,14 @@ node! {
MathAttach
}
-impl MathAttach {
+impl<'a> MathAttach<'a> {
/// The base, to which things are attached.
- pub fn base(&self) -> Expr {
+ pub fn base(self) -> Expr<'a> {
self.0.cast_first_match().unwrap_or_default()
}
/// The bottom attachment.
- pub fn bottom(&self) -> Option<Expr> {
+ pub fn bottom(self) -> Option<Expr<'a>> {
self.0
.children()
.skip_while(|node| !matches!(node.kind(), SyntaxKind::Underscore))
@@ -841,7 +853,7 @@ impl MathAttach {
}
/// The top attachment.
- pub fn top(&self) -> Option<Expr> {
+ pub fn top(self) -> Option<Expr<'a>> {
self.0
.children()
.skip_while(|node| !matches!(node.kind(), SyntaxKind::Hat))
@@ -849,7 +861,7 @@ impl MathAttach {
}
/// Extract attached primes if present.
- pub fn primes(&self) -> Option<MathPrimes> {
+ pub fn primes(self) -> Option<MathPrimes<'a>> {
self.0.children().nth(1).and_then(|n| n.cast())
}
}
@@ -859,8 +871,8 @@ node! {
MathPrimes
}
-impl MathPrimes {
- pub fn count(&self) -> usize {
+impl MathPrimes<'_> {
+ pub fn count(self) -> usize {
self.0
.children()
.filter(|node| matches!(node.kind(), SyntaxKind::Prime))
@@ -873,14 +885,14 @@ node! {
MathFrac
}
-impl MathFrac {
+impl<'a> MathFrac<'a> {
/// The numerator.
- pub fn num(&self) -> Expr {
+ pub fn num(self) -> Expr<'a> {
self.0.cast_first_match().unwrap_or_default()
}
/// The denominator.
- pub fn denom(&self) -> Expr {
+ pub fn denom(self) -> Expr<'a> {
self.0.cast_last_match().unwrap_or_default()
}
}
@@ -890,9 +902,9 @@ node! {
MathRoot
}
-impl MathRoot {
+impl<'a> MathRoot<'a> {
/// The index of the root.
- pub fn index(&self) -> Option<usize> {
+ pub fn index(self) -> Option<usize> {
match self.0.children().next().map(|node| node.text().as_str()) {
Some("∜") => Some(4),
Some("∛") => Some(3),
@@ -902,7 +914,7 @@ impl MathRoot {
}
/// The radicand.
- pub fn radicand(&self) -> Expr {
+ pub fn radicand(self) -> Expr<'a> {
self.0.cast_first_match().unwrap_or_default()
}
}
@@ -912,26 +924,23 @@ node! {
Ident
}
-impl Ident {
+impl<'a> Ident<'a> {
/// Get the identifier.
- pub fn get(&self) -> &EcoString {
+ pub fn get(self) -> &'a EcoString {
self.0.text()
}
- /// Take out the contained identifier.
- pub fn take(self) -> EcoString {
- self.0.into_text()
- }
-
/// Get the identifier as a string slice.
- pub fn as_str(&self) -> &str {
+ pub fn as_str(self) -> &'a str {
self.get()
}
}
-impl Deref for Ident {
+impl Deref for Ident<'_> {
type Target = str;
+ /// Dereference to a string. Note that this shortens the lifetime, so you
+ /// may need to use [`get()`](Self::get) instead in some situations.
fn deref(&self) -> &Self::Target {
self.as_str()
}
@@ -952,9 +961,9 @@ node! {
Bool
}
-impl Bool {
+impl Bool<'_> {
/// Get the boolean value.
- pub fn get(&self) -> bool {
+ pub fn get(self) -> bool {
self.0.text() == "true"
}
}
@@ -964,9 +973,9 @@ node! {
Int
}
-impl Int {
+impl Int<'_> {
/// Get the integer value.
- pub fn get(&self) -> i64 {
+ pub fn get(self) -> i64 {
let text = self.0.text();
if let Some(rest) = text.strip_prefix("0x") {
i64::from_str_radix(rest, 16)
@@ -986,9 +995,9 @@ node! {
Float
}
-impl Float {
+impl Float<'_> {
/// Get the floating-point value.
- pub fn get(&self) -> f64 {
+ pub fn get(self) -> f64 {
self.0.text().parse().unwrap_or_default()
}
}
@@ -998,9 +1007,9 @@ node! {
Numeric
}
-impl Numeric {
+impl Numeric<'_> {
/// Get the numeric value and unit.
- pub fn get(&self) -> (f64, Unit) {
+ pub fn get(self) -> (f64, Unit) {
let text = self.0.text();
let count = text
.chars()
@@ -1055,9 +1064,9 @@ node! {
Str
}
-impl Str {
+impl Str<'_> {
/// Get the string value with resolved escape sequences.
- pub fn get(&self) -> EcoString {
+ pub fn get(self) -> EcoString {
let text = self.0.text();
let unquoted = &text[1..text.len() - 1];
if !unquoted.contains('\\') {
@@ -1105,21 +1114,21 @@ node! {
CodeBlock
}
-impl CodeBlock {
+impl<'a> CodeBlock<'a> {
/// The contained code.
- pub fn body(&self) -> Code {
+ pub fn body(self) -> Code<'a> {
self.0.cast_first_match().unwrap_or_default()
}
}
node! {
- /// Code.
+ /// The body of a code block.
Code
}
-impl Code {
+impl<'a> Code<'a> {
/// The list of expressions contained in the code.
- pub fn exprs(&self) -> impl DoubleEndedIterator<Item = Expr> + '_ {
+ pub fn exprs(self) -> impl DoubleEndedIterator<Item = Expr<'a>> {
self.0.children().filter_map(SyntaxNode::cast)
}
}
@@ -1129,9 +1138,9 @@ node! {
ContentBlock
}
-impl ContentBlock {
+impl<'a> ContentBlock<'a> {
/// The contained markup.
- pub fn body(&self) -> Markup {
+ pub fn body(self) -> Markup<'a> {
self.0.cast_first_match().unwrap_or_default()
}
}
@@ -1141,9 +1150,9 @@ node! {
Parenthesized
}
-impl Parenthesized {
+impl<'a> Parenthesized<'a> {
/// The wrapped expression.
- pub fn expr(&self) -> Expr {
+ pub fn expr(self) -> Expr<'a> {
self.0.cast_first_match().unwrap_or_default()
}
}
@@ -1153,34 +1162,34 @@ node! {
Array
}
-impl Array {
+impl<'a> Array<'a> {
/// The array's items.
- pub fn items(&self) -> impl DoubleEndedIterator<Item = ArrayItem> + '_ {
+ pub fn items(self) -> impl DoubleEndedIterator<Item = ArrayItem<'a>> {
self.0.children().filter_map(SyntaxNode::cast)
}
}
/// An item in an array.
-#[derive(Debug, Clone, Hash)]
-pub enum ArrayItem {
+#[derive(Debug, Copy, Clone, Hash)]
+pub enum ArrayItem<'a> {
/// A bare expression: `12`.
- Pos(Expr),
+ Pos(Expr<'a>),
/// A spread expression: `..things`.
- Spread(Expr),
+ Spread(Expr<'a>),
}
-impl AstNode for ArrayItem {
- fn from_untyped(node: &SyntaxNode) -> Option<Self> {
+impl<'a> AstNode<'a> for ArrayItem<'a> {
+ fn from_untyped(node: &'a SyntaxNode) -> Option<Self> {
match node.kind() {
SyntaxKind::Spread => node.cast_first_match().map(Self::Spread),
_ => node.cast().map(Self::Pos),
}
}
- fn as_untyped(&self) -> &SyntaxNode {
+ fn to_untyped(self) -> &'a SyntaxNode {
match self {
- Self::Pos(v) => v.as_untyped(),
- Self::Spread(v) => v.as_untyped(),
+ Self::Pos(v) => v.to_untyped(),
+ Self::Spread(v) => v.to_untyped(),
}
}
}
@@ -1190,26 +1199,26 @@ node! {
Dict
}
-impl Dict {
+impl<'a> Dict<'a> {
/// The dictionary's items.
- pub fn items(&self) -> impl DoubleEndedIterator<Item = DictItem> + '_ {
+ pub fn items(self) -> impl DoubleEndedIterator<Item = DictItem<'a>> {
self.0.children().filter_map(SyntaxNode::cast)
}
}
/// An item in an dictionary expression.
-#[derive(Debug, Clone, Hash)]
-pub enum DictItem {
+#[derive(Debug, Copy, Clone, Hash)]
+pub enum DictItem<'a> {
/// A named pair: `thickness: 3pt`.
- Named(Named),
+ Named(Named<'a>),
/// A keyed pair: `"spacy key": true`.
- Keyed(Keyed),
+ Keyed(Keyed<'a>),
/// A spread expression: `..things`.
- Spread(Expr),
+ Spread(Expr<'a>),
}
-impl AstNode for DictItem {
- fn from_untyped(node: &SyntaxNode) -> Option<Self> {
+impl<'a> AstNode<'a> for DictItem<'a> {
+ fn from_untyped(node: &'a SyntaxNode) -> Option<Self> {
match node.kind() {
SyntaxKind::Named => node.cast().map(Self::Named),
SyntaxKind::Keyed => node.cast().map(Self::Keyed),
@@ -1218,11 +1227,11 @@ impl AstNode for DictItem {
}
}
- fn as_untyped(&self) -> &SyntaxNode {
+ fn to_untyped(self) -> &'a SyntaxNode {
match self {
- Self::Named(v) => v.as_untyped(),
- Self::Keyed(v) => v.as_untyped(),
- Self::Spread(v) => v.as_untyped(),
+ Self::Named(v) => v.to_untyped(),
+ Self::Keyed(v) => v.to_untyped(),
+ Self::Spread(v) => v.to_untyped(),
}
}
}
@@ -1232,19 +1241,19 @@ node! {
Named
}
-impl Named {
+impl<'a> Named<'a> {
/// The name: `thickness`.
- pub fn name(&self) -> Ident {
+ pub fn name(self) -> Ident<'a> {
self.0.cast_first_match().unwrap_or_default()
}
/// The right-hand side of the pair: `3pt`.
- pub fn expr(&self) -> Expr {
+ pub fn expr(self) -> Expr<'a> {
self.0.cast_last_match().unwrap_or_default()
}
/// The right-hand side of the pair as an identifier.
- pub fn expr_ident(&self) -> Option<Ident> {
+ pub fn expr_ident(self) -> Option<Ident<'a>> {
self.0.cast_last_match()
}
}
@@ -1254,9 +1263,9 @@ node! {
Keyed
}
-impl Keyed {
+impl<'a> Keyed<'a> {
/// The key: `"spacy key"`.
- pub fn key(&self) -> Str {
+ pub fn key(self) -> Str<'a> {
self.0
.children()
.find_map(|node| node.cast::<Str>())
@@ -1264,7 +1273,7 @@ impl Keyed {
}
/// The right-hand side of the pair: `true`.
- pub fn expr(&self) -> Expr {
+ pub fn expr(self) -> Expr<'a> {
self.0.cast_last_match().unwrap_or_default()
}
}
@@ -1274,9 +1283,9 @@ node! {
Unary
}
-impl Unary {
+impl<'a> Unary<'a> {
/// The operator: `-`.
- pub fn op(&self) -> UnOp {
+ pub fn op(self) -> UnOp {
self.0
.children()
.find_map(|node| UnOp::from_kind(node.kind()))
@@ -1284,7 +1293,7 @@ impl Unary {
}
/// The expression to operate on: `x`.
- pub fn expr(&self) -> Expr {
+ pub fn expr(self) -> Expr<'a> {
self.0.cast_last_match().unwrap_or_default()
}
}
@@ -1334,9 +1343,9 @@ node! {
Binary
}
-impl Binary {
+impl<'a> Binary<'a> {
/// The binary operator: `+`.
- pub fn op(&self) -> BinOp {
+ pub fn op(self) -> BinOp {
let mut not = false;
self.0
.children()
@@ -1352,12 +1361,12 @@ impl Binary {
}
/// The left-hand side of the operation: `a`.
- pub fn lhs(&self) -> Expr {
+ pub fn lhs(self) -> Expr<'a> {
self.0.cast_first_match().unwrap_or_default()
}
/// The right-hand side of the operation: `b`.
- pub fn rhs(&self) -> Expr {
+ pub fn rhs(self) -> Expr<'a> {
self.0.cast_last_match().unwrap_or_default()
}
}
@@ -1521,14 +1530,14 @@ node! {
FieldAccess
}
-impl FieldAccess {
+impl<'a> FieldAccess<'a> {
/// The expression to access the field on.
- pub fn target(&self) -> Expr {
+ pub fn target(self) -> Expr<'a> {
self.0.cast_first_match().unwrap_or_default()
}
/// The name of the field.
- pub fn field(&self) -> Ident {
+ pub fn field(self) -> Ident<'a> {
self.0.cast_last_match().unwrap_or_default()
}
}
@@ -1538,14 +1547,14 @@ node! {
FuncCall
}
-impl FuncCall {
+impl<'a> FuncCall<'a> {
/// The function to call.
- pub fn callee(&self) -> Expr {
+ pub fn callee(self) -> Expr<'a> {
self.0.cast_first_match().unwrap_or_default()
}
/// The arguments to the function.
- pub fn args(&self) -> Args {
+ pub fn args(self) -> Args<'a> {
self.0.cast_last_match().unwrap_or_default()
}
}
@@ -1555,26 +1564,26 @@ node! {
Args
}
-impl Args {
+impl<'a> Args<'a> {
/// The positional and named arguments.
- pub fn items(&self) -> impl DoubleEndedIterator<Item = Arg> + '_ {
+ pub fn items(self) -> impl DoubleEndedIterator<Item = Arg<'a>> {
self.0.children().filter_map(SyntaxNode::cast)
}
}
/// An argument to a function call.
-#[derive(Debug, Clone, Hash)]
-pub enum Arg {
+#[derive(Debug, Copy, Clone, Hash)]
+pub enum Arg<'a> {
/// A positional argument: `12`.
- Pos(Expr),
+ Pos(Expr<'a>),
/// A named argument: `draw: false`.
- Named(Named),
+ Named(Named<'a>),
/// A spread argument: `..things`.
- Spread(Expr),
+ Spread(Expr<'a>),
}
-impl AstNode for Arg {
- fn from_untyped(node: &SyntaxNode) -> Option<Self> {
+impl<'a> AstNode<'a> for Arg<'a> {
+ fn from_untyped(node: &'a SyntaxNode) -> Option<Self> {
match node.kind() {
SyntaxKind::Named => node.cast().map(Self::Named),
SyntaxKind::Spread => node.cast_first_match().map(Self::Spread),
@@ -1582,11 +1591,11 @@ impl AstNode for Arg {
}
}
- fn as_untyped(&self) -> &SyntaxNode {
+ fn to_untyped(self) -> &'a SyntaxNode {
match self {
- Self::Pos(v) => v.as_untyped(),
- Self::Named(v) => v.as_untyped(),
- Self::Spread(v) => v.as_untyped(),
+ Self::Pos(v) => v.to_untyped(),
+ Self::Named(v) => v.to_untyped(),
+ Self::Spread(v) => v.to_untyped(),
}
}
}
@@ -1596,21 +1605,21 @@ node! {
Closure
}
-impl Closure {
+impl<'a> Closure<'a> {
/// The name of the closure.
///
/// This only exists if you use the function syntax sugar: `let f(x) = y`.
- pub fn name(&self) -> Option<Ident> {
+ pub fn name(self) -> Option<Ident<'a>> {
self.0.children().next()?.cast()
}
/// The parameter bindings.
- pub fn params(&self) -> Params {
+ pub fn params(self) -> Params<'a> {
self.0.cast_first_match().unwrap_or_default()
}
/// The body of the closure.
- pub fn body(&self) -> Expr {
+ pub fn body(self) -> Expr<'a> {
self.0.cast_last_match().unwrap_or_default()
}
}
@@ -1620,9 +1629,9 @@ node! {
Params
}
-impl Params {
+impl<'a> Params<'a> {
/// The parameter bindings.
- pub fn children(&self) -> impl DoubleEndedIterator<Item = Param> + '_ {
+ pub fn children(self) -> impl DoubleEndedIterator<Item = Param<'a>> {
self.0.children().filter_map(SyntaxNode::cast)
}
}
@@ -1632,14 +1641,14 @@ node! {
Spread
}
-impl Spread {
+impl<'a> Spread<'a> {
/// Try to get an identifier.
- pub fn name(&self) -> Option<Ident> {
+ pub fn name(self) -> Option<Ident<'a>> {
self.0.cast_first_match()
}
/// Try to get an expression.
- pub fn expr(&self) -> Option<Expr> {
+ pub fn expr(self) -> Option<Expr<'a>> {
self.0.cast_first_match()
}
}
@@ -1650,18 +1659,18 @@ node! {
}
/// A parameter to a closure.
-#[derive(Debug, Clone, Hash)]
-pub enum Param {
+#[derive(Debug, Copy, Clone, Hash)]
+pub enum Param<'a> {
/// A positional parameter: `x`.
- Pos(Pattern),
+ Pos(Pattern<'a>),
/// A named parameter with a default value: `draw: false`.
- Named(Named),
+ Named(Named<'a>),
/// An argument sink: `..args`.
- Sink(Spread),
+ Sink(Spread<'a>),
}
-impl AstNode for Param {
- fn from_untyped(node: &SyntaxNode) -> Option<Self> {
+impl<'a> AstNode<'a> for Param<'a> {
+ fn from_untyped(node: &'a SyntaxNode) -> Option<Self> {
match node.kind() {
SyntaxKind::Named => node.cast().map(Self::Named),
SyntaxKind::Spread => node.cast().map(Self::Sink),
@@ -1669,11 +1678,11 @@ impl AstNode for Param {
}
}
- fn as_untyped(&self) -> &SyntaxNode {
+ fn to_untyped(self) -> &'a SyntaxNode {
match self {
- Self::Pos(v) => v.as_untyped(),
- Self::Named(v) => v.as_untyped(),
- Self::Sink(v) => v.as_untyped(),
+ Self::Pos(v) => v.to_untyped(),
+ Self::Named(v) => v.to_untyped(),
+ Self::Sink(v) => v.to_untyped(),
}
}
}
@@ -1683,14 +1692,14 @@ node! {
Destructuring
}
-impl Destructuring {
+impl<'a> Destructuring<'a> {
/// The bindings of the destructuring.
- pub fn bindings(&self) -> impl Iterator<Item = DestructuringKind> + '_ {
+ pub fn bindings(self) -> impl DoubleEndedIterator<Item = DestructuringKind<'a>> {
self.0.children().filter_map(SyntaxNode::cast)
}
- // Returns a list of all identifiers in the pattern.
- pub fn idents(&self) -> impl Iterator<Item = Ident> + '_ {
+ /// Returns a list of all identifiers in the pattern.
+ pub fn idents(self) -> impl DoubleEndedIterator<Item = Ident<'a>> {
self.bindings().filter_map(|binding| match binding {
DestructuringKind::Normal(Expr::Ident(ident)) => Some(ident),
DestructuringKind::Sink(spread) => spread.name(),
@@ -1701,20 +1710,20 @@ impl Destructuring {
}
/// The kind of an element in a destructuring pattern.
-#[derive(Debug, Clone, Hash)]
-pub enum DestructuringKind {
+#[derive(Debug, Copy, Clone, Hash)]
+pub enum DestructuringKind<'a> {
/// An expression: `x`.
- Normal(Expr),
+ Normal(Expr<'a>),
/// An argument sink: `..y`.
- Sink(Spread),
+ Sink(Spread<'a>),
/// Named arguments: `x: 1`.
- Named(Named),
+ Named(Named<'a>),
/// A placeholder: `_`.
- Placeholder(Underscore),
+ Placeholder(Underscore<'a>),
}
-impl AstNode for DestructuringKind {
- fn from_untyped(node: &SyntaxNode) -> Option<Self> {
+impl<'a> AstNode<'a> for DestructuringKind<'a> {
+ fn from_untyped(node: &'a SyntaxNode) -> Option<Self> {
match node.kind() {
SyntaxKind::Named => node.cast().map(Self::Named),
SyntaxKind::Spread => node.cast().map(Self::Sink),
@@ -1723,29 +1732,29 @@ impl AstNode for DestructuringKind {
}
}
- fn as_untyped(&self) -> &SyntaxNode {
+ fn to_untyped(self) -> &'a SyntaxNode {
match self {
- Self::Normal(v) => v.as_untyped(),
- Self::Named(v) => v.as_untyped(),
- Self::Sink(v) => v.as_untyped(),
- Self::Placeholder(v) => v.as_untyped(),
+ Self::Normal(v) => v.to_untyped(),
+ Self::Named(v) => v.to_untyped(),
+ Self::Sink(v) => v.to_untyped(),
+ Self::Placeholder(v) => v.to_untyped(),
}
}
}
/// The kind of a pattern.
-#[derive(Debug, Clone, Hash)]
-pub enum Pattern {
+#[derive(Debug, Copy, Clone, Hash)]
+pub enum Pattern<'a> {
/// A single expression: `x`.
- Normal(Expr),
+ Normal(Expr<'a>),
/// A placeholder: `_`.
- Placeholder(Underscore),
+ Placeholder(Underscore<'a>),
/// A destructuring pattern: `(x, _, ..y)`.
- Destructuring(Destructuring),
+ Destructuring(Destructuring<'a>),
}
-impl AstNode for Pattern {
- fn from_untyped(node: &SyntaxNode) -> Option<Self> {
+impl<'a> AstNode<'a> for Pattern<'a> {
+ fn from_untyped(node: &'a SyntaxNode) -> Option<Self> {
match node.kind() {
SyntaxKind::Destructuring => node.cast().map(Self::Destructuring),
SyntaxKind::Underscore => node.cast().map(Self::Placeholder),
@@ -1753,27 +1762,27 @@ impl AstNode for Pattern {
}
}
- fn as_untyped(&self) -> &SyntaxNode {
+ fn to_untyped(self) -> &'a SyntaxNode {
match self {
- Self::Normal(v) => v.as_untyped(),
- Self::Destructuring(v) => v.as_untyped(),
- Self::Placeholder(v) => v.as_untyped(),
+ Self::Normal(v) => v.to_untyped(),
+ Self::Destructuring(v) => v.to_untyped(),
+ Self::Placeholder(v) => v.to_untyped(),
}
}
}
-impl Pattern {
- // Returns a list of all identifiers in the pattern.
- pub fn idents(&self) -> Vec<Ident> {
+impl<'a> Pattern<'a> {
+ /// Returns a list of all identifiers in the pattern.
+ pub fn idents(self) -> Vec<Ident<'a>> {
match self {
- Pattern::Normal(Expr::Ident(ident)) => vec![ident.clone()],
+ Pattern::Normal(Expr::Ident(ident)) => vec![ident],
Pattern::Destructuring(destruct) => destruct.idents().collect(),
_ => vec![],
}
}
}
-impl Default for Pattern {
+impl Default for Pattern<'_> {
fn default() -> Self {
Self::Normal(Expr::default())
}
@@ -1784,29 +1793,30 @@ node! {
LetBinding
}
+/// The kind of a let binding, either a normal one or a closure.
#[derive(Debug)]
-pub enum LetBindingKind {
+pub enum LetBindingKind<'a> {
/// A normal binding: `let x = 1`.
- Normal(Pattern),
+ Normal(Pattern<'a>),
/// A closure binding: `let f(x) = 1`.
- Closure(Ident),
+ Closure(Ident<'a>),
}
-impl LetBindingKind {
- // Returns a list of all identifiers in the pattern.
- pub fn idents(&self) -> Vec<Ident> {
+impl<'a> LetBindingKind<'a> {
+ /// Returns a list of all identifiers in the pattern.
+ pub fn idents(self) -> Vec<Ident<'a>> {
match self {
LetBindingKind::Normal(pattern) => pattern.idents(),
LetBindingKind::Closure(ident) => {
- vec![ident.clone()]
+ vec![ident]
}
}
}
}
-impl LetBinding {
+impl<'a> LetBinding<'a> {
/// The kind of the let binding.
- pub fn kind(&self) -> LetBindingKind {
+ pub fn kind(self) -> LetBindingKind<'a> {
match self.0.cast_first_match::<Pattern>() {
Some(Pattern::Normal(Expr::Closure(closure))) => {
LetBindingKind::Closure(closure.name().unwrap_or_default())
@@ -1816,7 +1826,7 @@ impl LetBinding {
}
/// The expression the binding is initialized with.
- pub fn init(&self) -> Option<Expr> {
+ pub fn init(self) -> Option<Expr<'a>> {
match self.kind() {
LetBindingKind::Normal(Pattern::Normal(_)) => {
self.0.children().filter_map(SyntaxNode::cast).nth(1)
@@ -1832,14 +1842,14 @@ node! {
DestructAssignment
}
-impl DestructAssignment {
+impl<'a> DestructAssignment<'a> {
/// The pattern of the assignment.
- pub fn pattern(&self) -> Pattern {
+ pub fn pattern(self) -> Pattern<'a> {
self.0.cast_first_match::<Pattern>().unwrap_or_default()
}
/// The expression that is assigned.
- pub fn value(&self) -> Expr {
+ pub fn value(self) -> Expr<'a> {
self.0.cast_last_match().unwrap_or_default()
}
}
@@ -1849,19 +1859,19 @@ node! {
SetRule
}
-impl SetRule {
+impl<'a> SetRule<'a> {
/// The function to set style properties for.
- pub fn target(&self) -> Expr {
+ pub fn target(self) -> Expr<'a> {
self.0.cast_first_match().unwrap_or_default()
}
/// The style properties to set.
- pub fn args(&self) -> Args {
+ pub fn args(self) -> Args<'a> {
self.0.cast_last_match().unwrap_or_default()
}
/// A condition under which the set rule applies.
- pub fn condition(&self) -> Option<Expr> {
+ pub fn condition(self) -> Option<Expr<'a>> {
self.0
.children()
.skip_while(|child| child.kind() != SyntaxKind::If)
@@ -1874,9 +1884,9 @@ node! {
ShowRule
}
-impl ShowRule {
+impl<'a> ShowRule<'a> {
/// Defines which nodes the show rule applies to.
- pub fn selector(&self) -> Option<Expr> {
+ pub fn selector(self) -> Option<Expr<'a>> {
self.0
.children()
.rev()
@@ -1885,7 +1895,7 @@ impl ShowRule {
}
/// The transformation recipe.
- pub fn transform(&self) -> Expr {
+ pub fn transform(self) -> Expr<'a> {
self.0.cast_last_match().unwrap_or_default()
}
}
@@ -1895,14 +1905,14 @@ node! {
Conditional
}
-impl Conditional {
+impl<'a> Conditional<'a> {
/// The condition which selects the body to evaluate.
- pub fn condition(&self) -> Expr {
+ pub fn condition(self) -> Expr<'a> {
self.0.cast_first_match().unwrap_or_default()
}
/// The expression to evaluate if the condition is true.
- pub fn if_body(&self) -> Expr {
+ pub fn if_body(self) -> Expr<'a> {
self.0
.children()
.filter_map(SyntaxNode::cast)
@@ -1911,7 +1921,7 @@ impl Conditional {
}
/// The expression to evaluate if the condition is false.
- pub fn else_body(&self) -> Option<Expr> {
+ pub fn else_body(self) -> Option<Expr<'a>> {
self.0.children().filter_map(SyntaxNode::cast).nth(2)
}
}
@@ -1921,14 +1931,14 @@ node! {
WhileLoop
}
-impl WhileLoop {
+impl<'a> WhileLoop<'a> {
/// The condition which selects whether to evaluate the body.
- pub fn condition(&self) -> Expr {
+ pub fn condition(self) -> Expr<'a> {
self.0.cast_first_match().unwrap_or_default()
}
/// The expression to evaluate while the condition is true.
- pub fn body(&self) -> Expr {
+ pub fn body(self) -> Expr<'a> {
self.0.cast_last_match().unwrap_or_default()
}
}
@@ -1938,14 +1948,14 @@ node! {
ForLoop
}
-impl ForLoop {
+impl<'a> ForLoop<'a> {
/// The pattern to assign to.
- pub fn pattern(&self) -> Pattern {
+ pub fn pattern(self) -> Pattern<'a> {
self.0.cast_first_match().unwrap_or_default()
}
/// The expression to iterate over.
- pub fn iter(&self) -> Expr {
+ pub fn iter(self) -> Expr<'a> {
self.0
.children()
.skip_while(|&c| c.kind() != SyntaxKind::In)
@@ -1954,7 +1964,7 @@ impl ForLoop {
}
/// The expression to evaluate for each iteration.
- pub fn body(&self) -> Expr {
+ pub fn body(self) -> Expr<'a> {
self.0.cast_last_match().unwrap_or_default()
}
}
@@ -1964,32 +1974,41 @@ node! {
ModuleImport
}
-impl ModuleImport {
+impl<'a> ModuleImport<'a> {
/// The module or path from which the items should be imported.
- pub fn source(&self) -> Expr {
+ pub fn source(self) -> Expr<'a> {
self.0.cast_first_match().unwrap_or_default()
}
/// The items to be imported.
- pub fn imports(&self) -> Option<Imports> {
+ pub fn imports(self) -> Option<Imports<'a>> {
self.0.children().find_map(|node| match node.kind() {
SyntaxKind::Star => Some(Imports::Wildcard),
- SyntaxKind::ImportItems => {
- let items = node.children().filter_map(SyntaxNode::cast).collect();
- Some(Imports::Items(items))
- }
+ SyntaxKind::ImportItems => node.cast().map(Imports::Items),
_ => Option::None,
})
}
}
/// The items that ought to be imported from a file.
-#[derive(Debug, Clone, Hash)]
-pub enum Imports {
+#[derive(Debug, Copy, Clone, Hash)]
+pub enum Imports<'a> {
/// All items in the scope of the file should be imported.
Wildcard,
/// The specified items from the file should be imported.
- Items(Vec<Ident>),
+ Items(ImportItems<'a>),
+}
+
+node! {
+ /// Items to import from a module: `a, b, c`.
+ ImportItems
+}
+
+impl<'a> ImportItems<'a> {
+ /// The items to import from the module.
+ pub fn idents(self) -> impl DoubleEndedIterator<Item = Ident<'a>> {
+ self.0.children().filter_map(SyntaxNode::cast)
+ }
}
node! {
@@ -1997,9 +2016,9 @@ node! {
ModuleInclude
}
-impl ModuleInclude {
+impl<'a> ModuleInclude<'a> {
/// The module or path from which the content should be included.
- pub fn source(&self) -> Expr {
+ pub fn source(self) -> Expr<'a> {
self.0.cast_last_match().unwrap_or_default()
}
}
@@ -2019,9 +2038,9 @@ node! {
FuncReturn
}
-impl FuncReturn {
+impl<'a> FuncReturn<'a> {
/// The expression to return.
- pub fn body(&self) -> Option<Expr> {
+ pub fn body(self) -> Option<Expr<'a>> {
self.0.cast_last_match()
}
}
diff --git a/crates/typst-syntax/src/node.rs b/crates/typst-syntax/src/node.rs
index f949b4dd..8e4e056e 100644
--- a/crates/typst-syntax/src/node.rs
+++ b/crates/typst-syntax/src/node.rs
@@ -105,22 +105,22 @@ impl SyntaxNode {
}
/// Whether the node can be cast to the given AST node.
- pub fn is<T: AstNode>(&self) -> bool {
+ pub fn is<'a, T: AstNode<'a>>(&'a self) -> bool {
self.cast::<T>().is_some()
}
/// Try to convert the node to a typed AST node.
- pub fn cast<T: AstNode>(&self) -> Option<T> {
+ pub fn cast<'a, T: AstNode<'a>>(&'a self) -> Option<T> {
T::from_untyped(self)
}
/// Cast the first child that can cast to the AST type `T`.
- pub fn cast_first_match<T: AstNode>(&self) -> Option<T> {
+ pub fn cast_first_match<'a, T: AstNode<'a>>(&'a self) -> Option<T> {
self.children().find_map(Self::cast)
}
/// Cast the last child that can cast to the AST type `T`.
- pub fn cast_last_match<T: AstNode>(&self) -> Option<T> {
+ pub fn cast_last_match<'a, T: AstNode<'a>>(&'a self) -> Option<T> {
self.children().rev().find_map(Self::cast)
}
@@ -273,6 +273,17 @@ impl SyntaxNode {
Repr::Error(node) => node.error.span.number() + 1,
}
}
+
+ /// An arbitrary node just for filling a slot in memory.
+ ///
+ /// In contrast to `default()`, this is a const fn.
+ pub(super) const fn arbitrary() -> Self {
+ Self(Repr::Leaf(LeafNode {
+ kind: SyntaxKind::Eof,
+ text: EcoString::new(),
+ span: Span::detached(),
+ }))
+ }
}
impl Debug for SyntaxNode {
@@ -287,7 +298,7 @@ impl Debug for SyntaxNode {
impl Default for SyntaxNode {
fn default() -> Self {
- Self::error("", "")
+ Self::arbitrary()
}
}
@@ -802,6 +813,8 @@ impl<'a> LinkedNode<'a> {
impl Deref for LinkedNode<'_> {
type Target = SyntaxNode;
+ /// Dereference to a syntax node. Note that this shortens the lifetime, so
+ /// you may need to use [`get()`](Self::get) instead in some situations.
fn deref(&self) -> &Self::Target {
self.get()
}
diff --git a/crates/typst/src/eval/func.rs b/crates/typst/src/eval/func.rs
index 372e3042..65b4ce10 100644
--- a/crates/typst/src/eval/func.rs
+++ b/crates/typst/src/eval/func.rs
@@ -12,7 +12,7 @@ use super::{
};
use crate::diag::{bail, SourceResult, StrResult};
use crate::model::{DelayedErrors, ElemFunc, Introspector, Locator, Vt};
-use crate::syntax::ast::{self, AstNode, Expr, Ident};
+use crate::syntax::ast::{self, AstNode};
use crate::syntax::{FileId, Span, SyntaxNode};
use crate::World;
@@ -45,7 +45,7 @@ impl Func {
match &self.repr {
Repr::Native(native) => Some(native.info.name),
Repr::Elem(func) => Some(func.info().name),
- Repr::Closure(closure) => closure.name.as_deref(),
+ Repr::Closure(closure) => closure.name(),
Repr::With(arc) => arc.0.name(),
}
}
@@ -295,36 +295,32 @@ pub struct ParamInfo {
/// A user-defined closure.
#[derive(Hash)]
pub(super) struct Closure {
+ /// The closure's syntax node. Must be castable to `ast::Closure`.
+ pub node: SyntaxNode,
/// The source file where the closure was defined.
pub location: FileId,
- /// The name of the closure.
- pub name: Option<Ident>,
+ /// Default values of named parameters.
+ pub defaults: Vec<Value>,
/// Captured values from outer scopes.
pub captured: Scope,
- /// The list of parameters.
- pub params: Vec<Param>,
- /// The expression the closure should evaluate to.
- pub body: Expr,
-}
-
-/// A closure parameter.
-#[derive(Hash)]
-pub enum Param {
- /// A positional parameter: `x`.
- Pos(ast::Pattern),
- /// A named parameter with a default value: `draw: false`.
- Named(Ident, Value),
- /// An argument sink: `..args`.
- Sink(Option<Ident>),
}
impl Closure {
+ /// The name of the closure.
+ pub fn name(&self) -> Option<&str> {
+ self.node
+ .cast::<ast::Closure>()
+ .unwrap()
+ .name()
+ .map(|ident| ident.as_str())
+ }
+
/// Call the function in the context with the arguments.
#[comemo::memoize]
#[tracing::instrument(skip_all)]
#[allow(clippy::too_many_arguments)]
fn call(
- this: &Func,
+ func: &Func,
world: Tracked<dyn World + '_>,
route: Tracked<Route>,
introspector: Tracked<Introspector>,
@@ -334,15 +330,15 @@ impl Closure {
depth: usize,
mut args: Args,
) -> SourceResult<Value> {
- let closure = match &this.repr {
- Repr::Closure(closure) => closure,
- _ => panic!("`this` must be a closure"),
+ let Repr::Closure(this) = &func.repr else {
+ panic!("`this` must be a closure");
};
+ let closure = this.node.cast::<ast::Closure>().unwrap();
// Don't leak the scopes from the call site. Instead, we use the scope
// of captured variables we collected earlier.
let mut scopes = Scopes::new(None);
- scopes.top = closure.captured.clone();
+ scopes.top = this.captured.clone();
// Prepare VT.
let mut locator = Locator::chained(locator);
@@ -355,30 +351,34 @@ impl Closure {
};
// Prepare VM.
- let mut vm = Vm::new(vt, route, closure.location, scopes);
+ let mut vm = Vm::new(vt, route, this.location, scopes);
vm.depth = depth;
// Provide the closure itself for recursive calls.
- if let Some(name) = &closure.name {
- vm.define(name.clone(), Value::Func(this.clone()));
+ if let Some(name) = closure.name() {
+ vm.define(name, Value::Func(func.clone()));
}
// Parse the arguments according to the parameter list.
- let num_pos_params =
- closure.params.iter().filter(|p| matches!(p, Param::Pos(_))).count();
+ let num_pos_params = closure
+ .params()
+ .children()
+ .filter(|p| matches!(p, ast::Param::Pos(_)))
+ .count();
let num_pos_args = args.to_pos().len();
let sink_size = num_pos_args.checked_sub(num_pos_params);
let mut sink = None;
let mut sink_pos_values = None;
- for p in &closure.params {
+ let mut defaults = this.defaults.iter();
+ for p in closure.params().children() {
match p {
- Param::Pos(pattern) => match pattern {
+ ast::Param::Pos(pattern) => match pattern {
ast::Pattern::Normal(ast::Expr::Ident(ident)) => {
- vm.define(ident.clone(), args.expect::<Value>(ident)?)
+ vm.define(ident, args.expect::<Value>(&ident)?)
}
ast::Pattern::Normal(_) => unreachable!(),
- _ => {
+ pattern => {
super::define_pattern(
&mut vm,
pattern,
@@ -386,16 +386,18 @@ impl Closure {
)?;
}
},
- Param::Sink(ident) => {
- sink = ident.clone();
+ ast::Param::Sink(ident) => {
+ sink = ident.name();
if let Some(sink_size) = sink_size {
sink_pos_values = Some(args.consume(sink_size)?);
}
}
- Param::Named(ident, default) => {
+ ast::Param::Named(named) => {
+ let name = named.name();
+ let default = defaults.next().unwrap();
let value =
- args.named::<Value>(ident)?.unwrap_or_else(|| default.clone());
- vm.define(ident.clone(), value);
+ args.named::<Value>(&name)?.unwrap_or_else(|| default.clone());
+ vm.define(name, value);
}
}
}
@@ -412,7 +414,7 @@ impl Closure {
args.finish()?;
// Handle control flow.
- let result = closure.body.eval(&mut vm);
+ let result = closure.body().eval(&mut vm);
match vm.flow {
Some(FlowEvent::Return(_, Some(explicit))) => return Ok(explicit),
Some(FlowEvent::Return(_, None)) => {}
@@ -483,7 +485,7 @@ impl<'a> CapturesVisitor<'a> {
Some(ast::Expr::Closure(expr)) => {
for param in expr.params().children() {
if let ast::Param::Named(named) = param {
- self.visit(named.expr().as_untyped());
+ self.visit(named.expr().to_untyped());
}
}
@@ -506,7 +508,7 @@ impl<'a> CapturesVisitor<'a> {
}
}
- self.visit(expr.body().as_untyped());
+ self.visit(expr.body().to_untyped());
self.internal.exit();
}
@@ -514,7 +516,7 @@ impl<'a> CapturesVisitor<'a> {
// active after the body is evaluated.
Some(ast::Expr::Let(expr)) => {
if let Some(init) = expr.init() {
- self.visit(init.as_untyped());
+ self.visit(init.to_untyped());
}
for ident in expr.kind().idents() {
@@ -526,7 +528,7 @@ impl<'a> CapturesVisitor<'a> {
// active after the iterable is evaluated but before the body is
// evaluated.
Some(ast::Expr::For(expr)) => {
- self.visit(expr.iter().as_untyped());
+ self.visit(expr.iter().to_untyped());
self.internal.enter();
let pattern = expr.pattern();
@@ -534,16 +536,16 @@ impl<'a> CapturesVisitor<'a> {
self.bind(ident);
}
- self.visit(expr.body().as_untyped());
+ self.visit(expr.body().to_untyped());
self.internal.exit();
}
// An import contains items, but these are active only after the
// path is evaluated.
Some(ast::Expr::Import(expr)) => {
- self.visit(expr.source().as_untyped());
+ self.visit(expr.source().to_untyped());
if let Some(ast::Imports::Items(items)) = expr.imports() {
- for item in items {
+ for item in items.idents() {
self.bind(item);
}
}
@@ -560,14 +562,14 @@ impl<'a> CapturesVisitor<'a> {
/// Bind a new internal variable.
fn bind(&mut self, ident: ast::Ident) {
- self.internal.top.define(ident.take(), Value::None);
+ self.internal.top.define(ident.get().clone(), Value::None);
}
/// Capture a variable if it isn't internal.
fn capture(&mut self, ident: ast::Ident) {
if self.internal.get(&ident).is_err() {
if let Ok(value) = self.external.get(&ident) {
- self.captures.define_captured(ident.take(), value.clone());
+ self.captures.define_captured(ident.get().clone(), value.clone());
}
}
}
@@ -576,7 +578,7 @@ impl<'a> CapturesVisitor<'a> {
fn capture_in_math(&mut self, ident: ast::MathIdent) {
if self.internal.get(&ident).is_err() {
if let Ok(value) = self.external.get_in_math(&ident) {
- self.captures.define_captured(ident.take(), value.clone());
+ self.captures.define_captured(ident.get().clone(), value.clone());
}
}
}
diff --git a/crates/typst/src/eval/mod.rs b/crates/typst/src/eval/mod.rs
index d1f248c8..9141544e 100644
--- a/crates/typst/src/eval/mod.rs
+++ b/crates/typst/src/eval/mod.rs
@@ -48,7 +48,7 @@ pub use self::cast::{
pub use self::datetime::Datetime;
pub use self::dict::{dict, Dict};
pub use self::fields::fields_on;
-pub use self::func::{Func, FuncInfo, NativeFunc, Param, ParamInfo};
+pub use self::func::{Func, FuncInfo, NativeFunc, ParamInfo};
pub use self::library::{set_lang_items, LangItems, Library};
pub use self::methods::methods_on;
pub use self::module::Module;
@@ -279,7 +279,7 @@ impl<'a> Vm<'a> {
if self.traced == Some(var.span()) {
self.vt.tracer.trace(value.clone());
}
- self.scopes.top.define(var.take(), value);
+ self.scopes.top.define(var.get().clone(), value);
}
}
@@ -362,21 +362,21 @@ pub(super) trait Eval {
type Output;
/// Evaluate the expression to the output value.
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output>;
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output>;
}
-impl Eval for ast::Markup {
+impl Eval for ast::Markup<'_> {
type Output = Content;
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
eval_markup(vm, &mut self.exprs())
}
}
/// Evaluate a stream of markup.
-fn eval_markup(
+fn eval_markup<'a>(
vm: &mut Vm,
- exprs: &mut impl Iterator<Item = ast::Expr>,
+ exprs: &mut impl Iterator<Item = ast::Expr<'a>>,
) -> SourceResult<Content> {
let flow = vm.flow.take();
let mut seq = Vec::with_capacity(exprs.size_hint().1.unwrap_or_default());
@@ -424,11 +424,11 @@ fn eval_markup(
Ok(Content::sequence(seq))
}
-impl Eval for ast::Expr {
+impl Eval for ast::Expr<'_> {
type Output = Value;
#[tracing::instrument(name = "Expr::eval", skip_all)]
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
let span = self.span();
let forbidden = |name| {
error!(span, "{} is only allowed directly in code and content blocks", name)
@@ -506,80 +506,80 @@ trait ExprExt {
fn eval_display(&self, vm: &mut Vm) -> SourceResult<Content>;
}
-impl ExprExt for ast::Expr {
+impl ExprExt for ast::Expr<'_> {
fn eval_display(&self, vm: &mut Vm) -> SourceResult<Content> {
Ok(self.eval(vm)?.display().spanned(self.span()))
}
}
-impl Eval for ast::Text {
+impl Eval for ast::Text<'_> {
type Output = Content;
#[tracing::instrument(name = "Text::eval", skip_all)]
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
Ok((vm.items.text)(self.get().clone()))
}
}
-impl Eval for ast::Space {
+impl Eval for ast::Space<'_> {
type Output = Content;
#[tracing::instrument(name = "Space::eval", skip_all)]
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
Ok((vm.items.space)())
}
}
-impl Eval for ast::Linebreak {
+impl Eval for ast::Linebreak<'_> {
type Output = Content;
#[tracing::instrument(name = "Linebreak::eval", skip_all)]
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
Ok((vm.items.linebreak)())
}
}
-impl Eval for ast::Parbreak {
+impl Eval for ast::Parbreak<'_> {
type Output = Content;
#[tracing::instrument(name = "Parbreak::eval", skip_all)]
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
Ok((vm.items.parbreak)())
}
}
-impl Eval for ast::Escape {
+impl Eval for ast::Escape<'_> {
type Output = Value;
#[tracing::instrument(name = "Escape::eval", skip_all)]
- fn eval(&self, _: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, _: &mut Vm) -> SourceResult<Self::Output> {
Ok(Value::Symbol(Symbol::new(self.get())))
}
}
-impl Eval for ast::Shorthand {
+impl Eval for ast::Shorthand<'_> {
type Output = Value;
#[tracing::instrument(name = "Shorthand::eval", skip_all)]
- fn eval(&self, _: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, _: &mut Vm) -> SourceResult<Self::Output> {
Ok(Value::Symbol(Symbol::new(self.get())))
}
}
-impl Eval for ast::SmartQuote {
+impl Eval for ast::SmartQuote<'_> {
type Output = Content;
#[tracing::instrument(name = "SmartQuote::eval", skip_all)]
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
Ok((vm.items.smart_quote)(self.double()))
}
}
-impl Eval for ast::Strong {
+impl Eval for ast::Strong<'_> {
type Output = Content;
#[tracing::instrument(name = "Strong::eval", skip_all)]
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
let body = self.body();
if body.exprs().next().is_none() {
vm.vt
@@ -593,11 +593,11 @@ impl Eval for ast::Strong {
}
}
-impl Eval for ast::Emph {
+impl Eval for ast::Emph<'_> {
type Output = Content;
#[tracing::instrument(name = "Emph::eval", skip_all)]
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
let body = self.body();
if body.exprs().next().is_none() {
vm.vt
@@ -611,11 +611,11 @@ impl Eval for ast::Emph {
}
}
-impl Eval for ast::Raw {
+impl Eval for ast::Raw<'_> {
type Output = Content;
#[tracing::instrument(name = "Raw::eval", skip_all)]
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
let text = self.text();
let lang = self.lang().map(Into::into);
let block = self.block();
@@ -623,93 +623,93 @@ impl Eval for ast::Raw {
}
}
-impl Eval for ast::Link {
+impl Eval for ast::Link<'_> {
type Output = Content;
#[tracing::instrument(name = "Link::eval", skip_all)]
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
Ok((vm.items.link)(self.get().clone()))
}
}
-impl Eval for ast::Label {
+impl Eval for ast::Label<'_> {
type Output = Value;
#[tracing::instrument(name = "Label::eval", skip_all)]
- fn eval(&self, _: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, _: &mut Vm) -> SourceResult<Self::Output> {
Ok(Value::Label(Label(self.get().into())))
}
}
-impl Eval for ast::Ref {
+impl Eval for ast::Ref<'_> {
type Output = Content;
#[tracing::instrument(name = "Ref::eval", skip_all)]
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
let label = Label(self.target().into());
let supplement = self.supplement().map(|block| block.eval(vm)).transpose()?;
Ok((vm.items.reference)(label, supplement))
}
}
-impl Eval for ast::Heading {
+impl Eval for ast::Heading<'_> {
type Output = Content;
#[tracing::instrument(name = "Heading::eval", skip_all)]
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
let level = self.level();
let body = self.body().eval(vm)?;
Ok((vm.items.heading)(level, body))
}
}
-impl Eval for ast::ListItem {
+impl Eval for ast::ListItem<'_> {
type Output = Content;
#[tracing::instrument(name = "ListItem::eval", skip_all)]
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
Ok((vm.items.list_item)(self.body().eval(vm)?))
}
}
-impl Eval for ast::EnumItem {
+impl Eval for ast::EnumItem<'_> {
type Output = Content;
#[tracing::instrument(name = "EnumItem::eval", skip_all)]
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
let number = self.number();
let body = self.body().eval(vm)?;
Ok((vm.items.enum_item)(number, body))
}
}
-impl Eval for ast::TermItem {
+impl Eval for ast::TermItem<'_> {
type Output = Content;
#[tracing::instrument(name = "TermItem::eval", skip_all)]
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
let term = self.term().eval(vm)?;
let description = self.description().eval(vm)?;
Ok((vm.items.term_item)(term, description))
}
}
-impl Eval for ast::Equation {
+impl Eval for ast::Equation<'_> {
type Output = Content;
#[tracing::instrument(name = "Equation::eval", skip_all)]
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
let body = self.body().eval(vm)?;
let block = self.block();
Ok((vm.items.equation)(body, block))
}
}
-impl Eval for ast::Math {
+impl Eval for ast::Math<'_> {
type Output = Content;
#[tracing::instrument(name = "Math::eval", skip_all)]
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
Ok(Content::sequence(
self.exprs()
.map(|expr| expr.eval_display(vm))
@@ -718,29 +718,29 @@ impl Eval for ast::Math {
}
}
-impl Eval for ast::MathIdent {
+impl Eval for ast::MathIdent<'_> {
type Output = Value;
#[tracing::instrument(name = "MathIdent::eval", skip_all)]
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
- vm.scopes.get_in_math(self).cloned().at(self.span())
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ vm.scopes.get_in_math(&self).cloned().at(self.span())
}
}
-impl Eval for ast::MathAlignPoint {
+impl Eval for ast::MathAlignPoint<'_> {
type Output = Content;
#[tracing::instrument(name = "MathAlignPoint::eval", skip_all)]
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
Ok((vm.items.math_align_point)())
}
}
-impl Eval for ast::MathDelimited {
+impl Eval for ast::MathDelimited<'_> {
type Output = Content;
#[tracing::instrument(name = "MathDelimited::eval", skip_all)]
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
let open = self.open().eval_display(vm)?;
let body = self.body().eval(vm)?;
let close = self.close().eval_display(vm)?;
@@ -748,11 +748,11 @@ impl Eval for ast::MathDelimited {
}
}
-impl Eval for ast::MathAttach {
+impl Eval for ast::MathAttach<'_> {
type Output = Content;
#[tracing::instrument(name = "MathAttach::eval", skip_all)]
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
let base = self.base().eval_display(vm)?;
let mut top = self.top().map(|expr| expr.eval_display(vm)).transpose()?;
@@ -767,113 +767,113 @@ impl Eval for ast::MathAttach {
}
}
-impl Eval for ast::MathPrimes {
+impl Eval for ast::MathPrimes<'_> {
type Output = Content;
#[tracing::instrument(name = "MathPrimes::eval", skip_all)]
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
Ok((vm.items.math_primes)(self.count()))
}
}
-impl Eval for ast::MathFrac {
+impl Eval for ast::MathFrac<'_> {
type Output = Content;
#[tracing::instrument(name = "MathFrac::eval", skip_all)]
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
let num = self.num().eval_display(vm)?;
let denom = self.denom().eval_display(vm)?;
Ok((vm.items.math_frac)(num, denom))
}
}
-impl Eval for ast::MathRoot {
+impl Eval for ast::MathRoot<'_> {
type Output = Content;
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
let index = self.index().map(|i| (vm.items.text)(eco_format!("{i}")));
let radicand = self.radicand().eval_display(vm)?;
Ok((vm.items.math_root)(index, radicand))
}
}
-impl Eval for ast::Ident {
+impl Eval for ast::Ident<'_> {
type Output = Value;
#[tracing::instrument(name = "Ident::eval", skip_all)]
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
- vm.scopes.get(self).cloned().at(self.span())
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ vm.scopes.get(&self).cloned().at(self.span())
}
}
-impl Eval for ast::None {
+impl Eval for ast::None<'_> {
type Output = Value;
#[tracing::instrument(name = "None::eval", skip_all)]
- fn eval(&self, _: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, _: &mut Vm) -> SourceResult<Self::Output> {
Ok(Value::None)
}
}
-impl Eval for ast::Auto {
+impl Eval for ast::Auto<'_> {
type Output = Value;
#[tracing::instrument(name = "Auto::eval", skip_all)]
- fn eval(&self, _: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, _: &mut Vm) -> SourceResult<Self::Output> {
Ok(Value::Auto)
}
}
-impl Eval for ast::Bool {
+impl Eval for ast::Bool<'_> {
type Output = Value;
#[tracing::instrument(name = "Bool::eval", skip_all)]
- fn eval(&self, _: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, _: &mut Vm) -> SourceResult<Self::Output> {
Ok(Value::Bool(self.get()))
}
}
-impl Eval for ast::Int {
+impl Eval for ast::Int<'_> {
type Output = Value;
#[tracing::instrument(name = "Int::eval", skip_all)]
- fn eval(&self, _: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, _: &mut Vm) -> SourceResult<Self::Output> {
Ok(Value::Int(self.get()))
}
}
-impl Eval for ast::Float {
+impl Eval for ast::Float<'_> {
type Output = Value;
#[tracing::instrument(name = "Float::eval", skip_all)]
- fn eval(&self, _: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, _: &mut Vm) -> SourceResult<Self::Output> {
Ok(Value::Float(self.get()))
}
}
-impl Eval for ast::Numeric {
+impl Eval for ast::Numeric<'_> {
type Output = Value;
#[tracing::instrument(name = "Numeric::eval", skip_all)]
- fn eval(&self, _: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, _: &mut Vm) -> SourceResult<Self::Output> {
Ok(Value::numeric(self.get()))
}
}
-impl Eval for ast::Str {
+impl Eval for ast::Str<'_> {
type Output = Value;
#[tracing::instrument(name = "Str::eval", skip_all)]
- fn eval(&self, _: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, _: &mut Vm) -> SourceResult<Self::Output> {
Ok(Value::Str(self.get().into()))
}
}
-impl Eval for ast::CodeBlock {
+impl Eval for ast::CodeBlock<'_> {
type Output = Value;
#[tracing::instrument(name = "CodeBlock::eval", skip_all)]
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
vm.scopes.enter();
let output = self.body().eval(vm)?;
vm.scopes.exit();
@@ -881,18 +881,18 @@ impl Eval for ast::CodeBlock {
}
}
-impl Eval for ast::Code {
+impl Eval for ast::Code<'_> {
type Output = Value;
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
eval_code(vm, &mut self.exprs())
}
}
/// Evaluate a stream of expressions.
-fn eval_code(
+fn eval_code<'a>(
vm: &mut Vm,
- exprs: &mut impl Iterator<Item = ast::Expr>,
+ exprs: &mut impl Iterator<Item = ast::Expr<'a>>,
) -> SourceResult<Value> {
let flow = vm.flow.take();
let mut output = Value::None;
@@ -935,11 +935,11 @@ fn eval_code(
Ok(output)
}
-impl Eval for ast::ContentBlock {
+impl Eval for ast::ContentBlock<'_> {
type Output = Content;
#[tracing::instrument(name = "ContentBlock::eval", skip_all)]
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
vm.scopes.enter();
let content = self.body().eval(vm)?;
vm.scopes.exit();
@@ -947,20 +947,20 @@ impl Eval for ast::ContentBlock {
}
}
-impl Eval for ast::Parenthesized {
+impl Eval for ast::Parenthesized<'_> {
type Output = Value;
#[tracing::instrument(name = "Parenthesized::eval", skip_all)]
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
self.expr().eval(vm)
}
}
-impl Eval for ast::Array {
+impl Eval for ast::Array<'_> {
type Output = Array;
#[tracing::instrument(skip_all)]
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
let items = self.items();
let mut vec = EcoVec::with_capacity(items.size_hint().0);
@@ -979,17 +979,17 @@ impl Eval for ast::Array {
}
}
-impl Eval for ast::Dict {
+impl Eval for ast::Dict<'_> {
type Output = Dict;
#[tracing::instrument(skip_all)]
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
let mut map = indexmap::IndexMap::new();
for item in self.items() {
match item {
ast::DictItem::Named(named) => {
- map.insert(named.name().take().into(), named.expr().eval(vm)?);
+ map.insert(named.name().get().clone().into(), named.expr().eval(vm)?);
}
ast::DictItem::Keyed(keyed) => {
map.insert(keyed.key().get().into(), keyed.expr().eval(vm)?);
@@ -1010,11 +1010,11 @@ impl Eval for ast::Dict {
}
}
-impl Eval for ast::Unary {
+impl Eval for ast::Unary<'_> {
type Output = Value;
#[tracing::instrument(name = "Unary::eval", skip_all)]
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
let value = self.expr().eval(vm)?;
let result = match self.op() {
ast::UnOp::Pos => ops::pos(value),
@@ -1025,11 +1025,11 @@ impl Eval for ast::Unary {
}
}
-impl Eval for ast::Binary {
+impl Eval for ast::Binary<'_> {
type Output = Value;
#[tracing::instrument(name = "Binary::eval", skip_all)]
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
match self.op() {
ast::BinOp::Add => apply_binary_expr(self, vm, ops::add),
ast::BinOp::Sub => apply_binary_expr(self, vm, ops::sub),
@@ -1056,7 +1056,7 @@ impl Eval for ast::Binary {
/// Apply a basic binary operation.
fn apply_binary_expr(
- binary: &ast::Binary,
+ binary: ast::Binary,
vm: &mut Vm,
op: fn(Value, Value) -> StrResult<Value>,
) -> SourceResult<Value> {
@@ -1075,7 +1075,7 @@ fn apply_binary_expr(
/// Apply an assignment operation.
fn apply_assignment(
- binary: &ast::Binary,
+ binary: ast::Binary,
vm: &mut Vm,
op: fn(Value, Value) -> StrResult<Value>,
) -> SourceResult<Value> {
@@ -1085,9 +1085,9 @@ fn apply_assignment(
// An assignment to a dictionary field is different from a normal access
// since it can create the field instead of just modifying it.
if binary.op() == ast::BinOp::Assign {
- if let ast::Expr::FieldAccess(access) = &lhs {
+ if let ast::Expr::FieldAccess(access) = lhs {
let dict = access_dict(vm, access)?;
- dict.insert(access.field().take().into(), rhs);
+ dict.insert(access.field().get().clone().into(), rhs);
return Ok(Value::None);
}
}
@@ -1098,29 +1098,29 @@ fn apply_assignment(
Ok(Value::None)
}
-impl Eval for ast::FieldAccess {
+impl Eval for ast::FieldAccess<'_> {
type Output = Value;
#[tracing::instrument(name = "FieldAccess::eval", skip_all)]
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
let value = self.target().eval(vm)?;
let field = self.field();
value.field(&field).at(field.span())
}
}
-impl Eval for ast::FuncCall {
+impl Eval for ast::FuncCall<'_> {
type Output = Value;
#[tracing::instrument(name = "FuncCall::eval", skip_all)]
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
let span = self.span();
if vm.depth >= MAX_CALL_DEPTH {
bail!(span, "maximum function call depth exceeded");
}
let callee = self.callee();
- let in_math = in_math(&callee);
+ let in_math = in_math(callee);
let callee_span = callee.span();
let args = self.args();
@@ -1129,9 +1129,7 @@ impl Eval for ast::FuncCall {
let (callee, mut args) = if let ast::Expr::FieldAccess(access) = callee {
let target = access.target();
let field = access.field();
- let field_span = field.span();
- let field = field.take();
- let point = || Tracepoint::Call(Some(field.clone()));
+ let point = || Tracepoint::Call(Some(field.get().clone()));
if methods::is_mutating(&field) {
let args = args.eval(vm)?;
let target = target.access(vm)?;
@@ -1142,7 +1140,9 @@ impl Eval for ast::FuncCall {
// ('methods_on' will be empty for Symbol and Module - their
// method calls always refer to their fields.)
if !matches!(target, Value::Symbol(_) | Value::Module(_) | Value::Func(_))
- || methods_on(target.type_name()).iter().any(|(m, _)| m == &field)
+ || methods_on(target.type_name())
+ .iter()
+ .any(|&(m, _)| m == field.as_str())
{
return methods::call_mut(target, &field, args, span).trace(
vm.world(),
@@ -1150,13 +1150,15 @@ impl Eval for ast::FuncCall {
span,
);
}
- (target.field(&field).at(field_span)?, args)
+ (target.field(&field).at(field.span())?, args)
} else {
let target = target.eval(vm)?;
let args = args.eval(vm)?;
if !matches!(target, Value::Symbol(_) | Value::Module(_) | Value::Func(_))
- || methods_on(target.type_name()).iter().any(|(m, _)| m == &field)
+ || methods_on(target.type_name())
+ .iter()
+ .any(|&(m, _)| m == field.as_str())
{
return methods::call(vm, target, &field, args, span).trace(
vm.world(),
@@ -1164,7 +1166,7 @@ impl Eval for ast::FuncCall {
span,
);
}
- (target.field(&field).at(field_span)?, args)
+ (target.field(&field).at(field.span())?, args)
}
} else {
(callee.eval(vm)?, args.eval(vm)?)
@@ -1212,18 +1214,18 @@ impl Eval for ast::FuncCall {
}
}
-fn in_math(expr: &ast::Expr) -> bool {
+fn in_math(expr: ast::Expr) -> bool {
match expr {
ast::Expr::MathIdent(_) => true,
- ast::Expr::FieldAccess(access) => in_math(&access.target()),
+ ast::Expr::FieldAccess(access) => in_math(access.target()),
_ => false,
}
}
-impl Eval for ast::Args {
+impl Eval for ast::Args<'_> {
type Output = Args;
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
let mut items = EcoVec::new();
for arg in self.items() {
@@ -1239,7 +1241,7 @@ impl Eval for ast::Args {
ast::Arg::Named(named) => {
items.push(Arg {
span,
- name: Some(named.name().take().into()),
+ name: Some(named.name().get().clone().into()),
value: Spanned::new(named.expr().eval(vm)?, named.expr().span()),
});
}
@@ -1269,40 +1271,32 @@ impl Eval for ast::Args {
}
}
-impl Eval for ast::Closure {
+impl Eval for ast::Closure<'_> {
type Output = Value;
#[tracing::instrument(name = "Closure::eval", skip_all)]
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
- // The closure's name is defined by its let binding if there's one.
- let name = self.name();
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ // Evaluate default values of named parameters.
+ let mut defaults = Vec::new();
+ for param in self.params().children() {
+ if let ast::Param::Named(named) = param {
+ defaults.push(named.expr().eval(vm)?);
+ }
+ }
// Collect captured variables.
let captured = {
let mut visitor = CapturesVisitor::new(&vm.scopes);
- visitor.visit(self.as_untyped());
+ visitor.visit(self.to_untyped());
visitor.finish()
};
- // Collect parameters and an optional sink parameter.
- let mut params = Vec::new();
- for param in self.params().children() {
- match param {
- ast::Param::Pos(pattern) => params.push(Param::Pos(pattern)),
- ast::Param::Named(named) => {
- params.push(Param::Named(named.name(), named.expr().eval(vm)?));
- }
- ast::Param::Sink(spread) => params.push(Param::Sink(spread.name())),
- }
- }
-
// Define the closure.
let closure = Closure {
+ node: self.to_untyped().clone(),
location: vm.location,
- name,
+ defaults,
captured,
- params,
- body: self.body(),
};
Ok(Value::Func(Func::from(closure).spanned(self.params().span())))
@@ -1312,7 +1306,7 @@ impl Eval for ast::Closure {
/// Destruct the value into the pattern by binding.
fn define_pattern(
vm: &mut Vm,
- pattern: &ast::Pattern,
+ pattern: ast::Pattern,
value: Value,
) -> SourceResult<Value> {
destructure(vm, pattern, value, |vm, expr, value| match expr {
@@ -1327,7 +1321,7 @@ fn define_pattern(
/// Destruct the value into the pattern by assignment.
fn assign_pattern(
vm: &mut Vm,
- pattern: &ast::Pattern,
+ pattern: ast::Pattern,
value: Value,
) -> SourceResult<Value> {
destructure(vm, pattern, value, |vm, expr, value| {
@@ -1341,7 +1335,7 @@ fn assign_pattern(
#[tracing::instrument(skip_all)]
fn destructure<T>(
vm: &mut Vm,
- pattern: &ast::Pattern,
+ pattern: ast::Pattern,
value: Value,
f: T,
) -> SourceResult<Value>
@@ -1350,7 +1344,7 @@ where
{
match pattern {
ast::Pattern::Normal(expr) => {
- f(vm, expr.clone(), value)?;
+ f(vm, expr, value)?;
Ok(Value::None)
}
ast::Pattern::Placeholder(_) => Ok(Value::None),
@@ -1364,10 +1358,10 @@ where
fn destructure_array<F>(
vm: &mut Vm,
- pattern: &ast::Pattern,
+ pattern: ast::Pattern,
value: Array,
f: F,
- destruct: &ast::Destructuring,
+ destruct: ast::Destructuring,
) -> SourceResult<Value>
where
F: Fn(&mut Vm, ast::Expr, Value) -> SourceResult<Value>,
@@ -1418,7 +1412,7 @@ fn destructure_dict<F>(
vm: &mut Vm,
dict: Dict,
f: F,
- destruct: &ast::Destructuring,
+ destruct: ast::Destructuring,
) -> SourceResult<Value>
where
F: Fn(&mut Vm, ast::Expr, Value) -> SourceResult<Value>,
@@ -1432,8 +1426,8 @@ where
.at(&ident, None)
.map_err(|_| "destructuring key not found in dictionary")
.at(ident.span())?;
- f(vm, ast::Expr::Ident(ident.clone()), v)?;
- used.insert(ident.take());
+ f(vm, ast::Expr::Ident(ident), v)?;
+ used.insert(ident.as_str());
}
ast::DestructuringKind::Sink(spread) => sink = spread.expr(),
ast::DestructuringKind::Named(named) => {
@@ -1443,7 +1437,7 @@ where
.map_err(|_| "destructuring key not found in dictionary")
.at(name.span())?;
f(vm, named.expr(), v)?;
- used.insert(name.take());
+ used.insert(name.as_str());
}
ast::DestructuringKind::Placeholder(_) => {}
ast::DestructuringKind::Normal(expr) => {
@@ -1465,18 +1459,18 @@ where
Ok(Value::None)
}
-impl Eval for ast::LetBinding {
+impl Eval for ast::LetBinding<'_> {
type Output = Value;
#[tracing::instrument(name = "LetBinding::eval", skip_all)]
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
let value = match self.init() {
Some(expr) => expr.eval(vm)?,
None => Value::None,
};
match self.kind() {
- ast::LetBindingKind::Normal(pattern) => define_pattern(vm, &pattern, value),
+ ast::LetBindingKind::Normal(pattern) => define_pattern(vm, pattern, value),
ast::LetBindingKind::Closure(ident) => {
vm.define(ident, value);
Ok(Value::None)
@@ -1485,20 +1479,20 @@ impl Eval for ast::LetBinding {
}
}
-impl Eval for ast::DestructAssignment {
+impl Eval for ast::DestructAssignment<'_> {
type Output = Value;
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
let value = self.value().eval(vm)?;
- assign_pattern(vm, &self.pattern(), value)?;
+ assign_pattern(vm, self.pattern(), value)?;
Ok(Value::None)
}
}
-impl Eval for ast::SetRule {
+impl Eval for ast::SetRule<'_> {
type Output = Styles;
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
if let Some(condition) = self.condition() {
if !condition.eval(vm)?.cast::<bool>().at(condition.span())? {
return Ok(Styles::new());
@@ -1520,10 +1514,10 @@ impl Eval for ast::SetRule {
}
}
-impl Eval for ast::ShowRule {
+impl Eval for ast::ShowRule<'_> {
type Output = Recipe;
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
let selector = self
.selector()
.map(|sel| sel.eval(vm)?.cast::<ShowableSelector>().at(sel.span()))
@@ -1542,11 +1536,11 @@ impl Eval for ast::ShowRule {
}
}
-impl Eval for ast::Conditional {
+impl Eval for ast::Conditional<'_> {
type Output = Value;
#[tracing::instrument(name = "Conditional::eval", skip_all)]
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
let condition = self.condition();
if condition.eval(vm)?.cast::<bool>().at(condition.span())? {
self.if_body().eval(vm)
@@ -1558,11 +1552,11 @@ impl Eval for ast::Conditional {
}
}
-impl Eval for ast::WhileLoop {
+impl Eval for ast::WhileLoop<'_> {
type Output = Value;
#[tracing::instrument(name = "WhileLoop::eval", skip_all)]
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
let flow = vm.flow.take();
let mut output = Value::None;
let mut i = 0;
@@ -1572,8 +1566,8 @@ impl Eval for ast::WhileLoop {
while condition.eval(vm)?.cast::<bool>().at(condition.span())? {
if i == 0
- && is_invariant(condition.as_untyped())
- && !can_diverge(body.as_untyped())
+ && is_invariant(condition.to_untyped())
+ && !can_diverge(body.to_untyped())
{
bail!(condition.span(), "condition is always true");
} else if i >= MAX_ITERATIONS {
@@ -1610,11 +1604,11 @@ fn is_invariant(expr: &SyntaxNode) -> bool {
Some(ast::Expr::Ident(_)) => false,
Some(ast::Expr::MathIdent(_)) => false,
Some(ast::Expr::FieldAccess(access)) => {
- is_invariant(access.target().as_untyped())
+ is_invariant(access.target().to_untyped())
}
Some(ast::Expr::FuncCall(call)) => {
- is_invariant(call.callee().as_untyped())
- && is_invariant(call.args().as_untyped())
+ is_invariant(call.callee().to_untyped())
+ && is_invariant(call.args().to_untyped())
}
_ => expr.children().all(is_invariant),
}
@@ -1626,11 +1620,11 @@ fn can_diverge(expr: &SyntaxNode) -> bool {
|| expr.children().any(can_diverge)
}
-impl Eval for ast::ForLoop {
+impl Eval for ast::ForLoop<'_> {
type Output = Value;
#[tracing::instrument(name = "ForLoop::eval", skip_all)]
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
let flow = vm.flow.take();
let mut output = Value::None;
@@ -1640,7 +1634,7 @@ impl Eval for ast::ForLoop {
#[allow(unused_parens)]
for value in $iter {
- define_pattern(vm, &$pat, value.into_value())?;
+ define_pattern(vm, $pat, value.into_value())?;
let body = self.body();
let value = body.eval(vm)?;
@@ -1710,10 +1704,10 @@ fn apply_imports<V: IntoValue>(
vm.scopes.top.define(var.clone(), value.clone());
}
}
- Some(ast::Imports::Items(idents)) => {
+ Some(ast::Imports::Items(items)) => {
let mut errors = vec![];
let scope = scope(&source_value);
- for ident in idents {
+ for ident in items.idents() {
if let Some(value) = scope.get(&ident) {
vm.define(ident, value.clone());
} else {
@@ -1729,11 +1723,11 @@ fn apply_imports<V: IntoValue>(
Ok(())
}
-impl Eval for ast::ModuleImport {
+impl Eval for ast::ModuleImport<'_> {
type Output = Value;
#[tracing::instrument(name = "ModuleImport::eval", skip_all)]
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
let span = self.source().span();
let source = self.source().eval(vm)?;
if let Value::Func(func) = source {
@@ -1762,11 +1756,11 @@ impl Eval for ast::ModuleImport {
}
}
-impl Eval for ast::ModuleInclude {
+impl Eval for ast::ModuleInclude<'_> {
type Output = Content;
#[tracing::instrument(name = "ModuleInclude::eval", skip_all)]
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
let span = self.source().span();
let source = self.source().eval(vm)?;
let module = import(vm, source, span, false)?;
@@ -1884,11 +1878,11 @@ struct PackageInfo {
entrypoint: EcoString,
}
-impl Eval for ast::LoopBreak {
+impl Eval for ast::LoopBreak<'_> {
type Output = Value;
#[tracing::instrument(name = "LoopBreak::eval", skip_all)]
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
if vm.flow.is_none() {
vm.flow = Some(FlowEvent::Break(self.span()));
}
@@ -1896,11 +1890,11 @@ impl Eval for ast::LoopBreak {
}
}
-impl Eval for ast::LoopContinue {
+impl Eval for ast::LoopContinue<'_> {
type Output = Value;
#[tracing::instrument(name = "LoopContinue::eval", skip_all)]
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
if vm.flow.is_none() {
vm.flow = Some(FlowEvent::Continue(self.span()));
}
@@ -1908,11 +1902,11 @@ impl Eval for ast::LoopContinue {
}
}
-impl Eval for ast::FuncReturn {
+impl Eval for ast::FuncReturn<'_> {
type Output = Value;
#[tracing::instrument(name = "FuncReturn::eval", skip_all)]
- fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
+ fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
let value = self.body().map(|body| body.eval(vm)).transpose()?;
if vm.flow.is_none() {
vm.flow = Some(FlowEvent::Return(self.span(), value));
@@ -1924,11 +1918,11 @@ impl Eval for ast::FuncReturn {
/// Access an expression mutably.
trait Access {
/// Access the value.
- fn access<'a>(&self, vm: &'a mut Vm) -> SourceResult<&'a mut Value>;
+ fn access<'a>(self, vm: &'a mut Vm) -> SourceResult<&'a mut Value>;
}
-impl Access for ast::Expr {
- fn access<'a>(&self, vm: &'a mut Vm) -> SourceResult<&'a mut Value> {
+impl Access for ast::Expr<'_> {
+ fn access<'a>(self, vm: &'a mut Vm) -> SourceResult<&'a mut Value> {
match self {
Self::Ident(v) => v.access(vm),
Self::Parenthesized(v) => v.access(vm),
@@ -1942,10 +1936,10 @@ impl Access for ast::Expr {
}
}
-impl Access for ast::Ident {
- fn access<'a>(&self, vm: &'a mut Vm) -> SourceResult<&'a mut Value> {
+impl Access for ast::Ident<'_> {
+ fn access<'a>(self, vm: &'a mut Vm) -> SourceResult<&'a mut Value> {
let span = self.span();
- let value = vm.scopes.get_mut(self).at(span)?;
+ let value = vm.scopes.get_mut(&self).at(span)?;
if vm.traced == Some(span) {
vm.vt.tracer.trace(value.clone());
}
@@ -1953,21 +1947,21 @@ impl Access for ast::Ident {
}
}
-impl Access for ast::Parenthesized {
- fn access<'a>(&self, vm: &'a mut Vm) -> SourceResult<&'a mut Value> {
+impl Access for ast::Parenthesized<'_> {
+ fn access<'a>(self, vm: &'a mut Vm) -> SourceResult<&'a mut Value> {
self.expr().access(vm)
}
}
-impl Access for ast::FieldAccess {
- fn access<'a>(&self, vm: &'a mut Vm) -> SourceResult<&'a mut Value> {
- access_dict(vm, self)?.at_mut(&self.field().take()).at(self.span())
+impl Access for ast::FieldAccess<'_> {
+ fn access<'a>(self, vm: &'a mut Vm) -> SourceResult<&'a mut Value> {
+ access_dict(vm, self)?.at_mut(self.field().get()).at(self.span())
}
}
fn access_dict<'a>(
vm: &'a mut Vm,
- access: &ast::FieldAccess,
+ access: ast::FieldAccess,
) -> SourceResult<&'a mut Dict> {
match access.target().access(vm)? {
Value::Dict(dict) => Ok(dict),
@@ -1992,17 +1986,17 @@ fn access_dict<'a>(
}
}
-impl Access for ast::FuncCall {
- fn access<'a>(&self, vm: &'a mut Vm) -> SourceResult<&'a mut Value> {
+impl Access for ast::FuncCall<'_> {
+ fn access<'a>(self, vm: &'a mut Vm) -> SourceResult<&'a mut Value> {
if let ast::Expr::FieldAccess(access) = self.callee() {
- let method = access.field().take();
+ let method = access.field();
if methods::is_accessor(&method) {
let span = self.span();
let world = vm.world();
let args = self.args().eval(vm)?;
let value = access.target().access(vm)?;
let result = methods::call_access(value, &method, args, span);
- let point = || Tracepoint::Call(Some(method.clone()));
+ let point = || Tracepoint::Call(Some(method.get().clone()));
return result.trace(world, point, span);
}
}
diff --git a/crates/typst/src/ide/complete.rs b/crates/typst/src/ide/complete.rs
index dcde0985..86b10d43 100644
--- a/crates/typst/src/ide/complete.rs
+++ b/crates/typst/src/ide/complete.rs
@@ -442,13 +442,13 @@ fn complete_imports(ctx: &mut CompletionContext) -> bool {
// "#import "path.typ": a, b, |".
if_chain! {
if let Some(prev) = ctx.leaf.prev_sibling();
- if let Some(ast::Expr::Import(import)) = prev.cast();
+ if let Some(ast::Expr::Import(import)) = prev.get().cast();
if let Some(ast::Imports::Items(items)) = import.imports();
if let Some(source) = prev.children().find(|child| child.is::<ast::Expr>());
if let Some(value) = analyze_expr(ctx.world, &source).into_iter().next();
then {
ctx.from = ctx.cursor;
- import_item_completions(ctx, &items, &value);
+ import_item_completions(ctx, items, &value);
return true;
}
}
@@ -460,13 +460,13 @@ fn complete_imports(ctx: &mut CompletionContext) -> bool {
if let Some(parent) = ctx.leaf.parent();
if parent.kind() == SyntaxKind::ImportItems;
if let Some(grand) = parent.parent();
- if let Some(ast::Expr::Import(import)) = grand.cast();
+ if let Some(ast::Expr::Import(import)) = grand.get().cast();
if let Some(ast::Imports::Items(items)) = import.imports();
if let Some(source) = grand.children().find(|child| child.is::<ast::Expr>());
if let Some(value) = analyze_expr(ctx.world, &source).into_iter().next();
then {
ctx.from = ctx.leaf.offset();
- import_item_completions(ctx, &items, &value);
+ import_item_completions(ctx, items, &value);
return true;
}
}
@@ -475,9 +475,9 @@ fn complete_imports(ctx: &mut CompletionContext) -> bool {
}
/// Add completions for all exports of a module.
-fn import_item_completions(
- ctx: &mut CompletionContext,
- existing: &[ast::Ident],
+fn import_item_completions<'a>(
+ ctx: &mut CompletionContext<'a>,
+ existing: ast::ImportItems<'a>,
value: &Value,
) {
let module = match value {
@@ -489,12 +489,12 @@ fn import_item_completions(
_ => return,
};
- if existing.is_empty() {
+ if existing.idents().next().is_none() {
ctx.snippet_completion("*", "*", "Import everything.");
}
for (name, value) in module.scope().iter() {
- if existing.iter().all(|ident| ident.as_str() != name) {
+ if existing.idents().all(|ident| ident.as_str() != name) {
ctx.value_completion(Some(name.clone()), value, false, None);
}
}
@@ -604,9 +604,9 @@ fn complete_params(ctx: &mut CompletionContext) -> bool {
SyntaxKind::Named => parent.parent(),
_ => Some(parent),
};
- if let Some(args) = parent.cast::<ast::Args>();
+ if let Some(args) = parent.get().cast::<ast::Args>();
if let Some(grand) = parent.parent();
- if let Some(expr) = grand.cast::<ast::Expr>();
+ if let Some(expr) = grand.get().cast::<ast::Expr>();
let set = matches!(expr, ast::Expr::Set(_));
if let Some(callee) = match expr {
ast::Expr::FuncCall(call) => Some(call.callee()),
@@ -634,13 +634,13 @@ fn complete_params(ctx: &mut CompletionContext) -> bool {
if_chain! {
if deciding.kind() == SyntaxKind::Colon;
if let Some(prev) = deciding.prev_leaf();
- if let Some(param) = prev.cast::<ast::Ident>();
+ if let Some(param) = prev.get().cast::<ast::Ident>();
then {
if let Some(next) = deciding.next_leaf() {
ctx.from = ctx.cursor.min(next.offset());
}
- named_param_value_completions(ctx, &callee, &param);
+ named_param_value_completions(ctx, callee, &param);
return true;
}
}
@@ -655,12 +655,15 @@ fn complete_params(ctx: &mut CompletionContext) -> bool {
}
// Exclude arguments which are already present.
- let exclude: Vec<_> = args.items().filter_map(|arg| match arg {
- ast::Arg::Named(named) => Some(named.name()),
- _ => None,
- }).collect();
-
- param_completions(ctx, &callee, set, &exclude);
+ let exclude: Vec<_> = args
+ .items()
+ .filter_map(|arg| match arg {
+ ast::Arg::Named(named) => Some(named.name()),
+ _ => None,
+ })
+ .collect();
+
+ param_completions(ctx, callee, set, &exclude);
return true;
}
}
@@ -669,11 +672,11 @@ fn complete_params(ctx: &mut CompletionContext) -> bool {
}
/// Add completions for the parameters of a function.
-fn param_completions(
- ctx: &mut CompletionContext,
- callee: &ast::Expr,
+fn param_completions<'a>(
+ ctx: &mut CompletionContext<'a>,
+ callee: ast::Expr<'a>,
set: bool,
- exclude: &[ast::Ident],
+ exclude: &[ast::Ident<'a>],
) {
let Some(func) = resolve_global_callee(ctx, callee) else { return };
let Some(info) = func.info() else { return };
@@ -707,9 +710,9 @@ fn param_completions(
}
/// Add completions for the values of a named function parameter.
-fn named_param_value_completions(
- ctx: &mut CompletionContext,
- callee: &ast::Expr,
+fn named_param_value_completions<'a>(
+ ctx: &mut CompletionContext<'a>,
+ callee: ast::Expr<'a>,
name: &str,
) {
let Some(func) = resolve_global_callee(ctx, callee) else { return };
@@ -732,10 +735,10 @@ fn named_param_value_completions(
/// Resolve a callee expression to a global function.
fn resolve_global_callee<'a>(
ctx: &CompletionContext<'a>,
- callee: &ast::Expr,
+ callee: ast::Expr<'a>,
) -> Option<&'a Func> {
let value = match callee {
- ast::Expr::Ident(ident) => ctx.global.get(ident)?,
+ ast::Expr::Ident(ident) => ctx.global.get(&ident)?,
ast::Expr::FieldAccess(access) => match access.target() {
ast::Expr::Ident(target) => match ctx.global.get(&target)? {
Value::Module(module) => module.get(&access.field()).ok()?,
@@ -1189,20 +1192,20 @@ impl<'a> CompletionContext<'a> {
while let Some(node) = &ancestor {
let mut sibling = Some(node.clone());
while let Some(node) = &sibling {
- if let Some(v) = node.cast::<ast::LetBinding>() {
+ if let Some(v) = node.get().cast::<ast::LetBinding>() {
for ident in v.kind().idents() {
- defined.insert(ident.take());
+ defined.insert(ident.get());
}
}
sibling = node.prev_sibling();
}
if let Some(parent) = node.parent() {
- if let Some(v) = parent.cast::<ast::ForLoop>() {
+ if let Some(v) = parent.get().cast::<ast::ForLoop>() {
if node.prev_sibling_kind() != Some(SyntaxKind::In) {
let pattern = v.pattern();
for ident in pattern.idents() {
- defined.insert(ident.take());
+ defined.insert(ident.get());
}
}
}
@@ -1233,7 +1236,7 @@ impl<'a> CompletionContext<'a> {
if !name.is_empty() {
self.completions.push(Completion {
kind: CompletionKind::Constant,
- label: name,
+ label: name.clone(),
apply: None,
detail: None,
});