gbf_core/decompiler/ast/
block.rs

1#![deny(missing_docs)]
2
3use gbf_macros::AstNodeTransform;
4use serde::{Deserialize, Serialize};
5
6use super::{AstKind, AstVisitable, ptr::P, visitors::AstVisitor};
7
8/// Represents a function call
9#[derive(Debug, Clone, Serialize, Deserialize, Eq, AstNodeTransform)]
10#[convert_to(AstKind::Block)]
11pub struct BlockNode {
12    /// The instructions in the block.
13    pub instructions: Vec<AstKind>,
14}
15
16impl BlockNode {
17    /// Creates a new block node.
18    ///
19    /// # Arguments
20    /// - `instructions`: The instructions in the block.
21    pub fn new<V>(instructions: Vec<V>) -> Self
22    where
23        V: Into<AstKind>,
24    {
25        Self {
26            instructions: instructions.into_iter().map(Into::into).collect(),
27        }
28    }
29}
30
31impl AstVisitable for P<BlockNode> {
32    fn accept<V: AstVisitor>(&self, visitor: &mut V) -> V::Output {
33        visitor.visit_block(self)
34    }
35}
36
37// == Other implementations for unary operations ==
38impl PartialEq for BlockNode {
39    fn eq(&self, other: &Self) -> bool {
40        self.instructions == other.instructions
41    }
42}
43
44#[cfg(test)]
45mod tests {
46    use super::*;
47    use crate::decompiler::ast::{emit, new_assignment, new_float, new_id};
48
49    #[test]
50    fn test_block_node() {
51        let stmt_1 = new_assignment(new_id("foo"), new_id("bar"));
52        let stmt_2 = new_assignment(new_id("baz"), new_float("3.14"));
53        let block = BlockNode::new(vec![stmt_1, stmt_2]);
54        assert_eq!(block.instructions.len(), 2);
55    }
56
57    #[test]
58    fn test_block_emit() {
59        let stmt_1 = new_assignment(new_id("foo"), new_id("bar"));
60        let stmt_2 = new_assignment(new_id("baz"), new_float("3.14"));
61        let block = BlockNode::new(vec![stmt_1, stmt_2]);
62        let output = emit(block);
63        assert_eq!(output, "\n{\n    foo = bar;\n    baz = 3.14;\n}");
64    }
65}