miden_assembly/ast/
block.rs

1use alloc::vec::Vec;
2use core::fmt;
3
4use super::Op;
5use crate::{SourceSpan, Spanned};
6
7// BASIC BLOCK
8// ================================================================================================
9
10/// Represents a basic block in Miden Assembly syntax.
11///
12/// Blocks can be nested, see [Op] for details.
13#[derive(Clone, Default)]
14pub struct Block {
15    span: SourceSpan,
16    body: Vec<Op>,
17}
18
19impl Block {
20    /// Creates a new [Block].
21    pub fn new(span: SourceSpan, body: Vec<Op>) -> Self {
22        Self { span, body }
23    }
24
25    /// Appends `op` to this block.
26    pub fn push(&mut self, op: Op) {
27        self.body.push(op);
28    }
29
30    /// Returns the number of ops in this block.
31    ///
32    /// NOTE: The count does not include nested ops,
33    /// only those at the root of the block.
34    pub fn len(&self) -> usize {
35        self.body.len()
36    }
37
38    /// Returns true if this block is empty
39    pub fn is_empty(&self) -> bool {
40        self.body.is_empty()
41    }
42
43    /// Returns an iterator for the operations in this block.
44    pub fn iter(&self) -> core::slice::Iter<'_, Op> {
45        self.body.iter()
46    }
47
48    /// Returns a mutable iterator for the operations in this block.
49    pub fn iter_mut(&mut self) -> core::slice::IterMut<'_, Op> {
50        self.body.iter_mut()
51    }
52}
53
54impl fmt::Debug for Block {
55    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
56        f.debug_list().entries(&self.body).finish()
57    }
58}
59
60impl crate::prettier::PrettyPrint for Block {
61    fn render(&self) -> crate::prettier::Document {
62        use crate::{Span, ast::Instruction, prettier::*};
63
64        // If a block is empty, pretty-print it with a `nop` instruction
65        let default_body = [Op::Inst(Span::new(self.span, Instruction::Nop))];
66        let body = if self.body.is_empty() {
67            default_body.as_slice().iter()
68        } else {
69            self.body.iter()
70        }
71        .map(PrettyPrint::render)
72        .reduce(|acc, doc| acc + nl() + doc)
73        .unwrap();
74
75        indent(4, nl() + body) + nl()
76    }
77}
78
79impl Spanned for Block {
80    fn span(&self) -> SourceSpan {
81        self.span
82    }
83}
84
85impl Eq for Block {}
86
87impl PartialEq for Block {
88    fn eq(&self, other: &Self) -> bool {
89        self.body == other.body
90    }
91}