diff --git a/crates/js/src/bytecode/builder.rs b/crates/js/src/bytecode/builder.rs deleted file mode 100644 index aa96e3fc..00000000 --- a/crates/js/src/bytecode/builder.rs +++ /dev/null @@ -1,360 +0,0 @@ -use super::{BasicBlock, BasicBlockExit, Instruction, Program}; -use crate::{parser::Identifier, value::object, Value}; - -#[derive(Clone, Copy, Debug)] -pub struct Register(usize); - -impl Register { - #[must_use] - pub const fn index(&self) -> usize { - self.0 - } -} - -#[derive(Clone, Debug)] -pub struct ProgramBuilder { - current_block: usize, - basic_blocks: Vec, -} - -impl Default for ProgramBuilder { - fn default() -> Self { - Self { - current_block: 0, - basic_blocks: vec![BasicBlock::default()], - } - } -} - -impl ProgramBuilder { - #[must_use] - pub fn get_current_block<'a>(&'a mut self) -> BasicBlockBuilder<'a> { - let index = self.current_block(); - self.get_block(index) - } - - #[must_use] - pub fn current_block(&self) -> usize { - self.current_block - } - - pub fn set_current_block(&mut self, current_block: usize) { - self.current_block = current_block; - } - - #[must_use] - pub fn get_block<'a>(&'a mut self, index: usize) -> BasicBlockBuilder<'a> { - BasicBlockBuilder::new(&mut self.basic_blocks[index]) - } - - #[must_use] - pub fn allocate_basic_block(&mut self) -> usize { - let index = self.basic_blocks.len(); - self.basic_blocks.push(BasicBlock::default()); - index - } - - #[must_use] - pub fn finish(self) -> Program { - Program { - basic_blocks: self.basic_blocks, - } - } -} - -#[derive(Debug)] -pub struct BasicBlockBuilder<'a> { - basic_block: &'a mut BasicBlock, -} - -impl<'a> BasicBlockBuilder<'a> { - pub fn new(basic_block: &'a mut BasicBlock) -> Self { - Self { basic_block } - } - - #[must_use] - pub fn allocate_register(&mut self) -> Register { - let register = Register(self.basic_block.registers_required); - self.basic_block.registers_required += 1; - - register - } - - fn push_instruction(&mut self, instruction: Instruction) { - self.basic_block.instructions.push(instruction); - } - - #[must_use] - pub fn allocate_register_with_value(&mut self, value: Value) -> Register { - let register = self.allocate_register(); - let instruction = Instruction::LoadImmediate { - destination: register, - immediate: value, - }; - self.push_instruction(instruction); - register - } - - pub fn create_variable(&mut self, name: &str) { - let instruction = Instruction::CreateVariable { - name: name.to_string(), - }; - self.push_instruction(instruction); - } - - pub fn update_variable(&mut self, name: String, src: Register) { - let instruction = Instruction::UpdateVariable { name, src }; - self.push_instruction(instruction); - } - - pub fn load_variable(&mut self, name: String, dst: Register) { - let instruction = Instruction::LoadVariable { name, dst }; - self.push_instruction(instruction); - } - - #[must_use] - pub fn add(&mut self, lhs: Register, rhs: Register) -> Register { - let dst = self.allocate_register(); - let instruction = Instruction::Add { lhs, rhs, dst }; - self.push_instruction(instruction); - dst - } - - #[must_use] - pub fn subtract(&mut self, lhs: Register, rhs: Register) -> Register { - let dst = self.allocate_register(); - let instruction = Instruction::Subtract { lhs, rhs, dst }; - self.push_instruction(instruction); - dst - } - - #[must_use] - pub fn multiply(&mut self, lhs: Register, rhs: Register) -> Register { - let dst = self.allocate_register(); - let instruction = Instruction::Multiply { lhs, rhs, dst }; - self.push_instruction(instruction); - dst - } - - #[must_use] - pub fn divide(&mut self, lhs: Register, rhs: Register) -> Register { - let dst = self.allocate_register(); - let instruction = Instruction::Divide { lhs, rhs, dst }; - self.push_instruction(instruction); - dst - } - - #[must_use] - pub fn modulo(&mut self, lhs: Register, rhs: Register) -> Register { - let dst = self.allocate_register(); - let instruction = Instruction::Modulo { lhs, rhs, dst }; - self.push_instruction(instruction); - dst - } - - #[must_use] - pub fn exponentiate(&mut self, lhs: Register, rhs: Register) -> Register { - let dst = self.allocate_register(); - let instruction = Instruction::Exponentiate { lhs, rhs, dst }; - self.push_instruction(instruction); - dst - } - - #[must_use] - pub fn bitwise_or(&mut self, lhs: Register, rhs: Register) -> Register { - let dst = self.allocate_register(); - let instruction = Instruction::BitwiseOr { lhs, rhs, dst }; - self.push_instruction(instruction); - dst - } - - #[must_use] - pub fn bitwise_and(&mut self, lhs: Register, rhs: Register) -> Register { - let dst = self.allocate_register(); - let instruction = Instruction::BitwiseAnd { lhs, rhs, dst }; - self.push_instruction(instruction); - dst - } - - #[must_use] - pub fn bitwise_xor(&mut self, lhs: Register, rhs: Register) -> Register { - let dst = self.allocate_register(); - let instruction = Instruction::BitwiseXor { lhs, rhs, dst }; - self.push_instruction(instruction); - dst - } - - #[must_use] - pub fn logical_and(&mut self, lhs: Register, rhs: Register) -> Register { - let dst = self.allocate_register(); - let instruction = Instruction::LogicalAnd { lhs, rhs, dst }; - self.push_instruction(instruction); - dst - } - - #[must_use] - pub fn logical_or(&mut self, lhs: Register, rhs: Register) -> Register { - let dst = self.allocate_register(); - let instruction = Instruction::LogicalOr { lhs, rhs, dst }; - self.push_instruction(instruction); - dst - } - - #[must_use] - pub fn coalesce(&mut self, lhs: Register, rhs: Register) -> Register { - let dst = self.allocate_register(); - let instruction = Instruction::Coalesce { lhs, rhs, dst }; - self.push_instruction(instruction); - dst - } - - #[must_use] - pub fn loosely_equal(&mut self, lhs: Register, rhs: Register) -> Register { - let dst = self.allocate_register(); - let instruction = Instruction::LooselyEqual { lhs, rhs, dst }; - self.push_instruction(instruction); - dst - } - - #[must_use] - pub fn strict_equal(&mut self, lhs: Register, rhs: Register) -> Register { - let dst = self.allocate_register(); - let instruction = Instruction::StrictEqual { lhs, rhs, dst }; - self.push_instruction(instruction); - dst - } - - #[must_use] - pub fn not_loosely_equal(&mut self, lhs: Register, rhs: Register) -> Register { - let dst = self.allocate_register(); - let instruction = Instruction::NotLooselyEqual { lhs, rhs, dst }; - self.push_instruction(instruction); - dst - } - - #[must_use] - pub fn strict_not_equal(&mut self, lhs: Register, rhs: Register) -> Register { - let dst = self.allocate_register(); - let instruction = Instruction::StrictNotEqual { lhs, rhs, dst }; - self.push_instruction(instruction); - dst - } - - #[must_use] - pub fn less_than(&mut self, lhs: Register, rhs: Register) -> Register { - let dst = self.allocate_register(); - let instruction = Instruction::LessThan { lhs, rhs, dst }; - self.push_instruction(instruction); - dst - } - - #[must_use] - pub fn greater_than(&mut self, lhs: Register, rhs: Register) -> Register { - let dst = self.allocate_register(); - let instruction = Instruction::GreaterThan { lhs, rhs, dst }; - self.push_instruction(instruction); - dst - } - - #[must_use] - pub fn less_than_or_equal(&mut self, lhs: Register, rhs: Register) -> Register { - let dst = self.allocate_register(); - let instruction = Instruction::LessThanOrEqual { lhs, rhs, dst }; - self.push_instruction(instruction); - dst - } - - #[must_use] - pub fn greater_than_or_equal(&mut self, lhs: Register, rhs: Register) -> Register { - let dst = self.allocate_register(); - let instruction = Instruction::GreaterThanOrEqual { lhs, rhs, dst }; - self.push_instruction(instruction); - dst - } - - #[must_use] - pub fn shift_left(&mut self, lhs: Register, rhs: Register) -> Register { - let dst = self.allocate_register(); - let instruction = Instruction::ShiftLeft { lhs, rhs, dst }; - self.push_instruction(instruction); - dst - } - - #[must_use] - pub fn shift_right(&mut self, lhs: Register, rhs: Register) -> Register { - let dst = self.allocate_register(); - let instruction = Instruction::ShiftRight { lhs, rhs, dst }; - self.push_instruction(instruction); - dst - } - - #[must_use] - pub fn shift_right_zeros(&mut self, lhs: Register, rhs: Register) -> Register { - let dst = self.allocate_register(); - let instruction = Instruction::ShiftRightZeros { lhs, rhs, dst }; - self.push_instruction(instruction); - dst - } - - pub fn throw(&mut self, value: Register) { - let instruction = Instruction::Throw { value }; - self.push_instruction(instruction); - } - - pub fn unconditionally_jump_to(&mut self, branch_to: usize) { - self.basic_block.exit = BasicBlockExit::GoTo(branch_to); - } - - pub fn branch_if(&mut self, branch_on: Register, if_true: usize, if_false: usize) { - self.basic_block.exit = BasicBlockExit::Branch { - branch_on, - if_true, - if_false, - } - } - - pub fn member_access_with_identifier( - &mut self, - base: Register, - identifier: Identifier, - ) -> Register { - let dst = self.allocate_register(); - let instruction = Instruction::MemberAccessWithIdentifier { - base, - identifier, - dst, - }; - self.push_instruction(instruction); - dst - } - - pub fn create_data_property_or_throw( - &mut self, - object: Register, - property_key: object::PropertyKey, - property_value: Register, - ) { - let instruction = Instruction::CreateDataPropertyOrThrow { - object, - property_key, - property_value, - }; - self.push_instruction(instruction); - } - - #[must_use] - /// - pub fn to_number(&mut self, src: Register) -> Register { - let dst = self.allocate_register(); - let instruction = Instruction::ToNumber { src, dst }; - self.push_instruction(instruction); - - dst - } - - #[must_use] - /// - pub fn call(&mut self, callable: Register, arguments: Vec) -> Register { - todo!("function call evaluation") - } -} diff --git a/crates/js/src/bytecode/instruction.rs b/crates/js/src/bytecode/instruction.rs deleted file mode 100644 index 53afbe49..00000000 --- a/crates/js/src/bytecode/instruction.rs +++ /dev/null @@ -1,168 +0,0 @@ -use super::Register; -use crate::{parser::Identifier, value::object, Value}; - -#[derive(Clone, Copy, Debug)] -pub struct VariableHandle(usize); - -impl VariableHandle { - #[must_use] - pub const fn new(index: usize) -> Self { - Self(index) - } - - #[must_use] - pub const fn index(&self) -> usize { - self.0 - } -} - -#[derive(Clone, Debug)] -pub enum Instruction { - LoadImmediate { - destination: Register, - immediate: Value, - }, - CreateVariable { - name: String, - }, - UpdateVariable { - name: String, - src: Register, - }, - LoadVariable { - name: String, - dst: Register, - }, - Add { - lhs: Register, - rhs: Register, - dst: Register, - }, - Subtract { - lhs: Register, - rhs: Register, - dst: Register, - }, - Multiply { - lhs: Register, - rhs: Register, - dst: Register, - }, - Divide { - lhs: Register, - rhs: Register, - dst: Register, - }, - Modulo { - lhs: Register, - rhs: Register, - dst: Register, - }, - Exponentiate { - lhs: Register, - rhs: Register, - dst: Register, - }, - BitwiseOr { - lhs: Register, - rhs: Register, - dst: Register, - }, - BitwiseAnd { - lhs: Register, - rhs: Register, - dst: Register, - }, - BitwiseXor { - lhs: Register, - rhs: Register, - dst: Register, - }, - LogicalAnd { - lhs: Register, - rhs: Register, - dst: Register, - }, - LogicalOr { - lhs: Register, - rhs: Register, - dst: Register, - }, - Coalesce { - lhs: Register, - rhs: Register, - dst: Register, - }, - LooselyEqual { - lhs: Register, - rhs: Register, - dst: Register, - }, - StrictEqual { - lhs: Register, - rhs: Register, - dst: Register, - }, - NotLooselyEqual { - lhs: Register, - rhs: Register, - dst: Register, - }, - StrictNotEqual { - lhs: Register, - rhs: Register, - dst: Register, - }, - LessThan { - lhs: Register, - rhs: Register, - dst: Register, - }, - GreaterThan { - lhs: Register, - rhs: Register, - dst: Register, - }, - LessThanOrEqual { - lhs: Register, - rhs: Register, - dst: Register, - }, - GreaterThanOrEqual { - lhs: Register, - rhs: Register, - dst: Register, - }, - ShiftLeft { - lhs: Register, - rhs: Register, - dst: Register, - }, - ShiftRight { - lhs: Register, - rhs: Register, - dst: Register, - }, - ShiftRightZeros { - lhs: Register, - rhs: Register, - dst: Register, - }, - Throw { - value: Register, - }, - MemberAccessWithIdentifier { - base: Register, - identifier: Identifier, - dst: Register, - }, - CreateDataPropertyOrThrow { - object: Register, - property_key: object::PropertyKey, - property_value: Register, - }, - ToNumber { - src: Register, - dst: Register, - }, -} diff --git a/crates/js/src/bytecode/mod.rs b/crates/js/src/bytecode/mod.rs deleted file mode 100644 index 2f27d71b..00000000 --- a/crates/js/src/bytecode/mod.rs +++ /dev/null @@ -1,17 +0,0 @@ -mod builder; -mod exception; -mod instruction; -mod program; -mod vm; - -pub use builder::{ProgramBuilder, Register}; -pub use exception::{Exception, ThrowCompletionOr}; -pub use instruction::Instruction; -pub use program::{BasicBlock, BasicBlockExit, Program}; -pub use vm::Vm; - -pub trait CompileToBytecode { - type Result = (); - - fn compile(&self, builder: &mut ProgramBuilder) -> Self::Result; -} diff --git a/crates/js/src/bytecode/program.rs b/crates/js/src/bytecode/program.rs deleted file mode 100644 index f9bb1c12..00000000 --- a/crates/js/src/bytecode/program.rs +++ /dev/null @@ -1,51 +0,0 @@ -use std::str::FromStr; - -use crate::parser::{ - tokenization::{GoalSymbol, Tokenizer}, - Script, SyntaxError, -}; - -use super::{CompileToBytecode, Instruction, ProgramBuilder, Register}; - -#[derive(Clone, Debug, Default)] -pub struct BasicBlock { - pub registers_required: usize, - pub instructions: Vec, - pub exit: BasicBlockExit, -} - -#[derive(Clone, Copy, Debug, Default)] -pub enum BasicBlockExit { - /// Terminate program execution - #[default] - Terminate, - - /// Execute either `if_true` or `if_false`, depending on `branch_on` - Branch { - branch_on: Register, - if_true: usize, - if_false: usize, - }, - - /// Unconditionally execute another basic block - GoTo(usize), -} - -#[derive(Clone, Debug, Default)] -pub struct Program { - pub(crate) basic_blocks: Vec, -} - -impl FromStr for Program { - type Err = SyntaxError; - - fn from_str(s: &str) -> Result { - let mut tokenizer = Tokenizer::new(s, GoalSymbol::Script); - let script = Script::parse(&mut tokenizer)?; - let mut builder = ProgramBuilder::default(); - script.compile(&mut builder); - let program = builder.finish(); - - Ok(program) - } -} diff --git a/crates/js/src/bytecode/vm.rs b/crates/js/src/bytecode/vm.rs deleted file mode 100644 index 80ade605..00000000 --- a/crates/js/src/bytecode/vm.rs +++ /dev/null @@ -1,305 +0,0 @@ -use std::collections::HashMap; - -use super::{ - BasicBlock, BasicBlockExit, Exception, Instruction, Program, Register, ThrowCompletionOr, -}; -use crate::{ - value::{ - evaluate_string_or_numeric_binary_expression, LeftFirst, StringOrNumericBinaryOperator, - ValueOrReference, - }, - Value, -}; - -#[derive(Clone, Debug, Default)] -pub struct Vm { - variables: HashMap, - registers: Vec, -} - -impl Vm { - pub fn dump(&self) { - println!("Registers:"); - for (index, reg) in self.registers.iter().enumerate() { - println!("\t{index}. {reg:?}"); - } - - println!("Variables:"); - for (index, (key, value)) in self.variables.iter().enumerate() { - println!("\t{index}. {key:?} -> {value:?}"); - } - } - - pub fn execute_program(&mut self, program: &Program) -> ThrowCompletionOr<()> { - let mut basic_block_index = 0; - loop { - let block_to_execute = &program.basic_blocks[basic_block_index]; - self.execute_basic_block(block_to_execute)?; - - match block_to_execute.exit { - BasicBlockExit::Terminate => break, - BasicBlockExit::GoTo(index) => basic_block_index = index, - BasicBlockExit::Branch { - branch_on, - if_true, - if_false, - } => { - if self.register(branch_on).get_value()?.to_boolean() { - basic_block_index = if_true; - } else { - basic_block_index = if_false; - } - }, - } - } - - Ok(()) - } - - fn execute_basic_block(&mut self, block: &BasicBlock) -> ThrowCompletionOr<()> { - self.registers - .resize_with(block.registers_required, Default::default); - - for instruction in &block.instructions { - self.execute_instruction(instruction)?; - } - - Ok(()) - } - - #[must_use] - fn register(&self, register: Register) -> &ValueOrReference { - &self.registers[register.index()] - } - - fn set_register(&mut self, register: Register, value: ValueOrReference) { - self.registers[register.index()] = value; - } - - fn set_variable(&mut self, name: &str, value: Value) { - *self.variables.get_mut(name).expect("Variable not defined") = value; - } - - fn execute_instruction(&mut self, instruction: &Instruction) -> ThrowCompletionOr<()> { - match instruction { - Instruction::LoadImmediate { - destination, - immediate, - } => { - self.set_register(*destination, immediate.clone().into()); - }, - Instruction::CreateVariable { name } => { - self.variables.insert(name.clone(), Value::default()); - }, - Instruction::UpdateVariable { name, src } => { - self.set_variable(name, self.register(*src).clone().get_value()?.into()); - }, - Instruction::LoadVariable { name, dst } => { - let value = self - .variables - .get(name) - .expect("Variable not defined") - .clone(); - self.set_register(*dst, value.into()); - }, - Instruction::Add { lhs, rhs, dst } => { - // https://262.ecma-international.org/14.0/#sec-addition-operator-plus-runtime-semantics-evaluation - let result = evaluate_string_or_numeric_binary_expression( - self.register(*lhs).clone(), - StringOrNumericBinaryOperator::Add, - self.register(*rhs).clone(), - )?; - - self.set_register(*dst, result.into()); - }, - Instruction::Subtract { lhs, rhs, dst } => { - // https://262.ecma-international.org/14.0/#sec-subtraction-operator-minus-runtime-semantics-evaluation - let result = evaluate_string_or_numeric_binary_expression( - self.register(*lhs).clone(), - StringOrNumericBinaryOperator::Subtract, - self.register(*rhs).clone(), - )?; - - self.set_register(*dst, result.into()); - }, - Instruction::Multiply { lhs, rhs, dst } => { - // https://262.ecma-international.org/14.0/#sec-multiplicative-operators-runtime-semantics-evaluation - let result = evaluate_string_or_numeric_binary_expression( - self.register(*lhs).clone(), - StringOrNumericBinaryOperator::Multiply, - self.register(*rhs).clone(), - )?; - - self.set_register(*dst, result.into()); - }, - Instruction::Divide { lhs, rhs, dst } => { - // https://262.ecma-international.org/14.0/#sec-multiplicative-operators-runtime-semantics-evaluation - let result = evaluate_string_or_numeric_binary_expression( - self.register(*lhs).clone(), - StringOrNumericBinaryOperator::Divide, - self.register(*rhs).clone(), - )?; - - self.set_register(*dst, result.into()); - }, - Instruction::Modulo { lhs, rhs, dst } => { - // https://262.ecma-international.org/14.0/#sec-multiplicative-operators-runtime-semantics-evaluation - let result = evaluate_string_or_numeric_binary_expression( - self.register(*lhs).clone(), - StringOrNumericBinaryOperator::Modulo, - self.register(*rhs).clone(), - )?; - - self.set_register(*dst, result.into()); - }, - Instruction::Exponentiate { lhs, rhs, dst } => { - // https://262.ecma-international.org/14.0/#sec-exp-operator-runtime-semantics-evaluation - let result = evaluate_string_or_numeric_binary_expression( - self.register(*lhs).clone(), - StringOrNumericBinaryOperator::Exponentiate, - self.register(*rhs).clone(), - )?; - - self.set_register(*dst, result.into()); - }, - Instruction::BitwiseAnd { lhs, rhs, dst } => { - // https://262.ecma-international.org/14.0/#sec-binary-bitwise-operators-runtime-semantics-evaluation - let result = evaluate_string_or_numeric_binary_expression( - self.register(*lhs).clone(), - StringOrNumericBinaryOperator::BitwiseAnd, - self.register(*rhs).clone(), - )?; - - self.set_register(*dst, result.into()); - }, - Instruction::BitwiseOr { lhs, rhs, dst } => { - // https://262.ecma-international.org/14.0/#sec-binary-bitwise-operators-runtime-semantics-evaluation - let result = evaluate_string_or_numeric_binary_expression( - self.register(*lhs).clone(), - StringOrNumericBinaryOperator::BitwiseOr, - self.register(*rhs).clone(), - )?; - - self.set_register(*dst, result.into()); - }, - Instruction::BitwiseXor { lhs, rhs, dst } => { - // https://262.ecma-international.org/14.0/#sec-binary-bitwise-operators-runtime-semantics-evaluation - let result = evaluate_string_or_numeric_binary_expression( - self.register(*lhs).clone(), - StringOrNumericBinaryOperator::BitwiseExclusiveOr, - self.register(*rhs).clone(), - )?; - - self.set_register(*dst, result.into()); - }, - Instruction::ShiftLeft { lhs, rhs, dst } => { - // https://262.ecma-international.org/14.0/#sec-left-shift-operator-runtime-semantics-evaluation - let result = evaluate_string_or_numeric_binary_expression( - self.register(*lhs).clone(), - StringOrNumericBinaryOperator::ShiftLeft, - self.register(*rhs).clone(), - )?; - - self.set_register(*dst, result.into()); - }, - Instruction::ShiftRight { lhs, rhs, dst } => { - // https://262.ecma-international.org/14.0/#sec-signed-right-shift-operator - let result = evaluate_string_or_numeric_binary_expression( - self.register(*lhs).clone(), - StringOrNumericBinaryOperator::ShiftLeft, - self.register(*rhs).clone(), - )?; - - self.set_register(*dst, result.into()); - }, - Instruction::ShiftRightZeros { lhs, rhs, dst } => { - // https://262.ecma-international.org/14.0/#sec-unsigned-right-shift-operator - let result = evaluate_string_or_numeric_binary_expression( - self.register(*lhs).clone(), - StringOrNumericBinaryOperator::ShiftLeft, - self.register(*rhs).clone(), - )?; - - self.set_register(*dst, result.into()); - }, - Instruction::LogicalAnd { lhs, rhs, dst } => { - // https://262.ecma-international.org/14.0/#sec-binary-logical-operators-runtime-semantics-evaluation - let lval = self.register(*lhs).get_value()?; - let result = if !lval.to_boolean() { - lval - } else { - self.register(*rhs).get_value()? - }; - - self.set_register(*dst, result.into()); - }, - Instruction::StrictEqual { lhs, rhs, dst } => { - // https://262.ecma-international.org/14.0/#sec-equality-operators-runtime-semantics-evaluation - let result = Value::is_strictly_equal( - &self.register(*lhs).get_value()?, - &self.register(*rhs).get_value()?, - )?; - self.set_register(*dst, Value::from(result).into()); - }, - Instruction::StrictNotEqual { lhs, rhs, dst } => { - // https://262.ecma-international.org/14.0/#sec-equality-operators-runtime-semantics-evaluation - let result = Value::is_strictly_equal( - &self.register(*lhs).get_value()?, - &self.register(*rhs).get_value()?, - )?; - self.set_register(*dst, Value::from(!result).into()); - }, - Instruction::LooselyEqual { lhs, rhs, dst } => { - // https://262.ecma-international.org/14.0/#sec-equality-operators-runtime-semantics-evaluation - let result = Value::is_loosely_equal( - &self.register(*lhs).get_value()?, - &self.register(*rhs).get_value()?, - )?; - self.set_register(*dst, Value::from(result).into()); - }, - Instruction::NotLooselyEqual { lhs, rhs, dst } => { - // https://262.ecma-international.org/14.0/#sec-equality-operators-runtime-semantics-evaluation - let result = !Value::is_loosely_equal( - &self.register(*lhs).get_value()?, - &self.register(*rhs).get_value()?, - )?; - self.set_register(*dst, Value::from(result).into()); - }, - Instruction::LessThan { lhs, rhs, dst } => { - let r = Value::is_less_than( - &self.register(*lhs).get_value()?, - &self.register(*rhs).get_value()?, - LeftFirst::Yes, - )?; - - let result = if r.is_undefined() { - Value::from(false) - } else { - r - }; - - self.set_register(*dst, result.into()); - }, - Instruction::Throw { value } => { - let value = self.register(*value).clone().get_value()?; - return Err(Exception::new(value)); - }, - Instruction::MemberAccessWithIdentifier { - base, - identifier, - dst, - } => { - // https://262.ecma-international.org/14.0/#sec-property-accessors-runtime-semantics-evaluation - let base_value = self.register(*base).get_value()?; - let result = Value::evaluate_property_access_with_identifier_key( - base_value, - identifier.clone(), - ); - self.set_register(*dst, result.into()); - }, - other => todo!("Implement instruction {other:?}"), - } - - Ok(()) - } -} diff --git a/crates/js/src/lib.rs b/crates/js/src/lib.rs index 1f809747..88fa1611 100644 --- a/crates/js/src/lib.rs +++ b/crates/js/src/lib.rs @@ -1,11 +1,9 @@ #![feature(iter_advance_by, associated_type_defaults, assert_matches)] -mod bytecode; mod compiler; mod parser; mod runtime; mod value; -pub use bytecode::Program; pub use runtime::{Executable, Vm}; pub use value::{Number, Value}; diff --git a/crates/js/src/parser/expressions/assignment_expression.rs b/crates/js/src/parser/expressions/assignment_expression.rs index 09d9e470..af689e4c 100644 --- a/crates/js/src/parser/expressions/assignment_expression.rs +++ b/crates/js/src/parser/expressions/assignment_expression.rs @@ -1,11 +1,8 @@ //! -use crate::{ - bytecode::{self, CompileToBytecode}, - parser::{ - tokenization::{Punctuator, SkipLineTerminators, Token, Tokenizer}, - SyntaxError, - }, +use crate::parser::{ + tokenization::{Punctuator, SkipLineTerminators, Token, Tokenizer}, + SyntaxError, }; use super::{ConditionalExpression, Expression}; @@ -152,18 +149,6 @@ enum AssignmentOp { NullishCoalescingAssignment, } -impl CompileToBytecode for AssignmentExpression { - type Result = bytecode::Register; - - fn compile(&self, builder: &mut bytecode::ProgramBuilder) -> Self::Result { - _ = builder; - _ = self.lhs; - _ = self.rhs; - _ = self.operator; - todo!("compile AssignmentExpression") - } -} - impl AssignmentOp { #[must_use] fn from_token(token: &Token) -> Option { @@ -222,15 +207,3 @@ impl AssignmentTarget { Some(assignment_target) } } - -impl CompileToBytecode for AssignmentTarget { - fn compile(&self, builder: &mut bytecode::ProgramBuilder) -> Self::Result { - match self { - Self::IdentifierRef(identifier_ref) => { - _ = builder; - _ = identifier_ref; - todo!() - }, - } - } -} diff --git a/crates/js/src/parser/expressions/binary_expression.rs b/crates/js/src/parser/expressions/binary_expression.rs index d05185e9..3ce8984c 100644 --- a/crates/js/src/parser/expressions/binary_expression.rs +++ b/crates/js/src/parser/expressions/binary_expression.rs @@ -1,10 +1,7 @@ -use crate::{ - bytecode::{self, CompileToBytecode}, - parser::{ - expressions::UpdateExpression, - tokenization::{Punctuator, SkipLineTerminators, Token, Tokenizer}, - SyntaxError, - }, +use crate::parser::{ + expressions::UpdateExpression, + tokenization::{Punctuator, SkipLineTerminators, Token, Tokenizer}, + SyntaxError, }; use super::{Expression, UnaryExpression}; @@ -241,52 +238,6 @@ pub fn parse_exponentiation_expression( Ok(exponentiation_expression) } -impl CompileToBytecode for BinaryExpression { - type Result = bytecode::Register; - - fn compile(&self, builder: &mut bytecode::ProgramBuilder) -> Self::Result { - let lhs = self.lhs.compile(builder); - let rhs = self.rhs.compile(builder); - let mut current_block = builder.get_current_block(); - - let dst = match self.op { - BinaryOp::Arithmetic(ArithmeticOp::Add) => current_block.add(lhs, rhs), - BinaryOp::Arithmetic(ArithmeticOp::Subtract) => current_block.subtract(lhs, rhs), - BinaryOp::Arithmetic(ArithmeticOp::Multiply) => current_block.multiply(lhs, rhs), - BinaryOp::Arithmetic(ArithmeticOp::Divide) => current_block.divide(lhs, rhs), - BinaryOp::Arithmetic(ArithmeticOp::Modulo) => current_block.modulo(lhs, rhs), - BinaryOp::Arithmetic(ArithmeticOp::Exponentiation) => { - current_block.exponentiate(lhs, rhs) - }, - BinaryOp::Bitwise(BitwiseOp::And) => current_block.bitwise_and(lhs, rhs), - BinaryOp::Bitwise(BitwiseOp::Or) => current_block.bitwise_or(lhs, rhs), - BinaryOp::Bitwise(BitwiseOp::Xor) => current_block.bitwise_xor(lhs, rhs), - BinaryOp::Logical(LogicalOp::And) => current_block.logical_and(lhs, rhs), - BinaryOp::Logical(LogicalOp::Or) => current_block.logical_or(lhs, rhs), - BinaryOp::Logical(LogicalOp::Coalesce) => current_block.coalesce(lhs, rhs), - BinaryOp::Equality(EqualityOp::Equal) => current_block.loosely_equal(lhs, rhs), - BinaryOp::Equality(EqualityOp::NotEqual) => current_block.not_loosely_equal(lhs, rhs), - BinaryOp::Equality(EqualityOp::StrictEqual) => current_block.strict_equal(lhs, rhs), - BinaryOp::Equality(EqualityOp::StrictNotEqual) => { - current_block.strict_not_equal(lhs, rhs) - }, - BinaryOp::Relational(RelationalOp::LessThan) => current_block.less_than(lhs, rhs), - BinaryOp::Relational(RelationalOp::GreaterThan) => current_block.greater_than(lhs, rhs), - BinaryOp::Relational(RelationalOp::LessThanOrEqual) => { - current_block.less_than_or_equal(lhs, rhs) - }, - BinaryOp::Relational(RelationalOp::GreaterThanOrEqual) => { - current_block.greater_than_or_equal(lhs, rhs) - }, - BinaryOp::Shift(ShiftOp::ShiftLeft) => current_block.shift_left(lhs, rhs), - BinaryOp::Shift(ShiftOp::ShiftRight) => current_block.shift_right(lhs, rhs), - BinaryOp::Shift(ShiftOp::ShiftRightZeros) => current_block.shift_right_zeros(lhs, rhs), - }; - - dst - } -} - impl From for BinaryOp { fn from(value: ArithmeticOp) -> Self { Self::Arithmetic(value) diff --git a/crates/js/src/parser/expressions/call.rs b/crates/js/src/parser/expressions/call.rs index 8fb884bf..ebcf6595 100644 --- a/crates/js/src/parser/expressions/call.rs +++ b/crates/js/src/parser/expressions/call.rs @@ -1,10 +1,7 @@ //! -use crate::{ - bytecode::{self, CompileToBytecode}, - parser::{ - tokenization::{Punctuator, SkipLineTerminators, Token, Tokenizer}, - SyntaxError, - }, +use crate::parser::{ + tokenization::{Punctuator, SkipLineTerminators, Token, Tokenizer}, + SyntaxError, }; use super::{AssignmentExpression, Expression}; @@ -48,19 +45,3 @@ pub fn parse_arguments( Ok(arguments) } - -impl CompileToBytecode for CallExpression { - type Result = bytecode::Register; - - fn compile(&self, builder: &mut bytecode::ProgramBuilder) -> Self::Result { - // https://262.ecma-international.org/14.0/#sec-function-calls-runtime-semantics-evaluation - let callable = self.callable.compile(builder); - let arguments = self - .arguments - .iter() - .map(|arg| arg.compile(builder)) - .collect(); - - builder.get_current_block().call(callable, arguments) - } -} diff --git a/crates/js/src/parser/expressions/conditional.rs b/crates/js/src/parser/expressions/conditional.rs index fa387ba2..dc9be343 100644 --- a/crates/js/src/parser/expressions/conditional.rs +++ b/crates/js/src/parser/expressions/conditional.rs @@ -1,11 +1,8 @@ //! -use crate::{ - bytecode::{self, CompileToBytecode}, - parser::{ - tokenization::{Punctuator, SkipLineTerminators, Token, Tokenizer}, - SyntaxError, - }, +use crate::parser::{ + tokenization::{Punctuator, SkipLineTerminators, Token, Tokenizer}, + SyntaxError, }; use super::{short_circuit::parse_short_circuit_expression, AssignmentExpression, Expression}; @@ -48,15 +45,3 @@ impl ConditionalExpression { } } } - -impl CompileToBytecode for ConditionalExpression { - type Result = bytecode::Register; - - fn compile(&self, builder: &mut bytecode::ProgramBuilder) -> Self::Result { - _ = builder; - _ = self.condition; - _ = self.true_case; - _ = self.false_case; - todo!("implement conditional expression in bytecode"); - } -} diff --git a/crates/js/src/parser/expressions/left_hand_side_expression.rs b/crates/js/src/parser/expressions/left_hand_side_expression.rs index 244d971f..ae51f1e0 100644 --- a/crates/js/src/parser/expressions/left_hand_side_expression.rs +++ b/crates/js/src/parser/expressions/left_hand_side_expression.rs @@ -1,11 +1,8 @@ //! -use crate::{ - bytecode::{self, CompileToBytecode}, - parser::{ - tokenization::{Punctuator, SkipLineTerminators, Token, Tokenizer}, - SyntaxError, - }, +use crate::parser::{ + tokenization::{Punctuator, SkipLineTerminators, Token, Tokenizer}, + SyntaxError, }; use super::{ @@ -86,14 +83,3 @@ impl NewExpression { Ok(new_expression) } } - -impl CompileToBytecode for NewExpression { - type Result = bytecode::Register; - - fn compile(&self, builder: &mut bytecode::ProgramBuilder) -> Self::Result { - _ = builder; - _ = self.nest_level; - _ = self.expression; - todo!("compile NewExpression") - } -} diff --git a/crates/js/src/parser/expressions/member.rs b/crates/js/src/parser/expressions/member.rs index 4fae54d7..a82e2b4c 100644 --- a/crates/js/src/parser/expressions/member.rs +++ b/crates/js/src/parser/expressions/member.rs @@ -1,11 +1,8 @@ //! -use crate::{ - bytecode::{self, CompileToBytecode}, - parser::{ - identifiers::Identifier, - tokenization::{Punctuator, SkipLineTerminators, Token, Tokenizer}, - SyntaxError, - }, +use crate::parser::{ + identifiers::Identifier, + tokenization::{Punctuator, SkipLineTerminators, Token, Tokenizer}, + SyntaxError, }; use super::{parse_primary_expression, Expression}; @@ -67,24 +64,3 @@ impl MemberExpression { Ok(member_expression) } } - -impl CompileToBytecode for MemberExpression { - type Result = bytecode::Register; - - fn compile(&self, builder: &mut bytecode::ProgramBuilder) -> Self::Result { - // https://262.ecma-international.org/14.0/#sec-property-accessors-runtime-semantics-evaluation - let base = self.base.compile(builder); - match &self.member { - Member::Identifier(ident) => { - let value = builder - .get_current_block() - .member_access_with_identifier(base, ident.clone()); - value - }, - Member::Bracket(bracket) => { - _ = bracket; - todo!("compile member expression"); - }, - } - } -} diff --git a/crates/js/src/parser/expressions/mod.rs b/crates/js/src/parser/expressions/mod.rs index 84ba8ff2..6560bfd6 100644 --- a/crates/js/src/parser/expressions/mod.rs +++ b/crates/js/src/parser/expressions/mod.rs @@ -20,10 +20,7 @@ pub use member::MemberExpression; pub use unary_expression::UnaryExpression; pub use update_expression::UpdateExpression; -use crate::{ - bytecode::{self, CompileToBytecode}, - Number, -}; +use crate::Number; use self::object::ObjectLiteral; @@ -107,36 +104,6 @@ impl Expression { } } -impl CompileToBytecode for Expression { - type Result = bytecode::Register; - - fn compile(&self, builder: &mut bytecode::ProgramBuilder) -> Self::Result { - match self { - Self::This => todo!(), - Self::Assignment(assignment_expression) => assignment_expression.compile(builder), - Self::Binary(binary_expression) => binary_expression.compile(builder), - Self::Call(call_expression) => call_expression.compile(builder), - Self::ConditionalExpression(conditional_expression) => { - conditional_expression.compile(builder) - }, - Self::Unary(unary_expression) => unary_expression.compile(builder), - Self::Update(update_expression) => update_expression.compile(builder), - Self::IdentifierReference(identifier_reference) => { - let mut current_block = builder.get_current_block(); - let dst = current_block.allocate_register(); - current_block.load_variable(identifier_reference.clone(), dst); - dst - }, - Self::Literal(literal) => builder - .get_current_block() - .allocate_register_with_value(literal.clone().into()), - Self::ObjectLiteral(object_literal) => object_literal.compile(builder), - Self::New(new_expression) => new_expression.compile(builder), - Self::Member(member_expression) => member_expression.compile(builder), - } - } -} - impl From for Expression { fn from(value: Literal) -> Self { Self::Literal(value) diff --git a/crates/js/src/parser/expressions/object.rs b/crates/js/src/parser/expressions/object.rs index 3a256d09..f055d6eb 100644 --- a/crates/js/src/parser/expressions/object.rs +++ b/crates/js/src/parser/expressions/object.rs @@ -1,13 +1,9 @@ //! -use crate::{ - bytecode::{self, CompileToBytecode}, - parser::{ - identifiers::parse_identifier_reference, - tokenization::{Punctuator, SkipLineTerminators, Token, Tokenizer}, - SyntaxError, - }, - value::{object::PropertyKey, Object}, +use crate::parser::{ + identifiers::parse_identifier_reference, + tokenization::{Punctuator, SkipLineTerminators, Token, Tokenizer}, + SyntaxError, }; /// @@ -66,50 +62,3 @@ impl ObjectLiteral { Ok(object_literal) } } - -impl CompileToBytecode for ObjectLiteral { - type Result = bytecode::Register; - - fn compile(&self, builder: &mut bytecode::ProgramBuilder) -> Self::Result { - let object = builder - .get_current_block() - .allocate_register_with_value(Object::default().into()); - - for property_definition in &self.property_definitions { - let property_register = property_definition.compile(builder); - builder.get_current_block().create_data_property_or_throw( - object, - PropertyKey::String(property_register.name), - property_register.value, - ); - } - - object - } -} - -#[derive(Debug)] -struct PropertyToBeCreated { - name: String, - value: bytecode::Register, -} - -impl CompileToBytecode for PropertyDefinition { - type Result = PropertyToBeCreated; - - fn compile(&self, builder: &mut bytecode::ProgramBuilder) -> Self::Result { - let mut builder = builder.get_current_block(); - - match self { - Self::IdentifierRef(identifier_reference) => { - let expr_value = builder.allocate_register(); - builder.load_variable(identifier_reference.clone(), expr_value); - - PropertyToBeCreated { - name: identifier_reference.clone(), - value: expr_value, - } - }, - } - } -} diff --git a/crates/js/src/parser/expressions/unary_expression.rs b/crates/js/src/parser/expressions/unary_expression.rs index 0399aa8d..e7cd4df0 100644 --- a/crates/js/src/parser/expressions/unary_expression.rs +++ b/crates/js/src/parser/expressions/unary_expression.rs @@ -1,11 +1,8 @@ //! -use crate::{ - bytecode::{self, CompileToBytecode}, - parser::{ - tokenization::{Punctuator, SkipLineTerminators, Token, Tokenizer}, - SyntaxError, - }, +use crate::parser::{ + tokenization::{Punctuator, SkipLineTerminators, Token, Tokenizer}, + SyntaxError, }; use super::{Expression, UpdateExpression}; @@ -78,46 +75,3 @@ impl UnaryExpression { Ok(unary_expression.into()) } } - -impl CompileToBytecode for UnaryExpression { - type Result = bytecode::Register; - - fn compile(&self, builder: &mut bytecode::ProgramBuilder) -> Self::Result { - todo!() - // match self { - // Self::Delete(expression) => { - // _ = expression; - // todo!(); - // }, - // Self::Void(expression) => { - // _ = expression; - // todo!(); - // }, - // Self::TypeOf(expression) => { - // _ = expression; - // todo!(); - // }, - // Self::Plus(expression) => { - // // https://262.ecma-international.org/14.0/#sec-unary-plus-operator-runtime-semantics-evaluation - - // // 1. Let expr be ? Evaluation of UnaryExpression. - // let result = expression.compile(builder); - - // // 2. Return ? ToNumber(? GetValue(expr)). - // builder.get_current_block().to_number(result) - // }, - // Self::Minus(expression) => { - // _ = expression; - // todo!(); - // }, - // Self::BitwiseNot(expression) => { - // _ = expression; - // todo!(); - // }, - // Self::LogicalNot(expression) => { - // _ = expression; - // todo!(); - // }, - // } - } -} diff --git a/crates/js/src/parser/expressions/update_expression.rs b/crates/js/src/parser/expressions/update_expression.rs index cc1ce1f6..1a0d3337 100644 --- a/crates/js/src/parser/expressions/update_expression.rs +++ b/crates/js/src/parser/expressions/update_expression.rs @@ -1,11 +1,8 @@ //! -use crate::{ - bytecode::{self, CompileToBytecode}, - parser::{ - tokenization::{Punctuator, SkipLineTerminators, Token, Tokenizer}, - SyntaxError, - }, +use crate::parser::{ + tokenization::{Punctuator, SkipLineTerminators, Token, Tokenizer}, + SyntaxError, }; use super::{left_hand_side_expression::parse_lefthandside_expression, Expression}; @@ -63,30 +60,3 @@ impl UpdateExpression { Ok(update_expression.into()) } } - -impl CompileToBytecode for UpdateExpression { - type Result = bytecode::Register; - - fn compile(&self, builder: &mut bytecode::ProgramBuilder) -> Self::Result { - _ = builder; - - match self { - Self::PreDecrement(expression) => { - _ = expression; - todo!(); - }, - Self::PostDecrement(expression) => { - _ = expression; - todo!(); - }, - Self::PreIncrement(expression) => { - _ = expression; - todo!(); - }, - Self::PostIncrement(expression) => { - _ = expression; - todo!(); - }, - } - } -} diff --git a/crates/js/src/parser/functions_and_classes/function_definitions.rs b/crates/js/src/parser/functions_and_classes/function_definitions.rs index b9f987b0..c3245b7f 100644 --- a/crates/js/src/parser/functions_and_classes/function_definitions.rs +++ b/crates/js/src/parser/functions_and_classes/function_definitions.rs @@ -1,13 +1,10 @@ //! -use crate::{ - bytecode::{self, CompileToBytecode}, - parser::{ - identifiers::parse_binding_identifier, - statements_and_declarations::StatementListItem, - tokenization::{Punctuator, SkipLineTerminators, Tokenizer}, - SyntaxError, - }, +use crate::parser::{ + identifiers::parse_binding_identifier, + statements_and_declarations::StatementListItem, + tokenization::{Punctuator, SkipLineTerminators, Tokenizer}, + SyntaxError, }; /// @@ -56,12 +53,3 @@ impl FunctionDeclaration { &self.body } } - -impl CompileToBytecode for FunctionDeclaration { - fn compile(&self, builder: &mut bytecode::ProgramBuilder) { - _ = builder; - _ = self.identifier; - _ = self.body; - todo!() - } -} diff --git a/crates/js/src/parser/script.rs b/crates/js/src/parser/script.rs index 37efd61b..d54a4254 100644 --- a/crates/js/src/parser/script.rs +++ b/crates/js/src/parser/script.rs @@ -1,5 +1,3 @@ -use crate::bytecode::{self, CompileToBytecode}; - use super::{ statements_and_declarations::StatementListItem, tokenization::{SkipLineTerminators, Tokenizer}, @@ -27,11 +25,3 @@ impl Script { &self.0 } } - -impl CompileToBytecode for Script { - fn compile(&self, builder: &mut bytecode::ProgramBuilder) { - for statement in &self.0 { - statement.compile(builder); - } - } -} diff --git a/crates/js/src/parser/statements_and_declarations/block_statement.rs b/crates/js/src/parser/statements_and_declarations/block_statement.rs index 0a980ea5..e78a8bbc 100644 --- a/crates/js/src/parser/statements_and_declarations/block_statement.rs +++ b/crates/js/src/parser/statements_and_declarations/block_statement.rs @@ -1,12 +1,9 @@ //! use super::StatementListItem; -use crate::{ - bytecode::{self, CompileToBytecode}, - parser::{ - tokenization::{Punctuator, SkipLineTerminators, Token, Tokenizer}, - SyntaxError, - }, +use crate::parser::{ + tokenization::{Punctuator, SkipLineTerminators, Token, Tokenizer}, + SyntaxError, }; /// @@ -42,11 +39,3 @@ impl BlockStatement { &self.statements } } - -impl CompileToBytecode for BlockStatement { - fn compile(&self, builder: &mut bytecode::ProgramBuilder) { - for statement in &self.statements { - statement.compile(builder); - } - } -} diff --git a/crates/js/src/parser/statements_and_declarations/declaration.rs b/crates/js/src/parser/statements_and_declarations/declaration.rs index 99b00ec6..53318c51 100644 --- a/crates/js/src/parser/statements_and_declarations/declaration.rs +++ b/crates/js/src/parser/statements_and_declarations/declaration.rs @@ -1,14 +1,11 @@ //! -use crate::{ - bytecode::{self, CompileToBytecode}, - parser::{ - expressions::Expression, - functions_and_classes::FunctionDeclaration, - identifiers::parse_binding_identifier, - tokenization::{Punctuator, SkipLineTerminators, Token, Tokenizer}, - SyntaxError, - }, +use crate::parser::{ + expressions::Expression, + functions_and_classes::FunctionDeclaration, + identifiers::parse_binding_identifier, + tokenization::{Punctuator, SkipLineTerminators, Token, Tokenizer}, + SyntaxError, }; /// @@ -197,42 +194,6 @@ fn parse_initializer( Ok(assignment_expression) } -impl CompileToBytecode for Declaration { - fn compile(&self, builder: &mut bytecode::ProgramBuilder) { - match self { - Self::Lexical(lexical_declaration) => lexical_declaration.compile(builder), - Self::Function(function_declaration) => function_declaration.compile(builder), - } - } -} - -impl CompileToBytecode for LexicalDeclaration { - fn compile(&self, builder: &mut bytecode::ProgramBuilder) -> Self::Result { - let current_block = builder.current_block(); - let _ = self.let_or_const; // FIXME: Use this! - - for lexical_binding in &self.lexical_bindings { - match lexical_binding { - LexicalBinding::WithIdentifier { - identifier, - initializer, - } => { - builder - .get_block(current_block) - .create_variable(&identifier); - - if let Some(expression) = initializer { - let result = expression.compile(builder); - builder - .get_block(current_block) - .update_variable(identifier.clone(), result); - } - }, - } - } - } -} - impl From for Declaration { fn from(value: FunctionDeclaration) -> Self { Self::Function(value) diff --git a/crates/js/src/parser/statements_and_declarations/if_statement.rs b/crates/js/src/parser/statements_and_declarations/if_statement.rs index 920dfd8a..0920709c 100644 --- a/crates/js/src/parser/statements_and_declarations/if_statement.rs +++ b/crates/js/src/parser/statements_and_declarations/if_statement.rs @@ -1,12 +1,9 @@ //! -use crate::{ - bytecode::{self, CompileToBytecode}, - parser::{ - expressions::Expression, - tokenization::{Punctuator, SkipLineTerminators, Token, Tokenizer}, - SyntaxError, - }, +use crate::parser::{ + expressions::Expression, + tokenization::{Punctuator, SkipLineTerminators, Token, Tokenizer}, + SyntaxError, }; use super::Statement; @@ -66,43 +63,3 @@ impl IfStatement { Ok(if_statement) } } - -impl CompileToBytecode for IfStatement { - fn compile(&self, builder: &mut bytecode::ProgramBuilder) { - let condition_register = self.condition.compile(builder); - let branching_block = builder.current_block(); - - // The block that the two different executions will join on again - let after_block = builder.allocate_basic_block(); - - // Compile the "if" branch - let if_block = builder.allocate_basic_block(); - builder.set_current_block(if_block); - self.if_branch.compile(builder); - builder - .get_current_block() - .unconditionally_jump_to(after_block); - - if let Some(else_branch) = self.else_branch.as_ref() { - // Compile the "else" branch - let else_block = builder.allocate_basic_block(); - builder.set_current_block(else_block); - else_branch.compile(builder); - builder - .get_current_block() - .unconditionally_jump_to(after_block); - - // Branch to either the "if" or the "else" branch - builder - .get_block(branching_block) - .branch_if(condition_register, if_block, else_block); - } else { - // Branch to either the "if" or the "after" branch - builder - .get_block(branching_block) - .branch_if(condition_register, if_block, after_block); - } - - builder.set_current_block(after_block); - } -} diff --git a/crates/js/src/parser/statements_and_declarations/statement.rs b/crates/js/src/parser/statements_and_declarations/statement.rs index 727f51b7..f66e3683 100644 --- a/crates/js/src/parser/statements_and_declarations/statement.rs +++ b/crates/js/src/parser/statements_and_declarations/statement.rs @@ -1,10 +1,7 @@ -use crate::{ - bytecode::{self, CompileToBytecode}, - parser::{ - expressions::Expression, - tokenization::{Punctuator, SkipLineTerminators, Token, Tokenizer}, - SyntaxError, - }, +use crate::parser::{ + expressions::Expression, + tokenization::{Punctuator, SkipLineTerminators, Token, Tokenizer}, + SyntaxError, }; use super::{ @@ -97,30 +94,6 @@ impl Statement { } } -impl CompileToBytecode for StatementListItem { - fn compile(&self, builder: &mut bytecode::ProgramBuilder) { - match self { - Self::Statement(statement) => statement.compile(builder), - Self::Declaration(declaration) => declaration.compile(builder), - } - } -} - -impl CompileToBytecode for Statement { - fn compile(&self, builder: &mut bytecode::ProgramBuilder) { - match self { - Self::BlockStatement(block_statement) => block_statement.compile(builder), - Self::IfStatement(if_statement) => if_statement.compile(builder), - Self::WhileStatement(while_statement) => while_statement.compile(builder), - Self::EmptyStatement => {}, - Self::ExpressionStatement(expression) => { - expression.compile(builder); - }, - Self::ThrowStatement(throw_statement) => throw_statement.compile(builder), - } - } -} - impl From for StatementListItem { fn from(value: Statement) -> Self { Self::Statement(value) diff --git a/crates/js/src/parser/statements_and_declarations/throw_statement.rs b/crates/js/src/parser/statements_and_declarations/throw_statement.rs index e5edad4b..f8d3b48e 100644 --- a/crates/js/src/parser/statements_and_declarations/throw_statement.rs +++ b/crates/js/src/parser/statements_and_declarations/throw_statement.rs @@ -1,9 +1,6 @@ //! -use crate::{ - bytecode::{self, CompileToBytecode}, - parser::{expressions::Expression, tokenization::Tokenizer, SyntaxError}, -}; +use crate::parser::{expressions::Expression, tokenization::Tokenizer, SyntaxError}; /// #[derive(Clone, Debug)] @@ -28,18 +25,3 @@ impl ThrowStatement { Ok(throw_statement) } } - -impl CompileToBytecode for ThrowStatement { - fn compile(&self, builder: &mut bytecode::ProgramBuilder) -> Self::Result { - // - - // 1. Let exprRef be ? Evaluation of Expression. - let expr_ref = self.expression.compile(builder); - - // FIXME: 2. Let exprValue be ? GetValue(exprRef). - let expr_value = expr_ref; - - // 3. Return ThrowCompletion(exprValue). - builder.get_current_block().throw(expr_value); - } -} diff --git a/crates/js/src/parser/statements_and_declarations/while_statement.rs b/crates/js/src/parser/statements_and_declarations/while_statement.rs index a5891116..562a170c 100644 --- a/crates/js/src/parser/statements_and_declarations/while_statement.rs +++ b/crates/js/src/parser/statements_and_declarations/while_statement.rs @@ -1,12 +1,9 @@ //! -use crate::{ - bytecode::{self, CompileToBytecode}, - parser::{ - expressions::Expression, - tokenization::{Punctuator, Tokenizer}, - SyntaxError, - }, +use crate::parser::{ + expressions::Expression, + tokenization::{Punctuator, Tokenizer}, + SyntaxError, }; use super::Statement; @@ -37,12 +34,3 @@ impl WhileStatement { Ok(while_statement) } } - -impl CompileToBytecode for WhileStatement { - fn compile(&self, builder: &mut bytecode::ProgramBuilder) -> Self::Result { - _ = builder; - _ = self.loop_condition; - _ = self.body; - todo!() - } -} diff --git a/crates/js/src/bytecode/exception.rs b/crates/js/src/runtime/exception.rs similarity index 100% rename from crates/js/src/bytecode/exception.rs rename to crates/js/src/runtime/exception.rs diff --git a/crates/js/src/runtime/mod.rs b/crates/js/src/runtime/mod.rs index a40be391..643deed0 100644 --- a/crates/js/src/runtime/mod.rs +++ b/crates/js/src/runtime/mod.rs @@ -1,8 +1,10 @@ +mod exception; mod executable; mod lexical_environment; mod opcode; mod vm; +pub use exception::{Exception, ThrowCompletionOr}; pub use executable::Executable; pub use lexical_environment::LexicalEnvironment; pub use opcode::OpCode; diff --git a/crates/js/src/value/mod.rs b/crates/js/src/value/mod.rs index b9d5569c..3dee0e38 100644 --- a/crates/js/src/value/mod.rs +++ b/crates/js/src/value/mod.rs @@ -9,8 +9,8 @@ pub use reference_record::{ReferenceRecord, ValueOrReference}; pub use symbol::Symbol; use crate::{ - bytecode::{Exception, ThrowCompletionOr}, parser::Identifier, + runtime::{Exception, ThrowCompletionOr}, }; const SPEC_CANNOT_FAIL: &str = diff --git a/crates/js/src/value/object/mod.rs b/crates/js/src/value/object/mod.rs index 2f45d7bb..eff39343 100644 --- a/crates/js/src/value/object/mod.rs +++ b/crates/js/src/value/object/mod.rs @@ -2,7 +2,7 @@ mod vtable; -use crate::bytecode::{Exception, ThrowCompletionOr}; +use crate::runtime::{Exception, ThrowCompletionOr}; use self::vtable::ObjectMethods; diff --git a/crates/js/src/value/reference_record.rs b/crates/js/src/value/reference_record.rs index 38527c8a..2ba2ef4e 100644 --- a/crates/js/src/value/reference_record.rs +++ b/crates/js/src/value/reference_record.rs @@ -1,6 +1,6 @@ //! -use crate::bytecode::ThrowCompletionOr; +use crate::runtime::ThrowCompletionOr; use super::{object::PropertyKey, Value};