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::{
|
||||
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));
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user