Skip to content

Commit

Permalink
Merge dc7346f into 5f7ec62
Browse files Browse the repository at this point in the history
  • Loading branch information
jasonwilliams authored Jul 5, 2020
2 parents 5f7ec62 + dc7346f commit fc915c7
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 8 deletions.
13 changes: 11 additions & 2 deletions boa/src/exec/iteration/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,17 @@ impl Executable for ForLoop {
let result = self.body().run(interpreter)?;

match interpreter.get_current_state() {
InterpreterState::Break(_label) => {
// TODO break to label.
InterpreterState::Break(label) => {
// If a label is set we want to break the current block and still keep state as Break if the label is a block above
if let Some(stmt_label) = &self.label {
if let Some(brk_label) = label {
// We have a label, but not for the current statement
// break without resetting to executing
if stmt_label != brk_label {
break;
}
}
}

// Loops 'consume' breaks.
interpreter.set_current_state(InterpreterState::Executing);
Expand Down
10 changes: 9 additions & 1 deletion boa/src/syntax/ast/node/iteration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,18 @@ use serde::{Deserialize, Serialize};
pub struct ForLoop {
#[cfg_attr(feature = "serde", serde(flatten))]
inner: Box<InnerForLoop>,
pub label: Option<String>,
}

impl ForLoop {
/// Creates a new for loop AST node.
pub(in crate::syntax) fn new<I, C, E, B>(init: I, condition: C, final_expr: E, body: B) -> Self
pub(in crate::syntax) fn new<I, C, E, B>(
init: I,
condition: C,
final_expr: E,
body: B,
label: Option<String>,
) -> Self
where
I: Into<Option<Node>>,
C: Into<Option<Node>>,
Expand All @@ -34,6 +41,7 @@ impl ForLoop {
{
Self {
inner: Box::new(InnerForLoop::new(init, condition, final_expr, body)),
label,
}
}

Expand Down
7 changes: 5 additions & 2 deletions boa/src/syntax/parser/statement/iteration/for_statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,12 @@ use crate::{
///
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for
/// [spec]: https://tc39.es/ecma262/#sec-for-statement
#[derive(Debug, Clone, Copy)]
#[derive(Debug, Clone)]
pub(in crate::syntax::parser::statement) struct ForStatement {
allow_yield: AllowYield,
allow_await: AllowAwait,
allow_return: AllowReturn,
label: Option<String>,
}

impl ForStatement {
Expand All @@ -44,6 +45,7 @@ impl ForStatement {
allow_yield: Y,
allow_await: A,
allow_return: R,
label: Option<String>,
) -> Self
where
Y: Into<AllowYield>,
Expand All @@ -54,6 +56,7 @@ impl ForStatement {
allow_yield: allow_yield.into(),
allow_await: allow_await.into(),
allow_return: allow_return.into(),
label,
}
}
}
Expand Down Expand Up @@ -104,6 +107,6 @@ impl TokenParser for ForStatement {
Statement::new(self.allow_yield, self.allow_await, self.allow_return).parse(cursor)?;

// TODO: do not encapsulate the `for` in a block just to have an inner scope.
Ok(ForLoop::new(init, cond, step, body))
Ok(ForLoop::new(init, cond, step, body, self.label))
}
}
50 changes: 50 additions & 0 deletions boa/src/syntax/parser/statement/labelled_stm/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
use super::LabelIdentifier;
use crate::{
syntax::{
ast::Punctuator,
parser::{
cursor::Cursor, error::ParseError, AllowAwait, AllowReturn, AllowYield, TokenParser,
},
},
BoaProfiler,
};
/// Labelled Statement Parsing
///
/// More information
/// - [MDN documentation][mdn]
/// - [ECMAScript specification][spec]
///
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/label
/// [spec]: https://tc39.es/ecma262/#sec-labelled-statements
#[derive(Debug, Clone, Copy)]
pub(super) struct Label {
allow_yield: AllowYield,
allow_await: AllowAwait,
allow_return: AllowReturn,
}

impl Label {
pub(super) fn new<Y, A, R>(allow_yield: Y, allow_await: A, allow_return: R) -> Self
where
Y: Into<AllowYield>,
A: Into<AllowAwait>,
R: Into<AllowReturn>,
{
Self {
allow_yield: allow_yield.into(),
allow_await: allow_await.into(),
allow_return: allow_return.into(),
}
}
}

impl TokenParser for Label {
type Output = String;

fn parse(self, cursor: &mut Cursor<'_>) -> Result<Self::Output, ParseError> {
let _timer = BoaProfiler::global().start_event("Label", "Parsing");
let name = LabelIdentifier::new(self.allow_yield, self.allow_await).parse(cursor)?;
cursor.expect(Punctuator::Colon, "Labelled Statement")?;
Ok(name.to_string())
}
}
19 changes: 16 additions & 3 deletions boa/src/syntax/parser/statement/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ mod declaration;
mod expression;
mod if_stm;
mod iteration;
mod labelled_stm;
mod return_stm;
mod switch;
mod throw;
Expand All @@ -39,6 +40,7 @@ use crate::{
syntax::ast::{node, Keyword, Node, Punctuator, TokenKind},
BoaProfiler,
};
use labelled_stm::Label;

/// Statement parsing.
///
Expand Down Expand Up @@ -95,7 +97,15 @@ impl TokenParser for Statement {
fn parse(self, cursor: &mut Cursor<'_>) -> Result<Self::Output, ParseError> {
let _timer = BoaProfiler::global().start_event("Statement", "Parsing");
// TODO: add BreakableStatement and divide Whiles, fors and so on to another place.
let tok = cursor.peek(0).ok_or(ParseError::AbruptEnd)?;
let mut tok = cursor.peek(0).ok_or(ParseError::AbruptEnd)?;

// Is this statement prefixed with a label?
let label =
Label::new(self.allow_yield, self.allow_await, self.allow_return).try_parse(cursor);

if label.is_some() {
tok = cursor.peek(0).ok_or(ParseError::AbruptEnd)?;
}

match tok.kind {
TokenKind::Keyword(Keyword::If) => {
Expand All @@ -119,7 +129,7 @@ impl TokenParser for Statement {
.map(Node::from)
}
TokenKind::Keyword(Keyword::For) => {
ForStatement::new(self.allow_yield, self.allow_await, self.allow_return)
ForStatement::new(self.allow_yield, self.allow_await, self.allow_return, label)
.parse(cursor)
.map(Node::from)
}
Expand Down Expand Up @@ -162,6 +172,9 @@ impl TokenParser for Statement {
.parse(cursor)
.map(Node::from)
}
// TokenKind::Identifier(name) => LabelIdentifier::new(self.allow_yield, self.allow_await)
// .parse(cursor)
// .map(Node::from),
// TODO: https://tc39.es/ecma262/#prod-LabelledStatement
// TokenKind::Punctuator(Punctuator::Semicolon) => {
// return Ok(Node::new(NodeBase::Nope, tok.pos))
Expand Down Expand Up @@ -350,7 +363,7 @@ impl TokenParser for StatementListItem {
/// - [ECMAScript specification][spec]
///
/// [spec]: https://tc39.es/ecma262/#prod-LabelIdentifier
type LabelIdentifier = BindingIdentifier;
pub(super) type LabelIdentifier = BindingIdentifier;

/// Binding identifier parsing.
///
Expand Down

0 comments on commit fc915c7

Please sign in to comment.