Skip to content

Commit

Permalink
Merge 35fb745 into e82dee1
Browse files Browse the repository at this point in the history
  • Loading branch information
Paul Lancaster authored Oct 10, 2020
2 parents e82dee1 + 35fb745 commit f06c10f
Show file tree
Hide file tree
Showing 10 changed files with 432 additions and 19 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
99 changes: 99 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,99 @@
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};

/// Async Function Declaration.
///
/// 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, interpreter: &mut Context) -> Result<Value> {
let _timer = BoaProfiler::global().start_event("AsyncFunctionDecl", "exec");
unimplemented!("Execute 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)
}
}
94 changes: 94 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,94 @@
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};

/// AsyncFunctionExpr.
///
/// 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, interpreter: &mut Context) -> Result<Value> {
unimplemented!("Execute AsyncFunctionExpr");
}
}

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
16 changes: 13 additions & 3 deletions boa/src/syntax/ast/node/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ pub use self::{
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 +65,12 @@ 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),

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

Expand Down Expand Up @@ -104,7 +110,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 +249,8 @@ 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),
}
}
}
Expand All @@ -251,6 +259,8 @@ 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::Call(ref call) => call.run(interpreter),
Node::Const(Const::Null) => Ok(Value::null()),
Node::Const(Const::Num(num)) => Ok(Value::rational(num)),
Expand Down
31 changes: 24 additions & 7 deletions boa/src/syntax/parser/cursor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,6 @@ where
}

/// Returns an error if the next token is not of kind `kind`.
///
/// Note: it will consume the next token only if the next token is the expected type.
///
/// If skip_line_terminators is true then line terminators will be discarded.
#[inline]
pub(super) fn expect<K>(&mut self, kind: K, context: &'static str) -> Result<Token, ParseError>
where
Expand Down Expand Up @@ -134,7 +130,7 @@ where
///
/// It expects that the token stream does not end here.
///
/// This is just syntatic sugar for a .peek(skip_n, false) call followed by a check that the result is not a line terminator or None.
/// This is just syntatic sugar for a .peek(skip_n) call followed by a check that the result is not a line terminator or None.
#[inline]
pub(super) fn peek_expect_no_lineterminator(
&mut self,
Expand All @@ -151,13 +147,34 @@ where
}
}

/// Returns an error if the next token is not of kind `kind`.
#[inline]
pub(super) fn expect_no_skip_lineterminator<K>(
&mut self,
kind: K,
context: &'static str,
) -> Result<Token, ParseError>
where
K: Into<TokenKind>,
{
let next_token = self
.buffered_lexer
.next(false)?
.ok_or(ParseError::AbruptEnd)?;
let kind = kind.into();

if next_token.kind() == &kind {
Ok(next_token)
} else {
Err(ParseError::expected(vec![kind], next_token, context))
}
}

/// Advance the cursor to the next token and retrieve it, only if it's of `kind` type.
///
/// When the next token is a `kind` token, get the token, otherwise return `None`.
///
/// No next token also returns None.
///
/// If skip_line_terminators is true then line terminators will be discarded.
#[inline]
pub(super) fn next_if<K>(&mut self, kind: K) -> Result<Option<Token>, ParseError>
where
Expand Down
Loading

0 comments on commit f06c10f

Please sign in to comment.