feat(runtime): Phase 87 CoreBoxId/CoreMethodId 箱化完了
ハードコード文字列から型安全な enum への箱化により、 Box名・メソッド名管理を完全にコンパイル時検証可能に。 主な実装: - CoreBoxId enum 定義(19個) - core_required: 6個(String, Integer, Bool, Array, Map, Console) - core_optional: 9個(Float, Null, File, Path, Regex, Math, Time, Json, Toml) - 特殊型: 4個(Function, Result, Method, Missing) - CoreMethodId enum 定義(30個) - 各 Box のメソッドを型安全に管理 - 引数数、戻り値型情報を統合 - is_reserved_type() を CoreBoxId ベースにリファクタリング - infer_boxcall_return_type() を CoreMethodId ベースに改良(75行 → 25行、67%削減) 検証結果: - テスト: ✅ 11/11 passed(新規追加) - ビルド: ✅ 成功(0エラー) - 型安全性: ✅ タイポ不可能 効果: - SSOT 確立(src/runtime/core_box_ids.rs に一元化) - コンパイル時検証(実行時エラー → コンパイルエラー) - 保守性向上(変更箇所の一元化) - IDE 支援(enum 補完可能) ドキュメント: - core_boxes_design.md 作成(Phase 87 完全仕様) - Phase 85 README 更新(Phase 87 セクション追加) Phase 15.5「Everything is Plugin」アーキテクチャ基盤完成 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
241
docs/development/current/main/core_boxes_design.md
Normal file
241
docs/development/current/main/core_boxes_design.md
Normal file
@ -0,0 +1,241 @@
|
||||
# Core Boxes 設計ドキュメント(Phase 87 完了版)
|
||||
|
||||
Phase 87 で実装された CoreBoxId/CoreMethodId の完全仕様。
|
||||
|
||||
**目的**: Box名・メソッド名のハードコードを型安全な enum に箱化することで、以下を実現:
|
||||
- ✅ コンパイル時検証(タイポ撲滅)
|
||||
- ✅ IDE 支援(補完・リファクタリング)
|
||||
- ✅ SSOT(Single Source of Truth)確立
|
||||
- ✅ 保守性向上
|
||||
|
||||
**実装状況**: ✅ Phase 87 完了(2025-12-02)
|
||||
|
||||
---
|
||||
|
||||
## 1. CoreBoxId — コア Box の識別子(実装完了)
|
||||
|
||||
### 1.1 役割
|
||||
|
||||
- Nyash 言語仕様的に「コア」とみなす Box の ID を定義する。
|
||||
- 文字列名 `"StringBox"` / `"ArrayBox"` をここに集約し、他のモジュールは enum 経由で参照する。
|
||||
- 例:
|
||||
- 予約型チェック(BoxFactory)
|
||||
- core_required 判定(PluginHost / FactoryPolicy)
|
||||
- 将来の Method Registry との連携など。
|
||||
|
||||
### 1.2 想定 API
|
||||
|
||||
```rust
|
||||
pub enum CoreBoxId {
|
||||
String,
|
||||
Integer,
|
||||
Bool,
|
||||
Float,
|
||||
Null,
|
||||
Array,
|
||||
Map,
|
||||
Result,
|
||||
Method,
|
||||
Console,
|
||||
File,
|
||||
// 将来: Path, Json, Time, Regex, etc.
|
||||
}
|
||||
|
||||
impl CoreBoxId {
|
||||
/// "StringBox" / "ArrayBox" などの内部名
|
||||
pub fn name(&self) -> &'static str;
|
||||
|
||||
/// 将来のための iterator(予約型チェックなどで利用)
|
||||
pub fn iter() -> impl Iterator<Item = CoreBoxId>;
|
||||
}
|
||||
```
|
||||
|
||||
### 1.3 補足
|
||||
|
||||
- Ring0Context からはこの enum を直接は参照しない(あくまで ring1-core の責務)。
|
||||
- `is_reserved_type(name: &str)` のような関数は、この enum を使って実装する想定:
|
||||
|
||||
```rust
|
||||
fn is_reserved_type(name: &str) -> bool {
|
||||
CoreBoxId::iter().any(|id| id.name() == name)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. CoreMethodId — コアメソッドの識別子
|
||||
|
||||
### 2.1 役割
|
||||
|
||||
- 「どの Box のどのメソッドか」を安全に表現する ID。
|
||||
- メソッド名(`"length"` / `"push"` など)や arity を 1 箇所に集約し、呼ぶ側は enum だけを見る。
|
||||
- 代表例:
|
||||
- `StringBox.length/0`
|
||||
- `ArrayBox.push/1`
|
||||
- `MapBox.get/1`
|
||||
- `ConsoleBox.println/1`
|
||||
|
||||
### 2.2 想定 API
|
||||
|
||||
```rust
|
||||
pub enum CoreMethodId {
|
||||
// StringBox
|
||||
StringLength,
|
||||
StringSubstring,
|
||||
StringLastIndexOf,
|
||||
StringEscJson,
|
||||
|
||||
// ArrayBox
|
||||
ArraySize,
|
||||
ArrayGet,
|
||||
ArraySet,
|
||||
ArrayPush,
|
||||
|
||||
// MapBox
|
||||
MapSize,
|
||||
MapHas,
|
||||
MapGet,
|
||||
MapSet,
|
||||
|
||||
// ConsoleBox
|
||||
ConsolePrint,
|
||||
ConsolePrintln,
|
||||
ConsoleLog,
|
||||
|
||||
// FileBox
|
||||
FileOpen,
|
||||
FileRead,
|
||||
FileClose,
|
||||
}
|
||||
|
||||
impl CoreMethodId {
|
||||
/// このメソッドが属する Box(CoreBoxId)
|
||||
pub fn box_id(&self) -> CoreBoxId;
|
||||
|
||||
/// 実際のメソッド名("length" など)
|
||||
pub fn name(&self) -> &'static str;
|
||||
|
||||
/// 引数個数(将来可変長も考慮)
|
||||
pub fn arity(&self) -> usize;
|
||||
}
|
||||
```
|
||||
|
||||
### 2.3 用途の例
|
||||
|
||||
- Method Registry / BoxFactory でのメソッド解決:
|
||||
|
||||
```rust
|
||||
fn resolve_core_method(box_name: &str, method_name: &str, arity: usize) -> Option<CoreMethodId> {
|
||||
CoreMethodId::iter().find(|id| {
|
||||
id.box_id().name() == box_name && id.name() == method_name && id.arity() == arity
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
- 型推論や BoxCall lowering で、「この CoreMethodId なら戻り値型は Integer」という判定に使う。
|
||||
|
||||
---
|
||||
|
||||
## 3. BoxFactory / PluginHost との関係
|
||||
|
||||
### 3.1 BoxFactory 側
|
||||
|
||||
- 予約型チェックや FactoryPolicy の判定を、CoreBoxId ベースに書き換える想定:
|
||||
|
||||
```rust
|
||||
fn is_core_required(name: &str) -> bool {
|
||||
matches!(
|
||||
CoreBoxId::from_name(name),
|
||||
Some(CoreBoxId::String | CoreBoxId::Integer | CoreBoxId::Bool
|
||||
| CoreBoxId::Float | CoreBoxId::Null
|
||||
| CoreBoxId::Array | CoreBoxId::Map | CoreBoxId::Result | CoreBoxId::Method)
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2 PluginHost 側
|
||||
|
||||
- `PluginHost.core: CoreServices` の設計と合わせて、CoreBoxId に基づいた必須サービスセットを定義する:
|
||||
|
||||
```rust
|
||||
pub struct CoreServices {
|
||||
pub string: Arc<dyn StringService>,
|
||||
pub array: Arc<dyn ArrayService>,
|
||||
pub map: Arc<dyn MapService>,
|
||||
pub console: Arc<dyn ConsoleService>,
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
- 初期化時に CoreServices の全フィールドが埋まっているかチェックし、足りなければ起動時に fail-fast する方針にする。
|
||||
|
||||
---
|
||||
|
||||
## 4. Ring0Context との分離
|
||||
|
||||
- Ring0Context はあくまで「OS API」の箱であり、CoreBoxId/CoreMethodId を知らない。
|
||||
- CoreBoxes は Ring1-core 層として、Ring0Context の上に構築される:
|
||||
|
||||
```rust
|
||||
// Ring0: OS API
|
||||
pub struct Ring0Context { pub io: Box<dyn IoApi>, /* ... */ }
|
||||
|
||||
// Ring1-core: Box 実装(StringBox/ArrayBox/MapBox/FileBox/ConsoleBox)
|
||||
// CoreBoxId/CoreMethodId で識別される
|
||||
```
|
||||
|
||||
これにより、ring0 側の変更(IO 実装差し替えなど)が CoreBoxes の識別や FactoryPolicy に影響しないようにできる。
|
||||
|
||||
---
|
||||
|
||||
## 5. Phase 87 実装完了
|
||||
|
||||
### 5.1 実装内容
|
||||
|
||||
✅ **CoreBoxId enum 定義** (`src/runtime/core_box_ids.rs`)
|
||||
- 19個の CoreBox: core_required (6個), core_optional (9個), 特殊型 (4個)
|
||||
- API: `name()`, `from_name()`, `is_core_required()`, `category()`, `iter()`
|
||||
|
||||
✅ **CoreMethodId enum 定義** (`src/runtime/core_box_ids.rs`)
|
||||
- 30個のメソッド: StringBox (8), IntegerBox (3), BoolBox (3), ArrayBox (4), MapBox (4), ConsoleBox (3), FileBox (3), ResultBox (2)
|
||||
- API: `box_id()`, `name()`, `arity()`, `return_type_name()`, `from_box_and_method()`, `iter()`
|
||||
|
||||
✅ **is_reserved_type() リファクタリング** (`src/box_factory/mod.rs`)
|
||||
- ハードコード matches! → CoreBoxId による型安全判定
|
||||
- 環境変数 NYASH_USE_PLUGIN_BUILTINS / NYASH_PLUGIN_OVERRIDE_TYPES 対応維持
|
||||
|
||||
✅ **infer_boxcall_return_type() リファクタリング** (`src/mir/builder/utils.rs`)
|
||||
- 75行のハードコード → 25行の CoreMethodId ベース実装(**67%削減**)
|
||||
- 型推論が SSOT 化され、保守性が大幅向上
|
||||
|
||||
✅ **テスト 11件追加** (`src/runtime/core_box_ids.rs`)
|
||||
- CoreBoxId: from_name, name, iter, is_core_required, category (5件)
|
||||
- CoreMethodId: box_id, name, arity, return_type_name, from_box_and_method, iter (6件)
|
||||
|
||||
### 5.2 実装効果
|
||||
|
||||
| 項目 | Before | After | 効果 |
|
||||
|------|--------|-------|------|
|
||||
| infer_boxcall_return_type() | 75行 | 25行 | **67%削減** |
|
||||
| is_reserved_type() | 12行 | 9行 | 25%削減 |
|
||||
| 型安全性 | 文字列ハードコード | enum | タイポ不可能 |
|
||||
| SSOT | 分散 | 1ファイル | 保守性向上 |
|
||||
| IDE支援 | なし | 補完可能 | 開発体験向上 |
|
||||
|
||||
### 5.3 Phase 85 との関係
|
||||
|
||||
Phase 85 の調査結果を完全反映:
|
||||
- **core_required (6個)**: StringBox, IntegerBox, BoolBox, ArrayBox, MapBox, ConsoleBox
|
||||
- **core_optional (9個)**: FloatBox, NullBox, FileBox, PathBox, RegexBox, MathBox, TimeBox, JsonBox, TomlBox
|
||||
- **特殊型 (4個)**: FunctionBox, ResultBox, MethodBox, MissingBox
|
||||
|
||||
### 5.4 今後の拡張
|
||||
|
||||
新しいメソッド追加は `src/runtime/core_box_ids.rs` の編集のみで完結:
|
||||
1. CoreMethodId enum にバリアント追加
|
||||
2. box_id(), name(), arity(), return_type_name() に対応追加
|
||||
3. iter() にバリアント追加
|
||||
4. テスト追加
|
||||
|
||||
すべて1ファイルで完結するため、Phase 84-4-B のような分散ハードコード問題は完全解消。
|
||||
|
||||
Reference in New Issue
Block a user