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 26 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
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

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),
}
}
}
111 changes: 111 additions & 0 deletions boa_engine/src/syntax/ast/declaration/variable.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
//! Variable related declarations.

use std::convert::TryFrom;
use std::ops::ControlFlow;

use crate::syntax::ast::visitor::{VisitWith, Visitor, VisitorMut};
use crate::syntax::ast::{
expression::{Expression, Identifier},
join_nodes,
pattern::Pattern,
ContainsSymbol, Statement,
};
use crate::try_break;
use boa_interner::{Interner, ToInternedString};

use super::Declaration;
Expand Down Expand Up @@ -68,6 +71,22 @@ impl ToInternedString for VarDeclaration {
}
}

impl VisitWith for VarDeclaration {
fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: Visitor<'a>,
{
visitor.visit_variable_list(&self.0)
}

fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: VisitorMut<'a>,
{
visitor.visit_variable_list_mut(&mut self.0)
}
}

/// A **[lexical declaration]** defines variables that are scoped to the lexical environment of
/// the variable declaration.
///
Expand Down Expand Up @@ -141,6 +160,30 @@ impl ToInternedString for LexicalDeclaration {
}
}

impl VisitWith for LexicalDeclaration {
fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: Visitor<'a>,
{
match self {
LexicalDeclaration::Const(vars) | LexicalDeclaration::Let(vars) => {
visitor.visit_variable_list(vars)
}
}
}

fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: VisitorMut<'a>,
{
match self {
LexicalDeclaration::Const(vars) | LexicalDeclaration::Let(vars) => {
visitor.visit_variable_list_mut(vars)
}
}
}
}

/// List of variables in a variable declaration.
#[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Debug, PartialEq)]
Expand Down Expand Up @@ -171,6 +214,28 @@ impl ToInternedString for VariableList {
}
}

impl VisitWith for VariableList {
fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: Visitor<'a>,
{
for variable in self.list.iter() {
try_break!(visitor.visit_variable(variable));
}
ControlFlow::Continue(())
}

fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: VisitorMut<'a>,
{
for variable in self.list.iter_mut() {
try_break!(visitor.visit_variable_mut(variable));
}
ControlFlow::Continue(())
}
}

/// The error returned by the [`VariableList::try_from`] function.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct TryFromVariableListError(());
Expand Down Expand Up @@ -288,6 +353,30 @@ impl Variable {
}
}

impl VisitWith for Variable {
fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: Visitor<'a>,
{
try_break!(visitor.visit_binding(&self.binding));
if let Some(init) = &self.init {
try_break!(visitor.visit_expression(init));
}
ControlFlow::Continue(())
}

fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: VisitorMut<'a>,
{
try_break!(visitor.visit_binding_mut(&mut self.binding));
if let Some(init) = &mut self.init {
try_break!(visitor.visit_expression_mut(init));
}
ControlFlow::Continue(())
}
}

/// Binding represents either an individual binding or a binding pattern.
///
/// More information:
Expand Down Expand Up @@ -348,6 +437,28 @@ impl ToInternedString for Binding {
}
}

impl VisitWith for Binding {
fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: Visitor<'a>,
{
match self {
Binding::Identifier(id) => visitor.visit_identifier(id),
Binding::Pattern(pattern) => visitor.visit_pattern(pattern),
}
}

fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: VisitorMut<'a>,
{
match self {
Binding::Identifier(id) => visitor.visit_identifier_mut(id),
Binding::Pattern(pattern) => visitor.visit_pattern_mut(pattern),
}
}
}

#[cfg(test)]
mod tests {
#[test]
Expand Down
101 changes: 101 additions & 0 deletions boa_engine/src/syntax/ast/expression/access.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,11 @@
//! [spec]: https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-property-accessors
//! [access]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Property_Accessors

use crate::syntax::ast::visitor::{VisitWith, Visitor, VisitorMut};
use crate::syntax::ast::{expression::Expression, ContainsSymbol};
use crate::try_break;
use boa_interner::{Interner, Sym, ToInternedString};
use std::ops::ControlFlow;

/// A property access field.
///
Expand Down Expand Up @@ -59,6 +62,28 @@ impl From<Expression> for PropertyAccessField {
}
}

impl VisitWith for PropertyAccessField {
fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: Visitor<'a>,
{
match self {
PropertyAccessField::Const(sym) => visitor.visit_sym(sym),
PropertyAccessField::Expr(expr) => visitor.visit_expression(&*expr),
}
}

fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: VisitorMut<'a>,
{
match self {
PropertyAccessField::Const(sym) => visitor.visit_sym_mut(sym),
PropertyAccessField::Expr(expr) => visitor.visit_expression_mut(&mut *expr),
}
}
}

/// A property access expression.
///
/// See the [module level documentation][self] for more information.
Expand Down Expand Up @@ -111,6 +136,30 @@ impl From<PropertyAccess> for Expression {
}
}

impl VisitWith for PropertyAccess {
fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: Visitor<'a>,
{
match self {
PropertyAccess::Simple(spa) => visitor.visit_simple_property_access(spa),
PropertyAccess::Private(ppa) => visitor.visit_private_property_access(ppa),
PropertyAccess::Super(supa) => visitor.visit_super_property_access(supa),
}
}

fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: VisitorMut<'a>,
{
match self {
PropertyAccess::Simple(spa) => visitor.visit_simple_property_access_mut(spa),
PropertyAccess::Private(ppa) => visitor.visit_private_property_access_mut(ppa),
PropertyAccess::Super(supa) => visitor.visit_super_property_access_mut(supa),
}
}
}

/// A simple property access, where the target object is an [`Expression`].
#[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Debug, PartialEq)]
Expand Down Expand Up @@ -175,6 +224,24 @@ impl From<SimplePropertyAccess> for PropertyAccess {
}
}

impl VisitWith for SimplePropertyAccess {
fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: Visitor<'a>,
{
try_break!(visitor.visit_expression(&*self.target));
visitor.visit_property_access_field(&self.field)
}

fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: VisitorMut<'a>,
{
try_break!(visitor.visit_expression_mut(&mut *self.target));
visitor.visit_property_access_field_mut(&mut self.field)
}
}

/// An access expression to a class object's [private fields][mdn].
///
/// Private property accesses differ slightly from plain property accesses, since the accessed
Expand Down Expand Up @@ -243,6 +310,24 @@ impl From<PrivatePropertyAccess> for PropertyAccess {
}
}

impl VisitWith for PrivatePropertyAccess {
fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: Visitor<'a>,
{
try_break!(visitor.visit_expression(&*self.target));
visitor.visit_sym(&self.field)
}

fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: VisitorMut<'a>,
{
try_break!(visitor.visit_expression_mut(&mut *self.target));
visitor.visit_sym_mut(&mut self.field)
}
}

/// A property access of an object's parent, as defined by the [spec].
///
/// A `SuperPropertyAccess` is much like a regular [`PropertyAccess`], but where its `target` object
Expand Down Expand Up @@ -298,3 +383,19 @@ impl From<SuperPropertyAccess> for PropertyAccess {
Self::Super(access)
}
}

impl VisitWith for SuperPropertyAccess {
fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: Visitor<'a>,
{
visitor.visit_property_access_field(&self.field)
}

fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: VisitorMut<'a>,
{
visitor.visit_property_access_field_mut(&mut self.field)
}
}
18 changes: 18 additions & 0 deletions boa_engine/src/syntax/ast/expression/await.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
//! Await expression Expression.

use crate::syntax::ast::ContainsSymbol;
use std::ops::ControlFlow;

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

/// An await expression is used within an async function to pause execution and wait for a
Expand Down Expand Up @@ -62,6 +64,22 @@ impl From<Await> for Expression {
}
}

impl VisitWith for Await {
fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: Visitor<'a>,
{
visitor.visit_expression(&*self.target)
}

fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: VisitorMut<'a>,
{
visitor.visit_expression_mut(&mut *self.target)
}
}

#[cfg(test)]
mod tests {
#[test]
Expand Down
Loading