From 5560f996c02693bfe803615ff7e50e3d3dd45186 Mon Sep 17 00:00:00 2001 From: Jarred Holman Date: Sat, 15 Aug 2020 03:48:33 +0930 Subject: [PATCH] Add missing ops to exec module * Node::Const(Const::Undefined) * Node::ConditionalOp * Node::Continue --- boa/src/exec/block/mod.rs | 6 ++++- boa/src/exec/break_node/mod.rs | 9 ++++++++ boa/src/exec/break_node/tests.rs | 38 +++++++++++++++++++++++++++++++- boa/src/exec/conditional/mod.rs | 11 +++++++++ boa/src/exec/iteration/mod.rs | 28 +++++++++++++++++++---- boa/src/exec/mod.rs | 5 ++++- boa/src/exec/statement_list.rs | 6 ++++- boa/src/exec/switch/mod.rs | 7 +++++- 8 files changed, 101 insertions(+), 9 deletions(-) diff --git a/boa/src/exec/block/mod.rs b/boa/src/exec/block/mod.rs index c642caa4321..04bee20ed2f 100644 --- a/boa/src/exec/block/mod.rs +++ b/boa/src/exec/block/mod.rs @@ -33,7 +33,11 @@ impl Executable for Block { // Early break. break; } - _ => { + InterpreterState::Continue(_label) => { + // TODO, continue to a label + break; + } + InterpreterState::Executing => { // Continue execution } } diff --git a/boa/src/exec/break_node/mod.rs b/boa/src/exec/break_node/mod.rs index 11fdd4d5a6c..c9a5039b20a 100644 --- a/boa/src/exec/break_node/mod.rs +++ b/boa/src/exec/break_node/mod.rs @@ -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)] @@ -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()) + } +} diff --git a/boa/src/exec/break_node/tests.rs b/boa/src/exec/break_node/tests.rs index 2cbb2db0324..27a2ef38818 100644 --- a/boa/src/exec/break_node/tests.rs +++ b/boa/src/exec/break_node/tests.rs @@ -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() { @@ -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 ]"); +} diff --git a/boa/src/exec/conditional/mod.rs b/boa/src/exec/conditional/mod.rs index 7279fd87925..dea08bc9edd 100644 --- a/boa/src/exec/conditional/mod.rs +++ b/boa/src/exec/conditional/mod.rs @@ -2,6 +2,7 @@ use super::{Executable, Interpreter}; use crate::{ builtins::{ResultValue, Value}, syntax::ast::node::If, + syntax::ast::node::ConditionalOp, }; use std::borrow::Borrow; @@ -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)? + }) + } +} diff --git a/boa/src/exec/iteration/mod.rs b/boa/src/exec/iteration/mod.rs index 8835207ec9f..21aa8cdefb6 100644 --- a/boa/src/exec/iteration/mod.rs +++ b/boa/src/exec/iteration/mod.rs @@ -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. } } @@ -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. } } @@ -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. } } @@ -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. } } diff --git a/boa/src/exec/mod.rs b/boa/src/exec/mod.rs index c33117cb748..0829eb8c01a 100644 --- a/boa/src/exec/mod.rs +++ b/boa/src/exec/mod.rs @@ -53,6 +53,7 @@ pub(crate) enum InterpreterState { Executing, Return, Break(Option), + Continue(Option), } #[derive(Clone, Copy, Debug, PartialEq)] pub enum PreferredType { @@ -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)), @@ -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), @@ -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), } } } diff --git a/boa/src/exec/statement_list.rs b/boa/src/exec/statement_list.rs index 56862034fee..193d3a1f49e 100644 --- a/boa/src/exec/statement_list.rs +++ b/boa/src/exec/statement_list.rs @@ -26,7 +26,11 @@ impl Executable for StatementList { // Early break. break; } - _ => { + InterpreterState::Continue(_label) => { + // TODO, continue to a label. + break; + } + InterpreterState::Executing => { // Continue execution } } diff --git a/boa/src/exec/switch/mod.rs b/boa/src/exec/switch/mod.rs index ea202260414..e777e8d09ff 100644 --- a/boa/src/exec/switch/mod.rs +++ b/boa/src/exec/switch/mod.rs @@ -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; }