Skip to content

Commit

Permalink
Merge 127d038 into 98deb58
Browse files Browse the repository at this point in the history
  • Loading branch information
Paul Lancaster authored Oct 11, 2020
2 parents 98deb58 + 127d038 commit eaf55fc
Show file tree
Hide file tree
Showing 25 changed files with 837 additions and 105 deletions.
12 changes: 12 additions & 0 deletions boa/src/syntax/ast/keyword.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,16 @@ pub enum Keyword {
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await
Await,

/// The `async` keyword.
///
/// More information:
/// - [ECMAScript reference][spec]
/// - [MDN documentation][mdn]
///
/// [spec]: https://tc39.es/ecma262/#prod-AsyncMethod
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
Async,

/// The `break` keyword.
///
/// More information:
Expand Down Expand Up @@ -454,6 +464,7 @@ impl Keyword {
pub fn as_str(self) -> &'static str {
match self {
Self::Await => "await",
Self::Async => "async",
Self::Break => "break",
Self::Case => "case",
Self::Catch => "catch",
Expand Down Expand Up @@ -526,6 +537,7 @@ impl FromStr for Keyword {
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"await" => Ok(Self::Await),
"async" => Ok(Self::Async),
"break" => Ok(Self::Break),
"case" => Ok(Self::Case),
"catch" => Ok(Self::Catch),
Expand Down
61 changes: 61 additions & 0 deletions boa/src/syntax/ast/node/await_expr/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
//! Await expression node.
use super::Node;
use crate::{exec::Executable, BoaProfiler, Context, Result, Value};
use gc::{Finalize, Trace};
use std::fmt;

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

/// An await expression is used within an async function to pause execution and wait for a
/// promise to resolve.
///
/// More information:
/// - [ECMAScript reference][spec]
/// - [MDN documentation][mdn]
///
/// [spec]: https://tc39.es/ecma262/#prod-AwaitExpression
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, Trace, Finalize, PartialEq)]
pub struct AwaitExpr {
expr: Box<Node>,
}

impl Executable for AwaitExpr {
fn run(&self, _: &mut Context) -> Result<Value> {
let _timer = BoaProfiler::global().start_event("AwaitExpression", "exec");
// TODO: Implement AwaitExpr
Ok(Value::Undefined)
}
}

impl AwaitExpr {
/// Implements the display formatting with indentation.
pub(super) fn display(&self, f: &mut fmt::Formatter<'_>, indentation: usize) -> fmt::Result {
writeln!(f, "await ")?;
self.expr.display(f, indentation)
}
}

impl<T> From<T> for AwaitExpr
where
T: Into<Box<Node>>,
{
fn from(e: T) -> Self {
Self { expr: e.into() }
}
}

impl fmt::Display for AwaitExpr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.display(f, 0)
}
}

impl From<AwaitExpr> for Node {
fn from(awaitexpr: AwaitExpr) -> Self {
Self::AwaitExpr(awaitexpr)
}
}
101 changes: 101 additions & 0 deletions boa/src/syntax/ast/node/declaration/async_function_decl/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
//! Async Function Declaration.
use crate::{
exec::Executable,
syntax::ast::node::{join_nodes, FormalParameter, Node, StatementList},
BoaProfiler, Context, Result, Value,
};
use gc::{Finalize, Trace};
use std::fmt;

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

/// An async function is used to specify an action (or series of actions) to perform asynchronously.
///
/// More information:
/// - [ECMAScript reference][spec]
/// - [MDN documentation][mdn]
///
/// [spec]: https://tc39.es/ecma262/#sec-async-function-prototype-properties
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, Trace, Finalize, PartialEq)]
pub struct AsyncFunctionDecl {
name: Option<Box<str>>,
parameters: Box<[FormalParameter]>,
body: StatementList,
}

impl AsyncFunctionDecl {
/// Creates a new async function declaration.
pub(in crate::syntax) fn new<N, P, B>(name: N, parameters: P, body: B) -> Self
where
N: Into<Option<Box<str>>>,
P: Into<Box<[FormalParameter]>>,
B: Into<StatementList>,
{
Self {
name: name.into(),
parameters: parameters.into(),
body: body.into(),
}
}

/// Gets the name of the async function declaration.
pub fn name(&self) -> Option<&str> {
self.name.as_deref()
}

/// Gets the list of parameters of the async function declaration.
pub fn parameters(&self) -> &[FormalParameter] {
&self.parameters
}

/// Gets the body of the async function declaration.
pub fn body(&self) -> &[Node] {
self.body.statements()
}

/// Implements the display formatting with indentation.
pub(in crate::syntax::ast::node) fn display(
&self,
f: &mut fmt::Formatter<'_>,
indentation: usize,
) -> fmt::Result {
match &self.name {
Some(name) => {
write!(f, "async function {}(", name)?;
}
None => {
write!(f, "async function (")?;
}
}
join_nodes(f, &self.parameters)?;
f.write_str(") {{")?;

self.body.display(f, indentation + 1)?;

writeln!(f, "}}")
}
}

impl Executable for AsyncFunctionDecl {
fn run(&self, _: &mut Context) -> Result<Value> {
let _timer = BoaProfiler::global().start_event("AsyncFunctionDecl", "exec");
// TODO: Implement AsyncFunctionDecl
Ok(Value::undefined())
}
}

impl From<AsyncFunctionDecl> for Node {
fn from(decl: AsyncFunctionDecl) -> Self {
Self::AsyncFunctionDecl(decl)
}
}

impl fmt::Display for AsyncFunctionDecl {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.display(f, 0)
}
}
98 changes: 98 additions & 0 deletions boa/src/syntax/ast/node/declaration/async_function_expr/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
//! Async Function Expression.
use crate::{
exec::Executable,
syntax::ast::node::{join_nodes, FormalParameter, Node, StatementList},
Context, Result, Value,
};
use gc::{Finalize, Trace};
use std::fmt;

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

/// An async function expression is very similar to an async function declaration except used within
/// a wider expression (for example during an assignment).
///
/// More information:
/// - [ECMAScript reference][spec]
/// - [MDN documentation][mdn]
///
/// [spec]: https://tc39.es/ecma262/#prod-AsyncFunctionExpression
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/async_function
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, Trace, Finalize, PartialEq)]
pub struct AsyncFunctionExpr {
name: Option<Box<str>>,
parameters: Box<[FormalParameter]>,
body: StatementList,
}

impl AsyncFunctionExpr {
/// Creates a new function expression
pub(in crate::syntax) fn new<N, P, B>(name: N, parameters: P, body: B) -> Self
where
N: Into<Option<Box<str>>>,
P: Into<Box<[FormalParameter]>>,
B: Into<StatementList>,
{
Self {
name: name.into(),
parameters: parameters.into(),
body: body.into(),
}
}

/// Gets the name of the function declaration.
pub fn name(&self) -> Option<&str> {
self.name.as_ref().map(Box::as_ref)
}

/// Gets the list of parameters of the function declaration.
pub fn parameters(&self) -> &[FormalParameter] {
&self.parameters
}

/// Gets the body of the function declaration.
pub fn body(&self) -> &[Node] {
self.body.statements()
}

/// Implements the display formatting with indentation.
pub(in crate::syntax::ast::node) fn display(
&self,
f: &mut fmt::Formatter<'_>,
indentation: usize,
) -> fmt::Result {
f.write_str("function")?;
if let Some(ref name) = self.name {
write!(f, " {}", name)?;
}
f.write_str("(")?;
join_nodes(f, &self.parameters)?;
f.write_str(") {{")?;

self.body.display(f, indentation + 1)?;

writeln!(f, "}}")
}
}

impl Executable for AsyncFunctionExpr {
fn run(&self, _: &mut Context) -> Result<Value> {
// TODO: Implement AsyncFunctionExpr
Ok(Value::Undefined)
}
}

impl fmt::Display for AsyncFunctionExpr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.display(f, 0)
}
}

impl From<AsyncFunctionExpr> for Node {
fn from(expr: AsyncFunctionExpr) -> Self {
Self::AsyncFunctionExpr(expr)
}
}
4 changes: 4 additions & 0 deletions boa/src/syntax/ast/node/declaration/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
//! Declaration nodes
pub mod arrow_function_decl;
pub mod async_function_decl;
pub mod async_function_expr;
pub mod const_decl_list;
pub mod function_decl;
pub mod function_expr;
Expand All @@ -9,6 +11,8 @@ pub mod var_decl_list;

pub use self::{
arrow_function_decl::ArrowFunctionDecl,
async_function_decl::AsyncFunctionDecl,
async_function_expr::AsyncFunctionExpr,
const_decl_list::{ConstDecl, ConstDeclList},
function_decl::FunctionDecl,
function_expr::FunctionExpr,
Expand Down
23 changes: 20 additions & 3 deletions boa/src/syntax/ast/node/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! This module implements the `Node` structure, which composes the AST.
pub mod array;
pub mod await_expr;
pub mod block;
pub mod break_node;
pub mod call;
Expand All @@ -21,13 +22,14 @@ pub mod try_node;

pub use self::{
array::ArrayDecl,
await_expr::AwaitExpr,
block::Block,
break_node::Break,
call::Call,
conditional::{ConditionalOp, If},
declaration::{
ArrowFunctionDecl, ConstDecl, ConstDeclList, FunctionDecl, FunctionExpr, LetDecl,
LetDeclList, VarDecl, VarDeclList,
ArrowFunctionDecl, AsyncFunctionDecl, AsyncFunctionExpr, ConstDecl, ConstDeclList,
FunctionDecl, FunctionExpr, LetDecl, LetDeclList, VarDecl, VarDeclList,
},
field::{GetConstField, GetField},
identifier::Identifier,
Expand Down Expand Up @@ -65,6 +67,15 @@ pub enum Node {
/// An assignment operator node. [More information](./operator/struct.Assign.html).
Assign(Assign),

/// An async function declaration node. [More information](./declaration/struct.AsyncFunctionDecl.html).
AsyncFunctionDecl(AsyncFunctionDecl),

/// An async function expression node. [More information](./declaration/struct.AsyncFunctionExpr.html).
AsyncFunctionExpr(AsyncFunctionExpr),

/// An await expression node. [More information](./await_expr/struct.AwaitExpression.html).
AwaitExpr(AwaitExpr),

/// A binary operator node. [More information](./operator/struct.BinOp.html).
BinOp(BinOp),

Expand Down Expand Up @@ -104,7 +115,7 @@ pub enum Node {
/// A function declaration node. [More information](./declaration/struct.FunctionDecl.html).
FunctionDecl(FunctionDecl),

/// A function expressino node. [More information](./declaration/struct.FunctionExpr.html).
/// A function expression node. [More information](./declaration/struct.FunctionExpr.html).
FunctionExpr(FunctionExpr),

/// Provides access to an object types' constant properties. [More information](./declaration/struct.GetConstField.html).
Expand Down Expand Up @@ -243,6 +254,9 @@ impl Node {
Self::Assign(ref op) => Display::fmt(op, f),
Self::LetDeclList(ref decl) => Display::fmt(decl, f),
Self::ConstDeclList(ref decl) => Display::fmt(decl, f),
Self::AsyncFunctionDecl(ref decl) => decl.display(f, indentation),
Self::AsyncFunctionExpr(ref expr) => expr.display(f, indentation),
Self::AwaitExpr(ref expr) => expr.display(f, indentation),
}
}
}
Expand All @@ -251,6 +265,9 @@ impl Executable for Node {
fn run(&self, interpreter: &mut Context) -> Result<Value> {
let _timer = BoaProfiler::global().start_event("Executable", "exec");
match *self {
Node::AsyncFunctionDecl(ref decl) => decl.run(interpreter),
Node::AsyncFunctionExpr(ref function_expr) => function_expr.run(interpreter),
Node::AwaitExpr(ref expr) => expr.run(interpreter),
Node::Call(ref call) => call.run(interpreter),
Node::Const(Const::Null) => Ok(Value::null()),
Node::Const(Const::Num(num)) => Ok(Value::rational(num)),
Expand Down
Loading

0 comments on commit eaf55fc

Please sign in to comment.