Files
hakorune/src/runtime/box_registry.rs
Moe Charm c13d9c045e 📚 Phase 12: Nyashスクリプトプラグインシステム設計と埋め込みVM構想
## 主な成果
- Nyashスクリプトでプラグイン作成可能という革命的発見
- C ABI制約の分析と埋め込みVMによる解決策
- MIR/VM/JIT層での箱引数サポートの詳細分析

## ドキュメント作成
- Phase 12基本構想(README.md)
- Gemini/Codex先生の技術分析
- C ABIとの整合性問題と解決策
- 埋め込みVM実装ロードマップ
- 箱引数サポートの技術詳細

## 重要な洞察
- 制約は「リンク時にC ABI必要」のみ
- 埋め込みVMでMIRバイトコード実行により解決可能
- Nyashスクリプト→C ABIプラグイン変換が実現可能

Everything is Box → Everything is Plugin → Everything is Possible!
2025-08-30 22:52:16 +09:00

147 lines
5.1 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//! Boxファクトリレジストリ - Box生成の中央管理
//!
//! プラグインBoxを中心にBox生成を管理するPlugin-First
//! 旧ビルトイン経路は互換目的のAPIとして最小限に保持テスト用途
use crate::box_trait::NyashBox;
use crate::runtime::plugin_config::PluginConfig;
use std::collections::HashMap;
use std::sync::{Arc, RwLock};
/// Box生成方法を表す列挙型
pub enum BoxProvider {
/// 互換用ビルトイン実装Rust関数、現在は原則未使用
Builtin(BoxConstructor),
/// プラグイン実装(プラグイン名を保持)
Plugin(String),
}
/// 互換用ビルトインBoxのコンストラクタ関数型
pub type BoxConstructor = fn(&[Box<dyn NyashBox>]) -> Result<Box<dyn NyashBox>, String>;
/// Boxファクトリレジストリ
pub struct BoxFactoryRegistry {
/// Box名 → プロバイダーのマッピング
providers: RwLock<HashMap<String, BoxProvider>>,
}
impl BoxFactoryRegistry {
/// 新しいレジストリを作成
pub fn new() -> Self {
Self {
providers: RwLock::new(HashMap::new()),
}
}
/// 互換用ビルトインBoxを登録通常は使用しない
pub fn register_builtin(&self, name: &str, constructor: BoxConstructor) {
let mut providers = self.providers.write().unwrap();
providers.insert(name.to_string(), BoxProvider::Builtin(constructor));
}
/// プラグイン設定を適用(既存のビルトインを上書き)
pub fn apply_plugin_config(&self, config: &PluginConfig) {
let mut providers = self.providers.write().unwrap();
for (box_name, plugin_name) in &config.plugins {
providers.insert(
box_name.clone(),
BoxProvider::Plugin(plugin_name.clone())
);
}
}
/// Box名からプロバイダーを取得
pub fn get_provider(&self, name: &str) -> Option<BoxProvider> {
let providers = self.providers.read().unwrap();
providers.get(name).cloned()
}
/// Boxを生成
pub fn create_box(&self, name: &str, args: &[Box<dyn NyashBox>]) -> Result<Box<dyn NyashBox>, String> {
let provider = self.get_provider(name)
.ok_or_else(|| format!("Unknown Box type: {}", name))?;
match provider {
BoxProvider::Builtin(constructor) => {
// ビルトイン実装を直接呼び出し
constructor(args)
}
BoxProvider::Plugin(plugin_name) => {
// プラグインローダーと連携してプラグインBoxを生成
self.create_plugin_box(&plugin_name, name, args)
}
}
}
/// プラグインBoxを生成unified facade→v2
fn create_plugin_box(&self, plugin_name: &str, box_name: &str, args: &[Box<dyn NyashBox>]) -> Result<Box<dyn NyashBox>, String> {
use crate::runtime::get_global_plugin_host;
let host = get_global_plugin_host();
let host = host.read().unwrap();
host.create_box(box_name, args)
.map_err(|e| format!("Failed to create {} from plugin {}: {:?}", box_name, plugin_name, e))
}
}
impl Clone for BoxProvider {
fn clone(&self) -> Self {
match self {
BoxProvider::Builtin(f) => BoxProvider::Builtin(*f),
BoxProvider::Plugin(name) => BoxProvider::Plugin(name.clone()),
}
}
}
// グローバルレジストリインスタンス
use once_cell::sync::Lazy;
static GLOBAL_REGISTRY: Lazy<Arc<BoxFactoryRegistry>> =
Lazy::new(|| Arc::new(BoxFactoryRegistry::new()));
/// グローバルレジストリを取得
pub fn get_global_registry() -> Arc<BoxFactoryRegistry> {
GLOBAL_REGISTRY.clone()
}
#[cfg(test)]
mod tests {
use super::*;
use crate::box_trait::StringBox;
fn test_string_constructor(args: &[Box<dyn NyashBox>]) -> Result<Box<dyn NyashBox>, String> {
if args.is_empty() {
Ok(Box::new(StringBox::new("")))
} else {
Ok(Box::new(StringBox::new(&args[0].to_string_box().value)))
}
}
#[test]
fn test_builtin_registration() {
let registry = BoxFactoryRegistry::new();
registry.register_builtin("StringBox", test_string_constructor);
let result = registry.create_box("StringBox", &[]).unwrap();
assert_eq!(result.to_string_box().value, "");
}
#[test]
fn test_plugin_override() {
let registry = BoxFactoryRegistry::new();
registry.register_builtin("FileBox", test_string_constructor);
// プラグイン設定で上書き
let mut config = PluginConfig::default();
config.plugins.insert("FileBox".to_string(), "filebox".to_string());
registry.apply_plugin_config(&config);
// プロバイダーがプラグインに変わっているか確認
match registry.get_provider("FileBox").unwrap() {
BoxProvider::Plugin(name) => assert_eq!(name, "filebox"),
_ => panic!("Expected plugin provider"),
}
}
}