diff --git a/docs/development/current/main/core_boxes_design.md b/docs/development/current/main/core_boxes_design.md index 10ae0eae..949dfc2c 100644 --- a/docs/development/current/main/core_boxes_design.md +++ b/docs/development/current/main/core_boxes_design.md @@ -1,6 +1,6 @@ -# Core Boxes 設計ドキュメント(Phase 87 完了版) +# Core Boxes 設計ドキュメント(Phase 87–94 完了版) -Phase 87 で実装された CoreBoxId/CoreMethodId の完全仕様。 +Phase 87 で実装された CoreBoxId/CoreMethodId と、Phase 91–94 で統合された CoreServices/PluginHost/Adapter の仕様。 **目的**: Box名・メソッド名のハードコードを型安全な enum に箱化することで、以下を実現: - ✅ コンパイル時検証(タイポ撲滅) @@ -8,7 +8,10 @@ Phase 87 で実装された CoreBoxId/CoreMethodId の完全仕様。 - ✅ SSOT(Single Source of Truth)確立 - ✅ 保守性向上 -**実装状況**: ✅ Phase 87 完了(2025-12-02) +**実装状況**: +- ✅ Phase 87: CoreBoxId/CoreMethodId 実装 +- ✅ Phase 91: CoreServices/PluginHost skeleton +- ✅ Phase 94: Box → Service Adapter 実装と Dummy 削除 --- @@ -546,4 +549,3 @@ NYASH_USE_PLUGIN_HOST=1 ./target/release/nyash apps/tests/selfhost_min.hako 2. `src/runtime/core_services.rs`: CoreServices::dummy() ヘルパー 3. `src/runtime/mod.rs`: initialize_runtime() 実装(環境変数制御) 4. `src/runner/selfhost.rs`: PluginHost 初期化追加 - diff --git a/src/runtime/core_services.rs b/src/runtime/core_services.rs index 62c9ee2a..b1668496 100644 --- a/src/runtime/core_services.rs +++ b/src/runtime/core_services.rs @@ -5,6 +5,7 @@ use std::sync::Arc; use crate::runtime::CoreBoxId; +use crate::box_trait::NyashBox; /// StringBox Service trait pub trait StringService: Send + Sync { @@ -80,20 +81,108 @@ impl CoreServices { // Phase 92 以降で各 Service の初期化を検証 } - /// Phase 93: ダミー実装(Phase 94 で削除予定) - pub fn dummy() -> Self { - use crate::runtime::plugin_host::*; - Self { - string: Arc::new(DummyStringService), - integer: Arc::new(DummyIntegerService), - bool: Arc::new(DummyBoolService), - array: Arc::new(DummyArrayService), - map: Arc::new(DummyMapService), - console: Arc::new(DummyConsoleService), - } +} + +// ============================================================================ +// Phase 94: Adapter Pattern - Box → Service 変換 +// ============================================================================ + +/// StringBox → StringService Adapter +pub struct StringBoxAdapter { + #[allow(dead_code)] + inner: Box, +} + +impl StringBoxAdapter { + pub fn new(box_instance: Box) -> Self { + Self { inner: box_instance } } } +impl StringService for StringBoxAdapter { + // Phase 95 以降で実装 +} + +/// IntegerBox → IntegerService Adapter +pub struct IntegerBoxAdapter { + #[allow(dead_code)] + inner: Box, +} + +impl IntegerBoxAdapter { + pub fn new(box_instance: Box) -> Self { + Self { inner: box_instance } + } +} + +impl IntegerService for IntegerBoxAdapter { + // Phase 95 以降で実装 +} + +/// BoolBox → BoolService Adapter +pub struct BoolBoxAdapter { + #[allow(dead_code)] + inner: Box, +} + +impl BoolBoxAdapter { + pub fn new(box_instance: Box) -> Self { + Self { inner: box_instance } + } +} + +impl BoolService for BoolBoxAdapter { + // Phase 95 以降で実装 +} + +/// ArrayBox → ArrayService Adapter +pub struct ArrayBoxAdapter { + #[allow(dead_code)] + inner: Box, +} + +impl ArrayBoxAdapter { + pub fn new(box_instance: Box) -> Self { + Self { inner: box_instance } + } +} + +impl ArrayService for ArrayBoxAdapter { + // Phase 95 以降で実装 +} + +/// MapBox → MapService Adapter +pub struct MapBoxAdapter { + #[allow(dead_code)] + inner: Box, +} + +impl MapBoxAdapter { + pub fn new(box_instance: Box) -> Self { + Self { inner: box_instance } + } +} + +impl MapService for MapBoxAdapter { + // Phase 95 以降で実装 +} + +/// ConsoleBox → ConsoleService Adapter +pub struct ConsoleBoxAdapter { + #[allow(dead_code)] + inner: Box, +} + +impl ConsoleBoxAdapter { + pub fn new(box_instance: Box) -> Self { + Self { inner: box_instance } + } +} + +impl ConsoleService for ConsoleBoxAdapter { + // Phase 95 以降で実装 +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/runtime/mod.rs b/src/runtime/mod.rs index 7502222f..4e0d65c0 100644 --- a/src/runtime/mod.rs +++ b/src/runtime/mod.rs @@ -59,31 +59,20 @@ pub use unified_registry::{ // Use unified plugin loader (formerly v2) // pub use plugin_loader::{PluginLoaderV2 as PluginLoader, get_global_loader_v2 as get_global_loader}; // legacy -/// Runtime 初期化(Phase 93: 実装完了) +/// Runtime 初期化(Phase 94: Fail-Fast 実装完了) /// -/// 環境変数 NYASH_USE_PLUGIN_HOST=1 で PluginHost を有効化。 +/// Phase 94: フォールバック削除 - 常に実際の Box を使用 pub fn initialize_runtime(ring0: std::sync::Arc) -> Result { use crate::box_factory::UnifiedBoxRegistry; + use crate::box_factory::builtin::BuiltinBoxFactory; - let registry = UnifiedBoxRegistry::with_env_policy(); + let mut registry = UnifiedBoxRegistry::with_env_policy(); - // Phase 93: 環境変数で有効化(段階的展開) - let use_plugin_host = std::env::var("NYASH_USE_PLUGIN_HOST") - .ok() - .and_then(|v| if v == "1" { Some(()) } else { None }) - .is_some(); + // Phase 94: BuiltinBoxFactory を登録して core_required Boxes を提供 + registry.register(std::sync::Arc::new(BuiltinBoxFactory::new())); - if use_plugin_host { - let plugin_host = plugin_host::PluginHost::with_core_from_registry(ring0, ®istry)?; - plugin_host.ensure_core_initialized(); - Ok(plugin_host) - } else { - // フォールバック(Phase 94 で削除予定) - let core = core_services::CoreServices::dummy(); - Ok(plugin_host::PluginHost { - ring0, - core, - optional: std::collections::HashMap::new(), - }) - } + // Phase 94: 常に実際の Box → Service 変換を使用(Fail-Fast原則) + let plugin_host = plugin_host::PluginHost::with_core_from_registry(ring0, ®istry)?; + plugin_host.ensure_core_initialized(); + Ok(plugin_host) } diff --git a/src/runtime/plugin_host.rs b/src/runtime/plugin_host.rs index ad2f4c08..6e4fc6ce 100644 --- a/src/runtime/plugin_host.rs +++ b/src/runtime/plugin_host.rs @@ -90,33 +90,77 @@ impl PluginHost { /// UnifiedBoxRegistry から core_required Box を取得して CoreServices を初期化 /// - /// Phase 93: ダミー Service 実装(存在確認のみ) - /// Phase 94: 実際の Box → Service 変換実装予定 + /// Phase 94: 実際の Box → Service 変換実装 pub fn with_core_from_registry( ring0: Arc, registry: &UnifiedBoxRegistry, ) -> Result { - // Phase 93: 各 core_required Box が registry に存在するか確認 - for id in CoreServices::required_ids() { - let box_name = id.name(); + use crate::runtime::core_services::*; - // Phase 93: has_type() で存在確認 - if !registry.has_type(box_name) { - return Err(CoreInitError::MissingService { - box_id: *id, - message: format!("{} not found in registry", box_name), - }); - } - } + // Phase 94: 各 core_required Box を取得して Adapter に変換 - // Phase 93: ダミー Service 実装で CoreServices を構築 + // StringBox + let string_box = registry + .create_box("StringBox", &[]) + .map_err(|e| CoreInitError::MissingService { + box_id: CoreBoxId::String, + message: format!("StringBox creation failed: {}", e), + })?; + let string_service = Arc::new(StringBoxAdapter::new(string_box)); + + // IntegerBox + let integer_box = registry + .create_box("IntegerBox", &[]) + .map_err(|e| CoreInitError::MissingService { + box_id: CoreBoxId::Integer, + message: format!("IntegerBox creation failed: {}", e), + })?; + let integer_service = Arc::new(IntegerBoxAdapter::new(integer_box)); + + // BoolBox + let bool_box = registry + .create_box("BoolBox", &[]) + .map_err(|e| CoreInitError::MissingService { + box_id: CoreBoxId::Bool, + message: format!("BoolBox creation failed: {}", e), + })?; + let bool_service = Arc::new(BoolBoxAdapter::new(bool_box)); + + // ArrayBox + let array_box = registry + .create_box("ArrayBox", &[]) + .map_err(|e| CoreInitError::MissingService { + box_id: CoreBoxId::Array, + message: format!("ArrayBox creation failed: {}", e), + })?; + let array_service = Arc::new(ArrayBoxAdapter::new(array_box)); + + // MapBox + let map_box = registry + .create_box("MapBox", &[]) + .map_err(|e| CoreInitError::MissingService { + box_id: CoreBoxId::Map, + message: format!("MapBox creation failed: {}", e), + })?; + let map_service = Arc::new(MapBoxAdapter::new(map_box)); + + // ConsoleBox + let console_box = registry + .create_box("ConsoleBox", &[]) + .map_err(|e| CoreInitError::MissingService { + box_id: CoreBoxId::Console, + message: format!("ConsoleBox creation failed: {}", e), + })?; + let console_service = Arc::new(ConsoleBoxAdapter::new(console_box)); + + // Phase 94: 実際の Adapter を使用して CoreServices を構築 let core = CoreServices { - string: Arc::new(DummyStringService), - integer: Arc::new(DummyIntegerService), - bool: Arc::new(DummyBoolService), - array: Arc::new(DummyArrayService), - map: Arc::new(DummyMapService), - console: Arc::new(DummyConsoleService), + string: string_service, + integer: integer_service, + bool: bool_service, + array: array_service, + map: map_service, + console: console_service, }; Ok(PluginHost { @@ -132,25 +176,6 @@ impl PluginHost { } } -// Phase 93: ダミー Service 実装(Phase 94 で削除予定) -pub struct DummyStringService; -impl super::core_services::StringService for DummyStringService {} - -pub struct DummyIntegerService; -impl super::core_services::IntegerService for DummyIntegerService {} - -pub struct DummyBoolService; -impl super::core_services::BoolService for DummyBoolService {} - -pub struct DummyArrayService; -impl super::core_services::ArrayService for DummyArrayService {} - -pub struct DummyMapService; -impl super::core_services::MapService for DummyMapService {} - -pub struct DummyConsoleService; -impl super::core_services::ConsoleService for DummyConsoleService {} - #[cfg(test)] mod tests { use super::*; @@ -176,38 +201,42 @@ mod tests { #[test] fn test_core_services_all_fields() { - let services = CoreServices { - string: Arc::new(DummyStringService), - integer: Arc::new(DummyIntegerService), - bool: Arc::new(DummyBoolService), - array: Arc::new(DummyArrayService), - map: Arc::new(DummyMapService), - console: Arc::new(DummyConsoleService), - }; - services.ensure_initialized(); - // panic しないことを確認(Phase 92 で検証ロジック追加予定) + // Phase 94: 実際の registry を使用してテスト + use crate::runtime::ring0::default_ring0; + use crate::box_factory::builtin::BuiltinBoxFactory; + + let ring0 = Arc::new(default_ring0()); + let mut registry = UnifiedBoxRegistry::new(); + registry.register(Arc::new(BuiltinBoxFactory::new())); + + let plugin_host = PluginHost::with_core_from_registry(ring0, ®istry) + .expect("CoreServices should be initialized with builtin boxes"); + + plugin_host.ensure_core_initialized(); + // panic しないことを確認 } #[test] fn test_core_services_coverage() { - // Phase 87 CoreBoxId の core_required (6個) 全てをカバーすることを検証 - let services = CoreServices { - string: Arc::new(DummyStringService), - integer: Arc::new(DummyIntegerService), - bool: Arc::new(DummyBoolService), - array: Arc::new(DummyArrayService), - map: Arc::new(DummyMapService), - console: Arc::new(DummyConsoleService), - }; + // Phase 94: 実際の registry を使用して全フィールドが存在することを確認 + use crate::runtime::ring0::default_ring0; + use crate::box_factory::builtin::BuiltinBoxFactory; + + let ring0 = Arc::new(default_ring0()); + let mut registry = UnifiedBoxRegistry::new(); + registry.register(Arc::new(BuiltinBoxFactory::new())); + + let plugin_host = PluginHost::with_core_from_registry(ring0, ®istry) + .expect("CoreServices should be initialized"); // Phase 87 core_required (6個) と一致することを確認 // String, Integer, Bool, Array, Map, Console - let _string = &services.string; - let _integer = &services.integer; - let _bool = &services.bool; - let _array = &services.array; - let _map = &services.map; - let _console = &services.console; + let _string = &plugin_host.core.string; + let _integer = &plugin_host.core.integer; + let _bool = &plugin_host.core.bool; + let _array = &plugin_host.core.array; + let _map = &plugin_host.core.map; + let _console = &plugin_host.core.console; // 全フィールドが存在することを確認 } @@ -247,7 +276,7 @@ mod tests { #[test] fn test_with_core_from_registry_missing_box() { - // Phase 93: registry が空の場合はエラーを返すことを確認 + // Phase 94: registry が空の場合はエラーを返すことを確認 use crate::runtime::ring0::default_ring0; let ring0 = Arc::new(default_ring0()); let registry = UnifiedBoxRegistry::new(); @@ -255,10 +284,15 @@ mod tests { let result = PluginHost::with_core_from_registry(ring0, ®istry); assert!(result.is_err()); - // エラーメッセージに "not found" が含まれることを確認 + // Phase 94: エラーメッセージに "creation failed" または "Unknown Box type" が含まれることを確認 if let Err(e) = result { let msg = format!("{}", e); - assert!(msg.contains("not found")); + eprintln!("Error message: {}", msg); // デバッグ出力 + assert!( + msg.contains("creation failed") || msg.contains("Unknown Box type"), + "Error message should contain 'creation failed' or 'Unknown Box type', got: {}", + msg + ); } } }