feat(phase93): with_core_from_registry implementation complete
Phase 93 完了: UnifiedBoxRegistry 統合実装 & 起動パス統合 **実装内容**: - with_core_from_registry() 実装 - UnifiedBoxRegistry.has_type() で core Box の存在確認 - 不足時は CoreInitError::MissingService を返す - ダミー Service 実装で CoreServices を構築 - ダミー Service 実装を pub に - DummyStringService, DummyIntegerService 等を公開 - Phase 94 の実変換までの橋渡し - CoreServices::dummy() ヘルパー追加 - フォールバック用ダミー実装 - initialize_runtime() 実装(環境変数制御) - NYASH_USE_PLUGIN_HOST=1 で PluginHost 有効化 - 環境変数なしで従来通り動作(後方互換性) - selfhost に PluginHost 初期化追加 - CoreInitError 発生時は fail-fast - 既存ロジックは変更なし **Fail-Fast 設計**: - 起動時に core Box 不足を即座に検出 - CoreInitError で明示的なエラーメッセージ - デバッグ容易(ランタイムエラーではなく起動時エラー) **テスト結果**: - test_with_core_from_registry_missing_box 追加 - 7件全て成功 - ビルド成功(1分4秒) - 526 passed(既存36失敗は Phase 93 と無関係) **動作確認**: - 環境変数なし: 従来通り動作 ✅ - NYASH_USE_PLUGIN_HOST=1: PluginHost 初期化成功 ✅ - selfhost: fail-fast 動作確認済み ✅ **ドキュメント更新**: - Section 10 追加(77行) - 段階的展開戦略、Fail-Fast 設計を文書化 **次のステップ**: Phase 94 (実際の Box → Service 変換) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -467,3 +467,83 @@ pub fn initialize_runtime(ring0: Arc<Ring0Context>) -> Result<PluginHost, CoreIn
|
||||
- CoreServices の自動構築
|
||||
- ensure_initialized() の4箇所への配置
|
||||
|
||||
---
|
||||
|
||||
## 10. Phase 93: with_core_from_registry 実装(2025-12-03)
|
||||
|
||||
### 10.1 実装内容
|
||||
|
||||
**実装**: `src/runtime/plugin_host.rs`
|
||||
|
||||
```rust
|
||||
impl PluginHost {
|
||||
pub fn with_core_from_registry(
|
||||
ring0: Arc<Ring0Context>,
|
||||
registry: &UnifiedBoxRegistry,
|
||||
) -> Result<Self, CoreInitError> {
|
||||
// Phase 93: 各 core_required Box が registry に存在するか確認
|
||||
for id in CoreServices::required_ids() {
|
||||
let box_name = id.name();
|
||||
if !registry.has_type(box_name) {
|
||||
return Err(CoreInitError::MissingService {
|
||||
box_id: *id,
|
||||
message: format!("{} not found in registry", box_name),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Phase 93: ダミー Service 実装で 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),
|
||||
};
|
||||
|
||||
Ok(PluginHost {
|
||||
ring0,
|
||||
core,
|
||||
optional: HashMap::new(),
|
||||
})
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 10.2 段階的展開戦略
|
||||
|
||||
**Phase 93 アプローチ**:
|
||||
- 環境変数 `NYASH_USE_PLUGIN_HOST=1` で有効化
|
||||
- ダミー Service 実装で動作確認
|
||||
- selfhost のみ統合(hack_check は Phase 94)
|
||||
|
||||
**Phase 94 計画**:
|
||||
- 実際の Box → Service 変換実装
|
||||
- 環境変数削除(デフォルトで有効化)
|
||||
- 全起動パスへの展開
|
||||
|
||||
### 10.3 Fail-Fast 設計
|
||||
|
||||
**メリット**:
|
||||
- 起動時に core Box の不足を即座に検出
|
||||
- CoreInitError で明示的なエラーメッセージ
|
||||
- デバッグ容易(ランタイムエラーではなく起動時エラー)
|
||||
|
||||
### 10.4 動作確認方法
|
||||
|
||||
```bash
|
||||
# Phase 93 動作確認
|
||||
NYASH_USE_PLUGIN_HOST=1 ./target/release/nyash apps/tests/selfhost_min.hako
|
||||
|
||||
# Phase 93 では環境変数なしで従来通り動作
|
||||
./target/release/nyash apps/tests/selfhost_min.hako
|
||||
```
|
||||
|
||||
### 10.5 実装されたファイル
|
||||
|
||||
1. `src/runtime/plugin_host.rs`: with_core_from_registry() + ダミー Service 実装
|
||||
2. `src/runtime/core_services.rs`: CoreServices::dummy() ヘルパー
|
||||
3. `src/runtime/mod.rs`: initialize_runtime() 実装(環境変数制御)
|
||||
4. `src/runner/selfhost.rs`: PluginHost 初期化追加
|
||||
|
||||
|
||||
@ -43,6 +43,21 @@ impl NyashRunner {
|
||||
pub(crate) fn try_run_selfhost_pipeline(&self, filename: &str) -> bool {
|
||||
use std::io::Write;
|
||||
|
||||
// Phase 93: PluginHost 初期化(環境変数で制御)
|
||||
if std::env::var("NYASH_USE_PLUGIN_HOST").ok().as_deref() == Some("1") {
|
||||
let ring0 = crate::runtime::ring0::get_global_ring0();
|
||||
match crate::runtime::initialize_runtime(ring0) {
|
||||
Ok(_plugin_host) => {
|
||||
eprintln!("[selfhost] PluginHost initialized successfully");
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("[selfhost] CoreInitError: {}", e);
|
||||
// Phase 93: fail-fast(エラー時は即座に終了)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Phase 25.1b: guard selfhost pipeline to Ny-only sources.
|
||||
// `.hako` / other extensionsは Stage‑B / JSON v0 bridge 側の責務なので、
|
||||
// ここでは Ny/Nyash 拡張子以外は即座にスキップする。
|
||||
|
||||
@ -79,6 +79,19 @@ impl CoreServices {
|
||||
// Phase 91 では trait が空なので何もしない
|
||||
// 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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@ -59,18 +59,31 @@ 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 92: 接続ポイント決定)
|
||||
/// Runtime 初期化(Phase 93: 実装完了)
|
||||
///
|
||||
/// Phase 93 で実装予定の接続ポイント。
|
||||
/// Phase 92 では skeleton のみ(todo!() を呼ぶ)。
|
||||
#[allow(dead_code)]
|
||||
/// 環境変数 NYASH_USE_PLUGIN_HOST=1 で PluginHost を有効化。
|
||||
pub fn initialize_runtime(ring0: std::sync::Arc<Ring0Context>) -> Result<plugin_host::PluginHost, CoreInitError> {
|
||||
use crate::box_factory::UnifiedBoxRegistry;
|
||||
|
||||
let registry = UnifiedBoxRegistry::new();
|
||||
let registry = UnifiedBoxRegistry::with_env_policy();
|
||||
|
||||
// Phase 92: 接続ポイント決定(実装は Phase 93)
|
||||
let plugin_host = plugin_host::PluginHost::with_core_from_registry(ring0, ®istry)?;
|
||||
// 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();
|
||||
|
||||
Ok(plugin_host)
|
||||
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(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,17 +90,40 @@ impl PluginHost {
|
||||
|
||||
/// UnifiedBoxRegistry から core_required Box を取得して CoreServices を初期化
|
||||
///
|
||||
/// Phase 92: skeleton のみ(Phase 93 で実装)
|
||||
#[allow(dead_code)]
|
||||
/// Phase 93: ダミー Service 実装(存在確認のみ)
|
||||
/// Phase 94: 実際の Box → Service 変換実装予定
|
||||
pub fn with_core_from_registry(
|
||||
ring0: Arc<Ring0Context>,
|
||||
_registry: &UnifiedBoxRegistry,
|
||||
registry: &UnifiedBoxRegistry,
|
||||
) -> Result<Self, CoreInitError> {
|
||||
// Phase 93 で実装予定
|
||||
// TODO: registry から core_required Box を取得
|
||||
// TODO: 各 Box を対応する Service trait に変換
|
||||
// TODO: CoreServices を構築
|
||||
todo!("Phase 93: UnifiedBoxRegistry から CoreServices への変換実装")
|
||||
// Phase 93: 各 core_required Box が registry に存在するか確認
|
||||
for id in CoreServices::required_ids() {
|
||||
let box_name = id.name();
|
||||
|
||||
// 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 93: ダミー Service 実装で 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),
|
||||
};
|
||||
|
||||
Ok(PluginHost {
|
||||
ring0,
|
||||
core,
|
||||
optional: HashMap::new(),
|
||||
})
|
||||
}
|
||||
|
||||
/// core_required が全て揃っているか検証
|
||||
@ -109,6 +132,25 @@ 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::*;
|
||||
@ -132,25 +174,6 @@ mod tests {
|
||||
// panic しないことを確認
|
||||
}
|
||||
|
||||
// ダミー Service 実装
|
||||
struct DummyStringService;
|
||||
impl StringService for DummyStringService {}
|
||||
|
||||
struct DummyIntegerService;
|
||||
impl IntegerService for DummyIntegerService {}
|
||||
|
||||
struct DummyBoolService;
|
||||
impl BoolService for DummyBoolService {}
|
||||
|
||||
struct DummyArrayService;
|
||||
impl ArrayService for DummyArrayService {}
|
||||
|
||||
struct DummyMapService;
|
||||
impl MapService for DummyMapService {}
|
||||
|
||||
struct DummyConsoleService;
|
||||
impl ConsoleService for DummyConsoleService {}
|
||||
|
||||
#[test]
|
||||
fn test_core_services_all_fields() {
|
||||
let services = CoreServices {
|
||||
@ -223,14 +246,19 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "Phase 93")]
|
||||
fn test_with_core_from_registry_todo() {
|
||||
// Phase 92: todo!() を返すことを確認
|
||||
fn test_with_core_from_registry_missing_box() {
|
||||
// Phase 93: registry が空の場合はエラーを返すことを確認
|
||||
use crate::runtime::ring0::default_ring0;
|
||||
let ring0 = Arc::new(default_ring0());
|
||||
let registry = UnifiedBoxRegistry::new();
|
||||
|
||||
let _result = PluginHost::with_core_from_registry(ring0, ®istry);
|
||||
// Phase 93 で実装後はこのテストを削除
|
||||
let result = PluginHost::with_core_from_registry(ring0, ®istry);
|
||||
assert!(result.is_err());
|
||||
|
||||
// エラーメッセージに "not found" が含まれることを確認
|
||||
if let Err(e) = result {
|
||||
let msg = format!("{}", e);
|
||||
assert!(msg.contains("not found"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user