1
0

Add VM actions for add and less

This commit is contained in:
Jeff 2025-02-15 16:14:45 -05:00
parent afcc1874fe
commit 5030171bb6
3 changed files with 360 additions and 12 deletions

View File

@ -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));
}

View File

@ -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;
}
}

View File

@ -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,