You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

86 lines
2.1 KiB

use std::fmt;
use crate::value::Value;
#[derive(Debug)]
pub enum OpCode {
Constant(usize),
Add,
Subtract,
Multiply,
Divide,
Negate,
Return,
}
#[derive(Debug, Default)]
pub struct Chunk {
pub code: Vec<OpCode>,
pub lines: Vec<usize>,
pub constants: Vec<Value>,
}
impl Chunk {
pub fn push(&mut self, op_code: OpCode, line: usize) {
self.code.push(op_code);
self.lines.push(line);
}
pub fn push_constant(&mut self, value: Value, line: usize) {
self.constants.push(value);
self.push(OpCode::Constant(self.constants.len() - 1), line)
}
pub fn disassemble(&self, name: &str) {
println!("== {} ==\n{}", name, self);
}
}
impl fmt::Display for Chunk {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for i in 0..self.code.len() {
writeln!(f, "{}", DisassembledInstruction { i, chunk: self })?;
}
Ok(())
}
}
pub struct DisassembledInstruction<'a> {
i: usize,
chunk: &'a Chunk,
}
impl<'a> DisassembledInstruction<'a> {
pub fn new(i: usize, chunk: &'a Chunk) -> Self {
Self { i, chunk }
}
}
impl fmt::Display for DisassembledInstruction<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:04} ", self.i)?;
let line = self.chunk.lines[self.i];
if self.i > 0 && line != self.chunk.lines[self.i - 1] {
write!(f, " | ")?;
} else {
write!(f, "{:>4} ", line)?;
}
match self.chunk.code[self.i] {
OpCode::Constant(constant) => write!(
f,
"{:<16} {:4} '{}'",
"OP_CONSTANT", constant, self.chunk.constants[constant]
)?,
OpCode::Add => write!(f, "OP_ADD")?,
OpCode::Subtract => write!(f, "OP_SUBTRACT")?,
OpCode::Multiply => write!(f, "OP_MULTIPLY")?,
OpCode::Divide => write!(f, "OP_DIVIDE")?,
OpCode::Negate => write!(f, "OP_NEGATE")?,
OpCode::Return => write!(f, "OP_RETURN")?,
}
Ok(())
}
}