|
|
|
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(())
|
|
|
|
}
|
|
|
|
}
|