dust/dust-lang/src/instruction.rs

137 lines
4.6 KiB
Rust
Raw Normal View History

2024-09-10 03:24:22 +00:00
use std::fmt::{self, Display, Formatter};
use serde::{Deserialize, Serialize};
use crate::Chunk;
#[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize)]
pub enum Instruction {
Constant = 0,
Return = 1,
Pop = 2,
// Variables
DefineVariableRuntime = 3,
DefineVariableConstant = 4,
GetVariable = 5,
SetVariable = 6,
2024-09-10 03:24:22 +00:00
// Unary
Negate = 7,
Not = 8,
2024-09-10 03:24:22 +00:00
// Binary
Add = 9,
Subtract = 10,
Multiply = 11,
Divide = 12,
Greater = 13,
Less = 14,
GreaterEqual = 15,
LessEqual = 16,
Equal = 17,
NotEqual = 18,
And = 19,
Or = 20,
2024-09-10 03:24:22 +00:00
}
impl Instruction {
pub fn from_byte(byte: u8) -> Option<Self> {
match byte {
0 => Some(Instruction::Constant),
1 => Some(Instruction::Return),
2 => Some(Instruction::Pop),
3 => Some(Instruction::DefineVariableRuntime),
4 => Some(Instruction::DefineVariableConstant),
5 => Some(Instruction::GetVariable),
6 => Some(Instruction::SetVariable),
7 => Some(Instruction::Negate),
8 => Some(Instruction::Not),
9 => Some(Instruction::Add),
10 => Some(Instruction::Subtract),
11 => Some(Instruction::Multiply),
12 => Some(Instruction::Divide),
13 => Some(Instruction::Greater),
14 => Some(Instruction::Less),
15 => Some(Instruction::GreaterEqual),
16 => Some(Instruction::LessEqual),
17 => Some(Instruction::Equal),
18 => Some(Instruction::NotEqual),
19 => Some(Instruction::And),
20 => Some(Instruction::Or),
2024-09-10 03:24:22 +00:00
_ => None,
}
}
pub fn disassemble(&self, chunk: &Chunk, offset: usize) -> String {
match self {
Instruction::Constant => {
let (argument, _) = chunk.get_code(offset + 1).unwrap();
let value_display = chunk
.get_constant(*argument)
.map(|value| value.to_string())
.unwrap_or_else(|error| error.to_string());
format!("CONSTANT {argument} {value_display}")
2024-09-10 03:24:22 +00:00
}
Instruction::Return => "RETURN".to_string(),
Instruction::Pop => "POP".to_string(),
2024-09-10 03:24:22 +00:00
// Variables
Instruction::DefineVariableRuntime => "DEFINE_VARIABLE_RUNTIME".to_string(),
Instruction::DefineVariableConstant => {
let (argument, _) = chunk.get_code(offset + 1).unwrap();
let identifier_display = match chunk.get_identifier(*argument) {
2024-09-10 03:24:22 +00:00
Ok(identifier) => identifier.to_string(),
Err(error) => error.to_string(),
2024-09-10 03:24:22 +00:00
};
format!("DEFINE_VARIABLE_CONSTANT {argument} {identifier_display}")
2024-09-10 03:24:22 +00:00
}
Instruction::GetVariable => {
let (argument, _) = chunk.get_code(offset + 1).unwrap();
let identifier_display = match chunk.get_identifier(*argument) {
2024-09-10 03:24:22 +00:00
Ok(identifier) => identifier.to_string(),
Err(error) => error.to_string(),
2024-09-10 03:24:22 +00:00
};
format!("GET_VARIABLE {argument} {identifier_display}")
2024-09-10 03:24:22 +00:00
}
Instruction::SetVariable => {
let (argument, _) = chunk.get_code(offset + 1).unwrap();
let identifier_display = match chunk.get_identifier(*argument) {
2024-09-10 03:24:22 +00:00
Ok(identifier) => identifier.to_string(),
Err(error) => error.to_string(),
2024-09-10 03:24:22 +00:00
};
format!("SET_VARIABLE {identifier_display}")
2024-09-10 03:24:22 +00:00
}
// Unary
Instruction::Negate => "NEGATE".to_string(),
Instruction::Not => "NOT".to_string(),
// Binary
Instruction::Add => "ADD".to_string(),
Instruction::Subtract => "SUBTRACT".to_string(),
Instruction::Multiply => "MULTIPLY".to_string(),
Instruction::Divide => "DIVIDE".to_string(),
Instruction::Greater => "GREATER".to_string(),
Instruction::Less => "LESS".to_string(),
Instruction::GreaterEqual => "GREATER_EQUAL".to_string(),
Instruction::LessEqual => "LESS_EQUAL".to_string(),
Instruction::Equal => "EQUAL".to_string(),
Instruction::NotEqual => "NOT_EQUAL".to_string(),
Instruction::And => "AND".to_string(),
Instruction::Or => "OR".to_string(),
}
}
}
impl Display for Instruction {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{self:?}")
}
}