diff --git a/dust-lang/src/vm/action/add.rs b/dust-lang/src/vm/action/add.rs index 6023ed0..6162e83 100644 --- a/dust-lang/src/vm/action/add.rs +++ b/dust-lang/src/vm/action/add.rs @@ -1,19 +1,105 @@ -use tracing::trace; - use crate::{ instruction::InstructionFields, vm::{Register, Thread}, + DustString, }; -pub fn add_integers(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { - trace!("ADD: Run and cache pointers"); - +pub fn add_bytes(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { let destination = instruction.a_field as usize; let left = instruction.b_field as usize; let left_is_constant = instruction.b_is_constant; let right = instruction.c_field as usize; let right_is_constant = instruction.c_is_constant; + let left_value = if left_is_constant { + if cfg!(debug_assertions) { + thread.get_constant(left).as_byte().unwrap() + } else { + unsafe { thread.get_constant(left).as_byte().unwrap_unchecked() } + } + } else { + thread.get_byte_register(left) + }; + let right_value = if right_is_constant { + if cfg!(debug_assertions) { + thread.get_constant(right).as_byte().unwrap() + } else { + unsafe { thread.get_constant(right).as_byte().unwrap_unchecked() } + } + } else { + thread.get_byte_register(right) + }; + let sum = left_value.saturating_add(*right_value); + thread.set_byte_register(destination, Register::Value(sum)); +} + +pub fn add_characters(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { + let destination = instruction.a_field as usize; + let left = instruction.b_field as usize; + let left_is_constant = instruction.b_is_constant; + let right = instruction.c_field as usize; + let right_is_constant = instruction.c_is_constant; + let left_value = if left_is_constant { + if cfg!(debug_assertions) { + thread.get_constant(left).as_character().unwrap() + } else { + unsafe { thread.get_constant(left).as_character().unwrap_unchecked() } + } + } else { + thread.get_character_register(left) + }; + let right_value = if right_is_constant { + if cfg!(debug_assertions) { + thread.get_constant(right).as_character().unwrap() + } else { + unsafe { thread.get_constant(right).as_character().unwrap_unchecked() } + } + } else { + thread.get_character_register(right) + }; + let mut concatenated = DustString::from(String::with_capacity(2)); + + concatenated.push(*left_value); + concatenated.push(*right_value); + + thread.set_string_register(destination, Register::Value(concatenated)); +} + +pub fn add_floats(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { + let destination = instruction.a_field as usize; + let left = instruction.b_field as usize; + let left_is_constant = instruction.b_is_constant; + let right = instruction.c_field as usize; + let right_is_constant = instruction.c_is_constant; + let left_value = if left_is_constant { + if cfg!(debug_assertions) { + thread.get_constant(left).as_float().unwrap() + } else { + unsafe { thread.get_constant(left).as_float().unwrap_unchecked() } + } + } else { + thread.get_float_register(left) + }; + let right_value = if right_is_constant { + if cfg!(debug_assertions) { + thread.get_constant(right).as_float().unwrap() + } else { + unsafe { thread.get_constant(right).as_float().unwrap_unchecked() } + } + } else { + thread.get_float_register(right) + }; + let sum = left_value + *right_value; + + thread.set_float_register(destination, Register::Value(sum)); +} + +pub fn add_integers(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { + let destination = instruction.a_field as usize; + let left = instruction.b_field as usize; + let left_is_constant = instruction.b_is_constant; + let right = instruction.c_field as usize; + let right_is_constant = instruction.c_is_constant; let left_value = if left_is_constant { if cfg!(debug_assertions) { thread.get_constant(left).as_integer().unwrap() @@ -36,3 +122,100 @@ pub fn add_integers(_: &mut usize, instruction: &InstructionFields, thread: &mut thread.set_integer_register(destination, Register::Value(sum)); } + +pub fn add_strings(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { + let destination = instruction.a_field as usize; + let left = instruction.b_field as usize; + let left_is_constant = instruction.b_is_constant; + let right = instruction.c_field as usize; + let right_is_constant = instruction.c_is_constant; + let left_value = if left_is_constant { + if cfg!(debug_assertions) { + thread.get_constant(left).as_string().unwrap() + } else { + unsafe { thread.get_constant(left).as_string().unwrap_unchecked() } + } + } else { + thread.get_string_register(left) + }; + let right_value = if right_is_constant { + if cfg!(debug_assertions) { + thread.get_constant(right).as_string().unwrap() + } else { + unsafe { thread.get_constant(right).as_string().unwrap_unchecked() } + } + } else { + thread.get_string_register(right) + }; + let mut concatenated = + DustString::from(String::with_capacity(left_value.len() + right_value.len())); + + concatenated.push_str(left_value); + concatenated.push_str(right_value); + + thread.set_string_register(destination, Register::Value(concatenated)); +} + +pub fn add_character_string(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { + let destination = instruction.a_field as usize; + let left = instruction.b_field as usize; + let left_is_constant = instruction.b_is_constant; + let right = instruction.c_field as usize; + let right_is_constant = instruction.c_is_constant; + let left_value = if left_is_constant { + if cfg!(debug_assertions) { + thread.get_constant(left).as_character().unwrap() + } else { + unsafe { thread.get_constant(left).as_character().unwrap_unchecked() } + } + } else { + thread.get_character_register(left) + }; + let right_value = if right_is_constant { + if cfg!(debug_assertions) { + thread.get_constant(right).as_string().unwrap() + } else { + unsafe { thread.get_constant(right).as_string().unwrap_unchecked() } + } + } else { + thread.get_string_register(right) + }; + let mut concatenated = DustString::from(String::with_capacity(right_value.len() + 1)); + + concatenated.push(*left_value); + concatenated.push_str(right_value); + + thread.set_string_register(destination, Register::Value(concatenated)); +} + +pub fn add_string_character(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { + let destination = instruction.a_field as usize; + let left = instruction.b_field as usize; + let left_is_constant = instruction.b_is_constant; + let right = instruction.c_field as usize; + let right_is_constant = instruction.c_is_constant; + let left_value = if left_is_constant { + if cfg!(debug_assertions) { + thread.get_constant(left).as_string().unwrap() + } else { + unsafe { thread.get_constant(left).as_string().unwrap_unchecked() } + } + } else { + thread.get_string_register(left) + }; + let right_value = if right_is_constant { + if cfg!(debug_assertions) { + thread.get_constant(right).as_character().unwrap() + } else { + unsafe { thread.get_constant(right).as_character().unwrap_unchecked() } + } + } else { + thread.get_character_register(right) + }; + let mut concatenated = DustString::from(String::with_capacity(left_value.len() + 1)); + + concatenated.push_str(left_value); + concatenated.push(*right_value); + + thread.set_string_register(destination, Register::Value(concatenated)); +} diff --git a/dust-lang/src/vm/action/less.rs b/dust-lang/src/vm/action/less.rs index 254f692..b8dd71d 100644 --- a/dust-lang/src/vm/action/less.rs +++ b/dust-lang/src/vm/action/less.rs @@ -1,10 +1,130 @@ -use tracing::trace; - use crate::{instruction::InstructionFields, vm::Thread}; -pub fn less_integers(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { - trace!("LESS unoptimized"); +pub fn less_booleans(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { + let left = instruction.b_field as usize; + let left_is_constant = instruction.b_is_constant; + let right = instruction.c_field as usize; + let right_is_constant = instruction.c_is_constant; + let left_value = if left_is_constant { + if cfg!(debug_assertions) { + thread.get_constant(left).as_boolean().unwrap() + } else { + unsafe { thread.get_constant(left).as_boolean().unwrap_unchecked() } + } + } else { + thread.get_boolean_register(left) + }; + let right_value = if right_is_constant { + if cfg!(debug_assertions) { + thread.get_constant(right).as_boolean().unwrap() + } else { + unsafe { thread.get_constant(right).as_boolean().unwrap_unchecked() } + } + } else { + thread.get_boolean_register(right) + }; + let is_less_than = left_value < right_value; + let comparator = instruction.d_field; + if is_less_than == comparator { + *ip += 1; + } +} + +pub fn less_bytes(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { + let left = instruction.b_field as usize; + let left_is_constant = instruction.b_is_constant; + let right = instruction.c_field as usize; + let right_is_constant = instruction.c_is_constant; + let left_value = if left_is_constant { + if cfg!(debug_assertions) { + thread.get_constant(left).as_byte().unwrap() + } else { + unsafe { thread.get_constant(left).as_byte().unwrap_unchecked() } + } + } else { + thread.get_byte_register(left) + }; + let right_value = if right_is_constant { + if cfg!(debug_assertions) { + thread.get_constant(right).as_byte().unwrap() + } else { + unsafe { thread.get_constant(right).as_byte().unwrap_unchecked() } + } + } else { + thread.get_byte_register(right) + }; + let is_less_than = left_value < right_value; + let comparator = instruction.d_field; + + if is_less_than == comparator { + *ip += 1; + } +} + +pub fn less_characters(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { + let left = instruction.b_field as usize; + let left_is_constant = instruction.b_is_constant; + let right = instruction.c_field as usize; + let right_is_constant = instruction.c_is_constant; + let left_value = if left_is_constant { + if cfg!(debug_assertions) { + thread.get_constant(left).as_character().unwrap() + } else { + unsafe { thread.get_constant(left).as_character().unwrap_unchecked() } + } + } else { + thread.get_character_register(left) + }; + let right_value = if right_is_constant { + if cfg!(debug_assertions) { + thread.get_constant(right).as_character().unwrap() + } else { + unsafe { thread.get_constant(right).as_character().unwrap_unchecked() } + } + } else { + thread.get_character_register(right) + }; + let is_less_than = left_value < right_value; + let comparator = instruction.d_field; + + if is_less_than == comparator { + *ip += 1; + } +} + +pub fn less_floats(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { + let left = instruction.b_field as usize; + let left_is_constant = instruction.b_is_constant; + let right = instruction.c_field as usize; + let right_is_constant = instruction.c_is_constant; + let left_value = if left_is_constant { + if cfg!(debug_assertions) { + thread.get_constant(left).as_float().unwrap() + } else { + unsafe { thread.get_constant(left).as_float().unwrap_unchecked() } + } + } else { + thread.get_float_register(left) + }; + let right_value = if right_is_constant { + if cfg!(debug_assertions) { + thread.get_constant(right).as_float().unwrap() + } else { + unsafe { thread.get_constant(right).as_float().unwrap_unchecked() } + } + } else { + thread.get_float_register(right) + }; + let is_less_than = left_value < right_value; + let comparator = instruction.d_field; + + if is_less_than == comparator { + *ip += 1; + } +} + +pub fn less_integers(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { let left = instruction.b_field as usize; let left_is_constant = instruction.b_is_constant; let right = instruction.c_field as usize; @@ -34,3 +154,34 @@ pub fn less_integers(ip: &mut usize, instruction: &InstructionFields, thread: &m *ip += 1; } } + +pub fn less_strings(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { + let left = instruction.b_field as usize; + let left_is_constant = instruction.b_is_constant; + let right = instruction.c_field as usize; + let right_is_constant = instruction.c_is_constant; + let left_value = if left_is_constant { + if cfg!(debug_assertions) { + thread.get_constant(left).as_string().unwrap() + } else { + unsafe { thread.get_constant(left).as_string().unwrap_unchecked() } + } + } else { + thread.get_string_register(left) + }; + let right_value = if right_is_constant { + if cfg!(debug_assertions) { + thread.get_constant(right).as_string().unwrap() + } else { + unsafe { thread.get_constant(right).as_string().unwrap_unchecked() } + } + } else { + thread.get_string_register(right) + }; + let is_less_than = left_value < right_value; + let comparator = instruction.d_field; + + if is_less_than == comparator { + *ip += 1; + } +} diff --git a/dust-lang/src/vm/action/mod.rs b/dust-lang/src/vm/action/mod.rs index a10f4e7..a77e64d 100644 --- a/dust-lang/src/vm/action/mod.rs +++ b/dust-lang/src/vm/action/mod.rs @@ -2,9 +2,12 @@ mod add; mod jump; mod less; -use add::add_integers; +use add::{ + add_bytes, add_character_string, add_characters, add_floats, add_integers, + add_string_character, add_strings, +}; use jump::jump; -use less::less_integers; +use less::{less_booleans, less_bytes, less_characters, less_floats, less_integers, less_strings}; use tracing::trace; @@ -229,7 +232,13 @@ impl Action { Operation::LOAD_SELF => load_self, Operation::ADD => match (instruction.b_type, instruction.c_type) { (TypeCode::INTEGER, TypeCode::INTEGER) => add_integers, - _ => todo!(), + (TypeCode::FLOAT, TypeCode::FLOAT) => add_floats, + (TypeCode::BYTE, TypeCode::BYTE) => add_bytes, + (TypeCode::STRING, TypeCode::STRING) => add_strings, + (TypeCode::CHARACTER, TypeCode::CHARACTER) => add_characters, + (TypeCode::STRING, TypeCode::CHARACTER) => add_string_character, + (TypeCode::CHARACTER, TypeCode::STRING) => add_character_string, + _ => unreachable!(), }, Operation::SUBTRACT => subtract, Operation::MULTIPLY => multiply, @@ -239,7 +248,12 @@ impl Action { Operation::NOT => not, Operation::EQUAL => equal, Operation::LESS => match (instruction.b_type, instruction.c_type) { + (TypeCode::BOOLEAN, TypeCode::BOOLEAN) => less_booleans, + (TypeCode::BYTE, TypeCode::BYTE) => less_bytes, + (TypeCode::CHARACTER, TypeCode::CHARACTER) => less_characters, + (TypeCode::FLOAT, TypeCode::FLOAT) => less_floats, (TypeCode::INTEGER, TypeCode::INTEGER) => less_integers, + (TypeCode::STRING, TypeCode::STRING) => less_strings, _ => todo!(), }, Operation::LESS_EQUAL => less_equal,