opcode.rs 1.57 KiB
use std::error::Error;
use std::fmt::{Display, Formatter};
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
pub enum OpCode {
Return,
/// Load a constant value from the chunk's data pool. Data starts at the included offset
Constant(usize),
Invert,
Add,
Multiply,
Divide,
Subtract,
}
impl OpCode {
pub fn next_offset(&self, current: usize) -> usize {
match self {
_ => current + 1,
}
}
pub fn op_byte(&self) -> u8 {
match self {
OpCode::Return => 1,
OpCode::Constant(_) => 2,
OpCode::Invert => 3,
OpCode::Add => 4,
OpCode::Multiply => 5,
OpCode::Divide => 6,
OpCode::Subtract => 7,
}
}
pub fn operand_bytes(&self) -> Vec<u8> {
match self {
OpCode::Constant(value) => value.to_le_bytes().to_vec(),
_ => vec![],
}
}
pub fn format_operand(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
for byte in self.operand_bytes() {
write!(f, "{:02x}", byte)?;
}
Ok(())
}
}
#[derive(Clone, Debug)]
pub enum OpCodeError {
Unknown(u8),
}
impl Display for OpCodeError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::Unknown(value) => write!(f, "Unknown opcode {}", value),
}
}
}
impl Error for OpCodeError {}
impl Display for OpCode {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}",
match self {
OpCode::Return => "op_return",
OpCode::Constant(_) => "op_constant",
OpCode::Invert => "op_negate",
OpCode::Add => "op_add",
OpCode::Multiply => "op_multiply",
OpCode::Divide => "op_divide",
OpCode::Subtract => "op_subtract",
}
)
}
}