Skip to content

Commit

Permalink
extract Statement cases to module
Browse files Browse the repository at this point in the history
  • Loading branch information
e-codes-stuff committed Nov 15, 2022
1 parent 7327cfe commit 5e524f5
Show file tree
Hide file tree
Showing 3 changed files with 202 additions and 184 deletions.
191 changes: 7 additions & 184 deletions boa_engine/src/bytecompiler/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
mod expression;
mod function;
mod statement;

use crate::{
environments::{BindingLocator, CompileTimeEnvironment},
Expand All @@ -10,7 +11,6 @@ use boa_ast::{
declaration::{Binding, LexicalDeclaration, VarDeclaration},
expression::{
access::{PropertyAccess, PropertyAccessField},
literal::TemplateElement,
operator::assign::AssignTarget,
Call, Identifier, New, Optional, OptionalOperationKind,
},
Expand Down Expand Up @@ -921,19 +921,7 @@ impl<'b> ByteCompiler<'b> {
Expression::PropertyAccess(access) => {
self.access_get(Access::Property { access }, use_expr)?;
}
Expression::Conditional(op) => {
self.compile_expr(op.condition(), true)?;
let jelse = self.jump_if_false();
self.compile_expr(op.if_true(), true)?;
let exit = self.jump();
self.patch_jump(jelse);
self.compile_expr(op.if_false(), true)?;
self.patch_jump(exit);

if !use_expr {
self.emit(Opcode::Pop, &[]);
}
}
Expression::Conditional(op) => expression::compile_conditional(self, op, use_expr)?,
Expression::ArrayLiteral(array) => {
self.emit_opcode(Opcode::PushNewArray);
self.emit_opcode(Opcode::PopOnReturnAdd);
Expand Down Expand Up @@ -982,25 +970,7 @@ impl<'b> ByteCompiler<'b> {
Expression::Call(call) => self.call(Callable::Call(call), use_expr)?,
Expression::New(new) => self.call(Callable::New(new), use_expr)?,
Expression::TemplateLiteral(template_literal) => {
for element in template_literal.elements() {
match element {
TemplateElement::String(s) => self.emit_push_literal(Literal::String(
self.interner().resolve_expect(*s).into_common(false),
)),
TemplateElement::Expr(expr) => {
self.compile_expr(expr, true)?;
}
}
}

self.emit(
Opcode::ConcatToString,
&[template_literal.elements().len() as u32],
);

if !use_expr {
self.emit(Opcode::Pop, &[]);
}
expression::compile_template_literal(self, template_literal, use_expr)?
}
Expression::Await(expr) => {
self.compile_expr(expr.target(), true)?;
Expand Down Expand Up @@ -1843,24 +1813,7 @@ impl<'b> ByteCompiler<'b> {
) -> JsResult<()> {
match node {
Statement::Var(var) => self.compile_var_decl(var)?,
Statement::If(node) => {
self.compile_expr(node.cond(), true)?;
let jelse = self.jump_if_false();

self.compile_stmt(node.body(), false, configurable_globals)?;

match node.else_node() {
None => {
self.patch_jump(jelse);
}
Some(else_body) => {
let exit = self.jump();
self.patch_jump(jelse);
self.compile_stmt(else_body, false, configurable_globals)?;
self.patch_jump(exit);
}
}
}
Statement::If(node) => statement::compile_if(self, node, configurable_globals)?,
Statement::ForLoop(for_loop) => {
self.compile_for_loop(for_loop, None, configurable_globals)?;
}
Expand All @@ -1879,140 +1832,10 @@ impl<'b> ByteCompiler<'b> {
Statement::Block(block) => {
self.compile_block(block, None, use_expr, configurable_globals)?;
}
Statement::Labelled(labelled) => match labelled.item() {
LabelledItem::Statement(stmt) => match stmt {
Statement::ForLoop(for_loop) => {
self.compile_for_loop(
for_loop,
Some(labelled.label()),
configurable_globals,
)?;
}
Statement::ForInLoop(for_in_loop) => {
self.compile_for_in_loop(
for_in_loop,
Some(labelled.label()),
configurable_globals,
)?;
}
Statement::ForOfLoop(for_of_loop) => {
self.compile_for_of_loop(
for_of_loop,
Some(labelled.label()),
configurable_globals,
)?;
}
Statement::WhileLoop(while_loop) => {
self.compile_while_loop(
while_loop,
Some(labelled.label()),
configurable_globals,
)?;
}
Statement::DoWhileLoop(do_while_loop) => {
self.compile_do_while_loop(
do_while_loop,
Some(labelled.label()),
configurable_globals,
)?;
}
Statement::Block(block) => {
self.compile_block(
block,
Some(labelled.label()),
use_expr,
configurable_globals,
)?;
}
stmt => self.compile_stmt(stmt, use_expr, configurable_globals)?,
},
LabelledItem::Function(f) => {
self.function(f.into(), NodeKind::Declaration, false)?;
}
},
Statement::Continue(node) => {
let next = self.next_opcode_location();
if let Some(info) = self
.jump_info
.last()
.filter(|info| info.kind == JumpControlInfoKind::Try)
{
let start_address = info.start_address;
let in_finally = if let Some(finally_start) = info.finally_start {
next > finally_start.index
} else {
false
};
let in_catch_no_finally = !info.has_finally && info.in_catch;

if in_finally {
self.emit_opcode(Opcode::PopIfThrown);
}
if in_finally || in_catch_no_finally {
self.emit_opcode(Opcode::CatchEnd2);
self.emit(Opcode::FinallySetJump, &[start_address]);
} else {
self.emit_opcode(Opcode::TryEnd);
self.emit(Opcode::FinallySetJump, &[start_address]);
}
let label = self.jump();
self.jump_info
.last_mut()
.expect("no jump information found")
.try_continues
.push(label);
} else {
let mut items = self
.jump_info
.iter()
.rev()
.filter(|info| info.kind == JumpControlInfoKind::Loop);
let address = if let Some(label_name) = node.label() {
let mut num_loops = 0;
let mut emit_for_of_in_exit = 0;
let mut address_info = None;
for info in items {
if info.label == node.label() {
address_info = Some(info);
break;
}
num_loops += 1;
if info.for_of_in_loop {
emit_for_of_in_exit += 1;
}
}
// TODO: promote to an early error.
let address = address_info
.ok_or_else(|| {
JsNativeError::syntax().with_message(format!(
"Cannot use the undeclared label '{}'",
self.context.interner().resolve_expect(label_name)
))
})?
.start_address;
for _ in 0..emit_for_of_in_exit {
self.emit_opcode(Opcode::Pop);
self.emit_opcode(Opcode::Pop);
self.emit_opcode(Opcode::Pop);
}
for _ in 0..num_loops {
self.emit_opcode(Opcode::LoopEnd);
}
address
} else {
items
.next()
// TODO: promote to an early error.
.ok_or_else(|| {
JsNativeError::syntax().with_message("continue must be inside loop")
})?
.start_address
};
self.emit_opcode(Opcode::LoopEnd);
self.emit_opcode(Opcode::LoopStart);
self.emit(Opcode::Jump, &[address]);
}
Statement::Labelled(labelled) => {
statement::compile_labeled(self, labelled, use_expr, configurable_globals)?
}
Statement::Continue(node) => statement::compile_continue(self, node)?,
Statement::Break(node) => {
let next = self.next_opcode_location();
if let Some(info) = self
Expand Down
97 changes: 97 additions & 0 deletions boa_engine/src/bytecompiler/statement/kontinue.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
use boa_ast::statement::Continue;

use crate::{
bytecompiler::{ByteCompiler, JumpControlInfoKind},
vm::Opcode,
JsNativeError, JsResult,
};

pub(crate) fn compile_continue<'b>(
byte_compiler: &mut ByteCompiler<'b>,
node: &Continue,
) -> JsResult<()> {
let next = byte_compiler.next_opcode_location();
if let Some(info) = byte_compiler
.jump_info
.last()
.filter(|info| info.kind == JumpControlInfoKind::Try)
{
let start_address = info.start_address;
let in_finally = if let Some(finally_start) = info.finally_start {
next > finally_start.index
} else {
false
};
let in_catch_no_finally = !info.has_finally && info.in_catch;

if in_finally {
byte_compiler.emit_opcode(Opcode::PopIfThrown);
}
if in_finally || in_catch_no_finally {
byte_compiler.emit_opcode(Opcode::CatchEnd2);
byte_compiler.emit(Opcode::FinallySetJump, &[start_address]);
} else {
byte_compiler.emit_opcode(Opcode::TryEnd);
byte_compiler.emit(Opcode::FinallySetJump, &[start_address]);
}
let label = byte_compiler.jump();
byte_compiler
.jump_info
.last_mut()
.expect("no jump information found")
.try_continues
.push(label);
} else {
let mut items = byte_compiler
.jump_info
.iter()
.rev()
.filter(|info| info.kind == JumpControlInfoKind::Loop);
let address = if let Some(label_name) = node.label() {
let mut num_loops = 0;
let mut emit_for_of_in_exit = 0;
let mut address_info = None;
for info in items {
if info.label == node.label() {
address_info = Some(info);
break;
}
num_loops += 1;
if info.for_of_in_loop {
emit_for_of_in_exit += 1;
}
}
// TODO: promote to an early error.
let address = address_info
.ok_or_else(|| {
JsNativeError::syntax().with_message(format!(
"Cannot use the undeclared label '{}'",
byte_compiler.context.interner().resolve_expect(label_name)
))
})?
.start_address;
for _ in 0..emit_for_of_in_exit {
byte_compiler.emit_opcode(Opcode::Pop);
byte_compiler.emit_opcode(Opcode::Pop);
byte_compiler.emit_opcode(Opcode::Pop);
}
for _ in 0..num_loops {
byte_compiler.emit_opcode(Opcode::LoopEnd);
}
address
} else {
items
.next()
// TODO: promote to an early error.
.ok_or_else(|| {
JsNativeError::syntax().with_message("continue must be inside loop")
})?
.start_address
};
byte_compiler.emit_opcode(Opcode::LoopEnd);
byte_compiler.emit_opcode(Opcode::LoopStart);
byte_compiler.emit(Opcode::Jump, &[address]);
}

Ok(())
}
Loading

0 comments on commit 5e524f5

Please sign in to comment.