//! Basic-block storage for Slonik IR.
//!
//! A block is the unit of control-flow in the normalized IR.
//!
//! Each block owns:
//!
//! - a list of block parameters
//! - an ordered list of statements
//!
//! # Block parameters
//!
//! Slonik uses block arguments instead of phi nodes.
//! A predecessor transfers control to a block together with the incoming SSA
//! values for that block's parameters.
//!
//! # Statement order
//!
//! Statements inside a block are ordered.
//! Terminators, when present, must appear as the final statement in the block.
//!
//! # Scope
//!
//! This module only defines **per-block storage**.
//! It does not define:
//!
//! - global body ownership
//! - SSA value storage
//! - expression storage
//! - verification policy
//!
//! Those belong in other IR modules.

use cranelift_entity::EntityList;

use crate::ir::{Stmt, Value};

/// A compact list of block parameters, owned by the [`Body`].
pub type ParamList = EntityList<Value>;

/// A compact ordered list of statements, owned by the [`Body`].
pub type StmtList = EntityList<Stmt>;

/// Per-block storage.
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct BlockData {
    /// The SSA parameters accepted by this block.
    pub params: ParamList,

    /// The ordered statements inside this block.
    pub stmts: StmtList,
}

impl BlockData {
    /// Creates an empty block.
    pub fn new() -> Self {
        Self::default()
    }

    /// Returns whether the block has no parameters and no statements.
    pub fn is_empty(&self) -> bool {
        self.params.is_empty() && self.stmts.is_empty()
    }
}
