neo-decompiler 0.10.1

Neo N3 NEF decompiler: parse, disassemble, lift bytecode to high-level pseudocode and C# skeletons, with a CLI, JSON reports, and optional WebAssembly bindings.
Documentation
use std::fmt;

use super::stmt::SsaStmt;
use crate::decompiler::cfg::ssa::variable::PhiNode;

/// A basic block in SSA form.
///
/// SSA blocks have φ nodes at the beginning (before any regular statements),
/// followed by the SSA-converted statements.
#[derive(Debug, Clone, Default)]
pub struct SsaBlock {
    /// φ nodes at the start of this block.
    ///
    /// These must come first, as they conceptually execute at the edge
    /// from each predecessor.
    pub phi_nodes: Vec<PhiNode>,

    /// Regular statements in SSA form.
    pub stmts: Vec<SsaStmt>,
}

impl SsaBlock {
    /// Create a new empty SSA block.
    #[must_use]
    pub fn new() -> Self {
        Self::default()
    }

    /// Add a φ node to this block.
    pub fn add_phi(&mut self, phi: PhiNode) {
        self.phi_nodes.push(phi);
    }

    /// Add a statement to this block.
    pub fn add_stmt(&mut self, stmt: SsaStmt) {
        self.stmts.push(stmt);
    }

    /// Check if this block is empty.
    #[must_use]
    pub fn is_empty(&self) -> bool {
        self.phi_nodes.is_empty() && self.stmts.is_empty()
    }

    /// Get the total number of φ nodes.
    #[must_use]
    pub fn phi_count(&self) -> usize {
        self.phi_nodes.len()
    }

    /// Get the total number of statements.
    #[must_use]
    pub fn stmt_count(&self) -> usize {
        self.stmts.len()
    }
}

impl fmt::Display for SsaBlock {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        for phi in &self.phi_nodes {
            writeln!(f, "    {}", phi)?;
        }

        for stmt in &self.stmts {
            writeln!(f, "    {}", stmt)?;
        }

        Ok(())
    }
}