Skip to content
Snippets Groups Projects
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",
			}
		)
	}
}