From f4cef141b0817f7bd93ed68f8c220c393982d264 Mon Sep 17 00:00:00 2001 From: Iban Eguia Moraza Date: Sat, 22 Oct 2022 20:01:57 +0000 Subject: [PATCH] Removed some duplicate code, added `ToIndentedString` (#2367) In most cases, the `ToInternedString` was just calling `self.to_indented_string(interner, 0)`. This avoids all this duplicate code by adding a new trait, `ToIndentedString`. Any type implementing that automatically implements `ToInternedString`. I have also added a bunch of `#[inline]` in one-liners, and some one-line documentations for some functions. I have noticed that we also use `contains()` and `contains_arguments()` a lot. Would it make sense to create traits for this? --- boa_engine/src/syntax/ast/declaration/mod.rs | 29 ++--- boa_engine/src/syntax/ast/expression/await.rs | 2 +- .../ast/expression/literal/object/mod.rs | 39 +++--- boa_engine/src/syntax/ast/expression/mod.rs | 14 +-- .../src/syntax/ast/function/arrow_function.rs | 38 +++--- .../src/syntax/ast/function/async_function.rs | 19 +-- .../syntax/ast/function/async_generator.rs | 18 +-- boa_engine/src/syntax/ast/function/class.rs | 19 +-- .../src/syntax/ast/function/generator.rs | 19 +-- boa_engine/src/syntax/ast/function/mod.rs | 19 +-- boa_engine/src/syntax/ast/mod.rs | 2 +- boa_engine/src/syntax/ast/statement/block.rs | 30 +++-- boa_engine/src/syntax/ast/statement/if.rs | 44 +++---- .../ast/statement/iteration/do_while_loop.rs | 26 ++-- .../ast/statement/iteration/for_in_loop.rs | 37 +++--- .../ast/statement/iteration/for_loop.rs | 61 +++++---- .../ast/statement/iteration/for_of_loop.rs | 32 ++--- .../ast/statement/iteration/while_loop.rs | 40 +++--- .../src/syntax/ast/statement/labelled.rs | 6 +- boa_engine/src/syntax/ast/statement/mod.rs | 46 ++++--- .../src/syntax/ast/statement/switch/mod.rs | 45 +++---- .../src/syntax/ast/statement/try/mod.rs | 39 +++--- .../src/syntax/ast/statement_list/mod.rs | 118 +++++++++--------- .../src/syntax/parser/expression/tests.rs | 3 +- boa_interner/src/lib.rs | 12 +- 25 files changed, 385 insertions(+), 372 deletions(-) diff --git a/boa_engine/src/syntax/ast/declaration/mod.rs b/boa_engine/src/syntax/ast/declaration/mod.rs index 77845cef42..9dabe8ec5d 100644 --- a/boa_engine/src/syntax/ast/declaration/mod.rs +++ b/boa_engine/src/syntax/ast/declaration/mod.rs @@ -1,11 +1,10 @@ -use boa_interner::{Interner, ToInternedString}; -use tap::Tap; - use super::{ expression::Identifier, function::{AsyncFunction, AsyncGenerator, Class, Function, Generator}, ContainsSymbol, }; +use boa_interner::{Interner, ToIndentedString, ToInternedString}; +use tap::Tap; mod variable; @@ -34,17 +33,6 @@ pub enum Declaration { } impl Declaration { - pub(super) fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String { - match self { - Declaration::Function(f) => f.to_indented_string(interner, indentation), - Declaration::Generator(g) => g.to_indented_string(interner, indentation), - Declaration::AsyncFunction(af) => af.to_indented_string(interner, indentation), - Declaration::AsyncGenerator(ag) => ag.to_indented_string(interner, indentation), - Declaration::Class(c) => c.to_indented_string(interner, indentation), - Declaration::Lexical(l) => l.to_interned_string(interner).tap_mut(|s| s.push(';')), - } - } - /// Return the lexically declared names of a `Declaration`. /// /// The returned list may contain duplicates. @@ -146,8 +134,15 @@ impl Declaration { } } -impl ToInternedString for Declaration { - fn to_interned_string(&self, interner: &Interner) -> String { - self.to_indented_string(interner, 0) +impl ToIndentedString for Declaration { + fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String { + match self { + Declaration::Function(f) => f.to_indented_string(interner, indentation), + Declaration::Generator(g) => g.to_indented_string(interner, indentation), + Declaration::AsyncFunction(af) => af.to_indented_string(interner, indentation), + Declaration::AsyncGenerator(ag) => ag.to_indented_string(interner, indentation), + Declaration::Class(c) => c.to_indented_string(interner, indentation), + Declaration::Lexical(l) => l.to_interned_string(interner).tap_mut(|s| s.push(';')), + } } } diff --git a/boa_engine/src/syntax/ast/expression/await.rs b/boa_engine/src/syntax/ast/expression/await.rs index e6964ff811..0aae6a926e 100644 --- a/boa_engine/src/syntax/ast/expression/await.rs +++ b/boa_engine/src/syntax/ast/expression/await.rs @@ -3,7 +3,7 @@ use crate::syntax::ast::ContainsSymbol; use super::Expression; -use boa_interner::{Interner, ToInternedString}; +use boa_interner::{Interner, ToIndentedString, ToInternedString}; /// An await expression is used within an async function to pause execution and wait for a /// promise to resolve. diff --git a/boa_engine/src/syntax/ast/expression/literal/object/mod.rs b/boa_engine/src/syntax/ast/expression/literal/object/mod.rs index 020d5a466b..a736129edb 100644 --- a/boa_engine/src/syntax/ast/expression/literal/object/mod.rs +++ b/boa_engine/src/syntax/ast/expression/literal/object/mod.rs @@ -10,7 +10,7 @@ use crate::syntax::ast::{ property::{MethodDefinition, PropertyDefinition}, ContainsSymbol, }; -use boa_interner::{Interner, ToInternedString}; +use boa_interner::{Interner, ToIndentedString, ToInternedString}; /// Objects in JavaScript may be defined as an unordered collection of related data, of /// primitive or reference types, in the form of “key: value” pairs. @@ -39,13 +39,27 @@ pub struct ObjectLiteral { } impl ObjectLiteral { + /// Gets the object literal properties #[inline] pub fn properties(&self) -> &[PropertyDefinition] { &self.properties } - /// Implements the display formatting with indentation. - pub(crate) fn to_indented_string(&self, interner: &Interner, indent_n: usize) -> String { + #[inline] + pub(crate) fn contains_arguments(&self) -> bool { + self.properties + .iter() + .any(PropertyDefinition::contains_arguments) + } + + #[inline] + pub(crate) fn contains(&self, symbol: ContainsSymbol) -> bool { + self.properties.iter().any(|prop| prop.contains(symbol)) + } +} + +impl ToIndentedString for ObjectLiteral { + fn to_indented_string(&self, interner: &Interner, indent_n: usize) -> String { let mut buf = "{\n".to_owned(); let indentation = " ".repeat(indent_n + 1); for property in self.properties().iter() { @@ -119,25 +133,6 @@ impl ObjectLiteral { buf } - - #[inline] - pub(crate) fn contains_arguments(&self) -> bool { - self.properties - .iter() - .any(PropertyDefinition::contains_arguments) - } - - #[inline] - pub(crate) fn contains(&self, symbol: ContainsSymbol) -> bool { - self.properties.iter().any(|prop| prop.contains(symbol)) - } -} - -impl ToInternedString for ObjectLiteral { - #[inline] - fn to_interned_string(&self, interner: &Interner) -> String { - self.to_indented_string(interner, 0) - } } impl From for ObjectLiteral diff --git a/boa_engine/src/syntax/ast/expression/mod.rs b/boa_engine/src/syntax/ast/expression/mod.rs index c9584ab41d..7f9fd2300a 100644 --- a/boa_engine/src/syntax/ast/expression/mod.rs +++ b/boa_engine/src/syntax/ast/expression/mod.rs @@ -1,4 +1,4 @@ -use boa_interner::{Interner, Sym, ToInternedString}; +use boa_interner::{Interner, Sym, ToIndentedString, ToInternedString}; use self::{ access::{PrivatePropertyAccess, PropertyAccess, SuperPropertyAccess}, @@ -142,12 +142,6 @@ pub enum Expression { } impl Expression { - /// Creates a string of the value of the expression with the given indentation. - #[inline] - pub fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String { - self.to_no_indent_string(interner, indentation) - } - /// Implements the display formatting with indentation. /// /// This will not prefix the value with any indentation. If you want to prefix this with proper @@ -281,9 +275,9 @@ impl From for Statement { } } -impl ToInternedString for Expression { +impl ToIndentedString for Expression { #[inline] - fn to_interned_string(&self, interner: &Interner) -> String { - self.to_indented_string(interner, 0) + fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String { + self.to_no_indent_string(interner, indentation) } } diff --git a/boa_engine/src/syntax/ast/function/arrow_function.rs b/boa_engine/src/syntax/ast/function/arrow_function.rs index 5185190ae4..1f78ee0ae3 100644 --- a/boa_engine/src/syntax/ast/function/arrow_function.rs +++ b/boa_engine/src/syntax/ast/function/arrow_function.rs @@ -2,7 +2,7 @@ use crate::syntax::ast::{ expression::{Expression, Identifier}, join_nodes, ContainsSymbol, StatementList, }; -use boa_interner::{Interner, ToInternedString}; +use boa_interner::{Interner, ToIndentedString}; use super::FormalParameterList; @@ -29,6 +29,7 @@ pub struct ArrowFunction { impl ArrowFunction { /// Creates a new `ArrowFunctionDecl` AST Expression. + #[inline] pub(in crate::syntax) fn new( name: Option, params: FormalParameterList, @@ -42,40 +43,29 @@ impl ArrowFunction { } /// Gets the name of the function declaration. + #[inline] pub fn name(&self) -> Option { self.name } /// Sets the name of the function declaration. + #[inline] pub fn set_name(&mut self, name: Option) { self.name = name; } /// Gets the list of parameters of the arrow function. + #[inline] pub(crate) fn parameters(&self) -> &FormalParameterList { &self.parameters } /// Gets the body of the arrow function. + #[inline] pub(crate) fn body(&self) -> &StatementList { &self.body } - /// Implements the display formatting with indentation. - pub(crate) fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String { - let mut buf = format!("({}", join_nodes(interner, &self.parameters.parameters)); - if self.body().statements().is_empty() { - buf.push_str(") => {}"); - } else { - buf.push_str(&format!( - ") => {{\n{}{}}}", - self.body.to_indented_string(interner, indentation + 1), - " ".repeat(indentation) - )); - } - buf - } - #[inline] pub(crate) fn contains_arguments(&self) -> bool { self.parameters.contains_arguments() || self.body.contains_arguments() @@ -97,9 +87,19 @@ impl ArrowFunction { } } -impl ToInternedString for ArrowFunction { - fn to_interned_string(&self, interner: &Interner) -> String { - self.to_indented_string(interner, 0) +impl ToIndentedString for ArrowFunction { + fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String { + let mut buf = format!("({}", join_nodes(interner, &self.parameters.parameters)); + if self.body().statements().is_empty() { + buf.push_str(") => {}"); + } else { + buf.push_str(&format!( + ") => {{\n{}{}}}", + self.body.to_indented_string(interner, indentation + 1), + " ".repeat(indentation) + )); + } + buf } } diff --git a/boa_engine/src/syntax/ast/function/async_function.rs b/boa_engine/src/syntax/ast/function/async_function.rs index 088972ecb8..c0c18f29e2 100644 --- a/boa_engine/src/syntax/ast/function/async_function.rs +++ b/boa_engine/src/syntax/ast/function/async_function.rs @@ -4,7 +4,7 @@ use crate::syntax::ast::{ expression::{Expression, Identifier}, join_nodes, Declaration, StatementList, }; -use boa_interner::{Interner, ToInternedString}; +use boa_interner::{Interner, ToIndentedString}; use super::FormalParameterList; @@ -27,6 +27,7 @@ pub struct AsyncFunction { impl AsyncFunction { /// Creates a new function expression + #[inline] pub(in crate::syntax) fn new( name: Option, parameters: FormalParameterList, @@ -40,22 +41,26 @@ impl AsyncFunction { } /// Gets the name of the function declaration. + #[inline] pub fn name(&self) -> Option { self.name } /// Gets the list of parameters of the function declaration. + #[inline] pub fn parameters(&self) -> &FormalParameterList { &self.parameters } /// Gets the body of the function declaration. + #[inline] pub fn body(&self) -> &StatementList { &self.body } +} - /// Implements the display formatting with indentation. - pub(crate) fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String { +impl ToIndentedString for AsyncFunction { + fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String { let mut buf = "async function".to_owned(); if let Some(name) = self.name { buf.push_str(&format!(" {}", interner.resolve_expect(name.sym()))); @@ -77,19 +82,15 @@ impl AsyncFunction { } } -impl ToInternedString for AsyncFunction { - fn to_interned_string(&self, interner: &Interner) -> String { - self.to_indented_string(interner, 0) - } -} - impl From for Expression { + #[inline] fn from(expr: AsyncFunction) -> Self { Self::AsyncFunction(expr) } } impl From for Declaration { + #[inline] fn from(f: AsyncFunction) -> Self { Self::AsyncFunction(f) } diff --git a/boa_engine/src/syntax/ast/function/async_generator.rs b/boa_engine/src/syntax/ast/function/async_generator.rs index e390a37ab1..e2f1989491 100644 --- a/boa_engine/src/syntax/ast/function/async_generator.rs +++ b/boa_engine/src/syntax/ast/function/async_generator.rs @@ -4,7 +4,7 @@ use crate::syntax::ast::{ expression::{Expression, Identifier}, join_nodes, Declaration, StatementList, }; -use boa_interner::{Interner, ToInternedString}; +use boa_interner::{Interner, ToIndentedString}; use super::FormalParameterList; @@ -24,6 +24,7 @@ pub struct AsyncGenerator { impl AsyncGenerator { /// Creates a new async generator expression + #[inline] pub(in crate::syntax) fn new( name: Option, parameters: FormalParameterList, @@ -37,21 +38,26 @@ impl AsyncGenerator { } /// Gets the name of the async generator expression + #[inline] pub fn name(&self) -> Option { self.name } /// Gets the list of parameters of the async generator expression + #[inline] pub fn parameters(&self) -> &FormalParameterList { &self.parameters } /// Gets the body of the async generator expression + #[inline] pub fn body(&self) -> &StatementList { &self.body } +} - pub(crate) fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String { +impl ToIndentedString for AsyncGenerator { + fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String { let mut buf = "async function*".to_owned(); if let Some(name) = self.name { buf.push_str(&format!(" {}", interner.resolve_expect(name.sym()))); @@ -66,19 +72,15 @@ impl AsyncGenerator { } } -impl ToInternedString for AsyncGenerator { - fn to_interned_string(&self, interner: &Interner) -> String { - self.to_indented_string(interner, 0) - } -} - impl From for Expression { + #[inline] fn from(expr: AsyncGenerator) -> Self { Self::AsyncGenerator(expr) } } impl From for Declaration { + #[inline] fn from(f: AsyncGenerator) -> Self { Self::AsyncGenerator(f) } diff --git a/boa_engine/src/syntax/ast/function/class.rs b/boa_engine/src/syntax/ast/function/class.rs index 90a8dd27dc..5aa8b9db31 100644 --- a/boa_engine/src/syntax/ast/function/class.rs +++ b/boa_engine/src/syntax/ast/function/class.rs @@ -11,7 +11,7 @@ use crate::{ ContainsSymbol, Declaration, StatementList, }, }; -use boa_interner::{Interner, Sym, ToInternedString}; +use boa_interner::{Interner, Sym, ToIndentedString, ToInternedString}; use super::Function; @@ -36,6 +36,7 @@ pub struct Class { impl Class { /// Creates a new class declaration. + #[inline] pub(in crate::syntax) fn new( name: Option, super_ref: Option, @@ -51,25 +52,30 @@ impl Class { } /// Returns the name of the class. + #[inline] pub(crate) fn name(&self) -> Option { self.name } /// Returns the super class ref of the class. + #[inline] pub(crate) fn super_ref(&self) -> Option<&Expression> { self.super_ref.as_ref() } /// Returns the constructor of the class. + #[inline] pub(crate) fn constructor(&self) -> Option<&Function> { self.constructor.as_ref() } /// Gets the list of all fields defined on the class. + #[inline] pub(crate) fn elements(&self) -> &[ClassElement] { &self.elements } + #[inline] pub(crate) fn contains_arguments(&self) -> bool { matches!(self.name, Some(ref ident) if *ident == Sym::ARGUMENTS) || matches!(self.super_ref, Some(ref expr) if expr.contains_arguments()) @@ -88,9 +94,10 @@ impl Class { matches!(self.super_ref, Some(ref expr) if expr.contains(symbol)) || self.elements.iter().any(|elem| elem.contains(symbol)) } +} - /// Implements the display formatting with indentation. - pub(crate) fn to_indented_string(&self, interner: &Interner, indent_n: usize) -> String { +impl ToIndentedString for Class { + fn to_indented_string(&self, interner: &Interner, indent_n: usize) -> String { let class_name = self.name.map_or(Cow::Borrowed(""), |s| { interner.resolve_expect(s.sym()).join( Cow::Borrowed, @@ -362,12 +369,6 @@ impl Class { } } -impl ToInternedString for Class { - fn to_interned_string(&self, interner: &Interner) -> String { - self.to_indented_string(interner, 0) - } -} - impl From for Expression { fn from(expr: Class) -> Self { Self::Class(Box::new(expr)) diff --git a/boa_engine/src/syntax/ast/function/generator.rs b/boa_engine/src/syntax/ast/function/generator.rs index 88e9600470..d3aec682f6 100644 --- a/boa_engine/src/syntax/ast/function/generator.rs +++ b/boa_engine/src/syntax/ast/function/generator.rs @@ -4,7 +4,7 @@ use crate::syntax::ast::{ join_nodes, Declaration, StatementList, }; -use boa_interner::{Interner, ToInternedString}; +use boa_interner::{Interner, ToIndentedString}; use super::FormalParameterList; @@ -26,6 +26,7 @@ pub struct Generator { impl Generator { /// Creates a new generator expression + #[inline] pub(in crate::syntax) fn new( name: Option, parameters: FormalParameterList, @@ -39,22 +40,26 @@ impl Generator { } /// Gets the name of the generator declaration. + #[inline] pub fn name(&self) -> Option { self.name } /// Gets the list of parameters of the generator declaration. + #[inline] pub fn parameters(&self) -> &FormalParameterList { &self.parameters } /// Gets the body of the generator declaration. + #[inline] pub fn body(&self) -> &StatementList { &self.body } +} - /// Converts the generator expresion Expression to a string with indentation. - pub(crate) fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String { +impl ToIndentedString for Generator { + fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String { let mut buf = "function*".to_owned(); if let Some(name) = self.name { buf.push_str(&format!(" {}", interner.resolve_expect(name.sym()))); @@ -69,19 +74,15 @@ impl Generator { } } -impl ToInternedString for Generator { - fn to_interned_string(&self, interner: &Interner) -> String { - self.to_indented_string(interner, 0) - } -} - impl From for Expression { + #[inline] fn from(expr: Generator) -> Self { Self::Generator(expr) } } impl From for Declaration { + #[inline] fn from(f: Generator) -> Self { Self::Generator(f) } diff --git a/boa_engine/src/syntax/ast/function/mod.rs b/boa_engine/src/syntax/ast/function/mod.rs index 87c04184e0..7cc8b2c0c8 100644 --- a/boa_engine/src/syntax/ast/function/mod.rs +++ b/boa_engine/src/syntax/ast/function/mod.rs @@ -15,7 +15,7 @@ pub use parameters::{FormalParameter, FormalParameterList}; pub(crate) use parameters::FormalParameterListFlags; use crate::syntax::ast::{block_to_string, join_nodes, StatementList}; -use boa_interner::{Interner, ToInternedString}; +use boa_interner::{Interner, ToIndentedString}; use super::expression::{Expression, Identifier}; use super::{ContainsSymbol, Declaration}; @@ -46,6 +46,7 @@ pub struct Function { impl Function { /// Creates a new function expression + #[inline] pub(in crate::syntax) fn new( name: Option, parameters: FormalParameterList, @@ -59,22 +60,26 @@ impl Function { } /// Gets the name of the function declaration. + #[inline] pub fn name(&self) -> Option { self.name } /// Gets the list of parameters of the function declaration. + #[inline] pub fn parameters(&self) -> &FormalParameterList { &self.parameters } /// Gets the body of the function declaration. + #[inline] pub fn body(&self) -> &StatementList { &self.body } +} - /// Implements the display formatting with indentation. - pub(crate) fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String { +impl ToIndentedString for Function { + fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String { let mut buf = "function".to_owned(); if let Some(name) = self.name { buf.push_str(&format!(" {}", interner.resolve_expect(name.sym()))); @@ -89,19 +94,15 @@ impl Function { } } -impl ToInternedString for Function { - fn to_interned_string(&self, interner: &Interner) -> String { - self.to_indented_string(interner, 0) - } -} - impl From for Expression { + #[inline] fn from(expr: Function) -> Self { Self::Function(expr) } } impl From for Declaration { + #[inline] fn from(f: Function) -> Self { Self::Function(f) } diff --git a/boa_engine/src/syntax/ast/mod.rs b/boa_engine/src/syntax/ast/mod.rs index 267680d5a7..249d950fef 100644 --- a/boa_engine/src/syntax/ast/mod.rs +++ b/boa_engine/src/syntax/ast/mod.rs @@ -11,7 +11,7 @@ pub mod punctuator; pub mod statement; pub mod statement_list; -use boa_interner::{Interner, ToInternedString}; +use boa_interner::{Interner, ToIndentedString, ToInternedString}; pub use self::{ declaration::Declaration, diff --git a/boa_engine/src/syntax/ast/statement/block.rs b/boa_engine/src/syntax/ast/statement/block.rs index 12f2471ef0..5922326905 100644 --- a/boa_engine/src/syntax/ast/statement/block.rs +++ b/boa_engine/src/syntax/ast/statement/block.rs @@ -1,9 +1,8 @@ //! Block AST node. -use crate::syntax::ast::{expression::Identifier, ContainsSymbol, StatementList}; - use super::Statement; -use boa_interner::{Interner, ToInternedString}; +use crate::syntax::ast::{expression::Identifier, ContainsSymbol, StatementList}; +use boa_interner::{Interner, ToIndentedString}; /// A `block` statement (or compound statement in other languages) is used to group zero or /// more statements. @@ -29,25 +28,17 @@ pub struct Block { impl Block { /// Gets the list of statements and declarations in this block. + #[inline] pub(crate) fn statement_list(&self) -> &StatementList { &self.statements } /// Get the lexically declared names of the block. + #[inline] pub(crate) fn lexically_declared_names(&self) -> Vec<(Identifier, bool)> { self.statements.lexically_declared_names() } - /// Implements the display formatting with indentation. - pub(super) fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String { - format!( - "{{\n{}{}}}", - self.statements - .to_indented_string(interner, indentation + 1), - " ".repeat(indentation) - ) - } - #[inline] pub(crate) fn contains_arguments(&self) -> bool { self.statements.contains_arguments() @@ -63,6 +54,7 @@ impl From for Block where T: Into, { + #[inline] fn from(list: T) -> Self { Self { statements: list.into(), @@ -70,13 +62,19 @@ where } } -impl ToInternedString for Block { - fn to_interned_string(&self, interner: &Interner) -> String { - self.to_indented_string(interner, 0) +impl ToIndentedString for Block { + fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String { + format!( + "{{\n{}{}}}", + self.statements + .to_indented_string(interner, indentation + 1), + " ".repeat(indentation) + ) } } impl From for Statement { + #[inline] fn from(block: Block) -> Self { Self::Block(block) } diff --git a/boa_engine/src/syntax/ast/statement/if.rs b/boa_engine/src/syntax/ast/statement/if.rs index 567153e2bd..a81dc8f53e 100644 --- a/boa_engine/src/syntax/ast/statement/if.rs +++ b/boa_engine/src/syntax/ast/statement/if.rs @@ -1,7 +1,7 @@ //! If statement use crate::syntax::ast::{expression::Expression, statement::Statement, ContainsSymbol}; -use boa_interner::{Interner, ToInternedString}; +use boa_interner::{Interner, ToIndentedString, ToInternedString}; /// The `if` statement executes a statement if a specified condition is [`truthy`][truthy]. If /// the condition is [`falsy`][falsy], another statement can be executed. @@ -28,14 +28,20 @@ pub struct If { } impl If { + /// Gets the condition of the if statement. + #[inline] pub fn cond(&self) -> &Expression { &self.condition } + /// Gets the body to execute if the condition is true. + #[inline] pub fn body(&self) -> &Statement { &self.body } + /// Gets the `else` node, if it has one. + #[inline] pub fn else_node(&self) -> Option<&Statement> { self.else_node.as_ref().map(Box::as_ref) } @@ -49,23 +55,6 @@ impl If { } } - pub(crate) fn to_indented_string(&self, interner: &Interner, indent: usize) -> String { - let mut buf = format!("if ({}) ", self.cond().to_interned_string(interner)); - match self.else_node() { - Some(else_e) => { - buf.push_str(&format!( - "{} else {}", - self.body().to_indented_string(interner, indent), - else_e.to_indented_string(interner, indent) - )); - } - None => { - buf.push_str(&self.body().to_indented_string(interner, indent)); - } - } - buf - } - #[inline] pub(crate) fn contains_arguments(&self) -> bool { self.condition.contains_arguments() @@ -81,9 +70,22 @@ impl If { } } -impl ToInternedString for If { - fn to_interned_string(&self, interner: &Interner) -> String { - self.to_indented_string(interner, 0) +impl ToIndentedString for If { + fn to_indented_string(&self, interner: &Interner, indent: usize) -> String { + let mut buf = format!("if ({}) ", self.cond().to_interned_string(interner)); + match self.else_node() { + Some(else_e) => { + buf.push_str(&format!( + "{} else {}", + self.body().to_indented_string(interner, indent), + else_e.to_indented_string(interner, indent) + )); + } + None => { + buf.push_str(&self.body().to_indented_string(interner, indent)); + } + } + buf } } diff --git a/boa_engine/src/syntax/ast/statement/iteration/do_while_loop.rs b/boa_engine/src/syntax/ast/statement/iteration/do_while_loop.rs index 47f7f33a6e..35ceca07a6 100644 --- a/boa_engine/src/syntax/ast/statement/iteration/do_while_loop.rs +++ b/boa_engine/src/syntax/ast/statement/iteration/do_while_loop.rs @@ -1,5 +1,5 @@ use crate::syntax::ast::{expression::Expression, statement::Statement, ContainsSymbol}; -use boa_interner::{Interner, ToInternedString}; +use boa_interner::{Interner, ToIndentedString, ToInternedString}; /// The `do...while` statement creates a loop that executes a specified statement until the /// test condition evaluates to false. @@ -21,14 +21,19 @@ pub struct DoWhileLoop { } impl DoWhileLoop { + /// Gets the body of the do-while loop. + #[inline] pub fn body(&self) -> &Statement { &self.body } + /// Gets the condition of the do-while loop. + #[inline] pub fn cond(&self) -> &Expression { &self.condition } /// Creates a `DoWhileLoop` AST node. + #[inline] pub fn new(body: Statement, condition: Expression) -> Self { Self { body: body.into(), @@ -36,15 +41,6 @@ impl DoWhileLoop { } } - /// Converts the "do while" loop to a string with the given indentation. - pub(crate) fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String { - format!( - "do {} while ({})", - self.body().to_indented_string(interner, indentation), - self.cond().to_interned_string(interner) - ) - } - #[inline] pub(crate) fn contains_arguments(&self) -> bool { self.body.contains_arguments() || self.condition.contains_arguments() @@ -56,9 +52,13 @@ impl DoWhileLoop { } } -impl ToInternedString for DoWhileLoop { - fn to_interned_string(&self, interner: &Interner) -> String { - self.to_indented_string(interner, 0) +impl ToIndentedString for DoWhileLoop { + fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String { + format!( + "do {} while ({})", + self.body().to_indented_string(interner, indentation), + self.cond().to_interned_string(interner) + ) } } diff --git a/boa_engine/src/syntax/ast/statement/iteration/for_in_loop.rs b/boa_engine/src/syntax/ast/statement/iteration/for_in_loop.rs index e74dbba07b..9b32cbd80d 100644 --- a/boa_engine/src/syntax/ast/statement/iteration/for_in_loop.rs +++ b/boa_engine/src/syntax/ast/statement/iteration/for_in_loop.rs @@ -3,7 +3,8 @@ use crate::syntax::ast::{ statement::{iteration::IterableLoopInitializer, Statement}, ContainsSymbol, }; -use boa_interner::{Interner, ToInternedString}; +use boa_interner::{Interner, ToIndentedString, ToInternedString}; + #[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Debug, PartialEq)] pub struct ForInLoop { @@ -13,6 +14,8 @@ pub struct ForInLoop { } impl ForInLoop { + /// Creates a new `ForInLoop`. + #[inline] pub fn new(init: IterableLoopInitializer, expr: Expression, body: Statement) -> Self { Self { init, @@ -21,30 +24,24 @@ impl ForInLoop { } } + /// Gets the initializer of the for...in loop. + #[inline] pub fn init(&self) -> &IterableLoopInitializer { &self.init } + /// Gets the for...in loop expression. + #[inline] pub fn expr(&self) -> &Expression { &self.expr } + /// Gets the body of the for...in loop. + #[inline] pub fn body(&self) -> &Statement { &self.body } - /// Converts the "for in" loop to a string with the given indentation. - pub(crate) fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String { - let mut buf = format!( - "for ({} in {}) ", - self.init.to_interned_string(interner), - self.expr.to_interned_string(interner) - ); - buf.push_str(&self.body().to_indented_string(interner, indentation)); - - buf - } - #[inline] pub(crate) fn contains_arguments(&self) -> bool { self.init.contains_arguments() @@ -58,13 +55,21 @@ impl ForInLoop { } } -impl ToInternedString for ForInLoop { - fn to_interned_string(&self, interner: &Interner) -> String { - self.to_indented_string(interner, 0) +impl ToIndentedString for ForInLoop { + fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String { + let mut buf = format!( + "for ({} in {}) ", + self.init.to_interned_string(interner), + self.expr.to_interned_string(interner) + ); + buf.push_str(&self.body().to_indented_string(interner, indentation)); + + buf } } impl From for Statement { + #[inline] fn from(for_in: ForInLoop) -> Self { Self::ForInLoop(for_in) } diff --git a/boa_engine/src/syntax/ast/statement/iteration/for_loop.rs b/boa_engine/src/syntax/ast/statement/iteration/for_loop.rs index 29dd2f49a3..d9ff5b7b7a 100644 --- a/boa_engine/src/syntax/ast/statement/iteration/for_loop.rs +++ b/boa_engine/src/syntax/ast/statement/iteration/for_loop.rs @@ -4,7 +4,7 @@ use crate::syntax::ast::{ statement::Statement, ContainsSymbol, Expression, }; -use boa_interner::{Interner, ToInternedString}; +use boa_interner::{Interner, ToIndentedString, ToInternedString}; /// The `for` statement creates a loop that consists of three optional expressions. /// @@ -26,6 +26,7 @@ pub struct ForLoop { impl ForLoop { /// Creates a new for loop AST node. + #[inline] pub(in crate::syntax) fn new( init: Option, condition: Option, @@ -38,47 +39,29 @@ impl ForLoop { } /// Gets the initialization node. + #[inline] pub fn init(&self) -> Option<&ForLoopInitializer> { self.inner.init() } /// Gets the loop condition node. + #[inline] pub fn condition(&self) -> Option<&Expression> { self.inner.condition() } /// Gets the final expression node. + #[inline] pub fn final_expr(&self) -> Option<&Expression> { self.inner.final_expr() } /// Gets the body of the for loop. + #[inline] pub fn body(&self) -> &Statement { self.inner.body() } - /// Converts the for loop to a string with the given indentation. - pub(crate) fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String { - let mut buf = String::from("for ("); - if let Some(init) = self.init() { - buf.push_str(&init.to_interned_string(interner)); - } - buf.push_str("; "); - if let Some(condition) = self.condition() { - buf.push_str(&condition.to_interned_string(interner)); - } - buf.push_str("; "); - if let Some(final_expr) = self.final_expr() { - buf.push_str(&final_expr.to_interned_string(interner)); - } - buf.push_str(&format!( - ") {}", - self.inner.body().to_indented_string(interner, indentation) - )); - - buf - } - #[inline] pub(crate) fn contains_arguments(&self) -> bool { let inner = &self.inner; @@ -98,13 +81,31 @@ impl ForLoop { } } -impl ToInternedString for ForLoop { - fn to_interned_string(&self, interner: &Interner) -> String { - self.to_indented_string(interner, 0) +impl ToIndentedString for ForLoop { + fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String { + let mut buf = String::from("for ("); + if let Some(init) = self.init() { + buf.push_str(&init.to_interned_string(interner)); + } + buf.push_str("; "); + if let Some(condition) = self.condition() { + buf.push_str(&condition.to_interned_string(interner)); + } + buf.push_str("; "); + if let Some(final_expr) = self.final_expr() { + buf.push_str(&final_expr.to_interned_string(interner)); + } + buf.push_str(&format!( + ") {}", + self.inner.body().to_indented_string(interner, indentation) + )); + + buf } } impl From for Statement { + #[inline] fn from(for_loop: ForLoop) -> Self { Self::ForLoop(for_loop) } @@ -122,6 +123,7 @@ struct InnerForLoop { impl InnerForLoop { /// Creates a new inner for loop. + #[inline] fn new( init: Option, condition: Option, @@ -137,21 +139,25 @@ impl InnerForLoop { } /// Gets the initialization node. + #[inline] fn init(&self) -> Option<&ForLoopInitializer> { self.init.as_ref() } /// Gets the loop condition node. + #[inline] fn condition(&self) -> Option<&Expression> { self.condition.as_ref() } /// Gets the final expression node. + #[inline] fn final_expr(&self) -> Option<&Expression> { self.final_expr.as_ref() } /// Gets the body of the for loop. + #[inline] fn body(&self) -> &Statement { &self.body } @@ -213,18 +219,21 @@ impl ToInternedString for ForLoopInitializer { } impl From for ForLoopInitializer { + #[inline] fn from(expr: Expression) -> Self { ForLoopInitializer::Expression(expr) } } impl From for ForLoopInitializer { + #[inline] fn from(list: LexicalDeclaration) -> Self { ForLoopInitializer::Lexical(list) } } impl From for ForLoopInitializer { + #[inline] fn from(list: VarDeclaration) -> Self { ForLoopInitializer::Var(list) } diff --git a/boa_engine/src/syntax/ast/statement/iteration/for_of_loop.rs b/boa_engine/src/syntax/ast/statement/iteration/for_of_loop.rs index 57838c6319..455ea3f000 100644 --- a/boa_engine/src/syntax/ast/statement/iteration/for_of_loop.rs +++ b/boa_engine/src/syntax/ast/statement/iteration/for_of_loop.rs @@ -3,7 +3,7 @@ use crate::syntax::ast::{ statement::{iteration::IterableLoopInitializer, Statement}, ContainsSymbol, }; -use boa_interner::{Interner, ToInternedString}; +use boa_interner::{Interner, ToIndentedString, ToInternedString}; #[cfg(feature = "deser")] use serde::{Deserialize, Serialize}; @@ -19,6 +19,7 @@ pub struct ForOfLoop { impl ForOfLoop { /// Creates a new "for of" loop AST node. + #[inline] pub fn new( init: IterableLoopInitializer, iterable: Expression, @@ -33,33 +34,30 @@ impl ForOfLoop { } } + /// Gets the initializer of the for...of loop. + #[inline] pub fn init(&self) -> &IterableLoopInitializer { &self.init } + /// Gets the iterable expression of the for...of loop. + #[inline] pub fn iterable(&self) -> &Expression { &self.iterable } + /// Gets the body to execute in the for...of loop. + #[inline] pub fn body(&self) -> &Statement { &self.body } /// Returns true if this "for...of" loop is an "for await...of" loop. + #[inline] pub(crate) fn r#await(&self) -> bool { self.r#await } - /// Converts the "for of" loop to a string with the given indentation. - pub(crate) fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String { - format!( - "for ({} of {}) {}", - self.init.to_interned_string(interner), - self.iterable.to_interned_string(interner), - self.body().to_indented_string(interner, indentation) - ) - } - #[inline] pub(crate) fn contains_arguments(&self) -> bool { self.init.contains_arguments() @@ -73,13 +71,19 @@ impl ForOfLoop { } } -impl ToInternedString for ForOfLoop { - fn to_interned_string(&self, interner: &Interner) -> String { - self.to_indented_string(interner, 0) +impl ToIndentedString for ForOfLoop { + fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String { + format!( + "for ({} of {}) {}", + self.init.to_interned_string(interner), + self.iterable.to_interned_string(interner), + self.body().to_indented_string(interner, indentation) + ) } } impl From for Statement { + #[inline] fn from(for_of: ForOfLoop) -> Self { Self::ForOfLoop(for_of) } diff --git a/boa_engine/src/syntax/ast/statement/iteration/while_loop.rs b/boa_engine/src/syntax/ast/statement/iteration/while_loop.rs index 06c8515d75..a59dd56c9b 100644 --- a/boa_engine/src/syntax/ast/statement/iteration/while_loop.rs +++ b/boa_engine/src/syntax/ast/statement/iteration/while_loop.rs @@ -1,5 +1,6 @@ use crate::syntax::ast::{expression::Expression, statement::Statement, ContainsSymbol}; -use boa_interner::{Interner, ToInternedString}; +use boa_interner::{Interner, ToIndentedString, ToInternedString}; + /// The `while` statement creates a loop that executes a specified statement as long as the /// test condition evaluates to `true`. /// @@ -19,14 +20,8 @@ pub struct WhileLoop { } impl WhileLoop { - pub fn condition(&self) -> &Expression { - &self.condition - } - - pub fn body(&self) -> &Statement { - &self.body - } /// Creates a `WhileLoop` AST node. + #[inline] pub fn new(condition: Expression, body: Statement) -> Self { Self { condition, @@ -34,15 +29,19 @@ impl WhileLoop { } } - /// Converts the while loop to a string with the given indentation. - pub(crate) fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String { - format!( - "while ({}) {}", - self.condition().to_interned_string(interner), - self.body().to_indented_string(interner, indentation) - ) + /// Gets the condition of the while loop. + #[inline] + pub fn condition(&self) -> &Expression { + &self.condition + } + + /// Gets the body of the while loop. + #[inline] + pub fn body(&self) -> &Statement { + &self.body } + #[inline] pub(crate) fn contains_arguments(&self) -> bool { self.condition.contains_arguments() || self.body.contains_arguments() } @@ -53,13 +52,18 @@ impl WhileLoop { } } -impl ToInternedString for WhileLoop { - fn to_interned_string(&self, interner: &Interner) -> String { - self.to_indented_string(interner, 0) +impl ToIndentedString for WhileLoop { + fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String { + format!( + "while ({}) {}", + self.condition().to_interned_string(interner), + self.body().to_indented_string(interner, indentation) + ) } } impl From for Statement { + #[inline] fn from(while_loop: WhileLoop) -> Self { Self::WhileLoop(while_loop) } diff --git a/boa_engine/src/syntax/ast/statement/labelled.rs b/boa_engine/src/syntax/ast/statement/labelled.rs index 1e250df0a9..7f8ee21d99 100644 --- a/boa_engine/src/syntax/ast/statement/labelled.rs +++ b/boa_engine/src/syntax/ast/statement/labelled.rs @@ -1,8 +1,6 @@ -use boa_interner::{Interner, Sym, ToInternedString}; - -use crate::syntax::ast::{function::Function, ContainsSymbol}; - use super::Statement; +use crate::syntax::ast::{function::Function, ContainsSymbol}; +use boa_interner::{Interner, Sym, ToIndentedString, ToInternedString}; /// The set of AST nodes that can be preceded by a label, as defined by the [spec]. /// diff --git a/boa_engine/src/syntax/ast/statement/mod.rs b/boa_engine/src/syntax/ast/statement/mod.rs index 9edf371fb2..2b598f5a1d 100644 --- a/boa_engine/src/syntax/ast/statement/mod.rs +++ b/boa_engine/src/syntax/ast/statement/mod.rs @@ -22,7 +22,7 @@ pub use self::{ throw::Throw, }; -use boa_interner::{Interner, ToInternedString}; +use boa_interner::{Interner, ToIndentedString, ToInternedString}; use rustc_hash::FxHashSet; use tap::Tap; @@ -98,27 +98,6 @@ pub enum Statement { } impl Statement { - /// Creates a string of the value of the node with the given indentation. For example, an - /// indent level of 2 would produce this: - /// - /// ```js - /// function hello() { - /// console.log("hello"); - /// } - /// hello(); - /// a = 2; - /// ``` - fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String { - let mut buf = match *self { - Self::Block(_) => String::new(), - _ => " ".repeat(indentation), - }; - - buf.push_str(&self.to_no_indent_string(interner, indentation)); - - buf - } - /// Implements the display formatting with indentation. /// /// This will not prefix the value with any indentation. If you want to prefix this with proper @@ -302,8 +281,25 @@ impl Statement { } } -impl ToInternedString for Statement { - fn to_interned_string(&self, interner: &Interner) -> String { - self.to_indented_string(interner, 0) +impl ToIndentedString for Statement { + /// Creates a string of the value of the node with the given indentation. For example, an + /// indent level of 2 would produce this: + /// + /// ```js + /// function hello() { + /// console.log("hello"); + /// } + /// hello(); + /// a = 2; + /// ``` + fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String { + let mut buf = match *self { + Self::Block(_) => String::new(), + _ => " ".repeat(indentation), + }; + + buf.push_str(&self.to_no_indent_string(interner, indentation)); + + buf } } diff --git a/boa_engine/src/syntax/ast/statement/switch/mod.rs b/boa_engine/src/syntax/ast/statement/switch/mod.rs index 9a5fd59b39..564960d197 100644 --- a/boa_engine/src/syntax/ast/statement/switch/mod.rs +++ b/boa_engine/src/syntax/ast/statement/switch/mod.rs @@ -1,7 +1,7 @@ //! Switch node. //! use crate::syntax::ast::{expression::Expression, statement::Statement, StatementList}; -use boa_interner::{Interner, ToInternedString}; +use boa_interner::{Interner, ToIndentedString, ToInternedString}; use super::ContainsSymbol; @@ -17,16 +17,19 @@ pub struct Case { impl Case { /// Creates a `Case` AST node. + #[inline] pub fn new(condition: Expression, body: StatementList) -> Self { Self { condition, body } } /// Gets the condition of the case. + #[inline] pub fn condition(&self) -> &Expression { &self.condition } /// Gets the statement listin the body of the case. + #[inline] pub fn body(&self) -> &StatementList { &self.body } @@ -73,6 +76,7 @@ pub struct Switch { impl Switch { /// Creates a `Switch` AST node. + #[inline] pub fn new(val: Expression, cases: Box<[Case]>, default: Option) -> Self { Self { val, @@ -82,22 +86,38 @@ impl Switch { } /// Gets the value to switch. + #[inline] pub fn val(&self) -> &Expression { &self.val } /// Gets the list of cases for the switch statement. + #[inline] pub fn cases(&self) -> &[Case] { &self.cases } /// Gets the default statement list, if any. + #[inline] pub fn default(&self) -> Option<&StatementList> { self.default.as_ref() } - /// Implements the display formatting with indentation. - pub(crate) fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String { + #[inline] + pub(crate) fn contains_arguments(&self) -> bool { + self.val.contains_arguments() + || self.cases.iter().any(Case::contains_arguments) + || matches!(self.default, Some(ref stmts) if stmts.contains_arguments()) + } + + #[inline] + pub(crate) fn contains(&self, symbol: ContainsSymbol) -> bool { + self.val.contains(symbol) || self.cases.iter().any(|case| case.contains(symbol)) + } +} + +impl ToIndentedString for Switch { + fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String { let indent = " ".repeat(indentation); let mut buf = format!("switch ({}) {{\n", self.val().to_interned_string(interner)); for e in self.cases().iter() { @@ -119,27 +139,10 @@ impl Switch { buf } - - #[inline] - pub(crate) fn contains_arguments(&self) -> bool { - self.val.contains_arguments() - || self.cases.iter().any(Case::contains_arguments) - || matches!(self.default, Some(ref stmts) if stmts.contains_arguments()) - } - - #[inline] - pub(crate) fn contains(&self, symbol: ContainsSymbol) -> bool { - self.val.contains(symbol) || self.cases.iter().any(|case| case.contains(symbol)) - } -} - -impl ToInternedString for Switch { - fn to_interned_string(&self, interner: &Interner) -> String { - self.to_indented_string(interner, 0) - } } impl From for Statement { + #[inline] fn from(switch: Switch) -> Self { Self::Switch(switch) } diff --git a/boa_engine/src/syntax/ast/statement/try/mod.rs b/boa_engine/src/syntax/ast/statement/try/mod.rs index e921d89d38..bfbf0f4d57 100644 --- a/boa_engine/src/syntax/ast/statement/try/mod.rs +++ b/boa_engine/src/syntax/ast/statement/try/mod.rs @@ -3,7 +3,7 @@ use crate::syntax::ast::{ statement::{Block, Statement}, statement_list::StatementListItem, }; -use boa_interner::{Interner, ToInternedString}; +use boa_interner::{Interner, ToIndentedString, ToInternedString}; use super::ContainsSymbol; @@ -33,6 +33,7 @@ pub struct Try { impl Try { /// Creates a new `Try` AST node. + #[inline] pub(in crate::syntax) fn new( block: Block, catch: Option, @@ -51,16 +52,19 @@ impl Try { } /// Gets the `try` block. + #[inline] pub fn block(&self) -> &Block { &self.block } /// Gets the `catch` block, if any. + #[inline] pub fn catch(&self) -> Option<&Catch> { self.catch.as_ref() } /// Gets the `finally` block, if any. + #[inline] pub fn finally(&self) -> Option<&Block> { self.finally.as_ref().map(Finally::block) } @@ -78,9 +82,10 @@ impl Try { || matches!(self.catch, Some(ref catch) if catch.contains(symbol)) || matches!(self.finally, Some(ref finally) if finally.contains(symbol)) } +} - /// Implements the display formatting with indentation. - pub(crate) fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String { +impl ToIndentedString for Try { + fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String { let mut buf = format!( "{}try {}", " ".repeat(indentation), @@ -98,13 +103,8 @@ impl Try { } } -impl ToInternedString for Try { - fn to_interned_string(&self, interner: &Interner) -> String { - self.to_indented_string(interner, 0) - } -} - impl From for Statement { + #[inline] fn from(try_catch: Try) -> Self { Self::Try(try_catch) } @@ -120,16 +120,19 @@ pub struct Catch { impl Catch { /// Creates a new catch block. + #[inline] pub(in crate::syntax) fn new(parameter: Option, block: Block) -> Self { Self { parameter, block } } /// Gets the parameter of the catch block. + #[inline] pub fn parameter(&self) -> Option<&Binding> { self.parameter.as_ref() } /// Retrieves the catch execution block. + #[inline] pub fn block(&self) -> &Block { &self.block } @@ -151,9 +154,10 @@ impl Catch { .iter() .any(|stmt| stmt.contains(symbol)) } +} - /// Implements the display formatting with indentation. - pub(super) fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String { +impl ToIndentedString for Catch { + fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String { let mut buf = " catch".to_owned(); if let Some(ref param) = self.parameter { buf.push_str(&format!("({})", param.to_interned_string(interner))); @@ -167,12 +171,6 @@ impl Catch { } } -impl ToInternedString for Catch { - fn to_interned_string(&self, interner: &Interner) -> String { - self.to_indented_string(interner, 0) - } -} - /// Finally block. #[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Debug, PartialEq)] @@ -182,6 +180,7 @@ pub struct Finally { impl Finally { /// Gets the finally block. + #[inline] pub fn block(&self) -> &Block { &self.block } @@ -203,9 +202,10 @@ impl Finally { .iter() .any(|stmt| stmt.contains(symbol)) } +} - /// Implements the display formatting with indentation. - pub(super) fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String { +impl ToIndentedString for Finally { + fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String { format!( " finally {}", self.block.to_indented_string(interner, indentation) @@ -214,6 +214,7 @@ impl Finally { } impl From for Finally { + #[inline] fn from(block: Block) -> Self { Self { block } } diff --git a/boa_engine/src/syntax/ast/statement_list/mod.rs b/boa_engine/src/syntax/ast/statement_list/mod.rs index 0ba64d6f71..b52bae5256 100644 --- a/boa_engine/src/syntax/ast/statement_list/mod.rs +++ b/boa_engine/src/syntax/ast/statement_list/mod.rs @@ -1,13 +1,10 @@ //! Statement list node. -use std::cmp::Ordering; - +use super::{declaration::Binding, Declaration}; use crate::syntax::ast::{expression::Identifier, statement::Statement, ContainsSymbol}; -use boa_interner::{Interner, ToInternedString}; - +use boa_interner::{Interner, ToIndentedString}; use rustc_hash::FxHashSet; - -use super::{declaration::Binding, Declaration}; +use std::cmp::Ordering; #[cfg(test)] mod tests; @@ -33,21 +30,45 @@ impl StatementListItem { (_, _) => Ordering::Equal, } } -} -impl From for StatementListItem { - fn from(stmt: Statement) -> Self { - StatementListItem::Statement(stmt) + #[inline] + pub(crate) fn var_declared_names(&self, vars: &mut FxHashSet) { + match self { + StatementListItem::Statement(stmt) => stmt.var_declared_names(vars), + StatementListItem::Declaration(_) => {} + } } -} -impl From for StatementListItem { - fn from(decl: Declaration) -> Self { - StatementListItem::Declaration(decl) + /// Returns true if the node contains a identifier reference named 'arguments'. + /// + /// More information: + /// - [ECMAScript specification][spec] + /// + /// [spec]: https://tc39.es/ecma262/#sec-static-semantics-containsarguments + #[inline] + pub(crate) fn contains_arguments(&self) -> bool { + match self { + StatementListItem::Statement(stmt) => stmt.contains_arguments(), + StatementListItem::Declaration(decl) => decl.contains_arguments(), + } + } + + /// Returns `true` if the node contains the given token. + /// + /// More information: + /// - [ECMAScript specification][spec] + /// + /// [spec]: https://tc39.es/ecma262/#sec-static-semantics-contains + #[inline] + pub(crate) fn contains(&self, symbol: ContainsSymbol) -> bool { + match self { + StatementListItem::Statement(stmt) => stmt.contains(symbol), + StatementListItem::Declaration(decl) => decl.contains(symbol), + } } } -impl StatementListItem { +impl ToIndentedString for StatementListItem { /// Creates a string of the value of the node with the given indentation. For example, an /// indent level of 2 would produce this: /// @@ -72,40 +93,19 @@ impl StatementListItem { buf } +} - pub(crate) fn var_declared_names(&self, vars: &mut FxHashSet) { - match self { - StatementListItem::Statement(stmt) => stmt.var_declared_names(vars), - StatementListItem::Declaration(_) => {} - } - } - - /// Returns true if the node contains a identifier reference named 'arguments'. - /// - /// More information: - /// - [ECMAScript specification][spec] - /// - /// [spec]: https://tc39.es/ecma262/#sec-static-semantics-containsarguments +impl From for StatementListItem { #[inline] - pub(crate) fn contains_arguments(&self) -> bool { - match self { - StatementListItem::Statement(stmt) => stmt.contains_arguments(), - StatementListItem::Declaration(decl) => decl.contains_arguments(), - } + fn from(stmt: Statement) -> Self { + StatementListItem::Statement(stmt) } +} - /// Returns `true` if the node contains the given token. - /// - /// More information: - /// - [ECMAScript specification][spec] - /// - /// [spec]: https://tc39.es/ecma262/#sec-static-semantics-contains +impl From for StatementListItem { #[inline] - pub(crate) fn contains(&self, symbol: ContainsSymbol) -> bool { - match self { - StatementListItem::Statement(stmt) => stmt.contains(symbol), - StatementListItem::Declaration(decl) => decl.contains(symbol), - } + fn from(decl: Declaration) -> Self { + StatementListItem::Declaration(decl) } } @@ -141,19 +141,7 @@ impl StatementList { self.strict = strict; } - /// Implements the display formatting with indentation. - pub(crate) fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String { - let mut buf = String::new(); - // Print statements - for item in self.statements.iter() { - // We rely on the node to add the correct indent. - buf.push_str(&item.to_indented_string(interner, indentation)); - - buf.push('\n'); - } - buf - } - + #[inline] pub(crate) fn var_declared_names(&self, vars: &mut FxHashSet) { for stmt in &*self.statements { stmt.var_declared_names(vars); @@ -250,6 +238,7 @@ impl StatementList { } impl From> for StatementList { + #[inline] fn from(stm: Box<[StatementListItem]>) -> Self { Self { statements: stm, @@ -259,6 +248,7 @@ impl From> for StatementList { } impl From> for StatementList { + #[inline] fn from(stm: Vec) -> Self { Self { statements: stm.into(), @@ -267,8 +257,16 @@ impl From> for StatementList { } } -impl ToInternedString for StatementList { - fn to_interned_string(&self, interner: &Interner) -> String { - self.to_indented_string(interner, 0) +impl ToIndentedString for StatementList { + fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String { + let mut buf = String::new(); + // Print statements + for item in self.statements.iter() { + // We rely on the node to add the correct indent. + buf.push_str(&item.to_indented_string(interner, indentation)); + + buf.push('\n'); + } + buf } } diff --git a/boa_engine/src/syntax/parser/expression/tests.rs b/boa_engine/src/syntax/parser/expression/tests.rs index 0602184b03..8f6b9f3eff 100644 --- a/boa_engine/src/syntax/parser/expression/tests.rs +++ b/boa_engine/src/syntax/parser/expression/tests.rs @@ -148,8 +148,7 @@ fn check_numeric_operations() { ArithmeticOp::Div.into(), Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern_static("b", utf16!("b"))).into(), - )) - .into()] + ))] .into(), ))) .into()], diff --git a/boa_interner/src/lib.rs b/boa_interner/src/lib.rs index 079e058228..884dbc0bcc 100644 --- a/boa_interner/src/lib.rs +++ b/boa_interner/src/lib.rs @@ -409,6 +409,12 @@ impl Interner { } } +/// Implements the display formatting with indentation. +pub trait ToIndentedString { + /// Converts the element to a string using an interner, with the given indentation. + fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String; +} + /// Converts a given element to a string using an interner. pub trait ToInternedString { /// Converts a given element to a string using an interner. @@ -417,9 +423,9 @@ pub trait ToInternedString { impl ToInternedString for T where - T: std::fmt::Display, + T: ToIndentedString, { - fn to_interned_string(&self, _interner: &Interner) -> String { - self.to_string() + fn to_interned_string(&self, interner: &Interner) -> String { + self.to_indented_string(interner, 0) } }