Skip to content

Commit

Permalink
* Continue and Break hold Box<str> instead of Strings which is more e…
Browse files Browse the repository at this point in the history
…fficient
  • Loading branch information
jasonwilliams committed Sep 27, 2020
1 parent a10dced commit 14d3d76
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 45 deletions.
4 changes: 2 additions & 2 deletions boa/src/exec/break_node/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ impl Executable for Break {
fn run(&self, interpreter: &mut Context) -> Result<Value> {
interpreter
.executor()
.set_current_state(InterpreterState::Break(self.label().map(String::from)));
.set_current_state(InterpreterState::Break(self.label().map(Box::from)));

Ok(Value::undefined())
}
Expand All @@ -21,7 +21,7 @@ impl Executable for Continue {
fn run(&self, interpreter: &mut Context) -> Result<Value> {
interpreter
.executor()
.set_current_state(InterpreterState::Continue(self.label().map(String::from)));
.set_current_state(InterpreterState::Continue(self.label().map(Box::from)));

Ok(Value::undefined())
}
Expand Down
2 changes: 1 addition & 1 deletion boa/src/exec/break_node/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ fn check_post_state() {

assert_eq!(
engine.executor().get_current_state(),
&InterpreterState::Break(Some("label".to_string()))
&InterpreterState::Break(Some("label".into()))
);
}
68 changes: 29 additions & 39 deletions boa/src/exec/iteration/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,27 @@ use crate::{
#[cfg(test)]
mod tests;

// Checking labels for break and continue is the same operation for `ForLoop`, `While` and `DoWhile`
macro_rules! handle_state_with_labels {
($self:ident, $label:ident, $interpreter:ident, $state:tt) => {{
if let Some(brk_label) = $label {
if let Some(stmt_label) = $self.label() {
// Break from where we are, keeping "continue" set as the state
if stmt_label != brk_label.as_ref() {
break;
}
} else {
// if a label is set but the current block has no label, break
break;
}
}

$interpreter
.executor()
.set_current_state(InterpreterState::Executing);
}};
}

impl Executable for ForLoop {
fn run(&self, interpreter: &mut Context) -> Result<Value> {
// Create the block environment.
Expand All @@ -35,35 +56,13 @@ impl Executable for ForLoop {

match interpreter.executor().get_current_state() {
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 executings
if stmt_label.to_string() != *brk_label {
break;
} else {
interpreter
.executor()
.set_current_state(InterpreterState::Executing);
break;
}
}
}

// Loops 'consume' breaks.
interpreter
.executor()
.set_current_state(InterpreterState::Executing);
handle_state_with_labels!(self, label, interpreter, break);
break;
}
InterpreterState::Continue(_label) => {
// TODO continue to label.
interpreter
.executor()
.set_current_state(InterpreterState::Executing);
// after breaking out of the block, continue execution of the loop
InterpreterState::Continue(label) => {
handle_state_with_labels!(self, label, interpreter, continue);
}

InterpreterState::Return => {
return Ok(result);
}
Expand All @@ -90,21 +89,12 @@ impl Executable for WhileLoop {
while self.cond().run(interpreter)?.to_boolean() {
result = self.expr().run(interpreter)?;
match interpreter.executor().get_current_state() {
InterpreterState::Break(_label) => {
// TODO break to label.

// Loops 'consume' breaks.
interpreter
.executor()
.set_current_state(InterpreterState::Executing);
InterpreterState::Break(label) => {
handle_state_with_labels!(self, label, interpreter, break);
break;
}
InterpreterState::Continue(_label) => {
// TODO continue to label.
interpreter
.executor()
.set_current_state(InterpreterState::Executing);
// after breaking out of the block, continue execution of the loop
InterpreterState::Continue(label) => {
handle_state_with_labels!(self, label, interpreter, continue)
}
InterpreterState::Return => {
return Ok(result);
Expand Down
4 changes: 2 additions & 2 deletions boa/src/exec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ pub trait Executable {
pub(crate) enum InterpreterState {
Executing,
Return,
Break(Option<String>),
Continue(Option<String>),
Break(Option<Box<str>>),
Continue(Option<Box<str>>),
}

/// A Javascript intepreter
Expand Down
18 changes: 17 additions & 1 deletion boa/src/syntax/ast/node/iteration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use serde::{Deserialize, Serialize};
pub struct ForLoop {
#[cfg_attr(feature = "serde", serde(flatten))]
inner: Box<InnerForLoop>,
pub(crate) label: Option<Box<str>>,
label: Option<Box<str>>,
}

impl ForLoop {
Expand Down Expand Up @@ -79,6 +79,10 @@ impl ForLoop {
write!(f, "}}")
}

pub fn label(&self) -> Option<&str> {
self.label.as_ref().map(Box::as_ref)
}

pub fn set_label(&mut self, label: Box<str>) {
self.label = Some(label);
}
Expand Down Expand Up @@ -160,6 +164,7 @@ impl InnerForLoop {
pub struct WhileLoop {
cond: Box<Node>,
expr: Box<Node>,
label: Option<Box<str>>,
}

impl WhileLoop {
Expand All @@ -171,6 +176,10 @@ impl WhileLoop {
&self.expr
}

pub fn label(&self) -> Option<&str> {
self.label.as_ref().map(Box::as_ref)
}

/// Creates a `WhileLoop` AST node.
pub fn new<C, B>(condition: C, body: B) -> Self
where
Expand All @@ -180,6 +189,7 @@ impl WhileLoop {
Self {
cond: Box::new(condition.into()),
expr: Box::new(body.into()),
label: None,
}
}

Expand Down Expand Up @@ -218,6 +228,7 @@ impl From<WhileLoop> for Node {
pub struct DoWhileLoop {
body: Box<Node>,
cond: Box<Node>,
label: Option<Box<str>>,
}

impl DoWhileLoop {
Expand All @@ -229,6 +240,10 @@ impl DoWhileLoop {
&self.cond
}

pub fn label(&self) -> Option<&str> {
self.label.as_ref().map(Box::as_ref)
}

/// Creates a `DoWhileLoop` AST node.
pub fn new<B, C>(body: B, condition: C) -> Self
where
Expand All @@ -238,6 +253,7 @@ impl DoWhileLoop {
Self {
body: Box::new(body.into()),
cond: Box::new(condition.into()),
label: None,
}
}

Expand Down

0 comments on commit 14d3d76

Please sign in to comment.