use crate::debug::{info::DebugInfo, printable::Printable};
use super::{
instructions::{DrawInstr, Instr},
lexer::Token,
};
#[derive(Debug)]
pub enum PInstr<'s> {
Instr(Instr),
Draw(DrawInstr),
Code(Box<[Token<'s>]>),
Comment(&'s str),
}
impl Printable for PInstr<'_> {
fn print(&self, info: &DebugInfo<'_>, f: &mut impl std::fmt::Write) -> std::fmt::Result {
match self {
Self::Instr(i) => i.print(info, f),
Self::Draw(i) => i.print(info, f),
Self::Code(c) => {
let mut toks = c.iter();
if let Some(t) = toks.next() {
write!(f, "{t}")?;
}
for token in toks {
write!(f, " {token}")?;
}
Ok(())
}
Self::Comment(c) => write!(f, "{c}"),
}
}
}
impl Printable for Code<'_> {
fn print(&self, info: &DebugInfo<'_>, f: &mut impl std::fmt::Write) -> std::fmt::Result {
for instr in &*self.0 {
instr.print(info, f)?;
writeln!(f)?;
}
Ok(())
}
}
#[repr(transparent)]
#[derive(Debug)]
pub struct Code<'s>(Box<[PInstr<'s>]>);
// Pin requires
impl<'s> std::ops::Deref for Code<'s> {
type Target = [PInstr<'s>];
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<'s> Code<'s> {
pub(crate) fn new(code: Box<[PInstr<'s>]>) -> Self {
Self(code)
}
}