//! Compile-time-populated registries, distributed across the consuming crate's
//! source via linkme. The proc macros emit `#[linkme::distributed_slice(...)]`
//! statics that land here at link time.

use crate::ir::NamedType;
use crate::traits::FunctionSpec;
use linkme::distributed_slice;

/// One named-type registration. Emitted by `#[derive(Mizan)]`.
pub struct TypeEntry {
    pub name: &'static str,
    pub shape_fn: fn() -> NamedType,
}

/// One context-marker registration. Emitted by `#[mizan::context]`.
pub struct ContextEntry {
    pub name: &'static str,
}

#[distributed_slice]
pub static TYPES: [TypeEntry] = [..];

#[distributed_slice]
pub static CONTEXTS: [ContextEntry] = [..];

#[distributed_slice]
pub static FUNCTIONS: [&'static dyn FunctionSpec] = [..];

/// Find a registered function by wire name. Used by the HTTP adapter.
pub fn lookup_function(name: &str) -> Option<&'static dyn FunctionSpec> {
    FUNCTIONS.iter().copied().find(|f| f.name() == name)
}

/// Find a registered context by name. Used by graph_check.
pub fn lookup_context(name: &str) -> Option<&'static ContextEntry> {
    CONTEXTS.iter().find(|c| c.name == name)
}

/// All functions that declare a given context as their `context` membership.
/// Order matches `FUNCTIONS` iteration order — i.e., registration order.
pub fn context_members(ctx_name: &str) -> Vec<&'static dyn FunctionSpec> {
    FUNCTIONS
        .iter()
        .copied()
        .filter(|f| f.context() == Some(ctx_name))
        .collect()
}
