Skip to content

Commit

Permalink
extract unary to file
Browse files Browse the repository at this point in the history
  • Loading branch information
e-codes-stuff committed Nov 15, 2022
1 parent d56a342 commit 7327cfe
Show file tree
Hide file tree
Showing 2 changed files with 151 additions and 93 deletions.
133 changes: 40 additions & 93 deletions boa_engine/src/bytecompiler/expression/mod.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,23 @@
use crate::{
bytecompiler::{ByteCompiler, Literal},
vm::Opcode,
JsNativeError, JsResult,
JsResult,
};

use boa_ast::{
expression::{
literal::Literal as AstLiteral,
operator::{unary::UnaryOp, Unary},
},
Expression,
use boa_ast::expression::{
literal::{Literal as AstLiteral, TemplateElement, TemplateLiteral},
operator::Conditional,
};

use super::Access;

mod assign;
mod binary;
mod object_literal;
mod unary;

pub(crate) use assign::compile_assign;
pub(crate) use binary::compile_binary;
pub(crate) use object_literal::compile_object_literal;
pub(crate) use unary::compile_unary;

pub(crate) fn compile_literal<'b>(
byte_compiler: &mut ByteCompiler<'b>,
Expand Down Expand Up @@ -50,100 +47,50 @@ pub(crate) fn compile_literal<'b>(
}
}

pub(crate) fn compile_unary<'b>(
pub(crate) fn compile_conditional<'b>(
byte_compiler: &mut ByteCompiler<'b>,
unary: &Unary,
op: &Conditional,
use_expr: bool,
) -> JsResult<()> {
let opcode = match unary.op() {
UnaryOp::IncrementPre => {
// TODO: promote to an early error.
let access = Access::from_expression(unary.target())
.ok_or_else(|| JsNativeError::syntax().with_message("Invalid increment operand"))?;

byte_compiler.access_set(access, true, |compiler, _| {
compiler.compile_expr(unary.target(), true)?;
compiler.emit(Opcode::Inc, &[]);
Ok(())
})?;

None
}
UnaryOp::DecrementPre => {
// TODO: promote to an early error.
let access = Access::from_expression(unary.target())
.ok_or_else(|| JsNativeError::syntax().with_message("Invalid decrement operand"))?;

byte_compiler.access_set(access, true, |compiler, _| {
compiler.compile_expr(unary.target(), true)?;
compiler.emit(Opcode::Dec, &[]);
Ok(())
})?;
None
}
UnaryOp::IncrementPost => {
// TODO: promote to an early error.
let access = Access::from_expression(unary.target())
.ok_or_else(|| JsNativeError::syntax().with_message("Invalid increment operand"))?;
byte_compiler.compile_expr(op.condition(), true)?;
let jelse = byte_compiler.jump_if_false();
byte_compiler.compile_expr(op.if_true(), true)?;
let exit = byte_compiler.jump();
byte_compiler.patch_jump(jelse);
byte_compiler.compile_expr(op.if_false(), true)?;
byte_compiler.patch_jump(exit);

byte_compiler.access_set(access, false, |compiler, level| {
compiler.compile_expr(unary.target(), true)?;
compiler.emit(Opcode::IncPost, &[]);
compiler.emit_opcode(Opcode::RotateRight);
compiler.emit_u8(level + 2);
Ok(())
})?;

None
}
UnaryOp::DecrementPost => {
// TODO: promote to an early error.
let access = Access::from_expression(unary.target())
.ok_or_else(|| JsNativeError::syntax().with_message("Invalid decrement operand"))?;
if !use_expr {
byte_compiler.emit(Opcode::Pop, &[]);
};

byte_compiler.access_set(access, false, |compiler, level| {
compiler.compile_expr(unary.target(), true)?;
compiler.emit(Opcode::DecPost, &[]);
compiler.emit_opcode(Opcode::RotateRight);
compiler.emit_u8(level + 2);
Ok(())
})?;
Ok(())
}

None
}
UnaryOp::Delete => {
if let Some(access) = Access::from_expression(unary.target()) {
byte_compiler.access_delete(access)?;
} else {
byte_compiler.compile_expr(unary.target(), false)?;
byte_compiler.emit(Opcode::PushTrue, &[]);
}
None
}
UnaryOp::Minus => Some(Opcode::Neg),
UnaryOp::Plus => Some(Opcode::Pos),
UnaryOp::Not => Some(Opcode::LogicalNot),
UnaryOp::Tilde => Some(Opcode::BitNot),
UnaryOp::TypeOf => {
match &unary.target() {
Expression::Identifier(identifier) => {
let binding = byte_compiler.context.get_binding_value(*identifier);
let index = byte_compiler.get_or_insert_binding(binding);
byte_compiler.emit(Opcode::GetNameOrUndefined, &[index]);
}
expr => byte_compiler.compile_expr(expr, true)?,
pub(crate) fn compile_template_literal<'b>(
byte_compiler: &mut ByteCompiler<'b>,
template_literal: &TemplateLiteral,
use_expr: bool,
) -> JsResult<()> {
for element in template_literal.elements() {
match element {
TemplateElement::String(s) => byte_compiler.emit_push_literal(Literal::String(
byte_compiler
.interner()
.resolve_expect(*s)
.into_common(false),
)),
TemplateElement::Expr(expr) => {
byte_compiler.compile_expr(expr, true)?;
}
byte_compiler.emit_opcode(Opcode::TypeOf);
None
}
UnaryOp::Void => Some(Opcode::Void),
};

if let Some(opcode) = opcode {
byte_compiler.compile_expr(unary.target(), true)?;
byte_compiler.emit(opcode, &[]);
}

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

if !use_expr {
byte_compiler.emit(Opcode::Pop, &[]);
}
Expand Down
111 changes: 111 additions & 0 deletions boa_engine/src/bytecompiler/expression/unary.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
use boa_ast::{
expression::operator::{unary::UnaryOp, Unary},
Expression,
};

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

pub(crate) fn compile_unary<'b>(
byte_compiler: &mut ByteCompiler<'b>,
unary: &Unary,
use_expr: bool,
) -> JsResult<()> {
let opcode = match unary.op() {
UnaryOp::IncrementPre => {
// TODO: promote to an early error.
let access = Access::from_expression(unary.target())
.ok_or_else(|| JsNativeError::syntax().with_message("Invalid increment operand"))?;

byte_compiler.access_set(access, true, |compiler, _| {
compiler.compile_expr(unary.target(), true)?;
compiler.emit(Opcode::Inc, &[]);
Ok(())
})?;

None
}
UnaryOp::DecrementPre => {
// TODO: promote to an early error.
let access = Access::from_expression(unary.target())
.ok_or_else(|| JsNativeError::syntax().with_message("Invalid decrement operand"))?;

byte_compiler.access_set(access, true, |compiler, _| {
compiler.compile_expr(unary.target(), true)?;
compiler.emit(Opcode::Dec, &[]);
Ok(())
})?;
None
}
UnaryOp::IncrementPost => {
// TODO: promote to an early error.
let access = Access::from_expression(unary.target())
.ok_or_else(|| JsNativeError::syntax().with_message("Invalid increment operand"))?;

byte_compiler.access_set(access, false, |compiler, level| {
compiler.compile_expr(unary.target(), true)?;
compiler.emit(Opcode::IncPost, &[]);
compiler.emit_opcode(Opcode::RotateRight);
compiler.emit_u8(level + 2);
Ok(())
})?;

None
}
UnaryOp::DecrementPost => {
// TODO: promote to an early error.
let access = Access::from_expression(unary.target())
.ok_or_else(|| JsNativeError::syntax().with_message("Invalid decrement operand"))?;

byte_compiler.access_set(access, false, |compiler, level| {
compiler.compile_expr(unary.target(), true)?;
compiler.emit(Opcode::DecPost, &[]);
compiler.emit_opcode(Opcode::RotateRight);
compiler.emit_u8(level + 2);
Ok(())
})?;

None
}
UnaryOp::Delete => {
if let Some(access) = Access::from_expression(unary.target()) {
byte_compiler.access_delete(access)?;
} else {
byte_compiler.compile_expr(unary.target(), false)?;
byte_compiler.emit(Opcode::PushTrue, &[]);
}
None
}
UnaryOp::Minus => Some(Opcode::Neg),
UnaryOp::Plus => Some(Opcode::Pos),
UnaryOp::Not => Some(Opcode::LogicalNot),
UnaryOp::Tilde => Some(Opcode::BitNot),
UnaryOp::TypeOf => {
match &unary.target() {
Expression::Identifier(identifier) => {
let binding = byte_compiler.context.get_binding_value(*identifier);
let index = byte_compiler.get_or_insert_binding(binding);
byte_compiler.emit(Opcode::GetNameOrUndefined, &[index]);
}
expr => byte_compiler.compile_expr(expr, true)?,
}
byte_compiler.emit_opcode(Opcode::TypeOf);
None
}
UnaryOp::Void => Some(Opcode::Void),
};

if let Some(opcode) = opcode {
byte_compiler.compile_expr(unary.target(), true)?;
byte_compiler.emit(opcode, &[]);
}

if !use_expr {
byte_compiler.emit(Opcode::Pop, &[]);
}

Ok(())
}

0 comments on commit 7327cfe

Please sign in to comment.