Skip to main content

rune_ssa/
program.rs

1use crate::global::Global;
2use crate::{Block, Error, Var};
3use std::fmt;
4
5/// The central state machine assembler.
6pub struct Program {
7    global: Global,
8    blocks: Vec<Block>,
9}
10
11impl Program {
12    /// Construct a new empty state machine.
13    pub fn new() -> Self {
14        Self {
15            global: Global::default(),
16            blocks: Vec::new(),
17        }
18    }
19
20    /// Seal the given program.
21    pub fn seal(&self) -> Result<(), Error> {
22        for block in &self.blocks {
23            block.seal()?;
24        }
25
26        Ok(())
27    }
28
29    /// Allocate a new value.
30    pub fn var(&self) -> Var {
31        self.global.var()
32    }
33
34    /// Construct a new block associated with the state machine.
35    pub fn block(&mut self) -> Block {
36        let block = self.global.block(None);
37        self.blocks.push(block.clone());
38        block
39    }
40
41    /// Construct a block with a name.
42    pub fn named(&mut self, name: &str) -> Block {
43        let block = self.global.block(Some(name.into()));
44        self.blocks.push(block.clone());
45        block
46    }
47
48    /// Dump the current state of the program.
49    ///
50    /// This is useful for diagnostics.
51    pub fn dump(&self) -> ProgramDump<'_> {
52        ProgramDump(self)
53    }
54}
55
56pub struct ProgramDump<'a>(&'a Program);
57
58impl fmt::Display for ProgramDump<'_> {
59    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
60        let constants = self.0.global.constants();
61
62        if !constants.is_empty() {
63            writeln!(f, "constants:")?;
64
65            for (id, c) in constants.iter().enumerate() {
66                writeln!(f, "  C{} <- {:?}", id, c)?;
67            }
68
69            if !self.0.blocks.is_empty() {
70                writeln!(f)?;
71            }
72        }
73
74        let mut it = self.0.blocks.iter();
75        let last = it.next_back();
76
77        for b in it {
78            writeln!(f, "{}", b.dump())?;
79        }
80
81        if let Some(b) = last {
82            write!(f, "{}", b.dump())?;
83        }
84
85        Ok(())
86    }
87}