/*! * Unified Box Factory Architecture * * Phase 9.78: 統合BoxFactoryアーキテクチャ * すべてのBox生成(ビルトイン、ユーザー定義、プラグイン)を統一的に扱う * * Design principles: * - "Everything is Box" 哲学の実装レベルでの体現 * - birth/finiライフサイクルの明確な責務分離 * - 保守性と拡張性の劇的向上 */ use crate::box_trait::NyashBox; use crate::interpreter::RuntimeError; use std::collections::HashMap; use std::sync::{Arc, RwLock}; /// Unified interface for all Box creation pub trait BoxFactory: Send + Sync { /// Create a new Box instance with given arguments fn create_box( &self, name: &str, args: &[Box], ) -> Result, RuntimeError>; /// Check if this factory is currently available fn is_available(&self) -> bool { true } /// Get list of Box types this factory can create fn box_types(&self) -> Vec<&str>; /// Check if this factory supports birth/fini lifecycle fn supports_birth(&self) -> bool { true } /// Identify builtin factory to enforce reserved-name protections fn is_builtin_factory(&self) -> bool { false } } /// Registry that manages all BoxFactory implementations pub struct UnifiedBoxRegistry { /// Ordered list of factories (priority: builtin > user > plugin) pub factories: Vec>, /// Quick lookup cache for performance type_cache: RwLock>, // maps type name to factory index } impl UnifiedBoxRegistry { /// Create a new empty registry pub fn new() -> Self { Self { factories: Vec::new(), type_cache: RwLock::new(HashMap::new()), } } /// Register a new factory pub fn register(&mut self, factory: Arc) { // Get all types this factory can create let types = factory.box_types(); let factory_index = self.factories.len(); // Update cache let mut cache = self.type_cache.write().unwrap(); // Reserved core types that must remain builtin-owned fn is_reserved_type(name: &str) -> bool { matches!( name, // Core value types "StringBox" | "IntegerBox" | "BoolBox" | "FloatBox" | "NullBox" // Core containers and result | "ArrayBox" | "MapBox" | "ResultBox" // Core method indirection | "MethodBox" ) } for type_name in types { // Enforce reserved names: only builtin factory may claim them if is_reserved_type(type_name) && !factory.is_builtin_factory() { eprintln!( "[UnifiedBoxRegistry] ❌ Rejecting registration of reserved type '{}' by non-builtin factory #{}", type_name, factory_index ); continue; } // First registered factory wins (priority order) let entry = cache.entry(type_name.to_string()); use std::collections::hash_map::Entry; match entry { Entry::Occupied(existing) => { // Collision: type already claimed by earlier factory eprintln!("[UnifiedBoxRegistry] ⚠️ Duplicate registration for '{}': keeping factory #{}, ignoring later factory #{}", existing.key(), existing.get(), factory_index); } Entry::Vacant(v) => { v.insert(factory_index); } } } self.factories.push(factory); } /// Create a Box using the unified interface pub fn create_box( &self, name: &str, args: &[Box], ) -> Result, RuntimeError> { // Prefer plugin-builtins when enabled and provider is available in v2 registry if std::env::var("NYASH_USE_PLUGIN_BUILTINS").ok().as_deref() == Some("1") { use crate::runtime::{get_global_registry, BoxProvider}; // Allowlist types for override: env NYASH_PLUGIN_OVERRIDE_TYPES="ArrayBox,MapBox" (default: ArrayBox,MapBox) let allow: Vec = if let Ok(list) = std::env::var("NYASH_PLUGIN_OVERRIDE_TYPES") { list.split(',').map(|s| s.trim().to_string()).filter(|s| !s.is_empty()).collect() } else { vec!["ArrayBox".into(), "MapBox".into()] }; if allow.iter().any(|t| t == name) { let v2 = get_global_registry(); if let Some(provider) = v2.get_provider(name) { if let BoxProvider::Plugin(_lib) = provider { return v2.create_box(name, args) .map_err(|e| RuntimeError::InvalidOperation { message: format!("Plugin Box creation failed: {}", e) }); } } } } // Check cache first let cache = self.type_cache.read().unwrap(); if let Some(&factory_index) = cache.get(name) { if let Some(factory) = self.factories.get(factory_index) { if factory.is_available() { return factory.create_box(name, args); } } } drop(cache); // Linear search through all factories for factory in &self.factories { if !factory.is_available() { continue; } // For factories that advertise types, check if they support this type let box_types = factory.box_types(); if !box_types.is_empty() && !box_types.contains(&name) { continue; } // Try to create the box (factories with empty box_types() will always be tried) match factory.create_box(name, args) { Ok(boxed) => return Ok(boxed), Err(_) => continue, // Try next factory } } // Final fallback: if v2 plugin registry has a provider for this name, try it once { let v2 = crate::runtime::get_global_registry(); if let Some(_prov) = v2.get_provider(name) { if let Ok(b) = v2.create_box(name, args) { return Ok(b); } } } Err(RuntimeError::InvalidOperation { message: format!("Unknown Box type: {}", name), }) } /// Check whether a type name is known to the registry pub fn has_type(&self, name: &str) -> bool { // Check cache first { let cache = self.type_cache.read().unwrap(); if let Some(&idx) = cache.get(name) { if let Some(factory) = self.factories.get(idx) { if factory.is_available() { return true; } } } } // Fallback: scan factories that can enumerate types for factory in &self.factories { if !factory.is_available() { continue; } let types = factory.box_types(); if !types.is_empty() && types.contains(&name) { return true; } } false } /// Get all available Box types pub fn available_types(&self) -> Vec { let mut types = Vec::new(); for factory in &self.factories { if factory.is_available() { for type_name in factory.box_types() { types.push(type_name.to_string()); } } } types.sort(); types.dedup(); types } } /// Re-export submodules pub mod user_defined; pub mod plugin; pub mod builtin; #[cfg(test)] mod tests { use super::*; #[test] fn test_registry_creation() { let registry = UnifiedBoxRegistry::new(); assert_eq!(registry.available_types().len(), 0); } }