Skip to content

Commit

Permalink
Add missing ops to exec module
Browse files Browse the repository at this point in the history
* Node::Const(Const::Undefined)
* Node::ConditionalOp
* Node::Continue
  • Loading branch information
jarredholman committed Aug 14, 2020
1 parent b8d0b3c commit d5c1440
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 9 deletions.
6 changes: 5 additions & 1 deletion boa/src/exec/block/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ impl Executable for Block {
// Early break.
break;
}
_ => {
InterpreterState::Continue(_label) => {
// TODO, continue to a label
break;
}
InterpreterState::Executing => {
// Continue execution
}
}
Expand Down
9 changes: 9 additions & 0 deletions boa/src/exec/break_node/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use super::{Executable, Interpreter, InterpreterState};
use crate::{
builtins::value::{ResultValue, Value},
syntax::ast::node::Break,
syntax::ast::node::Continue,
};

#[cfg(test)]
Expand All @@ -14,3 +15,11 @@ impl Executable for Break {
Ok(Value::undefined())
}
}

impl Executable for Continue {
fn run(&self, interpreter: &mut Interpreter) -> ResultValue {
interpreter.set_current_state(InterpreterState::Continue(self.label().map(String::from)));

Ok(Value::undefined())
}
}
38 changes: 37 additions & 1 deletion boa/src/exec/break_node/tests.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::{Interpreter, InterpreterState};
use crate::{exec::Executable, syntax::ast::node::Break, Realm};
use crate::{exec, exec::Executable, syntax::ast::node::Break, Realm};

#[test]
fn check_post_state() {
Expand All @@ -15,3 +15,39 @@ fn check_post_state() {
&InterpreterState::Break(Some("label".to_string()))
);
}

#[test]
fn break_out_of_inner_loop() {
let scenario = r#"
var a = 0, b = 0;
for (let i = 0; i < 2; i++) {
a++;
for (let j = 0; j < 10; j++) {
b++;
if (j == 3)
break;
}
a++;
}
[a, b]
"#;
assert_eq!(&exec(scenario), "[ 4, 8 ]");
}

#[test]
fn continue_inner_loop() {
let scenario = r#"
var a = 0, b = 0;
for (let i = 0; i < 2; i++) {
a++;
for (let j = 0; j < 10; j++) {
if (j < 3)
continue;
b++;
}
a++;
}
[a, b]
"#;
assert_eq!(&exec(scenario), "[ 4, 14 ]");
}
11 changes: 11 additions & 0 deletions boa/src/exec/conditional/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use super::{Executable, Interpreter};
use crate::{
builtins::{ResultValue, Value},
syntax::ast::node::ConditionalOp,
syntax::ast::node::If,
};
use std::borrow::Borrow;
Expand All @@ -16,3 +17,13 @@ impl Executable for If {
})
}
}

impl Executable for ConditionalOp {
fn run(&self, interpreter: &mut Interpreter) -> ResultValue {
Ok(if self.cond().run(interpreter)?.borrow().to_boolean() {
self.if_true().run(interpreter)?
} else {
self.if_false().run(interpreter)?
})
}
}
28 changes: 24 additions & 4 deletions boa/src/exec/iteration/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,15 @@ impl Executable for ForLoop {
interpreter.set_current_state(InterpreterState::Executing);
break;
}
InterpreterState::Continue(_label) => {
// TODO continue to label.
interpreter.set_current_state(InterpreterState::Executing);
// after breaking out of the block, continue execution of the loop
}
InterpreterState::Return => {
return Ok(result);
}
_ => {
InterpreterState::Executing => {
// Continue execution.
}
}
Expand Down Expand Up @@ -76,10 +81,15 @@ impl Executable for WhileLoop {
interpreter.set_current_state(InterpreterState::Executing);
break;
}
InterpreterState::Continue(_label) => {
// TODO continue to label.
interpreter.set_current_state(InterpreterState::Executing);
// after breaking out of the block, continue execution of the loop
}
InterpreterState::Return => {
return Ok(result);
}
_ => {
InterpreterState::Executing => {
// Continue execution.
}
}
Expand All @@ -99,10 +109,15 @@ impl Executable for DoWhileLoop {
interpreter.set_current_state(InterpreterState::Executing);
return Ok(result);
}
InterpreterState::Continue(_label) => {
// TODO continue to label;
interpreter.set_current_state(InterpreterState::Executing);
// after breaking out of the block, continue execution of the loop
}
InterpreterState::Return => {
return Ok(result);
}
_ => {
InterpreterState::Executing => {
// Continue execution.
}
}
Expand All @@ -117,10 +132,15 @@ impl Executable for DoWhileLoop {
interpreter.set_current_state(InterpreterState::Executing);
break;
}
InterpreterState::Continue(_label) => {
// TODO continue to label.
interpreter.set_current_state(InterpreterState::Executing);
// after breaking out of the block, continue execution of the loop
}
InterpreterState::Return => {
return Ok(result);
}
_ => {
InterpreterState::Executing => {
// Continue execution.
}
}
Expand Down
5 changes: 4 additions & 1 deletion boa/src/exec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ pub(crate) enum InterpreterState {
Executing,
Return,
Break(Option<String>),
Continue(Option<String>),
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum PreferredType {
Expand Down Expand Up @@ -681,6 +682,7 @@ impl Executable for Node {
fn run(&self, interpreter: &mut Interpreter) -> ResultValue {
let _timer = BoaProfiler::global().start_event("Executable", "exec");
match *self {
Node::Const(Const::Undefined) => Ok(Value::undefined()),
Node::Const(Const::Null) => Ok(Value::null()),
Node::Const(Const::Num(num)) => Ok(Value::rational(num)),
Node::Const(Const::Int(num)) => Ok(Value::integer(num)),
Expand All @@ -699,6 +701,7 @@ impl Executable for Node {
Node::DoWhileLoop(ref do_while) => do_while.run(interpreter),
Node::ForLoop(ref for_loop) => for_loop.run(interpreter),
Node::If(ref if_smt) => if_smt.run(interpreter),
Node::ConditionalOp(ref op) => op.run(interpreter),
Node::Switch(ref switch) => switch.run(interpreter),
Node::Object(ref obj) => obj.run(interpreter),
Node::ArrayDecl(ref arr) => arr.run(interpreter),
Expand All @@ -723,7 +726,7 @@ impl Executable for Node {
}
Node::Try(ref try_node) => try_node.run(interpreter),
Node::Break(ref break_node) => break_node.run(interpreter),
ref i => unimplemented!("{:?}", i),
Node::Continue(ref continue_node) => continue_node.run(interpreter),
}
}
}
6 changes: 5 additions & 1 deletion boa/src/exec/statement_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,11 @@ impl Executable for StatementList {
// Early break.
break;
}
_ => {
InterpreterState::Continue(_label) => {
// TODO, continue to a label.
break;
}
InterpreterState::Executing => {
// Continue execution
}
}
Expand Down
7 changes: 6 additions & 1 deletion boa/src/exec/switch/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,16 @@ impl Executable for Switch {
return Ok(result);
}
InterpreterState::Break(_label) => {
// TODO, break to a label.
// Break statement encountered so therefore end switch statement.
interpreter.set_current_state(InterpreterState::Executing);
break;
}
_ => {
InterpreterState::Continue(_label) => {
// TODO, continue to a label.
break;
}
InterpreterState::Executing => {
// Continuing execution / falling through to next case statement(s).
fall_through = true;
}
Expand Down

0 comments on commit d5c1440

Please sign in to comment.