Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Merged by Bors] - Implement AST Visitor pattern (attempt #3) #2392

Closed
wants to merge 34 commits into from
Closed
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
ad14efe
use chalk/swc patterns
addisoncrump Nov 1, 2022
9b8089a
make fmt happy
addisoncrump Nov 1, 2022
548a44b
whoops, missed a spot
addisoncrump Nov 1, 2022
3905165
more precise missing_docs
addisoncrump Nov 1, 2022
481c433
again
addisoncrump Nov 1, 2022
5250407
Create documentation for Visitor{,Mut} dynamically
addisoncrump Nov 1, 2022
0bbe562
expand for declaration, statement; move V parameter to function
addisoncrump Nov 1, 2022
803ed95
expand for Function
addisoncrump Nov 1, 2022
350656d
expand other function types
addisoncrump Nov 1, 2022
b0b7433
expand class
addisoncrump Nov 1, 2022
fe4bbd5
expand variable
addisoncrump Nov 1, 2022
0b57f6b
expand block
addisoncrump Nov 1, 2022
b2e730e
expand vardeclaration
addisoncrump Nov 1, 2022
4743d45
expand expression
addisoncrump Nov 1, 2022
49e9d15
loops
addisoncrump Nov 1, 2022
0889981
switch
addisoncrump Nov 1, 2022
5c1b507
several additional expansions
addisoncrump Nov 1, 2022
de634a9
formal parameter list
addisoncrump Nov 1, 2022
accf453
class element
addisoncrump Nov 1, 2022
5cccd2e
lots of expansions, forgot to commit individually
addisoncrump Nov 1, 2022
b47bb94
await, yield, loops
addisoncrump Nov 1, 2022
942c38d
several more expansions
addisoncrump Nov 1, 2022
f3a40ef
add todo for formal parameter flag recompute
addisoncrump Nov 1, 2022
89b3d66
implement remaining, prep next pass
addisoncrump Nov 1, 2022
0e06f05
finish visitors
addisoncrump Nov 1, 2022
61ca13d
simplify visitor example
addisoncrump Nov 1, 2022
dc9aa74
Add VisitorMut example
addisoncrump Nov 1, 2022
1dc7657
simplify Cargo.toml
addisoncrump Nov 1, 2022
0953cfc
cleanup examples
addisoncrump Nov 1, 2022
c1ce837
apply clippy fixes
addisoncrump Nov 1, 2022
88c6f01
fixup fmt
addisoncrump Nov 1, 2022
468ecb9
{std=>core}::ops::ControlFlow
addisoncrump Nov 1, 2022
04b2482
undo comment
addisoncrump Nov 1, 2022
58aa397
poof
addisoncrump Nov 1, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions boa_engine/src/syntax/ast/declaration/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@ use super::{
ContainsSymbol,
};
use boa_interner::{Interner, ToIndentedString, ToInternedString};
use core::ops::ControlFlow;
use tap::Tap;

mod variable;

use crate::syntax::ast::visitor::{VisitWith, Visitor, VisitorMut};
pub use variable::*;

/// The `Declaration` Parse Node.
Expand Down Expand Up @@ -165,3 +167,33 @@ impl ToIndentedString for Declaration {
}
}
}

impl VisitWith for Declaration {
fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: Visitor<'a>,
{
match self {
Declaration::Function(f) => visitor.visit_function(f),
Declaration::Generator(g) => visitor.visit_generator(g),
Declaration::AsyncFunction(af) => visitor.visit_async_function(af),
Declaration::AsyncGenerator(ag) => visitor.visit_async_generator(ag),
Declaration::Class(c) => visitor.visit_class(c),
Declaration::Lexical(ld) => visitor.visit_lexical_declaration(ld),
}
}

fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: VisitorMut<'a>,
{
match self {
Declaration::Function(f) => visitor.visit_function_mut(f),
Declaration::Generator(g) => visitor.visit_generator_mut(g),
Declaration::AsyncFunction(af) => visitor.visit_async_function_mut(af),
Declaration::AsyncGenerator(ag) => visitor.visit_async_generator_mut(ag),
Declaration::Class(c) => visitor.visit_class_mut(c),
Declaration::Lexical(ld) => visitor.visit_lexical_declaration_mut(ld),
}
}
}
27 changes: 27 additions & 0 deletions boa_engine/src/syntax/ast/function/async_function.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
//! Async Function Expression.

use crate::syntax::ast::visitor::{VisitWith, Visitor, VisitorMut};
use crate::syntax::ast::{
expression::{Expression, Identifier},
join_nodes, Declaration, StatementList,
};
use crate::try_break;
use boa_interner::{Interner, ToIndentedString};
use std::ops::ControlFlow;

use super::FormalParameterList;

Expand Down Expand Up @@ -95,6 +98,30 @@ impl From<AsyncFunction> for Declaration {
}
}

impl VisitWith for AsyncFunction {
fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: Visitor<'a>,
{
if let Some(ident) = &self.name {
try_break!(visitor.visit_identifier(ident));
}
try_break!(visitor.visit_formal_parameter_list(&self.parameters));
visitor.visit_statement_list(&self.body)
}

fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: VisitorMut<'a>,
{
if let Some(ident) = &mut self.name {
try_break!(visitor.visit_identifier_mut(ident));
}
try_break!(visitor.visit_formal_parameter_list_mut(&mut self.parameters));
visitor.visit_statement_list_mut(&mut self.body)
}
}

#[cfg(test)]
mod tests {
#[test]
Expand Down
27 changes: 27 additions & 0 deletions boa_engine/src/syntax/ast/function/async_generator.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
//! Async Generator Expression
use crate::syntax::ast::visitor::{VisitWith, Visitor, VisitorMut};
use crate::syntax::ast::{
block_to_string,
expression::{Expression, Identifier},
join_nodes, Declaration, StatementList,
};
use crate::try_break;
use boa_interner::{Interner, ToIndentedString};
use std::ops::ControlFlow;

use super::FormalParameterList;

Expand Down Expand Up @@ -86,3 +89,27 @@ impl From<AsyncGenerator> for Declaration {
Self::AsyncGenerator(f)
}
}

impl VisitWith for AsyncGenerator {
fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: Visitor<'a>,
{
if let Some(ident) = &self.name {
try_break!(visitor.visit_identifier(ident));
}
try_break!(visitor.visit_formal_parameter_list(&self.parameters));
visitor.visit_statement_list(&self.body)
}

fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: VisitorMut<'a>,
{
if let Some(ident) = &mut self.name {
try_break!(visitor.visit_identifier_mut(ident));
}
try_break!(visitor.visit_formal_parameter_list_mut(&mut self.parameters));
visitor.visit_statement_list_mut(&mut self.body)
}
}
43 changes: 43 additions & 0 deletions boa_engine/src/syntax/ast/function/class.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use std::borrow::Cow;
use std::ops::ControlFlow;

use crate::syntax::ast::visitor::{VisitWith, Visitor, VisitorMut};
use crate::{
string::ToStringEscaped,
syntax::ast::{
Expand All @@ -9,6 +11,7 @@ use crate::{
property::{MethodDefinition, PropertyName},
ContainsSymbol, Declaration, StatementList, StatementListItem,
},
try_break,
};
use boa_interner::{Interner, Sym, ToIndentedString, ToInternedString};

Expand Down Expand Up @@ -446,6 +449,46 @@ impl ClassElement {
}
}

impl VisitWith for Class {
fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: Visitor<'a>,
{
if let Some(ident) = &self.name {
try_break!(visitor.visit_identifier(ident));
}
if let Some(expr) = &self.super_ref {
try_break!(visitor.visit_expression(expr));
}
if let Some(func) = &self.constructor {
try_break!(visitor.visit_function(func));
}
for elem in self.elements.iter() {
try_break!(visitor.visit_class_element(elem));
}
ControlFlow::Continue(())
}

fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: VisitorMut<'a>,
{
if let Some(ident) = &mut self.name {
try_break!(visitor.visit_identifier_mut(ident));
}
if let Some(expr) = &mut self.super_ref {
try_break!(visitor.visit_expression_mut(expr));
}
if let Some(func) = &mut self.constructor {
try_break!(visitor.visit_function_mut(func));
}
for elem in self.elements.iter_mut() {
try_break!(visitor.visit_class_element_mut(elem));
}
ControlFlow::Continue(())
}
}

#[cfg(test)]
mod tests {
use crate::syntax::ast::test_formatting;
Expand Down
27 changes: 27 additions & 0 deletions boa_engine/src/syntax/ast/function/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ use crate::syntax::ast::{
expression::{Expression, Identifier},
join_nodes, Declaration, StatementList,
};
use std::ops::ControlFlow;

use crate::syntax::ast::visitor::{VisitWith, Visitor, VisitorMut};
use crate::try_break;
use boa_interner::{Interner, ToIndentedString};

use super::FormalParameterList;
Expand Down Expand Up @@ -88,3 +91,27 @@ impl From<Generator> for Declaration {
Self::Generator(f)
}
}

impl VisitWith for Generator {
fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: Visitor<'a>,
{
if let Some(ident) = &self.name {
try_break!(visitor.visit_identifier(ident));
}
try_break!(visitor.visit_formal_parameter_list(&self.parameters));
visitor.visit_statement_list(&self.body)
}

fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: VisitorMut<'a>,
{
if let Some(ident) = &mut self.name {
try_break!(visitor.visit_identifier_mut(ident));
}
try_break!(visitor.visit_formal_parameter_list_mut(&mut self.parameters));
visitor.visit_statement_list_mut(&mut self.body)
}
}
27 changes: 27 additions & 0 deletions boa_engine/src/syntax/ast/function/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,13 @@ pub use async_generator::AsyncGenerator;
pub use class::{Class, ClassElement};
pub use generator::Generator;
pub use parameters::{FormalParameter, FormalParameterList};
use std::ops::ControlFlow;

pub(crate) use parameters::FormalParameterListFlags;

use crate::syntax::ast::visitor::{VisitWith, Visitor, VisitorMut};
use crate::syntax::ast::{block_to_string, join_nodes, StatementList};
use crate::try_break;
use boa_interner::{Interner, ToIndentedString};

use super::expression::{Expression, Identifier};
Expand Down Expand Up @@ -165,6 +168,30 @@ pub(crate) fn has_direct_super(body: &StatementList, parameters: &FormalParamete
false
}

impl VisitWith for Function {
fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: Visitor<'a>,
{
if let Some(ident) = &self.name {
try_break!(visitor.visit_identifier(ident));
}
try_break!(visitor.visit_formal_parameter_list(&self.parameters));
visitor.visit_statement_list(&self.body)
}

fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: VisitorMut<'a>,
{
if let Some(ident) = &mut self.name {
try_break!(visitor.visit_identifier_mut(ident));
}
try_break!(visitor.visit_formal_parameter_list_mut(&mut self.parameters));
visitor.visit_statement_list_mut(&mut self.body)
}
}

#[cfg(test)]
mod tests {

Expand Down
1 change: 1 addition & 0 deletions boa_engine/src/syntax/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ pub mod keyword;
pub mod pattern;
pub mod property;
pub mod statement;
pub mod visitor;

use boa_interner::{Interner, ToIndentedString, ToInternedString};

Expand Down
60 changes: 60 additions & 0 deletions boa_engine/src/syntax/ast/statement/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ pub use self::{
switch::{Case, Switch},
throw::Throw,
};
use core::ops::ControlFlow;

use crate::syntax::ast::visitor::{VisitWith, Visitor, VisitorMut};
use boa_interner::{Interner, ToIndentedString, ToInternedString};
use rustc_hash::FxHashSet;
use tap::Tap;
Expand Down Expand Up @@ -313,3 +315,61 @@ impl ToIndentedString for Statement {
buf
}
}

impl VisitWith for Statement {
fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: Visitor<'a>,
{
match self {
Statement::Block(b) => visitor.visit_block(b),
Statement::Var(v) => visitor.visit_var_declaration(v),
Statement::Empty => {
// do nothing; there is nothing to visit here
ControlFlow::Continue(())
}
Statement::Expression(e) => visitor.visit_expression(e),
Statement::If(i) => visitor.visit_if(i),
Statement::DoWhileLoop(dw) => visitor.visit_do_while_loop(dw),
Statement::WhileLoop(w) => visitor.visit_while_loop(w),
Statement::ForLoop(f) => visitor.visit_for_loop(f),
Statement::ForInLoop(fi) => visitor.visit_for_in_loop(fi),
Statement::ForOfLoop(fo) => visitor.visit_for_of_loop(fo),
Statement::Switch(s) => visitor.visit_switch(s),
Statement::Continue(c) => visitor.visit_continue(c),
Statement::Break(b) => visitor.visit_break(b),
Statement::Return(r) => visitor.visit_return(r),
Statement::Labelled(l) => visitor.visit_labelled(l),
Statement::Throw(th) => visitor.visit_throw(th),
Statement::Try(tr) => visitor.visit_try(tr),
}
}

fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: VisitorMut<'a>,
{
match self {
Statement::Block(b) => visitor.visit_block_mut(b),
Statement::Var(v) => visitor.visit_var_declaration_mut(v),
Statement::Empty => {
// do nothing; there is nothing to visit here
ControlFlow::Continue(())
}
Statement::Expression(e) => visitor.visit_expression_mut(e),
Statement::If(i) => visitor.visit_if_mut(i),
Statement::DoWhileLoop(dw) => visitor.visit_do_while_loop_mut(dw),
Statement::WhileLoop(w) => visitor.visit_while_loop_mut(w),
Statement::ForLoop(f) => visitor.visit_for_loop_mut(f),
Statement::ForInLoop(fi) => visitor.visit_for_in_loop_mut(fi),
Statement::ForOfLoop(fo) => visitor.visit_for_of_loop_mut(fo),
Statement::Switch(s) => visitor.visit_switch_mut(s),
Statement::Continue(c) => visitor.visit_continue_mut(c),
Statement::Break(b) => visitor.visit_break_mut(b),
Statement::Return(r) => visitor.visit_return_mut(r),
Statement::Labelled(l) => visitor.visit_labelled_mut(l),
Statement::Throw(th) => visitor.visit_throw_mut(th),
Statement::Try(tr) => visitor.visit_try_mut(tr),
}
}
}
Loading