Add VM actions for add and less
This commit is contained in:
parent
afcc1874fe
commit
5030171bb6
@ -1,19 +1,105 @@
|
|||||||
use tracing::trace;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
instruction::InstructionFields,
|
instruction::InstructionFields,
|
||||||
vm::{Register, Thread},
|
vm::{Register, Thread},
|
||||||
|
DustString,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn add_integers(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
pub fn add_bytes(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
||||||
trace!("ADD: Run and cache pointers");
|
|
||||||
|
|
||||||
let destination = instruction.a_field as usize;
|
let destination = instruction.a_field as usize;
|
||||||
let left = instruction.b_field as usize;
|
let left = instruction.b_field as usize;
|
||||||
let left_is_constant = instruction.b_is_constant;
|
let left_is_constant = instruction.b_is_constant;
|
||||||
let right = instruction.c_field as usize;
|
let right = instruction.c_field as usize;
|
||||||
let right_is_constant = instruction.c_is_constant;
|
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 {
|
let left_value = if left_is_constant {
|
||||||
if cfg!(debug_assertions) {
|
if cfg!(debug_assertions) {
|
||||||
thread.get_constant(left).as_integer().unwrap()
|
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));
|
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));
|
||||||
|
}
|
||||||
|
@ -1,10 +1,130 @@
|
|||||||
use tracing::trace;
|
|
||||||
|
|
||||||
use crate::{instruction::InstructionFields, vm::Thread};
|
use crate::{instruction::InstructionFields, vm::Thread};
|
||||||
|
|
||||||
pub fn less_integers(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
pub fn less_booleans(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
||||||
trace!("LESS unoptimized");
|
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 = instruction.b_field as usize;
|
||||||
let left_is_constant = instruction.b_is_constant;
|
let left_is_constant = instruction.b_is_constant;
|
||||||
let right = instruction.c_field as usize;
|
let right = instruction.c_field as usize;
|
||||||
@ -34,3 +154,34 @@ pub fn less_integers(ip: &mut usize, instruction: &InstructionFields, thread: &m
|
|||||||
*ip += 1;
|
*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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -2,9 +2,12 @@ mod add;
|
|||||||
mod jump;
|
mod jump;
|
||||||
mod less;
|
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 jump::jump;
|
||||||
use less::less_integers;
|
use less::{less_booleans, less_bytes, less_characters, less_floats, less_integers, less_strings};
|
||||||
|
|
||||||
use tracing::trace;
|
use tracing::trace;
|
||||||
|
|
||||||
@ -229,7 +232,13 @@ impl Action {
|
|||||||
Operation::LOAD_SELF => load_self,
|
Operation::LOAD_SELF => load_self,
|
||||||
Operation::ADD => match (instruction.b_type, instruction.c_type) {
|
Operation::ADD => match (instruction.b_type, instruction.c_type) {
|
||||||
(TypeCode::INTEGER, TypeCode::INTEGER) => add_integers,
|
(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::SUBTRACT => subtract,
|
||||||
Operation::MULTIPLY => multiply,
|
Operation::MULTIPLY => multiply,
|
||||||
@ -239,7 +248,12 @@ impl Action {
|
|||||||
Operation::NOT => not,
|
Operation::NOT => not,
|
||||||
Operation::EQUAL => equal,
|
Operation::EQUAL => equal,
|
||||||
Operation::LESS => match (instruction.b_type, instruction.c_type) {
|
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::INTEGER, TypeCode::INTEGER) => less_integers,
|
||||||
|
(TypeCode::STRING, TypeCode::STRING) => less_strings,
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
},
|
},
|
||||||
Operation::LESS_EQUAL => less_equal,
|
Operation::LESS_EQUAL => less_equal,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user