Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Divide the run() function #422

Merged
merged 52 commits into from
Jun 6, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
c4fb91c
Merge pull request #4 from boa-dev/master
May 26, 2020
7ffc0c8
Adding Object Execution trait
May 26, 2020
57fa83d
Moved Object AST related parts into their own files
May 26, 2020
88a5ba3
Rustfmt
May 26, 2020
e51d8be
Make clippy happier
May 26, 2020
4c058c0
Starting to reimplement switch
May 26, 2020
744dee8
Remove extra newline
May 27, 2020
dc6b371
Replaced AST object new with From
May 27, 2020
8995fb2
Merge branch 'divide_run' of https://github.com/Lan2u/boa into divide…
May 27, 2020
d91ac61
Rustfmt
May 27, 2020
274910a
Merge pull request #5 from Lan2u/divide_run
May 27, 2020
4b0bed1
Starting to move switch AST into seperate files
May 27, 2020
8ff5590
Seperated switch AST node into seperate files
May 27, 2020
d0e82b5
Merge: Seperated switch AST node into seperate files
May 27, 2020
6851036
Started moving GetConstField related parts into own file
May 27, 2020
153f0b1
Correcting various references to Node::GetConstField to use new signa…
May 28, 2020
c0404f3
Extracted GetField code
May 29, 2020
e33a1a5
Fmt, clippy
May 29, 2020
9969748
Merge pull request #7 from Lan2u/divide_run_get_const_field
May 29, 2020
4937dc3
WhileLoop
May 29, 2020
ad07527
Impl fmt::display for WhileLoop
May 29, 2020
be04070
DoWhileLoop struct created
May 29, 2020
58f83f7
Seperated out do while loop
May 29, 2020
26fdf9d
Merge pull request #8 from Lan2u/divide_run_dowhile
May 30, 2020
13daec1
Created Return struct
May 30, 2020
2116152
Seperated Return statement out
May 30, 2020
cc7261a
Seperated IF statement out
May 30, 2020
c858a79
Removed unused imports, fmt
May 30, 2020
b5ca4b8
Created Break struct
May 30, 2020
94dcacc
Break impl
May 31, 2020
5c90059
Conditional Op impl
May 31, 2020
4e267c3
Continue impl
May 31, 2020
e3882d7
Throw impl
May 31, 2020
bb33532
Spread impl
May 31, 2020
022b48e
Object initalizer now returns Object in result rather than Node
May 31, 2020
57cace0
Update boa/src/exec/throw/mod.rs
Jun 1, 2020
e96f79c
Update boa/src/syntax/ast/node/break_node.rs
Jun 1, 2020
44da6aa
Update boa/src/syntax/ast/node/conditional.rs
Jun 1, 2020
43a046f
Update boa/src/syntax/ast/node/iteration.rs
Jun 1, 2020
7604c0f
Made Switch::new() more generic, added TODO for break in Switch::run()
Jun 1, 2020
ba5a63b
Merge branch 'divide_run' of https://github.com/Lan2u/boa into divide…
Jun 1, 2020
b7a641b
Making parse functions return the actual result of the parse rather t…
Jun 1, 2020
ea45b26
Reworked switch::new, added Case struct
Jun 1, 2020
7733da2
Switch::run() refractored, rustfmt
Jun 1, 2020
cf75799
Merge branch 'master' into divide_run
Jun 1, 2020
b73182e
Update boa/src/syntax/ast/node/return_smt.rs
Jun 1, 2020
e95b6e4
Update boa/src/syntax/ast/node/switch.rs
Jun 1, 2020
e6072c8
Update boa/src/syntax/ast/node/return_smt.rs
Jun 1, 2020
ad91f42
Small fixes to return_smt
Jun 1, 2020
b0293ac
Merge branch 'master' into divide_run
Jun 3, 2020
2234ed6
Merge branch 'master' into divide_run
Jun 5, 2020
e50a741
Finished merge
Jun 5, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions boa/src/exec/conditional/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use super::{Executable, Interpreter};
use crate::{
builtins::{ResultValue, Value},
syntax::ast::node::If,
};
use std::borrow::Borrow;

impl Executable for If {
fn run(&self, interpreter: &mut Interpreter) -> ResultValue {
Ok(if self.cond().run(interpreter)?.borrow().is_true() {
self.body().run(interpreter)?
} else {
match self.else_node() {
Some(ref else_e) => else_e.run(interpreter)?,
None => Value::undefined(),
}
})
}
}
14 changes: 7 additions & 7 deletions boa/src/exec/expression/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,19 @@ impl Executable for Call {
fn run(&self, interpreter: &mut Interpreter) -> ResultValue {
let _timer = BoaProfiler::global().start_event("Call", "exec");
let (mut this, func) = match self.expr() {
Node::GetConstField(ref obj, ref field) => {
let mut obj = obj.run(interpreter)?;
Node::GetConstField(ref get_const_field) => {
let mut obj = get_const_field.obj().run(interpreter)?;
if obj.get_type() != "object" || obj.get_type() != "symbol" {
obj = interpreter
.to_object(&obj)
.expect("failed to convert to object");
}
(obj.clone(), obj.get_field(field))
(obj.clone(), obj.get_field(get_const_field.field()))
}
Node::GetField(ref obj, ref field) => {
let obj = obj.run(interpreter)?;
let field = field.run(interpreter)?;
(obj.clone(), obj.get_field(field))
Node::GetField(ref get_field) => {
let obj = get_field.obj().run(interpreter)?;
let field = get_field.field().run(interpreter)?;
(obj.clone(), obj.get_field(field.to_string()))
}
_ => (
interpreter.realm().global_obj.clone(),
Expand Down
27 changes: 27 additions & 0 deletions boa/src/exec/field/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
use super::{Executable, Interpreter};
use crate::{
builtins::value::ResultValue,
syntax::ast::node::{GetConstField, GetField},
};

impl Executable for GetConstField {
fn run(&self, interpreter: &mut Interpreter) -> ResultValue {
let mut obj = self.obj().run(interpreter)?;
if obj.get_type() != "object" || obj.get_type() != "symbol" {
obj = interpreter
.to_object(&obj)
.expect("failed to convert to object");
}

Ok(obj.get_field(self.field()))
}
}

impl Executable for GetField {
fn run(&self, interpreter: &mut Interpreter) -> ResultValue {
let obj = self.obj().run(interpreter)?;
let field = self.field().run(interpreter)?;

Ok(obj.get_field(field.to_string()))
}
}
23 changes: 22 additions & 1 deletion boa/src/exec/iteration/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ use super::{Executable, Interpreter};
use crate::{
builtins::value::{ResultValue, Value},
environment::lexical_environment::new_declarative_environment,
syntax::ast::node::ForLoop,
syntax::ast::node::{DoWhileLoop, ForLoop, WhileLoop},
BoaProfiler,
};
use std::borrow::Borrow;

impl Executable for ForLoop {
fn run(&self, interpreter: &mut Interpreter) -> ResultValue {
Expand Down Expand Up @@ -42,3 +43,23 @@ impl Executable for ForLoop {
Ok(Value::undefined())
}
}

impl Executable for WhileLoop {
fn run(&self, interpreter: &mut Interpreter) -> ResultValue {
let mut result = Value::undefined();
while self.cond().run(interpreter)?.borrow().is_true() {
result = self.expr().run(interpreter)?;
}
Ok(result)
}
}

impl Executable for DoWhileLoop {
fn run(&self, interpreter: &mut Interpreter) -> ResultValue {
let mut result = self.body().run(interpreter)?;
while self.cond().run(interpreter)?.borrow().is_true() {
result = self.body().run(interpreter)?;
}
Ok(result)
}
}
140 changes: 27 additions & 113 deletions boa/src/exec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,22 @@

mod array;
mod block;
mod conditional;
mod declaration;
mod exception;
mod expression;
mod field;
mod iteration;
mod object;
mod operator;
mod return_smt;
mod spread;
mod statement_list;
mod try_node;

mod switch;
#[cfg(test)]
mod tests;
mod throw;
mod try_node;

use crate::{
builtins::{
Expand All @@ -27,7 +33,7 @@ use crate::{
realm::Realm,
syntax::ast::{
constant::Const,
node::{FormalParameter, MethodDefinitionKind, Node, PropertyDefinition, StatementList},
node::{FormalParameter, Node, StatementList},
},
BoaProfiler,
};
Expand Down Expand Up @@ -352,10 +358,14 @@ impl Interpreter {
.set_mutable_binding(name.as_ref(), value.clone(), true);
Ok(value)
}
Node::GetConstField(ref obj, ref field) => Ok(obj.run(self)?.set_field(field, value)),
Node::GetField(ref obj, ref field) => {
Ok(obj.run(self)?.set_field(field.run(self)?, value))
}
Node::GetConstField(ref get_const_field_node) => Ok(get_const_field_node
.obj()
.run(self)?
.set_field(get_const_field_node.field(), value)),
Node::GetField(ref get_field) => Ok(get_field
.obj()
.run(self)?
.set_field(get_field.field().run(self)?, value)),
_ => panic!("TypeError: invalid assignment to {}", node),
}
}
Expand Down Expand Up @@ -383,100 +393,15 @@ impl Executable for Node {
.get_binding_value(name.as_ref());
Ok(val)
}
Node::GetConstField(ref obj, ref field) => {
let val_obj = obj.run(interpreter)?;
Ok(val_obj.borrow().get_field(field))
}
Node::GetField(ref obj, ref field) => {
let val_obj = obj.run(interpreter)?;
let val_field = field.run(interpreter)?;
Ok(val_obj.borrow().get_field(val_field.borrow().to_string()))
}
Node::GetConstField(ref get_const_field_node) => get_const_field_node.run(interpreter),
Node::GetField(ref get_field) => get_field.run(interpreter),
Node::Call(ref expr) => expr.run(interpreter),
Node::WhileLoop(ref cond, ref expr) => {
let mut result = Value::undefined();
while cond.run(interpreter)?.borrow().is_true() {
result = expr.run(interpreter)?;
}
Ok(result)
}
Node::DoWhileLoop(ref body, ref cond) => {
let mut result = body.run(interpreter)?;
while cond.run(interpreter)?.borrow().is_true() {
result = body.run(interpreter)?;
}
Ok(result)
}
Node::WhileLoop(ref while_loop) => while_loop.run(interpreter),
Node::DoWhileLoop(ref do_while) => do_while.run(interpreter),
Node::ForLoop(ref for_loop) => for_loop.run(interpreter),
Node::If(ref cond, ref expr, None) => {
Ok(if cond.run(interpreter)?.borrow().is_true() {
expr.run(interpreter)?
} else {
Value::undefined()
})
}
Node::If(ref cond, ref expr, Some(ref else_e)) => {
Ok(if cond.run(interpreter)?.borrow().is_true() {
expr.run(interpreter)?
} else {
else_e.run(interpreter)?
})
}
Node::Switch(ref val_e, ref vals, ref default) => {
let val = val_e.run(interpreter)?;
let mut result = Value::null();
let mut matched = false;
for tup in vals.iter() {
let cond = &tup.0;
let block = &tup.1;
if val.strict_equals(&cond.run(interpreter)?) {
matched = true;
let last_expr = block.last().expect("Block has no expressions");
for expr in block.iter() {
let e_result = expr.run(interpreter)?;
if expr == last_expr {
result = e_result;
}
}
}
}
if !matched {
if let Some(default) = default {
result = default.run(interpreter)?;
}
}
Ok(result)
}
Node::Object(ref properties) => {
let global_val = &interpreter
.realm()
.environment
.get_global_object()
.expect("Could not get the global object");
let obj = Value::new_object(Some(global_val));

// TODO: Implement the rest of the property types.
for property in properties.iter() {
match property {
PropertyDefinition::Property(key, value) => {
obj.borrow()
.set_field(&key.clone(), value.run(interpreter)?);
}
PropertyDefinition::MethodDefinition(kind, name, func) => {
if let MethodDefinitionKind::Ordinary = kind {
obj.borrow()
.set_field(&name.clone(), func.run(interpreter)?);
} else {
// TODO: Implement other types of MethodDefinitionKinds.
unimplemented!("other types of property method definitions.");
}
}
i => unimplemented!("{:?} type of property", i),
}
}

Ok(obj)
}
Node::If(ref if_smt) => if_smt.run(interpreter),
Node::Switch(ref switch) => switch.run(interpreter),
Node::Object(ref obj) => obj.run(interpreter),
Node::ArrayDecl(ref arr) => arr.run(interpreter),
// <https://tc39.es/ecma262/#sec-createdynamicfunction>
Node::FunctionDecl(ref decl) => decl.run(interpreter),
Expand All @@ -486,24 +411,13 @@ impl Executable for Node {
Node::BinOp(ref op) => op.run(interpreter),
Node::UnaryOp(ref op) => op.run(interpreter),
Node::New(ref call) => call.run(interpreter),
Node::Return(ref ret) => {
let result = match *ret {
Some(ref v) => v.run(interpreter),
None => Ok(Value::undefined()),
};
// Set flag for return
interpreter.is_return = true;
result
}
Node::Throw(ref ex) => Err(ex.run(interpreter)?),
Node::Return(ref ret) => ret.run(interpreter),
Node::Throw(ref throw) => throw.run(interpreter),
Node::Assign(ref op) => op.run(interpreter),
Node::VarDeclList(ref decl) => decl.run(interpreter),
Node::LetDeclList(ref decl) => decl.run(interpreter),
Node::ConstDeclList(ref decl) => decl.run(interpreter),
Node::Spread(ref node) => {
// TODO: for now we can do nothing but return the value as-is
node.run(interpreter)
}
Node::Spread(ref spread) => spread.run(interpreter),
Node::This => {
// Will either return `this` binding or undefined
Ok(interpreter.realm().environment.get_this_binding())
Expand Down
43 changes: 43 additions & 0 deletions boa/src/exec/object/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//! Object execution.

use super::{Executable, Interpreter};
use crate::{
builtins::value::{ResultValue, Value},
syntax::ast::node::MethodDefinitionKind,
syntax::ast::node::{Object, PropertyDefinition},
};

use std::borrow::Borrow;

impl Executable for Object {
fn run(&self, interpreter: &mut Interpreter) -> ResultValue {
let global_val = &interpreter
.realm()
.environment
.get_global_object()
.expect("Could not get the global object");
let obj = Value::new_object(Some(global_val));

// TODO: Implement the rest of the property types.
for property in self.properties().iter() {
match property {
PropertyDefinition::Property(key, value) => {
obj.borrow()
.set_field(&key.clone(), value.run(interpreter)?);
}
PropertyDefinition::MethodDefinition(kind, name, func) => {
if let MethodDefinitionKind::Ordinary = kind {
obj.borrow()
.set_field(&name.clone(), func.run(interpreter)?);
} else {
// TODO: Implement other types of MethodDefinitionKinds.
unimplemented!("other types of property method definitions.");
}
}
i => unimplemented!("{:?} type of property", i),
}
}

Ok(obj)
}
}
Loading