use std::fmt::{Debug, Display}; use crate::prelude::*; #[derive(Clone, Default)] pub struct Chunk { pub constants: Vec, pub code: Vec, pub pos: Vec, } impl Chunk { pub fn new() -> Self { Self { constants: Vec::new(), code: Vec::new(), pos: Vec::new(), } } } #[derive(Clone, Debug)] #[repr(align(4))] pub enum Instruction { NoOp, CreateLocal, LoadLocal(u16), StoreLocal(u16), DiscardLocals(u16), LoadGlobal(u16), StoreGlobal(u16), Const(u16), Int(i16), True, False, Nil, Dup, Discard(u16), UnaryOp(UnaryOp), BinaryOp(BinaryOp), NewList(u16), NewTable(u16), NewMatrix(u16, u8), Field(u16), StoreField(u16), Index(u8), StoreIndex(u8), Jump(u16), JumpTrue(u16), JumpFalse(u16), JumpNil(u16), IterCreate, IterNext, Try(u16), TryEnd, Call(u8), Return, } impl Debug for Chunk { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "[Chunk {}]", self.code.len()) } } impl Display for Chunk { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { writeln!(f, "constants: ")?; for (i, c) in self.constants.iter().enumerate() { writeln!(f, " {i:04}: {c}")?; } writeln!(f, "code:")?; for (i, ins) in self.code.iter().enumerate() { writeln!(f, " {i:04}: {ins}")?; } Ok(()) } } impl Display for Instruction { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { use Instruction::*; match self { NoOp => write!(f, "noop"), CreateLocal => write!(f, "create local"), LoadLocal(idx) => write!(f, "load local \x1b[33m{idx}\x1b[0m"), StoreLocal(idx) => write!(f, "store local \x1b[33m{idx}\x1b[0m"), DiscardLocals(count) => write!(f, "discard locals \x1b[35m{count}\x1b[0m"), LoadGlobal(name) => write!(f, "load global \x1b[36m{name}\x1b[0m"), StoreGlobal(name) => write!(f, "store global \x1b[36m{name}\x1b[0m"), Const(idx) => write!(f, "const \x1b[33m{idx}\x1b[0m"), Int(idx) => write!(f, "push \x1b[34m{idx}\x1b[0m"), True => write!(f, "push \x1b[34mtrue\x1b[0m"), False => write!(f, "push \x1b[34mfalse\x1b[0m"), Nil => write!(f, "push \x1b[34mnil\x1b[0m"), Dup => write!(f, "duplicate"), Discard(count) => write!(f, "discard \x1b[35m{count}\x1b[0m"), UnaryOp(op) => write!(f, "unary \x1b[32m{op:?}\x1b[0m"), BinaryOp(op) => write!(f, "binary \x1b[32m{op:?}\x1b[0m"), NewList(len) => write!(f, "list \x1b[35m{len}\x1b[0m"), NewTable(len) => write!(f, "table \x1b[35m{len}\x1b[0m"), NewMatrix(len, codomain) => write!(f, "matrix \x1b[35m{}\x1b[0mx\x1b[35m{}\x1b[0m", *len / (*codomain as u16), codomain), Index(idx) => write!(f, "index \x1b[33m{idx}\x1b[0m"), StoreIndex(idx) => write!(f, "store_index \x1b[33m{idx}\x1b[0m"), Jump(idx) => write!(f, "jump \x1b[33m{idx}\x1b[0m"), JumpTrue(idx) => write!(f, "jumpt \x1b[33m{idx}\x1b[0m"), JumpFalse(idx) => write!(f, "jumpf \x1b[33m{idx}\x1b[0m"), JumpNil(idx) => write!(f, "jumpn \x1b[33m{idx}\x1b[0m"), Call(arity) => write!(f, "call \x1b[35m{arity}\x1b[0m"), Return => write!(f, "return"), IterCreate => write!(f, "iter create"), IterNext => write!(f, "iter next"), Field(name_idx) => write!(f, "field \x1b[33m{name_idx}\x1b[0m"), StoreField(name_idx) => write!(f, "store field \x1b[33m{name_idx}\x1b[0m"), Try(idx) => write!(f, "try \x1b[33m{idx}\x1b[0m"), TryEnd => write!(f, "try end"), } } }