Files
hakorune/docs/development/current/main/phase131-2-box-resolution-map.md
nyash-codex e912ef9134 docs(phase131): SSOT整備 - VM入口/env var/次の入口を1箇所に固定
Phase 131 SSOT 整備完了:

1) VM Box 解決の入口SSOT(phase131-2-box-resolution-map.md)
   - 📍 入口3行を先頭に追記(handle_new_box/UnifiedRegistry/BoxFactoryRegistry)
   - NYASH_VM_FAST を bench/profile-only 特例と明記

2) 環境変数のSSOTを1箇所へ(environment-variables.md)
   - ## LLVM Build Pipeline セクション新設(14変数)
   - phase87 の Environment Variables セクションを参照リンクに置き換え
   - 重複表を削除、SSOTドキュメントへの導線確立

3) 次の開発の入口を明確化(CURRENT_TASK.md)
   - P1(Loop Canonicalizer): 🔶 設計待ち(外部検討中)
   - P2(JoinIR / Selfhost depth-2):  実装可能
   - 次に触るSSOTを1行で指定:
     - Loop系: joinir-architecture-overview.md
     - VM Box系: phase131-2-box-resolution-map.md

Impact:
- 迷子防止: 各領域のSSOTが1行で分かる
- 重複削減: env var 表を environment-variables.md に集約
- 状態明確化: P1/P2 の「設計待ち/実装可能」が一目瞭然

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-14 05:27:39 +09:00

10 KiB
Raw Blame History

Phase 131-2: Box Resolution Mapping - 現状 vs 理想

📍 VM Box 解決の入口SSOT迷ったらここ

  • MIR NewBox 受付: src/backend/mir_interpreter/handlers/boxes.rshandle_new_box()
  • Box 登録管理: src/runtime/unified_registry.rsUnifiedBoxRegistry
  • Factory 実装: src/box_factory/mod.rs + Plugin は src/runtime/box_registry.rsBoxFactoryRegistry
  • NYASH_VM_FAST: bench/profile-only 特例既定OFF、本番では使わない

🗺️ 現状マップVM Backend

MIR NewBox ConsoleBox
        ↓
MirInterpreter::handle_new_box()  (src/backend/mir_interpreter/handlers/boxes.rs)
        ↓
    [分岐点 1: Fast path?]
        ├─ Yes (NYASH_VM_FAST=1 + StringBox) → Direct creationbench/profile-only
        └─ No → Continue
                ↓
    [分岐点 2: Provider Lock]
        ├─ guard_before_new_box() → OK/NG
        └─ Continue
                ↓
    get_global_unified_registry() (src/runtime/unified_registry.rs)
                ↓
    UnifiedBoxRegistry::create_box("ConsoleBox", args) (src/box_factory/mod.rs)
                ↓
        [分岐点 3: FactoryPolicy による優先順位]
                ├─ BuiltinBoxFactory → builtin_implssrc/box_factory/builtin_impls/*
                └─ PluginBoxFactory  → BoxFactoryRegistry → PluginHost
                       (src/box_factory/plugin.rs)  (src/runtime/box_registry.rs)
                       ※ plugin_loader_unified が BoxFactoryRegistry を populate する
                         src/runtime/plugin_loader_unified.rs

問題点:

  • 「Box 解決 SSOT」が 1 箇所に見えないUnifiedBoxRegistry と BoxFactoryRegistry に分散)
  • 優先順位が “FactoryPolicy + provider mapping” の合成で、全体像が追いにくい
  • NYASH_VM_FAST の特例が入口にあり、観測なしだと混乱しやすい

🎯 理想マップSSOT 化後)

MIR NewBox ConsoleBox
        ↓
handle_new_box()
        ↓
CoreBoxRegistry::create("ConsoleBox", args)
        ↓
    [SSOT: 登録情報検索]
    CoreBoxId::Console in registry?
        ├─ Yes → Continue
        └─ No → Error: "ConsoleBox not registered" (Fail-Fast!)
                ↓
    [優先順位: Plugin > Builtin]
    registered_provider?
        ├─ Plugin → PluginHost.create_box()
        │            ↓
        │       TypeBox v2 FFI
        │            ↓
        │       console_invoke_id()
        │            ↓
        │       ConsoleInstance::new()
        │
        └─ Builtin → builtin::ConsoleBox::new()
                ↓
        VMValue::BoxRef(ConsoleBox)

改善点:

  • 単一の Box 解決ルートSSOT
  • CoreBoxId による型安全性
  • 明確な優先順位Plugin > Builtin
  • Fail-Fast見つからない = エラー)

📊 VM vs LLVM 比較表

項目 VM Backend現状 LLVM BackendPhase 133 理想SSOT化後
Box 登録 ⚠️ UnifiedBoxRegistry + BoxFactoryRegistry TypeRegistry + Plugin FFI CoreBoxRegistry
メソッド解決 複数経路boxes.rs 分岐) ConsoleLlvmBridge 箱化 箱化モジュール
ABI NyashBox trait i8* + i64 (llvmlite) 統一TypeRegistry SSOT
優先順位 不明確 Plugin > Builtin 明示的優先順位
Fail-Fast フォールバック多数 エラー即座に報告 Fail-Fast 原則
型安全性 文字列ベース TypeBox v2 CoreBoxId enum
SSOT 化 分散 完了Phase 133 完了(目標)

🔍 登録システム詳細比較

現状VM Backend

// System 1: BoxFactoryRegistryplugin provider mapping
impl BoxFactoryRegistry {
    pub fn create_box(&self, name: &str, args: &[Box<dyn NyashBox>])
        -> Result<Box<dyn NyashBox>, String>
    {
        let provider = self.get_provider(name)?;
        match provider {
            BoxProvider::Builtin(constructor) => constructor(args),
            BoxProvider::Plugin(plugin_name) =>
                self.create_plugin_box(&plugin_name, name, args),
        }
    }
}

// System 2: UnifiedBoxRegistryVM NewBox の入口)
// src/backend/mir_interpreter/handlers/boxes.rs::handle_new_box
let reg = crate::runtime::unified_registry::get_global_unified_registry();
let created = reg.lock().unwrap().create_box(box_type, &converted)?;

// Builtins は UnifiedBoxRegistry 内で BuiltinBoxFactory が担当し、
// builtin_impls/* の実装へ委譲される(外部フォールバックではない)。

問題:

  • 3つのシステムの関係が不明
  • どれが優先されるのか不明確
  • エラーハンドリングが統一されていない

Phase 133LLVM Backend- 成功モデル

# ConsoleLlvmBridge: 単一の箱化モジュール
def emit_console_call(builder, module, method_name, args, ...):
    if method_name not in CONSOLE_METHODS:
        return False  # Fail-Fast: 即座に不明通知

    runtime_fn_name = CONSOLE_METHODS[method_name]
    callee = _declare(module, runtime_fn_name, i64, [i8p])
    builder.call(callee, [arg0_ptr])
    return True  # 成功

成功要因:

  • CONSOLE_METHODS が SSOT唯一の真実
  • 箱化モジュール1箇所に集約
  • Fail-Fast不明メソッド = False 即座)
  • TypeRegistry との ABI 一致

理想SSOT化後の VM Backend

// CoreBoxRegistry: 単一の SSOT
pub struct CoreBoxRegistry {
    core_boxes: RwLock<HashMap<CoreBoxId, CoreBoxEntry>>,
    user_boxes: RwLock<HashMap<String, UserBoxEntry>>,
}

impl CoreBoxRegistry {
    pub fn create(&self, box_name: &str, args: &[Box<dyn NyashBox>])
        -> Result<Box<dyn NyashBox>, RuntimeError>
    {
        // 1. CoreBoxId 変換
        let box_id = CoreBoxId::from_name(box_name)
            .ok_or_else(|| RuntimeError::InvalidOperation {
                message: format!("Unknown Box type: {}", box_name)
            })?;

        // 2. 登録情報取得SSOT
        let entry = self.core_boxes.read().unwrap()
            .get(&box_id)
            .ok_or_else(|| RuntimeError::InvalidOperation {
                message: format!("Box not registered: {:?}", box_id)
            })?
            .clone();

        // 3. 優先順位に従って生成
        match entry.provider {
            CoreBoxProvider::Plugin { plugin_name, type_id } => {
                self.plugin_host.create_box(&plugin_name, type_id, args)
            }
            CoreBoxProvider::Builtin { constructor } => {
                constructor(args)
            }
        }
    }
}

改善点:

  • CoreBoxId による型安全性
  • 単一の登録マップSSOT
  • 明示的な優先順位Plugin > Builtin
  • Fail-Fast登録なし = エラー)

🎯 Phase 133 の教訓

成功パターン: 箱化モジュール化

Before (Phase 132): 40 行の分岐が boxcall.py に埋め込み
After (Phase 133): 1 行の箱化呼び出し

# Before
if method_name in ("print", "println", "log"):
    # ... 40 行のロジック ...

# After
if emit_console_call(builder, module, method_name, args, ...):
    return

成果:

  • 分岐を 1 箇所に集約
  • テスト容易性向上
  • レガシー削除が簡単

VM Backend への適用

// Before現状: 複数経路の分岐
let reg = unified_registry::get_global_unified_registry();
let created = reg.lock().unwrap().create_box(box_type, &converted)?;

// AfterPhase 131-3: 箱化モジュール化
let created = CoreBoxRegistry::global()
    .create(box_type, &converted)?;

📋 Phase 131-3 実装ガイド

Step 1: 現状SSOTの所在を固定入口と接続

# VM NewBox の入口(ここから追う)
rg "fn handle_new_box\\(" src/backend/mir_interpreter/handlers/boxes.rs

# global accessor と registry 本体
rg "get_global_unified_registry\\(" src/runtime/unified_registry.rs
rg "struct UnifiedBoxRegistry" src/box_factory/mod.rs

# plugin 側の provider mapping
rg "struct BoxFactoryRegistry" src/runtime/box_registry.rs

前提:

  • UnifiedBoxRegistry は既に存在するNewBox の入口)。
  • BoxFactoryRegistry は PluginBoxFactory の provider mapping として間接利用される。

Step 2: CoreBoxId 統合

// CoreBoxId に基づく検証ロジック追加
impl CoreBoxRegistry {
    pub fn validate_on_startup(&self, profile: &RuntimeProfile)
        -> Result<(), String>
    {
        for box_id in CoreBoxId::iter() {
            if box_id.is_required_in(&profile) && !self.has(box_id) {
                return Err(format!("Missing core_required box: {:?}", box_id));
            }
        }
        Ok(())
    }
}

Step 3: プラグイン優先順位の明確化

// 登録時に優先順位を決定
impl CoreBoxRegistry {
    /// プラグイン設定適用(既存ビルトインを上書き)
    pub fn apply_plugin_config(&mut self, config: &PluginConfig) {
        for (box_name, plugin_name) in &config.plugins {
            if let Some(box_id) = CoreBoxId::from_name(box_name) {
                self.register_plugin(box_id, plugin_name);  // 上書き
            }
        }
    }
}

Step 4: Fail-Fast の徹底

// ❌ 削除対象: フォールバックロジック
if let Err(_) = create_plugin_box() {
    create_builtin_box()  // 隠蔽!
}

// ✅ 追加: 即座にエラー
create_plugin_box()
    .map_err(|e| VMError::InvalidInstruction(
        format!("ConsoleBox plugin failed: {:?}. Check nyash.toml", e)
    ))?

チェックリストPhase 131-3

  • UnifiedBoxRegistry / BoxFactoryRegistry の責務境界を SSOT として固定
  • CoreBoxRegistry を新設するなら “入口SSOT” を 1 箇所にするNewBox から見える形)
  • CoreBoxId 統合(型安全性)
  • プラグイン優先順位の明確化Plugin > Builtin
  • Fail-Fast 原則の徹底(フォールバック削除)
  • 起動時検証テスト追加
  • VM/LLVM 両方で ConsoleBox 生成確認

Status: Ready for Implementation Next Phase: 131-3 (SSOT Implementation) Estimated Time: 4-6 hours