miden_assembly_syntax/ast/
block.rs

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