use crate::global::Global;
use crate::{Block, Error, Var};
use std::fmt;
pub struct Program {
global: Global,
blocks: Vec<Block>,
}
impl Program {
pub fn new() -> Self {
Self {
global: Global::default(),
blocks: Vec::new(),
}
}
pub fn seal(&self) -> Result<(), Error> {
for block in &self.blocks {
block.seal()?;
}
Ok(())
}
pub fn var(&self) -> Var {
self.global.var()
}
pub fn block(&mut self) -> Block {
let block = self.global.block(None);
self.blocks.push(block.clone());
block
}
pub fn named(&mut self, name: &str) -> Block {
let block = self.global.block(Some(name.into()));
self.blocks.push(block.clone());
block
}
pub fn dump(&self) -> ProgramDump<'_> {
ProgramDump(self)
}
}
pub struct ProgramDump<'a>(&'a Program);
impl fmt::Display for ProgramDump<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let constants = self.0.global.constants();
if !constants.is_empty() {
writeln!(f, "constants:")?;
for (id, c) in constants.iter().enumerate() {
writeln!(f, " C{} <- {:?}", id, c)?;
}
if !self.0.blocks.is_empty() {
writeln!(f)?;
}
}
let mut it = self.0.blocks.iter();
let last = it.next_back();
for b in it {
writeln!(f, "{}", b.dump())?;
}
if let Some(b) = last {
write!(f, "{}", b.dump())?;
}
Ok(())
}
}