From 5fb5854ed80c48660b51ee163b3ff77f7e44ab94 Mon Sep 17 00:00:00 2001 From: Laurenz Date: Sat, 19 Aug 2023 19:44:08 +0200 Subject: [PATCH] Make AST borrowed --- crates/typst-syntax/src/ast.rs | 789 ++++++++++++++++--------------- crates/typst-syntax/src/node.rs | 23 +- crates/typst/src/eval/func.rs | 100 ++-- crates/typst/src/eval/mod.rs | 394 ++++++++------- crates/typst/src/ide/complete.rs | 67 +-- 5 files changed, 702 insertions(+), 671 deletions(-) diff --git a/crates/typst-syntax/src/ast.rs b/crates/typst-syntax/src/ast.rs index 65a91629f..7cf0cbd51 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; + fn from_untyped(node: &'a SyntaxNode) -> Option; /// 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 { + impl<'a> AstNode<'a> for $name<'a> { + #[inline] + fn from_untyped(node: &'a SyntaxNode) -> Option { 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 + '_ { + pub fn exprs(self) -> impl DoubleEndedIterator> { 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: ``. - 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 { +impl<'a> Expr<'a> { + fn cast_with_space(node: &'a SyntaxNode) -> Option { 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 { +impl<'a> AstNode<'a> for Expr<'a> { + fn from_untyped(node: &'a SyntaxNode) -> Option { 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 { + pub fn supplement(self) -> Option> { 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 { + pub fn number(self) -> Option { 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 + '_ { + pub fn exprs(self) -> impl DoubleEndedIterator> { 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 { + pub fn bottom(self) -> Option> { 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 { + pub fn top(self) -> Option> { 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 { + pub fn primes(self) -> Option> { 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 { + pub fn index(self) -> Option { 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 + '_ { + pub fn exprs(self) -> impl DoubleEndedIterator> { 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 + '_ { + pub fn items(self) -> impl DoubleEndedIterator> { 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 { +impl<'a> AstNode<'a> for ArrayItem<'a> { + fn from_untyped(node: &'a SyntaxNode) -> Option { 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 + '_ { + pub fn items(self) -> impl DoubleEndedIterator> { 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 { +impl<'a> AstNode<'a> for DictItem<'a> { + fn from_untyped(node: &'a SyntaxNode) -> Option { 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 { + pub fn expr_ident(self) -> Option> { 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::()) @@ -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 + '_ { + pub fn items(self) -> impl DoubleEndedIterator> { 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 { +impl<'a> AstNode<'a> for Arg<'a> { + fn from_untyped(node: &'a SyntaxNode) -> Option { 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 { + pub fn name(self) -> Option> { 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 + '_ { + pub fn children(self) -> impl DoubleEndedIterator> { 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 { + pub fn name(self) -> Option> { self.0.cast_first_match() } /// Try to get an expression. - pub fn expr(&self) -> Option { + pub fn expr(self) -> Option> { 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 { +impl<'a> AstNode<'a> for Param<'a> { + fn from_untyped(node: &'a SyntaxNode) -> Option { 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 + '_ { + pub fn bindings(self) -> impl DoubleEndedIterator> { self.0.children().filter_map(SyntaxNode::cast) } - // Returns a list of all identifiers in the pattern. - pub fn idents(&self) -> impl Iterator + '_ { + /// Returns a list of all identifiers in the pattern. + pub fn idents(self) -> impl DoubleEndedIterator> { 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 { +impl<'a> AstNode<'a> for DestructuringKind<'a> { + fn from_untyped(node: &'a SyntaxNode) -> Option { 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 { +impl<'a> AstNode<'a> for Pattern<'a> { + fn from_untyped(node: &'a SyntaxNode) -> Option { 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 { +impl<'a> Pattern<'a> { + /// Returns a list of all identifiers in the pattern. + pub fn idents(self) -> Vec> { 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 { +impl<'a> LetBindingKind<'a> { + /// Returns a list of all identifiers in the pattern. + pub fn idents(self) -> Vec> { 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::() { 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 { + pub fn init(self) -> Option> { 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::().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 { + pub fn condition(self) -> Option> { 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 { + pub fn selector(self) -> Option> { 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 { + pub fn else_body(self) -> Option> { 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 { + pub fn imports(self) -> Option> { 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), + 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> { + 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 { + pub fn body(self) -> Option> { self.0.cast_last_match() } } diff --git a/crates/typst-syntax/src/node.rs b/crates/typst-syntax/src/node.rs index f949b4ddc..8e4e056ec 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(&self) -> bool { + pub fn is<'a, T: AstNode<'a>>(&'a self) -> bool { self.cast::().is_some() } /// Try to convert the node to a typed AST node. - pub fn cast(&self) -> Option { + pub fn cast<'a, T: AstNode<'a>>(&'a self) -> Option { T::from_untyped(self) } /// Cast the first child that can cast to the AST type `T`. - pub fn cast_first_match(&self) -> Option { + pub fn cast_first_match<'a, T: AstNode<'a>>(&'a self) -> Option { self.children().find_map(Self::cast) } /// Cast the last child that can cast to the AST type `T`. - pub fn cast_last_match(&self) -> Option { + pub fn cast_last_match<'a, T: AstNode<'a>>(&'a self) -> Option { 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 372e3042f..65b4ce10e 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, + /// Default values of named parameters. + pub defaults: Vec, /// Captured values from outer scopes. pub captured: Scope, - /// The list of parameters. - pub params: Vec, - /// 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), } impl Closure { + /// The name of the closure. + pub fn name(&self) -> Option<&str> { + self.node + .cast::() + .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, route: Tracked, introspector: Tracked, @@ -334,15 +330,15 @@ impl Closure { depth: usize, mut args: Args, ) -> SourceResult { - 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::().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::(ident)?) + vm.define(ident, args.expect::(&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::(ident)?.unwrap_or_else(|| default.clone()); - vm.define(ident.clone(), value); + args.named::(&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 d1f248c87..9141544e1 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; + fn eval(self, vm: &mut Vm) -> SourceResult; } -impl Eval for ast::Markup { +impl Eval for ast::Markup<'_> { type Output = Content; - fn eval(&self, vm: &mut Vm) -> SourceResult { + fn eval(self, vm: &mut Vm) -> SourceResult { 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, + exprs: &mut impl Iterator>, ) -> SourceResult { 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 { + fn eval(self, vm: &mut Vm) -> SourceResult { 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; } -impl ExprExt for ast::Expr { +impl ExprExt for ast::Expr<'_> { fn eval_display(&self, vm: &mut Vm) -> SourceResult { 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 { + fn eval(self, vm: &mut Vm) -> SourceResult { 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 { + fn eval(self, vm: &mut Vm) -> SourceResult { 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 { + fn eval(self, vm: &mut Vm) -> SourceResult { 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 { + fn eval(self, vm: &mut Vm) -> SourceResult { 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 { + fn eval(self, _: &mut Vm) -> SourceResult { 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 { + fn eval(self, _: &mut Vm) -> SourceResult { 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 { + fn eval(self, vm: &mut Vm) -> SourceResult { 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 { + fn eval(self, vm: &mut Vm) -> SourceResult { 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 { + fn eval(self, vm: &mut Vm) -> SourceResult { 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 { + fn eval(self, vm: &mut Vm) -> SourceResult { 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 { + fn eval(self, vm: &mut Vm) -> SourceResult { 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 { + fn eval(self, _: &mut Vm) -> SourceResult { 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 { + fn eval(self, vm: &mut Vm) -> SourceResult { 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 { + fn eval(self, vm: &mut Vm) -> SourceResult { 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 { + fn eval(self, vm: &mut Vm) -> SourceResult { 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 { + fn eval(self, vm: &mut Vm) -> SourceResult { 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 { + fn eval(self, vm: &mut Vm) -> SourceResult { 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 { + fn eval(self, vm: &mut Vm) -> SourceResult { 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 { + fn eval(self, vm: &mut Vm) -> SourceResult { 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 { - vm.scopes.get_in_math(self).cloned().at(self.span()) + fn eval(self, vm: &mut Vm) -> SourceResult { + 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 { + fn eval(self, vm: &mut Vm) -> SourceResult { 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 { + fn eval(self, vm: &mut Vm) -> SourceResult { 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 { + fn eval(self, vm: &mut Vm) -> SourceResult { 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 { + fn eval(self, vm: &mut Vm) -> SourceResult { 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 { + fn eval(self, vm: &mut Vm) -> SourceResult { 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 { + fn eval(self, vm: &mut Vm) -> SourceResult { 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 { - vm.scopes.get(self).cloned().at(self.span()) + fn eval(self, vm: &mut Vm) -> SourceResult { + 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 { + fn eval(self, _: &mut Vm) -> SourceResult { 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 { + fn eval(self, _: &mut Vm) -> SourceResult { 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 { + fn eval(self, _: &mut Vm) -> SourceResult { 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 { + fn eval(self, _: &mut Vm) -> SourceResult { 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 { + fn eval(self, _: &mut Vm) -> SourceResult { 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 { + fn eval(self, _: &mut Vm) -> SourceResult { 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 { + fn eval(self, _: &mut Vm) -> SourceResult { 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 { + fn eval(self, vm: &mut Vm) -> SourceResult { 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 { + fn eval(self, vm: &mut Vm) -> SourceResult { 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, + exprs: &mut impl Iterator>, ) -> SourceResult { 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 { + fn eval(self, vm: &mut Vm) -> SourceResult { 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 { + fn eval(self, vm: &mut Vm) -> SourceResult { 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 { + fn eval(self, vm: &mut Vm) -> SourceResult { 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 { + fn eval(self, vm: &mut Vm) -> SourceResult { 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 { + fn eval(self, vm: &mut Vm) -> SourceResult { 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 { + fn eval(self, vm: &mut Vm) -> SourceResult { 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, ) -> SourceResult { @@ -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, ) -> SourceResult { @@ -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 { + fn eval(self, vm: &mut Vm) -> SourceResult { 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 { + fn eval(self, vm: &mut Vm) -> SourceResult { 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 { + fn eval(self, vm: &mut Vm) -> SourceResult { 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 { - // 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 { + // 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 { 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 { destructure(vm, pattern, value, |vm, expr, value| { @@ -1341,7 +1335,7 @@ fn assign_pattern( #[tracing::instrument(skip_all)] fn destructure( vm: &mut Vm, - pattern: &ast::Pattern, + pattern: ast::Pattern, value: Value, f: T, ) -> SourceResult @@ -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( vm: &mut Vm, - pattern: &ast::Pattern, + pattern: ast::Pattern, value: Array, f: F, - destruct: &ast::Destructuring, + destruct: ast::Destructuring, ) -> SourceResult where F: Fn(&mut Vm, ast::Expr, Value) -> SourceResult, @@ -1418,7 +1412,7 @@ fn destructure_dict( vm: &mut Vm, dict: Dict, f: F, - destruct: &ast::Destructuring, + destruct: ast::Destructuring, ) -> SourceResult where F: Fn(&mut Vm, ast::Expr, Value) -> SourceResult, @@ -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 { + fn eval(self, vm: &mut Vm) -> SourceResult { 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 { + fn eval(self, vm: &mut Vm) -> SourceResult { 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 { + fn eval(self, vm: &mut Vm) -> SourceResult { if let Some(condition) = self.condition() { if !condition.eval(vm)?.cast::().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 { + fn eval(self, vm: &mut Vm) -> SourceResult { let selector = self .selector() .map(|sel| sel.eval(vm)?.cast::().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 { + fn eval(self, vm: &mut Vm) -> SourceResult { let condition = self.condition(); if condition.eval(vm)?.cast::().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 { + fn eval(self, vm: &mut Vm) -> SourceResult { 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::().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 { + fn eval(self, vm: &mut Vm) -> SourceResult { 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( 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( 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 { + fn eval(self, vm: &mut Vm) -> SourceResult { 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 { + fn eval(self, vm: &mut Vm) -> SourceResult { 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 { + fn eval(self, vm: &mut Vm) -> SourceResult { 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 { + fn eval(self, vm: &mut Vm) -> SourceResult { 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 { + fn eval(self, vm: &mut Vm) -> SourceResult { 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 dcde0985c..86b10d43f 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::()); 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::()); 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::(); + if let Some(args) = parent.get().cast::(); if let Some(grand) = parent.parent(); - if let Some(expr) = grand.cast::(); + if let Some(expr) = grand.get().cast::(); 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::(); + if let Some(param) = prev.get().cast::(); then { if let Some(next) = deciding.next_leaf() { ctx.from = ctx.cursor.min(next.offset()); } - named_param_value_completions(ctx, &callee, ¶m); + named_param_value_completions(ctx, callee, ¶m); 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(); + 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); + 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::() { + if let Some(v) = node.get().cast::() { 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::() { + if let Some(v) = parent.get().cast::() { 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, });