Skip to content

Commit

Permalink
use chalk/swc patterns
Browse files Browse the repository at this point in the history
  • Loading branch information
addisoncrump committed Nov 1, 2022
1 parent c72e4c2 commit ad14efe
Show file tree
Hide file tree
Showing 7 changed files with 241 additions and 2 deletions.
20 changes: 20 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,21 @@ impl ToIndentedString for Declaration {
}
}
}

impl<V> VisitWith<V> for Declaration {
fn visit_with<'a>(&'a self, _visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: Visitor<'a>,
{
// TODO implement
ControlFlow::Continue(())
}

fn visit_with_mut<'a>(&'a mut self, _visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: VisitorMut<'a>,
{
// TODO implement
ControlFlow::Continue(())
}
}
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
20 changes: 20 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,21 @@ impl ToIndentedString for Statement {
buf
}
}

impl<V> VisitWith<V> for Statement {
fn visit_with<'a>(&'a self, _visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: Visitor<'a>,
{
// TODO implement
ControlFlow::Continue(())
}

fn visit_with_mut<'a>(&'a mut self, _visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: VisitorMut<'a>,
{
// TODO implement
ControlFlow::Continue(())
}
}
48 changes: 48 additions & 0 deletions boa_engine/src/syntax/ast/statement_list/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
//! Statement list node.
use super::{declaration::Binding, Declaration};
use crate::syntax::ast::visitor::{VisitWith, Visitor, VisitorMut};
use crate::syntax::ast::{expression::Identifier, statement::Statement, ContainsSymbol};
use boa_interner::{Interner, ToIndentedString};
use core::ops::ControlFlow;
use rustc_hash::FxHashSet;
use std::cmp::Ordering;

Expand Down Expand Up @@ -117,6 +119,30 @@ impl From<Declaration> for StatementListItem {
}
}

impl<V> VisitWith<V> for StatementListItem {
fn visit_with<'a>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: Visitor<'a>,
{
match self {
StatementListItem::Statement(statement) => visitor.visit_statement(statement),
StatementListItem::Declaration(declaration) => visitor.visit_declaration(declaration),
}
}

fn visit_with_mut<'a>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: VisitorMut<'a>,
{
match self {
StatementListItem::Statement(statement) => visitor.visit_statement_mut(statement),
StatementListItem::Declaration(declaration) => {
visitor.visit_declaration_mut(declaration)
}
}
}
}

/// List of statements.
///
/// More information:
Expand Down Expand Up @@ -278,3 +304,25 @@ impl ToIndentedString for StatementList {
buf
}
}

impl<V> VisitWith<V> for StatementList {
fn visit_with<'a>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: Visitor<'a>,
{
for statement in self.statements.iter() {
visitor.visit_statement_list_item(statement);
}
ControlFlow::Continue(())
}

fn visit_with_mut<'a>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: VisitorMut<'a>,
{
for statement in self.statements.iter_mut() {
visitor.visit_statement_list_item_mut(statement);
}
ControlFlow::Continue(())
}
}
86 changes: 86 additions & 0 deletions boa_engine/src/syntax/ast/visitor.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
//! Javascript Abstract Syntax Tree visitors.
//!
//! This module contains visitors which can be used to inspect or modify AST nodes. This allows for
//! fine-grained manipulation of ASTs for analysis, rewriting, or instrumentation.
#[cfg(doc)]
use super::statement_list::StatementListVisitor;

/// `Try`-like conditional unwrapping of `ControlFlow`.
#[macro_export]
macro_rules! try_break {
($expr:expr) => {
match $expr {
core::ops::ControlFlow::Continue(c) => c,
core::ops::ControlFlow::Break(b) => return core::ops::ControlFlow::Break(b),
}
};
}

use crate::syntax::ast::{Declaration, Statement, StatementList, StatementListItem};

macro_rules! define_visit {
($fn_name:ident, $type_name:ident) => {
fn $fn_name(&mut self, node: &'ast $type_name) -> core::ops::ControlFlow<Self::BreakTy> {
node.visit_with(self)
}
};
}

macro_rules! define_visit_mut {
($fn_name:ident, $type_name:ident) => {
fn $fn_name(
&mut self,
node: &'ast mut $type_name,
) -> core::ops::ControlFlow<Self::BreakTy> {
node.visit_with_mut(self)
}
};
}

/// Represents an AST visitor.
///
/// This implementation is based largely on [chalk](https://github.com/rust-lang/chalk/blob/23d39c90ceb9242fbd4c43e9368e813e7c2179f7/chalk-ir/src/visit.rs)'s
/// visitor pattern.
#[allow(unused_variables)]
#[allow(missing_docs)]
pub trait Visitor<'ast>: Sized {
/// Type which will be propagated from the visitor if completing early.
type BreakTy;

define_visit!(visit_statement_list, StatementList);
define_visit!(visit_statement_list_item, StatementListItem);
define_visit!(visit_statement, Statement);
define_visit!(visit_declaration, Declaration);
}

/// Represents an AST visitor which can modify AST content.
///
/// This implementation is based largely on [chalk](https://github.com/rust-lang/chalk/blob/23d39c90ceb9242fbd4c43e9368e813e7c2179f7/chalk-ir/src/visit.rs)'s
/// visitor pattern.
#[allow(unused_variables)]
#[allow(missing_docs)]
pub trait VisitorMut<'ast>: Sized {
/// Type which will be propagated from the visitor if completing early.
type BreakTy;

define_visit_mut!(visit_statement_list_mut, StatementList);
define_visit_mut!(visit_statement_list_item_mut, StatementListItem);
define_visit_mut!(visit_statement_mut, Statement);
define_visit_mut!(visit_declaration_mut, Declaration);
}

/// Denotes that a type may be visited, providing a method which allows a visitor to traverse its
/// private fields.
pub trait VisitWith<V> {
/// Visit this node with the provided visitor.
fn visit_with<'a>(&'a self, visitor: &mut V) -> core::ops::ControlFlow<V::BreakTy>
where
V: Visitor<'a>;

/// Visit this node with the provided visitor mutably, allowing the visitor to modify private
/// fields.
fn visit_with_mut<'a>(&'a mut self, visitor: &mut V) -> core::ops::ControlFlow<V::BreakTy>
where
V: VisitorMut<'a>;
}
4 changes: 2 additions & 2 deletions boa_engine/src/value/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ mod r#type;

pub use conversions::*;
pub use display::ValueDisplay;
pub use equality::*;
pub use hash::*;
// pub use equality::*;
// pub use hash::*;
pub use integer::IntegerOrInfinity;
pub use operations::*;
pub use r#type::Type;
Expand Down
64 changes: 64 additions & 0 deletions boa_examples/src/bin/printer_visitor.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
use boa_engine::syntax::ast::visitor::{VisitWith, Visitor};
use boa_engine::syntax::ast::{Declaration, Statement, StatementList, StatementListItem};
use boa_engine::syntax::Parser;
use boa_engine::Context;
use std::convert::Infallible;
use std::fs::File;
use std::io::BufReader;
use core::ops::ControlFlow;

#[derive(Debug, Clone, Default)]
struct PrinterVisitor {
indent: String,
}

impl<'ast> Visitor<'ast> for PrinterVisitor {
type BreakTy = Infallible;

fn visit_statement_list(&mut self, node: &'ast StatementList) -> ControlFlow<Self::BreakTy> {
println!(
"{}StatementList (strict: {}) {{",
self.indent,
node.strict()
);
self.indent.push(' ');
let res = node.visit_with(self);
self.indent.pop();
println!("{}}}", self.indent);
res
}

fn visit_statement_list_item(
&mut self,
node: &'ast StatementListItem,
) -> ControlFlow<Self::BreakTy> {
print!("{}StatementListItem: ", self.indent);
self.indent.push(' ');
let res = node.visit_with(self);
self.indent.pop();
res
}

fn visit_statement(&mut self, node: &'ast Statement) -> ControlFlow<Self::BreakTy> {
println!("Statement: {:?}", node);
ControlFlow::Continue(())
}

fn visit_declaration(&mut self, node: &'ast Declaration) -> ControlFlow<Self::BreakTy> {
println!("Declaration: {:?}", node);
ControlFlow::Continue(())
}
}

fn main() {
let mut parser = Parser::new(BufReader::new(
File::open("boa_examples/scripts/calctest.js").unwrap(),
));
let mut ctx = Context::default();

let statements = parser.parse_all(&mut ctx).unwrap();

let mut visitor = PrinterVisitor::default();

visitor.visit_statement_list(&statements);
}

0 comments on commit ad14efe

Please sign in to comment.