fix(joinir): Phase 241-EX - Remove hardcoded 'sum' check from Pattern3
Remove legacy hardcoded 'sum' carrier validation that was blocking array_filter patterns with different accumulator names (e.g., 'out'). Before: Pattern3 required carrier named 'sum' to exist After: Pattern3 uses carrier_info generically (any carrier name works) Test results: - phase49_joinir_array_filter_smoke: PASS ✅ - phase49_joinir_array_filter_fallback: PASS ✅ - phase49_joinir_array_filter_ab_comparison: PASS ✅ - Full suite: 909/909 PASS, 0 FAIL Also: Archive old roadmap documentation (67k lines moved to docs/archive/) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
149
docs/archive/roadmap/phases/phase-12/BREAKTHROUGH_CONCLUSION.md
Normal file
149
docs/archive/roadmap/phases/phase-12/BREAKTHROUGH_CONCLUSION.md
Normal file
@ -0,0 +1,149 @@
|
||||
# Phase 12: 究極のブレイクスルー - ユーザー箱とプラグイン箱の境界消滅
|
||||
|
||||
## 📅 2025-09-02 - ChatGPT5先生からの最終結論
|
||||
|
||||
### 🌟 結論
|
||||
|
||||
> **「ユーザー箱とプラグイン箱の境界をなくす」「Nyash ABIで拡張する」は綺麗に箱化して実装できます。既存のVM/PIC/vtable下地があるので、無理なく段階導入できます。**
|
||||
|
||||
## 🎯 これが意味すること
|
||||
|
||||
### 1. Everything is Box の究極形
|
||||
|
||||
```nyash
|
||||
// もはや区別がない世界
|
||||
box MyCustomBox { // ユーザー定義
|
||||
// 自動的にプラグインとしても使える!
|
||||
}
|
||||
|
||||
// C ABIプラグイン
|
||||
extern box FileBox { // プラグイン
|
||||
// ユーザーBoxと同じように扱える!
|
||||
}
|
||||
|
||||
// 完全に透明な相互運用
|
||||
local processor = new MyCustomBox()
|
||||
processor.processFile(new FileBox("data.txt"))
|
||||
```
|
||||
|
||||
### 2. 実装の現実性
|
||||
|
||||
既存インフラが整っている:
|
||||
- **VM**: すでにBoxCallを統一的に処理
|
||||
- **PIC**: Polymorphic Inline Cacheで高速化済み
|
||||
- **vtable**: 動的ディスパッチ基盤完成
|
||||
|
||||
### 3. 段階的導入計画
|
||||
|
||||
#### Phase 1: 境界の曖昧化(1週間)
|
||||
```nyash
|
||||
// ユーザーBoxに自動エクスポート機能
|
||||
@export
|
||||
box DataProcessor {
|
||||
process(data) { ... }
|
||||
}
|
||||
```
|
||||
|
||||
#### Phase 2: 統一レジストリ(2週間)
|
||||
```c
|
||||
// すべてのBoxが同じレジストリに登録
|
||||
NyRegisterBox(spec, ORIGIN_USER); // ユーザー定義
|
||||
NyRegisterBox(spec, ORIGIN_PLUGIN); // プラグイン
|
||||
NyRegisterBox(spec, ORIGIN_BUILTIN); // ビルトイン
|
||||
```
|
||||
|
||||
#### Phase 3: 完全統合(1ヶ月)
|
||||
- ユーザーBoxの自動C ABI生成
|
||||
- AOT時の最適化統一
|
||||
- 実行時の完全な相互運用性
|
||||
|
||||
## 🚀 技術的実現方法
|
||||
|
||||
### 1. ユーザーBox → プラグイン変換
|
||||
|
||||
```rust
|
||||
// コンパイル時に自動生成
|
||||
impl UserBoxToPlugin for DataProcessor {
|
||||
fn generate_c_abi() -> NyashTypeBox {
|
||||
NyashTypeBox {
|
||||
create: |args| Box::new(DataProcessor::new(args)),
|
||||
invoke_id: |self, id, args| {
|
||||
match id {
|
||||
1 => self.process(args[0]),
|
||||
_ => NyResult::Error("Unknown method")
|
||||
}
|
||||
},
|
||||
// ...
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 既存vtableの活用
|
||||
|
||||
```rust
|
||||
// 現在のVMコード(すでに統一的!)
|
||||
match value {
|
||||
VMValue::BoxRef(b) => {
|
||||
// ユーザーBox、プラグインBox、ビルトインBox
|
||||
// すべて同じ経路で処理される!
|
||||
self.call_box_method(b, method, args)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. PIC最適化の共有
|
||||
|
||||
```rust
|
||||
// 既存のPICがそのまま使える
|
||||
struct PolymorphicInlineCache {
|
||||
entries: [(TypeId, MethodId, FnPtr); 4],
|
||||
}
|
||||
// ユーザーBoxもプラグインBoxも同じ最適化を受ける
|
||||
```
|
||||
|
||||
## 💡 革命的な利点
|
||||
|
||||
### 1. 開発体験の統一
|
||||
- Nyashだけ書けばプラグインになる
|
||||
- C/Rustの知識不要
|
||||
- デバッグが容易
|
||||
|
||||
### 2. パフォーマンスの両立
|
||||
- 開発時: インタープリター実行
|
||||
- 本番時: AOT/JIT最適化
|
||||
- 同じコードで両方可能
|
||||
|
||||
### 3. エコシステムの爆発的成長
|
||||
- 誰でもプラグイン作者に
|
||||
- Nyashで書いたBoxが他言語から使える
|
||||
- 真の言語間相互運用性
|
||||
|
||||
## 📊 実装優先順位
|
||||
|
||||
1. **即実装可能**(既存基盤で動く)
|
||||
- ユーザーBox登録API拡張
|
||||
- 統一レジストリ実装
|
||||
- 基本的な相互運用テスト
|
||||
|
||||
2. **短期実装**(軽微な修正)
|
||||
- @exportアノテーション
|
||||
- 自動C ABI生成
|
||||
- ドキュメント整備
|
||||
|
||||
3. **中期実装**(最適化)
|
||||
- AOT時の統一最適化
|
||||
- クロスランゲージデバッガ
|
||||
- パッケージマネージャー統合
|
||||
|
||||
## 🎯 結論
|
||||
|
||||
**「箱の境界をなくす」は、単なる理想ではなく、現在のNyashアーキテクチャで実現可能な次のステップです。**
|
||||
|
||||
既存のVM/PIC/vtable基盤があるため、追加実装は最小限で済みます。これこそが「Everything is Box」哲学の究極の実現です。
|
||||
|
||||
## 📚 参照
|
||||
|
||||
- [統一TypeBox ABI](./unified-typebox-abi.md)
|
||||
- [ユーザー定義Box統合](./unified-typebox-user-box.md)
|
||||
- [AI先生たちの技術検討](./ai-consultation-unified-typebox.md)
|
||||
208
docs/archive/roadmap/phases/phase-12/IMPLEMENTATION_ROADMAP.md
Normal file
208
docs/archive/roadmap/phases/phase-12/IMPLEMENTATION_ROADMAP.md
Normal file
@ -0,0 +1,208 @@
|
||||
# Phase 12: 統一TypeBox ABI - 実装ロードマップ
|
||||
|
||||
## 🎯 概要
|
||||
|
||||
このドキュメントは、統一TypeBox ABIの実装を段階的に進めるための詳細なロードマップです。
|
||||
|
||||
## 📅 タイムライン
|
||||
|
||||
```
|
||||
2025年9月(Week 1-2): 基礎実装
|
||||
2025年9月(Week 3-4): 最適化・性能向上
|
||||
2025年10月(Week 1-2): 移行ツール・互換性
|
||||
2025年10月(Week 3-4): 完全移行・テスト
|
||||
2025年11月:リリース準備
|
||||
```
|
||||
|
||||
## 🚀 Phase 12.0: 基礎実装(Week 1-2)
|
||||
|
||||
### Week 1: コア構造体とAPI
|
||||
|
||||
#### タスク
|
||||
- [ ] `include/nyash/typebox.h` ヘッダー定義
|
||||
- [ ] NyashTypeBox構造体
|
||||
- [ ] NyBoxHeader構造体
|
||||
- [ ] NyValue統一表現
|
||||
- [ ] 基本的なヘルパーマクロ
|
||||
|
||||
- [ ] `src/runtime/typebox_registry.rs` 実装
|
||||
- [ ] Type ID管理システム
|
||||
- [ ] register_user_box基本実装
|
||||
- [ ] メソッドテーブル管理
|
||||
|
||||
- [ ] 基本的なテストケース
|
||||
- [ ] ユーザーBox登録テスト
|
||||
- [ ] メソッド呼び出しテスト
|
||||
- [ ] 参照カウントテスト
|
||||
|
||||
#### 成果物
|
||||
- 動作する最小限のTypeBox登録・呼び出し
|
||||
- ドキュメント化されたAPI
|
||||
|
||||
### Week 2: 互換レイヤー
|
||||
|
||||
#### タスク
|
||||
- [ ] 既存C ABIとの互換レイヤー
|
||||
- [ ] 旧形式→TypeBox自動変換
|
||||
- [ ] フォールバックメカニズム
|
||||
- [ ] 警告・移行推奨メッセージ
|
||||
|
||||
- [ ] 主要プラグインの動作確認
|
||||
- [ ] FileBox
|
||||
- [ ] StringBox
|
||||
- [ ] MapBox
|
||||
- [ ] ArrayBox
|
||||
|
||||
#### 成果物
|
||||
- 既存プラグインが新システムで動作
|
||||
- 移行ガイドの初版
|
||||
|
||||
## ⚡ Phase 12.1: 最適化(Week 3-4)
|
||||
|
||||
### Week 3: メソッドID最適化
|
||||
|
||||
#### タスク
|
||||
- [ ] メソッド名→ID解決システム
|
||||
- [ ] ハッシュテーブル実装
|
||||
- [ ] スロット割り当てアルゴリズム
|
||||
- [ ] キャッシュ機構
|
||||
|
||||
- [ ] パフォーマンス測定
|
||||
- [ ] ベンチマークスイート作成
|
||||
- [ ] 旧方式との比較測定
|
||||
- [ ] ボトルネック分析
|
||||
|
||||
#### 成果物
|
||||
- 10倍以上の高速化を確認
|
||||
- パフォーマンスレポート
|
||||
|
||||
### Week 4: JIT/AOT統合
|
||||
|
||||
#### タスク
|
||||
- [ ] インラインキャッシング基礎
|
||||
- [ ] Monomorphic IC実装
|
||||
- [ ] キャッシュヒット率測定
|
||||
- [ ] Deoptimizationフック
|
||||
|
||||
- [ ] JIT統合準備
|
||||
- [ ] メソッドポインタ直接呼び出し
|
||||
- [ ] 型情報の静的解析連携
|
||||
- [ ] AOT向け最適化ヒント
|
||||
|
||||
#### 成果物
|
||||
- IC有効時30倍高速化を達成
|
||||
- JIT統合設計書
|
||||
|
||||
## 🔄 Phase 12.2: 移行ツール(Week 5-6)
|
||||
|
||||
### Week 5: ツール開発
|
||||
|
||||
#### タスク
|
||||
- [ ] `ny-abi-gen` コード生成ツール
|
||||
- [ ] Cヘッダーからの自動生成
|
||||
- [ ] nyash.toml更新機能
|
||||
- [ ] ドキュメント生成
|
||||
|
||||
- [ ] `ny-abi-check` 検証ツール
|
||||
- [ ] ABI互換性チェック
|
||||
- [ ] 署名検証
|
||||
- [ ] セキュリティ監査
|
||||
|
||||
#### 成果物
|
||||
- 使いやすい移行ツール群
|
||||
- 自動化されたCI/CDパイプライン
|
||||
|
||||
### Week 6: プラグイン移行
|
||||
|
||||
#### タスク
|
||||
- [ ] コアプラグインの移行
|
||||
- [ ] すべてのビルトインBoxをTypeBox化
|
||||
- [ ] サードパーティプラグインサポート
|
||||
- [ ] 移行スクリプト提供
|
||||
|
||||
- [ ] ドキュメント整備
|
||||
- [ ] 移行ガイド完成版
|
||||
- [ ] APIリファレンス
|
||||
- [ ] サンプルコード集
|
||||
|
||||
#### 成果物
|
||||
- 90%以上のプラグインが新ABI対応
|
||||
- 完全なドキュメント
|
||||
|
||||
## ✅ Phase 12.3: 完全移行(Week 7-8)
|
||||
|
||||
### Week 7: 統合テスト
|
||||
|
||||
#### タスク
|
||||
- [ ] エンドツーエンドテスト
|
||||
- [ ] 実アプリケーションでの動作確認
|
||||
- [ ] パフォーマンス回帰テスト
|
||||
- [ ] メモリリークチェック
|
||||
|
||||
- [ ] セキュリティ監査
|
||||
- [ ] Wasmサンドボックステスト
|
||||
- [ ] 権限管理システム検証
|
||||
- [ ] ファジングテスト
|
||||
|
||||
#### 成果物
|
||||
- グリーンなテストスイート
|
||||
- セキュリティレポート
|
||||
|
||||
### Week 8: リリース準備
|
||||
|
||||
#### タスク
|
||||
- [ ] 最終調整
|
||||
- [ ] パフォーマンスチューニング
|
||||
- [ ] メモリ使用量最適化
|
||||
- [ ] エラーメッセージ改善
|
||||
|
||||
- [ ] リリース準備
|
||||
- [ ] CHANGELOG作成
|
||||
- [ ] アップグレードガイド
|
||||
- [ ] ブログ記事・アナウンス
|
||||
|
||||
#### 成果物
|
||||
- リリース候補版
|
||||
- 完全なリリースノート
|
||||
|
||||
## 📊 成功指標
|
||||
|
||||
### パフォーマンス
|
||||
- メソッド呼び出し: 50倍高速化(目標)
|
||||
- メモリ使用量: 現状維持または改善
|
||||
- 起動時間: 10%以内の増加
|
||||
|
||||
### 互換性
|
||||
- 既存プラグイン: 100%動作
|
||||
- 新規API採用率: 80%以上
|
||||
- 移行完了率: 90%以上
|
||||
|
||||
### 品質
|
||||
- テストカバレッジ: 90%以上
|
||||
- ドキュメント完成度: 100%
|
||||
- バグ報告: クリティカル0件
|
||||
|
||||
## 🚨 リスクと対策
|
||||
|
||||
### 技術的リスク
|
||||
- **ABI破壊的変更**: 段階的移行と互換レイヤーで対応
|
||||
- **パフォーマンス劣化**: 継続的なベンチマークで早期発見
|
||||
- **メモリリーク**: 自動テストとValgrind検証
|
||||
|
||||
### スケジュールリスク
|
||||
- **遅延**: 2週間のバッファを確保
|
||||
- **スコープクリープ**: 機能は段階的リリース
|
||||
- **リソース不足**: コミュニティ協力を促進
|
||||
|
||||
## 🎯 次のステップ
|
||||
|
||||
1. このロードマップのレビューと承認
|
||||
2. Week 1タスクの詳細化
|
||||
3. 開発環境のセットアップ
|
||||
4. キックオフミーティング
|
||||
|
||||
## 📚 参照
|
||||
|
||||
- [技術的決定事項](./TECHNICAL_DECISIONS.md)
|
||||
- [統一TypeBox ABI仕様](./unified-typebox-abi.md)
|
||||
- [AI先生たちの技術検討](./ai-consultation-unified-typebox.md)
|
||||
62
docs/archive/roadmap/phases/phase-12/PLAN.md
Normal file
62
docs/archive/roadmap/phases/phase-12/PLAN.md
Normal file
@ -0,0 +1,62 @@
|
||||
# Phase 12: ユーザー箱とプラグイン箱の境界撤廃 + Nyash ABI 導入計画(下準備)
|
||||
|
||||
目的
|
||||
- 境界撤廃: ユーザー箱/プラグイン箱/内蔵箱を「TypeBox + Instance」に統一。
|
||||
- Nyash ABI: vtable(slot優先)で高速・型安全に呼び出し、未対応は現行C ABI(TLV)へフォールバック。
|
||||
- 綺麗な箱化: VM/JIT/LLVM/WASMが同一ディスパッチ構造を共有できる形へ段階導入。
|
||||
- 同一実行: Nyashコードが VM と JIT で「意味・結果・副作用」が一致(同値性がテストで担保)。
|
||||
|
||||
非スコープ(当面)
|
||||
- 既存C ABIの破壊的変更。段階導入のためC ABIは維持(fallback専用)。
|
||||
- 直ちに全プラグインを移行すること(まずは1プラグインでPoC)。
|
||||
|
||||
設計の要点(サマリ)
|
||||
- TypeBox(静的メタ): 型名、メソッドslot→関数ポインタ、属性(可変/不変など)。
|
||||
- Instance(実体): type_id + 実体ハンドル(ユーザー/プラグイン/内蔵いずれも統一の箱)。
|
||||
- VMディスパッチ: method_id/slotがあれば vtable 直呼び。なければ name→slot 解決→vtable/PIC→C ABI。
|
||||
- JIT: まずはホストコールthunkでTypeBox vtable呼び出し→後続でモノモーフィック直埋め最適化。
|
||||
- GC/Barrier: BoxCall(setField)/ArraySetでWrite Barrier発火(既存fast-path維持)。
|
||||
|
||||
トグル(管理棟に集約予定)
|
||||
- NYASH_ABI_VTABLE=1 … vtable経路を有効化(既定OFF)
|
||||
- NYASH_ABI_STRICT=1 … vtable未登録メソッド時にC ABIフォールバック禁止(実験)
|
||||
|
||||
段階導入(Tier)
|
||||
1) Tier-0(雛形)
|
||||
- 追加: `src/runtime/type_box_abi.rs`(NyrtValue/TypeBox/関数ポインタ型、最小API)
|
||||
- 追加: `src/runtime/type_registry.rs`(TypeId→TypeBox参照)
|
||||
- VM: `execute_boxcall` に vtable 優先のstubを追加(`NYASH_ABI_VTABLE=1`時のみ)
|
||||
- Docs/CI: 仕様追記・スモーク追加準備(まだvtableは未実装でもOK)
|
||||
2) Tier-1(実証)
|
||||
- 1プラグイン(例: MapBox.getS)を Nyash ABI で動作させる(VM→vtable→関数ポインタ)
|
||||
- JIT: vtable呼び出しthunk追加(VM側レジストリから関数ポインタ取得)
|
||||
- テスト: C ABI とNyash ABIの同等性(差分テスト)
|
||||
3) Tier-2(拡張)
|
||||
- 内蔵箱のTypeBox化(Array/String/Mapの主要メソッド)
|
||||
- ユーザー箱(InstanceBox)をTypeBox上に還元(Rust関数を関数ポインタで包む)
|
||||
- name→slot化の徹底(slot_registry と連携強化)
|
||||
4) Tier-3(セルフホスティング準備)
|
||||
- Nyash ABI のC実装を開始(Rust⇔C シム)
|
||||
- JIT: モノモーフィックサイトで vtable_slot 直呼び最適化
|
||||
|
||||
完了条件(Phase 12の下準備)
|
||||
- PLAN/TASKS/TECHNICAL_DECISIONS に統一方針と段階計画が明記されている。
|
||||
- `NYASH_ABI_VTABLE` トグルの導入方針が定義済み(まだコードは雛形で可)。
|
||||
- VM側にvtable優先呼び出しstubの追加計画が固まり、レジストリ/TypeBox ABIの最小構成が決まっている。
|
||||
- Cross-backend同値テストの設計方針が固まっている(VM/JITを同条件で走らせ、結果/ログ/副作用を比較する仕組み)。
|
||||
|
||||
次アクション(このPR/コミット範囲外の実装)
|
||||
- TypeBox ABIモジュール雛形の追加、VM vtable stub の実装(既定OFF)。
|
||||
- MapBoxで最小PoC(getS)を先行導入(C ABIと同じ結果を返す)。
|
||||
- docs/TASKSのTier-0チェックを更新、CIスモークの草案を追加。
|
||||
|
||||
検証(同一実行)の方針
|
||||
- テストハーネス: 同一 Nyash プログラムを VM と JIT で実行し、以下を比較
|
||||
- 戻り値の等価(NyashValue同値: int/float/bool/string/null/void)
|
||||
- Box状態の差分(対象: Map/Array/Instance の代表ケース)
|
||||
- ログイベントの正規化比較(必要最小限)
|
||||
- スコープ: array/field/arithmetic/extern_call を最小セットにし、段階的に拡張
|
||||
- CI連携: `consistency` ラベルのテストジョブを追加(将来)
|
||||
|
||||
参考ドキュメント
|
||||
- Nyash ABI Minimal Coreと進化戦略: `docs/reference/abi/NYASH_ABI_MIN_CORE.md`
|
||||
271
docs/archive/roadmap/phases/phase-12/README.md
Normal file
271
docs/archive/roadmap/phases/phase-12/README.md
Normal file
@ -0,0 +1,271 @@
|
||||
# Phase 12: Nyashコード共有エコシステム - Everything is Box の実現
|
||||
|
||||
> Status note (Phase‑15): このフォルダは「統一TypeBox ABI」の長期設計(青写真)です。現在の main 実装は最小の v2 ABI に収束しており、実用重視で段階導入中です。現行仕様は `docs/reference/plugin-abi/nyash_abi_v2.md` を参照してください。Phase‑12 の要素(create/destroy、型メタ、NyValue、vtable/RC/GC)は前方互換を維持しつつ段階追加予定です。
|
||||
|
||||
## 🌟 最新ブレイクスルー (2025-09-02) - 統一TypeBox ABI誕生!
|
||||
|
||||
### 🚨 究極の発見:ユーザー定義Boxもプラグインに!
|
||||
|
||||
**AI先生たちの深い技術的検討により、革命的なアイデアが実現可能と判明!**
|
||||
|
||||
```c
|
||||
// ユーザーBoxもプラグインとして動的登録
|
||||
NyashTypeBox* register_user_box(const char* name,
|
||||
NyashBoxMethods* methods);
|
||||
```
|
||||
|
||||
**これにより実現すること**:
|
||||
- 🎯 **すべての箱をC ABI上で一つで管理**
|
||||
- 🔄 **ユーザー定義Box ↔ プラグインBox 完全相互運用**
|
||||
- 🚀 **Nyash側から見ると完全に統一された世界観**
|
||||
|
||||
詳細:[ユーザー定義Box統合](./unified-typebox-user-box.md) 🆕
|
||||
|
||||
### 🔥 究極の統合:すべてのプラグインがTypeBoxになる!
|
||||
|
||||
「Everything is Box」哲学の完成形:**C ABIもNyash ABIも統一TypeBoxに統合**!
|
||||
|
||||
```c
|
||||
// 統一TypeBox - すべてのプラグインがこの形式に!
|
||||
typedef struct {
|
||||
uint32_t abi_tag; // 'TYBX' - すべて同じ
|
||||
uint16_t version; // APIバージョン
|
||||
const char* name; // "StringBox", "FileBox", etc.
|
||||
|
||||
// 基本操作(旧C ABI互換)
|
||||
void* (*create)(void* args);
|
||||
void (*destroy)(void* self);
|
||||
|
||||
// 高速メソッドディスパッチ(新機能)
|
||||
uint32_t (*resolve)(const char* name); // 名前→ID変換
|
||||
NyResult (*invoke_id)(void* self, // ID呼び出し(JIT最適化)
|
||||
uint32_t method_id,
|
||||
NyValue* args, int argc);
|
||||
|
||||
// メタ情報
|
||||
uint64_t capabilities; // THREAD_SAFE | ASYNC_SAFE等
|
||||
} NyashTypeBox;
|
||||
```
|
||||
|
||||
**3大AI専門家の統合案への評価**:
|
||||
- **Gemini**: 「技術的妥当性は非常に高い。単なるアイデアではなく、堅牢なアーキテクチャ」
|
||||
- **Codex**: 「TypeBox統合は実現可能で有益。JIT最適化で33倍高速化も可能」
|
||||
- **ChatGPT5**: 「『Everything is Box』哲学に最も適した設計」(設計に反映済み)
|
||||
|
||||
### 🎯 なぜ統合するのか?
|
||||
|
||||
以前は2つのシステムが混在していました:
|
||||
- **C ABI**:シンプルだが拡張性に限界
|
||||
- **TypeBox**:プラグイン間連携は可能だが別システム
|
||||
|
||||
**統合により実現したこと**:
|
||||
1. **概念の統一**:すべてがTypeBoxという1つの形式
|
||||
2. **プラグイン間連携が標準装備**:どのプラグインも他のBoxを作れる
|
||||
3. **JIT/AOT最適化**:メソッドID化で最大33倍高速化
|
||||
4. **段階的移行**:既存資産を保護しながら進化
|
||||
|
||||
## 🎯 重要な変更 (2025-09-01)
|
||||
|
||||
Phase 12の議論とビルトインBox廃止により、プラグインシステムが進化:
|
||||
|
||||
**新しい3層プラグインシステムが確立されました!**
|
||||
|
||||
```nyash
|
||||
# Nyashスクリプトプラグイン(ユーザー定義Box)
|
||||
box DataProcessor {
|
||||
init {
|
||||
me.file = new FileBox() # C ABIプラグイン使用
|
||||
me.math = new MathBox() # C ABIプラグイン使用
|
||||
me.cache = new MapBox() # これもC ABIプラグイン(ビルトイン廃止)
|
||||
}
|
||||
|
||||
process(data) {
|
||||
local result = me.math.sin(data)
|
||||
me.file.write("log.txt", result.toString())
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
# 使用例
|
||||
local processor = new DataProcessor()
|
||||
processor.process(3.14) # すべてプラグインで動作!
|
||||
```
|
||||
|
||||
## 📝 なぜ誤解が生まれたのか
|
||||
|
||||
「プラグイン」という言葉から、特別な仕組みが必要だと考えてしまいましたが、Nyashの「Everything is Box」哲学により、ユーザー定義Boxこそが最高のプラグインシステムでした。
|
||||
|
||||
詳細な分析:[なぜ天才AIたちは間違えたのか](./design/WHY-AIS-FAILED.md)
|
||||
|
||||
## 🚀 Phase 12の真の価値:コード共有エコシステム(同一実行の確立)
|
||||
|
||||
最終ゴールは「Nyashコード → VM → JIT の同一実行」。同じプログラムがVMとJITで同じ意味・結果・副作用になるよう、ディスパッチ/ABI/Barrier/Safepointの規約を共有し、差分をなくします。テストハーネスで同値性を比較できるように整備します。
|
||||
|
||||
### 本当に必要なもの
|
||||
|
||||
1. **export/import構文**
|
||||
```nyash
|
||||
# math_utils.ny
|
||||
export box MathUtils {
|
||||
factorial(n) { ... }
|
||||
fibonacci(n) { ... }
|
||||
}
|
||||
|
||||
# main.ny
|
||||
import { MathUtils } from "math_utils.ny"
|
||||
local utils = new MathUtils()
|
||||
```
|
||||
|
||||
2. **パッケージマネージャー**
|
||||
```bash
|
||||
nyash install awesome-math-utils
|
||||
nyash publish my-cool-box
|
||||
```
|
||||
|
||||
3. **ドキュメント生成**
|
||||
```nyash
|
||||
# @doc 素晴らしい数学ユーティリティ
|
||||
# @param n 計算したい数値
|
||||
# @return 階乗の結果
|
||||
export box MathUtils { ... }
|
||||
```
|
||||
|
||||
## 📊 新しい統一プラグインシステム
|
||||
|
||||
```
|
||||
Nyashエコシステム(統一TypeBox ABI採用後):
|
||||
├── Nyashスクリプトプラグイン ← .hakoファイル(純粋なNyashコード)
|
||||
└── 統一TypeBoxプラグイン ← .so/.dll(ネイティブ実装)
|
||||
├── 基本機能(旧C ABI互換)
|
||||
├── 高速ディスパッチ(JIT最適化)
|
||||
└── プラグイン間連携(標準装備)
|
||||
```
|
||||
|
||||
### 🔄 移行パス
|
||||
- **既存C ABIプラグイン** → そのまま動作(互換レイヤー経由)
|
||||
- **新規プラグイン** → 統一TypeBox形式で作成
|
||||
- **段階的移行** → ツールで自動変換支援
|
||||
|
||||
### 📚 プラグインシステムドキュメント
|
||||
|
||||
- **[統一TypeBox ABI](./unified-typebox-abi.md)** 🆕 - すべてのプラグインの統一仕様
|
||||
- **[移行ガイド](./migration-guide.md)** 🆕 - 既存プラグインの移行方法
|
||||
- **[Nyashスクリプトプラグイン](./nyash-script-plugins.md)** - 純粋なNyashコードのプラグイン
|
||||
|
||||
### 📦 レガシードキュメント(参考用)
|
||||
- [旧C ABI仕様](./archive/legacy-abi-docs/c-abi.md)
|
||||
- [旧Nyash ABI仕様](./archive/legacy-abi-docs/nyash-abi.md)
|
||||
|
||||
### 💡 TypeBox:シンプルなプラグイン間連携
|
||||
|
||||
MapBox.keys()がArrayBoxを返したい場合:
|
||||
|
||||
```c
|
||||
// TypeBox構造体(型情報をBoxとして扱う)
|
||||
typedef struct {
|
||||
uint32_t abi_tag; // 'TYBX'
|
||||
const char* name; // "ArrayBox"
|
||||
void* (*create)(void); // Box生成関数
|
||||
} NyrtTypeBox;
|
||||
|
||||
// MapBox.keys()実装
|
||||
void* map_keys(void* self, void* array_type_box) {
|
||||
NyrtTypeBox* array_type = (NyrtTypeBox*)array_type_box;
|
||||
void* array = array_type->create(); // ArrayBox生成
|
||||
// ... キーを追加
|
||||
return array;
|
||||
}
|
||||
```
|
||||
|
||||
詳細: [C ABI TypeBox設計仕様書](./archive/legacy-abi-docs/C-ABI-BOX-FACTORY-DESIGN.md)
|
||||
|
||||
### プラグイン選択の指針
|
||||
- **C ABIで済むなら、C ABIを使う**(シンプルイズベスト)
|
||||
- Nyash ABIは以下の場合のみ:
|
||||
- 他言語(Python/Go等)からの呼び出し
|
||||
- 複雑な型の相互運用が必要
|
||||
- 将来の拡張性を重視する場合
|
||||
|
||||
### 📝 MIR命令統合(Phase 12での変更)
|
||||
- **PluginInvoke → BoxCall 統合**
|
||||
- ビルトインBox廃止によりフォールバックがなくなる
|
||||
- BoxCallとPluginInvokeの区別が不要に
|
||||
- VM層でC ABI/Nyash ABI/Scriptを自動判定
|
||||
- Core-15 → Core-14 へ(命令数削減)
|
||||
|
||||
## 🛣️ 実装ロードマップ(統一TypeBox ABI版)
|
||||
|
||||
### Phase 12.0: 統一TypeBox ABI実装(1週間)🆕
|
||||
- [ ] nyash_typebox.h完全ヘッダー定義
|
||||
- [ ] メソッドID解決・キャッシング機構
|
||||
- [ ] NyValue統一値表現の実装
|
||||
- [ ] 互換レイヤー(既存C ABI→TypeBox)
|
||||
- 📄 **[統一TypeBox ABI仕様](./unified-typebox-abi.md)**
|
||||
|
||||
### Phase 12.0.5: 移行ツール開発(2週間)🔧
|
||||
- [ ] プラグイン自動変換ツール
|
||||
- [ ] 検証・テストツール
|
||||
- [ ] パフォーマンスベンチマーク
|
||||
- [ ] サンプルプラグイン集
|
||||
- 📄 **[移行ガイド](./migration-guide.md)**
|
||||
|
||||
---
|
||||
|
||||
## 現状サマリ(2025-09-02)
|
||||
|
||||
- C ABI(TLV: 1/2/3/5/6/7/8)でのプラグイン呼び出しはVMで安定運用中。`returns_result` も `nyash.toml` で制御可能。
|
||||
- JIT は VM と同じBox境界で動作(フォールバック含む)。Cranelift AOT のオブジェクト出力は未配線(スケルトン)。
|
||||
- MapBox を拡張(stringキー、remove/clear/getOr/keysStr/valuesStr/toJson)。`keys()/values()` はランタイムシムで暫定提供。
|
||||
- Phase 12 設計(TypeBox + Unified Dispatch)は破壊的変更不要で段階導入可能と判断。
|
||||
|
||||
詳細タスクは [TASKS.md](./TASKS.md) を参照。
|
||||
|
||||
|
||||
### Phase 12.1: export/import構文(2週間)
|
||||
- [ ] exportキーワードのパーサー実装
|
||||
- [ ] importステートメントの実装
|
||||
- [ ] モジュール解決システム
|
||||
- 📄 **[詳細仕様書](./export-import-spec.md)**
|
||||
|
||||
### Phase 12.2: パッケージ管理(3週間)
|
||||
- [ ] nyash.tomlのdependencies対応
|
||||
- [ ] 中央リポジトリ設計
|
||||
- [ ] CLIツール(install/publish)
|
||||
- 📄 **[パッケージマネージャー設計書](./package-manager-design.md)**
|
||||
|
||||
### Phase 12.3: 開発者体験向上(継続的)
|
||||
- [ ] ドキュメント生成ツール
|
||||
- [ ] VSCode拡張(補完・定義ジャンプ)
|
||||
- [ ] サンプルパッケージ作成
|
||||
|
||||
## 📚 関連ドキュメント
|
||||
|
||||
### 🎯 プラグインシステムガイド(メインドキュメント)
|
||||
- **[統一TypeBox ABI](./unified-typebox-abi.md)** ← 🌟🆕 すべてのプラグインの新仕様!
|
||||
- **[ユーザー定義Box統合](./unified-typebox-user-box.md)** ← 🔥🆕 革命的な完全統合!
|
||||
- **[AI先生たちの技術的検討](./ai-consultation-unified-typebox.md)** ← 🤖🆕 深い分析と提言(Codex詳細版追加)
|
||||
- **[技術的決定事項](./TECHNICAL_DECISIONS.md)** ← 📋🆕 確定した技術仕様まとめ
|
||||
- **[実装ロードマップ](./IMPLEMENTATION_ROADMAP.md)** ← 📅🆕 詳細な実装計画
|
||||
- **[移行ガイド](./migration-guide.md)** ← 🆕 既存プラグインを新形式へ
|
||||
- **[Nyashスクリプトプラグイン](./nyash-script-plugins.md)** ← 純粋なNyashコードのプラグイン
|
||||
|
||||
### 📐 設計ドキュメント(design/)
|
||||
- **[統合ABI設計仕様書](./design/UNIFIED-ABI-DESIGN.md)** ← 統合の詳細設計
|
||||
- **[C ABI TypeBox設計仕様書](./archive/legacy-abi-docs/C-ABI-BOX-FACTORY-DESIGN.md)** ← TypeBoxの原点
|
||||
- **[Nyash ABI C実装設計書](./design/NYASH-ABI-C-IMPLEMENTATION.md)** ← セルフホスティング構想
|
||||
- **[なぜ天才AIたちは間違えたのか](./design/WHY-AIS-FAILED.md)** ← 設計プロセスの教訓
|
||||
|
||||
### 📋 仕様書(specs/)
|
||||
- **[export/import仕様](./specs/export-import-spec.md)** ← モジュールシステムの詳細仕様
|
||||
- **[パッケージマネージャー設計](./specs/package-manager-design.md)** ← パッケージ管理の設計
|
||||
|
||||
### 💬 議論の過程(discussions/)
|
||||
- **ABI戦略議論**: `discussions/abi-strategy-discussion/`
|
||||
- **Nyash ABI詳細**: `discussions/nyash-abi-discussion/`
|
||||
|
||||
### 📦 アーカイブ
|
||||
- **初期提案**: `archive/` ← 過去の提案や古いドキュメント
|
||||
|
||||
---
|
||||
|
||||
*AIたちがなぜ複雑な解決策を提案したのか、その議論の過程は `archive/` ディレクトリに保存されています。良い教訓として残しておきます。*
|
||||
66
docs/archive/roadmap/phases/phase-12/TASKS.md
Normal file
66
docs/archive/roadmap/phases/phase-12/TASKS.md
Normal file
@ -0,0 +1,66 @@
|
||||
# Phase 12 Task Board (v2 - セルフホスティング対応)
|
||||
|
||||
Status: Tier-0 完了(vtable雛形 + レジストリ + VM優先経路)。次は Tier-1 の最小Nyash ABIサンプル実装へ。
|
||||
|
||||
目的: C ABI を壊さず、TypeBox + 統一ディスパッチで Nyash ABI を段階導入。MIR→VM→JIT を「綺麗な箱」で統一。**最終的にRust依存を排除し、セルフホスティングを実現。**
|
||||
|
||||
## Tier-0(直近・安全に積める)
|
||||
- [x] MapBoxの実用拡張(stringキー/便利API)
|
||||
- [x] `keys()/values()` 実装(ArrayBox返却に更新)
|
||||
- [x] TypeBoxレジストリ(雛形)
|
||||
- Box名/FQN、type_id、メソッド表(静的スロット)を登録(`src/runtime/type_registry.rs`)
|
||||
- 既存 `nyash.toml` → TypeBoxInfo 変換層は別途(未着手)
|
||||
- [x] 統一ディスパッチ層(VM・雛形)
|
||||
- `NYASH_ABI_VTABLE=1` で vtable優先のVM経路を有効化(fallbackはC ABI/TLV)。
|
||||
- Array/Map/String/Instance の主要メソッドを最小カバレッジで処理(`try_boxcall_vtable_stub`)。
|
||||
- 所有権・セーフポイントのガードは既存Barrier呼び出しで一部対応(MAY_BLOCK等は今後拡張)。
|
||||
- [x] プラグインテスター更新(v2ローダに対応): `src/bin/test_plugin_loader_v2.rs`
|
||||
|
||||
## Tier-1(実証)
|
||||
- [ ] Nyash ABI vtable の最小サンプル(1プラグイン・1メソッド)
|
||||
- 例: MapBox.getS(name) を Nyash ABI で直接返却
|
||||
- 単体テスト(VM/JIT)
|
||||
- [ ] JIT側:統一ディスパッチthunkを呼ぶ経路を追加(フォールバックでも可)
|
||||
- [ ] 互換テスト: C ABI と Nyash ABI が同一結果になる差分テスト
|
||||
|
||||
## Tier-2(強化)
|
||||
- [ ] NyashValueインライン(i64/bool)の高速化
|
||||
- [ ] 例外/エラーの完全変換(panic→nyrt_err)
|
||||
- [ ] 所有権契約の遵守(TRANSFER/BORROW/CLONE)
|
||||
- [x] `keys()/values()` の正式実装(ArrayBox返却)
|
||||
- 採用: ランタイムで ArrayBox を構築(`src/boxes/map_box.rs`)
|
||||
|
||||
## Tier-3(セルフホスティング)🔥新規
|
||||
- [ ] Nyash ABI C実装の開始
|
||||
- [ ] nyash_abi_provider.h定義(16バイトアライメント)
|
||||
- [ ] C Shim実装(Rust FFI経由)
|
||||
- [ ] 基本型実装(Tagged Pointers対応)
|
||||
- [ ] アトミック参照カウント実装
|
||||
- [ ] 弱参照による循環参照対策
|
||||
- [ ] セレクターキャッシング実装
|
||||
- [ ] lookup_selector API
|
||||
- [ ] JIT統合(vtable_slot直接呼び出し)
|
||||
- [ ] 適合性テストスイート構築
|
||||
- [ ] Rust/C実装の差分テスト
|
||||
- [ ] パフォーマンス測定(1.5x以内)
|
||||
|
||||
## ドキュメント/管理
|
||||
- [ ] UNIFIED-ABI-DESIGN.md の「最小導入プロファイル」明記
|
||||
- [ ] VM/JIT実装メモ(統一ディスパッチの呼出し順)
|
||||
- [ ] リファクタリング計画(>1000行ファイルの分割方針)
|
||||
|
||||
## 既知のやり残し(Phase 12 関連)
|
||||
- TypeBoxレジストリ/統一ディスパッチのコード未導入
|
||||
- Nyash ABI vtableの実装サンプル未着手
|
||||
- 既存プラグインの対応(TypeBox vtable移行 or 互換レイヤ継続)
|
||||
- GCセーフポイントのMAY_BLOCK以外の一般化
|
||||
- keys()/values() の正式ArrayBox返却(現状はシム)
|
||||
- AOT(LLVM)のbuild失敗(nyrt借用修正、後回し方針)
|
||||
- Nyash ABI C実装(セルフホスティングの要)🔥新規
|
||||
|
||||
## Doneの定義(Phase 12 - 更新版)
|
||||
1) TypeBoxレジストリと統一ディスパッチがVMに入り、C ABI互換で全プラグインが動作
|
||||
2) 1プラグインでNyash ABIの成功パスが通る(VM/JIT)
|
||||
3) keys()/values() が ArrayBox 返却で安定
|
||||
4) 基本の所有権・セーフポイントルールが守られる
|
||||
5) **Nyash ABI C実装の基礎が動作し、セルフホスティングへの道筋が明確**🔥新規
|
||||
143
docs/archive/roadmap/phases/phase-12/TECHNICAL_DECISIONS.md
Normal file
143
docs/archive/roadmap/phases/phase-12/TECHNICAL_DECISIONS.md
Normal file
@ -0,0 +1,143 @@
|
||||
# Phase 12: 統一TypeBox ABI - 技術的決定事項
|
||||
|
||||
## 📅 最終更新: 2025-09-02
|
||||
|
||||
このドキュメントは、3人のAI専門家(Gemini、Codex、ChatGPT5)の深い技術検討を経て決定された、統一TypeBox ABIの技術的決定事項をまとめたものです。
|
||||
|
||||
## 🎯 核心的決定事項
|
||||
|
||||
### 1. 統一TypeBox構造体の確定
|
||||
|
||||
```c
|
||||
typedef struct NyashTypeBox {
|
||||
// === ヘッダー情報(不変のバイナリ契約)===
|
||||
uint32_t abi_tag; // 'TYBX' (0x54594258) - 必須
|
||||
uint16_t version; // APIバージョン(現在: 1)
|
||||
uint16_t struct_size; // 構造体サイズ(前方互換性)
|
||||
const char* name; // Box型名:"StringBox"
|
||||
|
||||
// === 基本操作(COM互換)===
|
||||
void* (*create)(void* args); // インスタンス生成
|
||||
void (*destroy)(void* self); // インスタンス破棄
|
||||
void (*retain)(void* self); // 参照カウント増加(新規)
|
||||
void (*release)(void* self); // 参照カウント減少(新規)
|
||||
|
||||
// === 高速メソッドディスパッチ ===
|
||||
uint32_t (*resolve)(const char* name); // メソッド名→ID変換
|
||||
NyResult (*invoke_id)(void* self, // ID指定の高速呼び出し
|
||||
uint32_t method_id,
|
||||
NyValue* args,
|
||||
int argc);
|
||||
|
||||
// === メタ情報 ===
|
||||
const char* (*get_type_info)(void); // JSON形式の型情報
|
||||
uint64_t capabilities; // 機能フラグ
|
||||
|
||||
// === 将来拡張用 ===
|
||||
void* reserved[4]; // NULL初期化必須
|
||||
} NyashTypeBox;
|
||||
```
|
||||
|
||||
### 2. Type ID管理戦略
|
||||
|
||||
64-bit構造: `[8b domain | 8b vendor | 16b category | 32b serial]`
|
||||
|
||||
- **0x00xxxxxx**: Core/Built-in types
|
||||
- **0x40xxxxxx**: First-party plugins
|
||||
- **0x80xxxxxx**: User-defined boxes (動的登録)
|
||||
- **0xC0xxxxxx**: Experimental/Debug
|
||||
|
||||
### 3. メモリ管理統一方針
|
||||
|
||||
#### 参照カウント(必須)
|
||||
- アトミック操作(`_Atomic uint64_t`)
|
||||
- retain/releaseはCOM互換の固定位置
|
||||
- 循環参照対策:Trial Deletion + Weak Boundary
|
||||
|
||||
#### GC協調(オプション)
|
||||
- traceメソッドの提供(プラグイン必須)
|
||||
- 世代別GCとの協調動作
|
||||
|
||||
### 4. パフォーマンス目標値
|
||||
|
||||
- **メソッド呼び出し**: 旧50-150ns → 新1-3ns(最大50倍高速化)
|
||||
- **インラインキャッシング**: Monomorphic IC標準装備
|
||||
- **JIT統合**: ウォームアップ後の直接インライン化
|
||||
|
||||
### 5. セキュリティレベル定義
|
||||
|
||||
1. **trusted**: 同一プロセス内、直接関数呼び出し
|
||||
2. **sandboxed**: Wasm/別プロセスで実行
|
||||
3. **restricted**: 限定的な権限のみ
|
||||
|
||||
## 🔧 実装上の決定事項
|
||||
|
||||
### メソッドディスパッチ戦略
|
||||
|
||||
1. **新規プラグイン**: invoke_id優先(高速パス)
|
||||
2. **既存プラグイン**: method経由でフォールバック
|
||||
3. **移行期間**: 両方サポート、段階的に新方式へ
|
||||
|
||||
### NyValue統一表現
|
||||
|
||||
```c
|
||||
typedef struct __attribute__((aligned(16))) {
|
||||
uint64_t type_tag; // 型識別子
|
||||
union {
|
||||
int64_t i64; // 整数
|
||||
double f64; // 浮動小数点
|
||||
void* ptr; // ポインタ(Box/String等)
|
||||
uint64_t bits; // ビットパターン(NaN-box/SMI)
|
||||
} payload;
|
||||
} NyValue;
|
||||
```
|
||||
|
||||
### API互換性保証
|
||||
|
||||
- `NyBoxHeader.header_size`による前方互換
|
||||
- vtableの先頭3メソッドは不変(COM準拠)
|
||||
- 新機能は`capabilities`フラグで判定
|
||||
|
||||
## 📊 移行戦略
|
||||
|
||||
### Phase 1: 基礎実装(1週間)
|
||||
- NyashTypeBox構造体定義
|
||||
- 基本的なregister_user_box実装
|
||||
- 互換レイヤー(既存C ABI→TypeBox)
|
||||
|
||||
### Phase 2: 最適化(2週間)
|
||||
- メソッドID解決機構
|
||||
- インラインキャッシング基礎
|
||||
- JIT統合準備
|
||||
|
||||
### Phase 3: 完全移行(1ヶ月)
|
||||
- すべてのビルトインBoxをTypeBox化
|
||||
- パフォーマンスベンチマーク
|
||||
- 移行ツール完成
|
||||
|
||||
## ✅ 合意済み事項
|
||||
|
||||
1. **Everything is Box哲学の完全実現**
|
||||
- すべてのBox(ビルトイン、プラグイン、ユーザー定義)が統一ABI
|
||||
- NyValue経由ですべて扱える
|
||||
|
||||
2. **段階的移行の保証**
|
||||
- 既存プラグインは動作継続
|
||||
- 新規開発は新ABIを推奨
|
||||
|
||||
3. **パフォーマンス優先**
|
||||
- メソッドIDによる高速化は必須
|
||||
- JIT/AOTとの密接な統合
|
||||
|
||||
## 🚫 却下された提案
|
||||
|
||||
1. **完全な動的型システム**: 静的解析を困難にするため
|
||||
2. **プロセス間通信ベース**: オーバーヘッドが大きすぎる
|
||||
3. **Rustネイティブ統合**: C ABIの安定性を優先
|
||||
|
||||
## 📚 参考資料
|
||||
|
||||
- [AI先生たちの技術的検討](./ai-consultation-unified-typebox.md)
|
||||
- [統一TypeBox ABI仕様](./unified-typebox-abi.md)
|
||||
- [ユーザー定義Box統合](./unified-typebox-user-box.md)
|
||||
- [Nyash ABI Minimal Coreと進化戦略](../../../../reference/abi/NYASH_ABI_MIN_CORE.md)
|
||||
154
docs/archive/roadmap/phases/phase-12/USER_BOX_FFI_CHALLENGE.md
Normal file
154
docs/archive/roadmap/phases/phase-12/USER_BOX_FFI_CHALLENGE.md
Normal file
@ -0,0 +1,154 @@
|
||||
# ユーザーBoxをC ABIで渡す技術的課題
|
||||
|
||||
## 🚨 現在の実装の問題点
|
||||
|
||||
### 1. ユーザーBoxの内部構造
|
||||
|
||||
```rust
|
||||
pub struct InstanceBox {
|
||||
// フィールドはHashMapで管理
|
||||
pub fields_ng: Arc<Mutex<HashMap<String, NyashValue>>>,
|
||||
|
||||
// メソッドはASTノードのまま!
|
||||
pub methods: Arc<HashMap<String, ASTNode>>,
|
||||
}
|
||||
```
|
||||
|
||||
**問題**: これらはRust固有の構造で、C ABIで直接渡せない
|
||||
|
||||
### 2. C ABIが期待する構造
|
||||
|
||||
```c
|
||||
typedef struct {
|
||||
// 固定的な関数ポインタが必要
|
||||
void* (*create)(void* args);
|
||||
void (*destroy)(void* self);
|
||||
NyResult (*invoke_id)(void* self, uint32_t method_id,
|
||||
NyValue* args, int argc);
|
||||
} NyashTypeBox;
|
||||
```
|
||||
|
||||
## 🔧 必要な変換層
|
||||
|
||||
### 1. メソッドのコンパイル
|
||||
|
||||
```rust
|
||||
// 現在: ASTNode(インタープリター実行)
|
||||
methods: HashMap<String, ASTNode>
|
||||
|
||||
// 必要: 関数ポインタ or トランポリン
|
||||
methods: HashMap<u32, fn(self, args) -> Result>
|
||||
```
|
||||
|
||||
### 2. フィールドアクセスの標準化
|
||||
|
||||
```c
|
||||
// C側から見えるインターフェース
|
||||
typedef struct {
|
||||
void* (*get_field)(void* self, const char* name);
|
||||
void (*set_field)(void* self, const char* name, void* value);
|
||||
} FieldAccessor;
|
||||
```
|
||||
|
||||
### 3. トランポリン関数の生成
|
||||
|
||||
```rust
|
||||
// ユーザーBoxごとに自動生成する必要がある
|
||||
extern "C" fn user_box_invoke(
|
||||
self_ptr: *mut c_void,
|
||||
method_id: u32,
|
||||
args: *mut NyValue,
|
||||
argc: c_int
|
||||
) -> NyResult {
|
||||
// 1. self_ptrからInstanceBoxを復元
|
||||
let instance = unsafe { &mut *(self_ptr as *mut InstanceBox) };
|
||||
|
||||
// 2. method_idからメソッド名を解決
|
||||
let method_name = resolve_method_name(method_id);
|
||||
|
||||
// 3. ASTNodeを取得
|
||||
let ast = instance.methods.get(&method_name)?;
|
||||
|
||||
// 4. インタープリターで実行(遅い!)
|
||||
let result = interpreter.execute_method(instance, ast, args);
|
||||
|
||||
// 5. 結果をC ABIに変換
|
||||
to_ny_result(result)
|
||||
}
|
||||
```
|
||||
|
||||
## 🚀 解決策の提案
|
||||
|
||||
### 案1: JITコンパイル(理想的だが複雑)
|
||||
|
||||
```rust
|
||||
// ユーザーBox登録時にJITコンパイル
|
||||
fn register_user_box(spec: &BoxSpec) -> TypeBox {
|
||||
let compiled_methods = jit_compile_methods(&spec.methods);
|
||||
|
||||
TypeBox {
|
||||
invoke_id: |self, id, args| {
|
||||
compiled_methods[id](self, args)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 案2: インタープリタートランポリン(現実的)
|
||||
|
||||
```rust
|
||||
// グローバルなインタープリター参照を保持
|
||||
static INTERPRETER: OnceCell<Arc<Interpreter>> = OnceCell::new();
|
||||
|
||||
extern "C" fn universal_user_box_invoke(
|
||||
handle: u64, // ハンドル経由
|
||||
method_id: u32,
|
||||
args: *mut NyValue,
|
||||
argc: c_int
|
||||
) -> NyResult {
|
||||
// ハンドルからBoxを取得
|
||||
let registry = HANDLE_REGISTRY.read();
|
||||
let instance = registry.get(handle)?;
|
||||
|
||||
// インタープリター経由で実行
|
||||
INTERPRETER.get().unwrap().invoke_method(
|
||||
instance, method_id, args, argc
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### 案3: ハイブリッドアプローチ(段階的)
|
||||
|
||||
1. **Phase 1**: インタープリタートランポリン(すぐ実装可能)
|
||||
2. **Phase 2**: 頻繁に呼ばれるメソッドをキャッシュ
|
||||
3. **Phase 3**: AOT時にネイティブコード生成
|
||||
|
||||
## 📊 パフォーマンスへの影響
|
||||
|
||||
```
|
||||
ビルトインBox呼び出し: 1-3ns
|
||||
プラグインBox呼び出し: 10-15ns
|
||||
ユーザーBox(トランポリン): 100-200ns
|
||||
ユーザーBox(JIT後): 15-20ns
|
||||
```
|
||||
|
||||
## 🎯 実装優先順位
|
||||
|
||||
1. **最小実装**(1週間)
|
||||
- ハンドル経由のトランポリン
|
||||
- グローバルインタープリター参照
|
||||
- 基本的なメソッド呼び出し
|
||||
|
||||
2. **最適化**(2週間)
|
||||
- メソッドIDキャッシュ
|
||||
- 引数変換の効率化
|
||||
- エラーハンドリング
|
||||
|
||||
3. **高速化**(1ヶ月)
|
||||
- 簡易JITコンパイル
|
||||
- AOT対応
|
||||
- ネイティブコード生成
|
||||
|
||||
## 結論
|
||||
|
||||
ユーザーBoxをC ABIで渡すには、**インタープリター実行をトランポリン関数でラップ**する必要があります。これは性能上のオーバーヘッドがありますが、段階的に最適化可能です。
|
||||
@ -0,0 +1,290 @@
|
||||
# 統一TypeBox ABI - AI先生たちの深い技術的検討
|
||||
|
||||
このドキュメントは、Gemini先生とCodex先生による統一TypeBox ABIの技術的検討をまとめたものです。
|
||||
|
||||
## 🎯 検討テーマ
|
||||
|
||||
ユーザー定義Boxをプラグインシステムに統合し、すべてのBoxをC ABI上で統一的に管理する提案について。
|
||||
|
||||
## 📅 相談日時
|
||||
2025-09-02
|
||||
|
||||
## 🤖 Gemini先生の回答
|
||||
|
||||
### 総評:提案されたアプローチの技術的健全性
|
||||
|
||||
まず結論から申し上げると、提案されている「ユーザー定義Boxを動的に登録し、プラグインBoxと統一的に扱うABI」というアプローチは、**技術的に非常に健全(sound)**です。これは、COM(Component Object Model)、Rustの`dyn Trait`オブジェクト、PythonのC APIなど、多くの成功した言語やフレームワークで採用されている**動的ディスパッチ(vtable)**の仕組みを、FFI(Foreign Function Interface)に応用した古典的かつ堅牢な設計パターンです。
|
||||
|
||||
このアプローチにより、「Everything is Box」というNyashの美しい設計哲学を、言語の境界を越えたC ABIレベルまで一貫して適用することが可能になります。
|
||||
|
||||
### 技術的検討事項の詳細分析
|
||||
|
||||
#### 1. メモリ管理:誰がBoxの命を握るか?
|
||||
|
||||
* **課題**: NyashのVM(おそらくガベージコレクタ(GC)を持つ)と、Cで書かれたプラグイン側とで、Boxインスタンスの所有権をどう管理し、いつメモリを解放するかが最大の課題です。
|
||||
* **解決策**: **参照カウント(Reference Counting)**が最も現実的で実績のある解決策です。
|
||||
* **実装**:
|
||||
1. `NyashTypeBox`構造体の先頭に参照カウンタ(`ref_count`)を持たせます。
|
||||
2. NyashのVMがBoxへの参照を生成したとき、またはFFIを通じてプラグインにBoxのポインタを渡すときに、カウンタをインクリメントする`retain`関数(または`add_ref`)を呼び出します。
|
||||
3. プラグイン側でBoxが不要になったとき、またはVMが参照を破棄するときに、カウンタをデクリメントする`release`関数を呼び出します。
|
||||
4. `release`関数内でカウンタが0になったら、そのBoxが使用していたメモリを解放する処理(デストラクタの呼び出しなど)を実行します。
|
||||
* **注意点**:
|
||||
* **スレッド安全性**: マルチスレッド環境をサポートする場合、参照カウンタのインクリメント/デクリメントは**アトミック操作**である必要があります(例: C11の`_Atomic`やGCCの`__atomic_*`組み込み関数)。
|
||||
* **循環参照**: 参照カウント方式の宿命ですが、2つのBoxが互いに参照し合うと、カウンタが0にならずメモリリークが発生します。これを解決するには**弱参照(Weak Reference)**の仕組みを併せて導入する必要があります。
|
||||
|
||||
#### 2. 型安全性:動的な世界で秩序を保てるか?
|
||||
|
||||
* **課題**: `void*`のような型消去されたポインタをやり取りするため、誤った型として扱ってしまう危険性(type confusion)があります。
|
||||
* **解決策**: **実行時型情報(RTTI)**を導入します。
|
||||
* **実装**:
|
||||
1. 提案にある通り、各Boxに一意な`type_id`を割り当てます。このIDは、実行時に登録されるユーザー定義Boxも含め、衝突しないように動的に生成・管理されるべきです(例: 単純なカウンタやアドレスのハッシュなど)。
|
||||
2. `NyashTypeBox`に`type_id`フィールドを持たせます。
|
||||
3. 特定のBox型へのダウンキャストを行いたい場合は、まず`type_id`を比較する安全なAPI(例: `nyash_box_downcast_as_mybox(box)`)を提供します。このAPIは、IDが一致しない場合は`NULL`を返すようにします。これにより、危険な強制キャストを防ぎます。
|
||||
* **哲学**: これは静的型付け言語のコンパイル時型チェックを、動的言語の実行時チェックで代替する考え方であり、Nyashの動的な性質と整合性が取れています。
|
||||
|
||||
#### 3. パフォーマンス:動的ディスパッチの代償は?
|
||||
|
||||
* **課題**: メソッドを呼び出すたびにメソッドテーブル(vtable)を介して間接的に呼び出すため、静的な関数呼び出しに比べてオーバーヘッドが生じます。
|
||||
* **評価**:
|
||||
* **許容範囲内**: このオーバーヘッドは通常、1回の呼び出しあたり数ナノ秒程度です。FFI呼び出し自体のコスト(引数のマーシャリングなど)や、プラグインが行うであろう処理(I/O、複雑な計算など)と比較すれば、**無視できるレベル**であることがほとんどです。
|
||||
* **最適化**: NyashがJITコンパイラを持つ場合、呼び出しが単一の型に集中するようなホットスポットでは、投機的にインライン化(de-virtualization)することで、このオーバーヘッドを削減することも理論的には可能です。
|
||||
* **結論**: 動的言語であるNyashにとって、このパフォーマンスコストは、得られる柔軟性と拡張性というメリットを考えれば、十分に許容できるトレードオフです。
|
||||
|
||||
#### 4. セキュリティ:信頼できないコードからの保護
|
||||
|
||||
* **課題**: 悪意のある、あるいはバグのあるユーザーBox/プラグインが、不正なメソッドポインタを登録することで、VMの内部状態を破壊したり、任意のコード実行(RCE)に繋がる可能性があります。
|
||||
* **対策(多層防御)**:
|
||||
1. **サンドボックス**: 最も強力な対策は、プラグインの実行環境をサンドボックス化することです。**WebAssembly (Wasm)** はこの目的で設計されており、優れた選択肢です。NyashのプラグインをWasmモジュールとしてコンパイルし、Wasmランタイム上で実行すれば、メモリ安全性が保証され、外部へのアクセスも厳密に制御できます。
|
||||
2. **検証**: 登録されるメソッドテーブルの内容をある程度検証します。例えば、関数ポインタが実行可能メモリ領域を指しているかなどをチェックしますが、完全な対策にはなりません。
|
||||
3. **権限モデル(Capability-based Security)**: プラグイン登録時に、そのプラグインがアクセスできるAPIやリソースを制限する権限セットを要求・付与する仕組みを導入します。
|
||||
|
||||
#### 5. 実装複雑度:既存システムとの調和
|
||||
|
||||
* **課題**: 既存のVM、GC、型システム、プラグインローダーと、この新しい統一ABIをスムーズに統合する必要があります。
|
||||
* **評価**: **実装の複雑度は高い**です。特に以下の点が難所となります。
|
||||
* **GCとの連携**: 参照カウントとGCを共存させる場合、両者の間でオブジェクトの生存情報を正しく伝達する必要があります。GCがオブジェクトを走査する際に、FFI境界を越えてプラグイン側にある参照を認識できるようにしなければなりません。
|
||||
* **ABIの安定化**: 一度公開したC ABI(構造体のレイアウトや関数のシグネチャ)は、後方互換性を維持するために慎重に設計・管理する必要があります。
|
||||
* **エラーハンドリング**: FFI境界を越えてエラー情報をどう伝播させるか、一貫した戦略が必要です(例: エラーコードを返す、`get_last_error`のような関数を用意する)。
|
||||
|
||||
### ご質問への回答
|
||||
|
||||
#### 1. この統一管理アプローチは技術的に健全か?
|
||||
はい、前述の通り**極めて健全**です。実績のある設計パターンであり、Nyashの哲学を強化する正しい方向性です。
|
||||
|
||||
#### 2. 他の言語での類似実装例はあるか?
|
||||
多数あります。これらは実装の際の優れた参考資料となります。
|
||||
* **Python C API**: 全てのPythonオブジェクトは`PyObject*`としてCから扱われます。`PyObject`は参照カウントと型オブジェクトへのポインタ(`ob_type`)を持ち、この`ob_type`がメソッドテーブル(vtable)などを含む構造体を指しています。ユーザーがCで新しい型を定義し、Pythonの型システムに動的に登録する仕組みは、今回の提案と非常によく似ています。
|
||||
* **Microsoft COM (Component Object Model)**: C++やVBなど異なる言語間でオブジェクトをやり取りするためのバイナリ互換仕様です。全てのインターフェースは`IUnknown`を継承し、`QueryInterface`(型キャスト)、`AddRef`(参照カウント増)、`Release`(参照カウント減)の3つのメソッドを必ず持ちます。
|
||||
* **Rust `dyn Trait`**: Rustのトレイトオブジェクトは、データへのポインタとvtableへのポインタからなる「ファットポインタ」として実現されます。これをC ABIで表現しようとすると、手動でデータポインタとvtable構造体ポインタをペアにした構造体を作ることになり、本提案と同じ形になります。
|
||||
|
||||
#### 3. 実装上の注意点・落とし穴は?
|
||||
* **ABIの厳密な定義**: 構造体のパディングやアライメント、呼び出し規約(calling convention)などをCレベルで厳密に定義し、ドキュメント化することが不可欠です。
|
||||
* **参照カウントのバグ**: `retain`/`release`のペアが崩れると、即座にメモリリークやクラッシュに繋がります。デバッグを支援する仕組み(例: 環境変数を設定すると`retain`/`release`の呼び出しをログに出力するなど)が有効です。
|
||||
* **スレッド安全性**: 最初からスレッドセーフに設計しないと、後からの修正は非常に困難です。`Arc<Mutex<...>>`のようなアトミック参照カウントと内部可変性のパターンを検討してください。
|
||||
|
||||
#### 4. より良い代替案はあるか?
|
||||
* **WebAssembly (Wasm) ベースのプラグインシステム**: 前述の通り、セキュリティとポータビリティを最優先するならば、これが最良の選択肢かもしれません。NyashのBoxをWasmのメモリ空間とホスト(VM)間でやり取りするためのシリアライズ/デシリアライズ層が必要になりますが、Wasm Interface Typesなどの標準化も進んでおり、将来性が高いです。
|
||||
* **IPC (プロセス間通信)**: プラグインを別プロセスとして実行し、ソケットやパイプで通信します。最も安全ですが、パフォーマンスのオーバーヘッドが大きいため、用途が限られます。
|
||||
|
||||
提案されているABI方式は、パフォーマンスと安全性のバランスが取れた優れた案であり、「より良い」というよりは「異なるトレードオフを持つ」代替案と言えます。
|
||||
|
||||
#### 5. Everything is Box哲学との整合性は完璧か?
|
||||
**はい、完璧に整合します。**
|
||||
この統一ABIは、「組み込みのBox」と「ユーザー定義のBox」という実装上の区別をユーザーやプラグイン開発者から完全に隠蔽します。全てのBoxが同じインターフェース(`NyashTypeBox*`)を通じて、同じ規則(参照カウント、動的ディスパッチ)に従って扱われる世界を実現します。これは、**「Everything is Box」という哲学を、言語仕様からABI、そしてエコシステム全体へと貫くための、論理的かつ必然的なステップ**と言えるでしょう。この実装が完了すれば、Nyashはより一貫性があり、強力で、拡張性の高い言語へと進化するはずです。
|
||||
|
||||
---
|
||||
|
||||
## 🤖 Codex先生の回答(タイムアウトしたが貴重な洞察)
|
||||
|
||||
Codex先生は深い分析を行い、以下の重要な洞察を提供しました:
|
||||
|
||||
### 主要な技術的提案
|
||||
|
||||
1. **ホスト管理型ハンドル**
|
||||
- registry_id + instance_id のペアで管理
|
||||
- 高ビットでホスト/プラグイン区別
|
||||
|
||||
2. **段階的実装戦略**
|
||||
- Phase 1: 基本的な動的登録機能
|
||||
- Phase 2: GCとの統合
|
||||
- Phase 3: 完全な相互運用性
|
||||
|
||||
3. **セキュリティ考慮**
|
||||
- ケイパビリティベースの権限管理
|
||||
- finalizer IDによるライフサイクル管理
|
||||
|
||||
4. **ABI安定性**
|
||||
- バージョニング戦略の重要性
|
||||
- 既存プラグインとの互換性維持
|
||||
|
||||
---
|
||||
|
||||
## 🤖 Codex先生の深い技術検討(2025-09-02 詳細版)
|
||||
|
||||
### 統一TypeBox ABIの包括的技術設計
|
||||
|
||||
以下は「統一TypeBox ABI」を中核に据えた、Nyash Phase 12の技術的検討まとめです。C ABI上でBoxの一元管理を行い、Nyash ABIの基盤としてユーザーBoxまでカバーする実装方針を、実装設計・性能・安全性・移行計画まで通して具体化します。
|
||||
|
||||
### 📐 提案レイアウト(縮約)
|
||||
|
||||
#### NyBoxHeader(常に先頭・不変のバイナリ契約)
|
||||
```c
|
||||
struct NyBoxHeader {
|
||||
uint64_t type_id; // 予約域+種別域+連番
|
||||
_Atomic uint64_t refcnt; // 0で解放、MAXでpin
|
||||
const NyTypeVTable* vtable; // 不変ポインタ
|
||||
uint32_t flags; // immediate/extern/sandbox/trusted/traceable 等
|
||||
uint32_t header_size; // 前方互換: 拡張時にサイズ確認
|
||||
};
|
||||
```
|
||||
|
||||
#### NyTypeVTable(固定順序・拡張可能)
|
||||
- `retain(self)`, `release(self)`, `query(self, iface_id, out)`
|
||||
- `trace(self, visitor)`(GC連携必須)
|
||||
- `method_dispatch(self, method_id, args, ctx, out)`(最低限)
|
||||
- `const NyMethod* methods` + `uint32_t method_count`
|
||||
- `const NyField* fields`(任意)
|
||||
|
||||
#### NyMethod(C ABI呼び出し用)
|
||||
- `uint32_t id`(スロット)、`NyCallSig sig_id`、`NyFnPtr fn`
|
||||
|
||||
#### NyValue(Everything is Boxの統一ハンドル)
|
||||
- `union { NyBoxHeader* ptr; uint64_t tagged; }`(NaN-box/SMI対応)
|
||||
- APIは常に`NyValue`で受け渡し
|
||||
|
||||
### 1. ユーザーBox動的登録
|
||||
|
||||
#### register_user_box()
|
||||
```c
|
||||
NyRegisterUserBox(const NyTypeSpec*, const NyMethodSpec*,
|
||||
const NySecuritySpec*, NyTypeId* out_type_id)
|
||||
```
|
||||
- **TypeSpec**: サイズ、アライン、デストラクタ、トレース関数、初期化子
|
||||
- **MethodSpec**: 名前→署名ID→関数ポインタの連想(登録時にスロット化)
|
||||
- **SecuritySpec**: 信頼レベル、サンドボックス種類、許可シグネチャ群
|
||||
|
||||
#### Type ID管理
|
||||
64-bit構造: `[8b domain | 8b vendor | 16b category | 32b serial]`
|
||||
- **domain**:
|
||||
- 0x00 = host(core)
|
||||
- 0x40 = plugin(first-party)
|
||||
- 0x80 = user(third-party)
|
||||
- 0xC0 = experimental
|
||||
- **vendor**: プラグイン/ユーザーのnamespace(nyash.tomlで予約・配布)
|
||||
|
||||
#### メソッドテーブル動的生成
|
||||
- 登録時に「名前→署名ID→固定スロット」へ展開し、`NyTypeVTable.methods`を配列化
|
||||
- 呼び出し側は「method_id(スロット)で直接インデックス」→ハッシュ探索不要
|
||||
- 互換性: 古いプラグインは`method_dispatch`へフォールバック
|
||||
|
||||
### 2. メモリ管理の統一
|
||||
|
||||
#### 参照カウント(RC)
|
||||
- `retain/release`はC ABIの最初の3メソッドとして固定(COM類似)
|
||||
- `_Atomic u64`でインクリメント/デクリメント(Acquire/Releaseセマンティクス)
|
||||
- 巨大グラフ/ホット経路は「ローカル借用カウント」最適化
|
||||
|
||||
#### GC協調
|
||||
- `trace(self, visitor)`で内部参照列挙(プラグインも必須)
|
||||
- NyRTは「世代別トレーサ+RC」のハイブリッド
|
||||
- 若世代: write barrier + remembered set、遅延スキャン
|
||||
- 老世代: 主にRC管理、traceは周期的
|
||||
|
||||
#### 循環参照の検出・解決
|
||||
- ベース: Trial Deletion(Bacon & Rajan)をバックグラウンドで実施
|
||||
- 代替: 一部型に弱参照境界(Weak boundary)を要求
|
||||
- プラグイン契約: traceの完全列挙必須
|
||||
|
||||
### 3. パフォーマンス最適化
|
||||
|
||||
#### メソッドID事前解決(33倍の根拠)
|
||||
- **旧**: 名前→ハッシュ→テーブル探索→関数ポインタ(〜50-150ns)
|
||||
- **新**: `methods[slot]`直参照(〜1-3ns)
|
||||
- さらに分岐予測命中とICヒットで関数ポインタ直呼び(〜1ns台)
|
||||
- 実測はワークロード依存だが、20-50×の改善が典型的
|
||||
|
||||
#### インラインキャッシング(IC)
|
||||
- Monomorphic IC: `(type_id, method_sig)`→`fn*`をコールサイトに1エントリキャッシュ
|
||||
- PIC(2-4型)で多相最適化、ミス時はスローペスへ
|
||||
- Deopt hookあり(型再定義・ホットパッチ時に失効)
|
||||
|
||||
#### JIT連携
|
||||
- コールサイトにパッチャブルスロットを持つ(NY_JITCALL)
|
||||
- ウォームアップ後、`fn*`を直接inlining or tailcall化
|
||||
- 署名IDに基づき引数マシャリング削減
|
||||
|
||||
### 4. セキュリティと安全性
|
||||
|
||||
#### 信頼レベル
|
||||
- `trusted`(同プロセス・直接関数)
|
||||
- `sandboxed`(Wasm/別プロセス)
|
||||
- `restricted`(機能限定)
|
||||
|
||||
#### Wasmサンドボックス統合
|
||||
- ユーザーBoxはWasmで実装→ホストは`NyTypeVTable`にWasmトランポリンを挿入
|
||||
- メモリは共有しない(コピーor借用ハンドル)
|
||||
- traceはホスト側のプロキシBoxで管理
|
||||
|
||||
#### メソッドポインタ検証
|
||||
- 登録時: `fn*`が許可セクション(.text/EXEC)内か確認
|
||||
- 実行時: CFIライト版(`type_id`一致+`sig_id`一致+レンジチェック)
|
||||
- W^X徹底、PLT経由の間接跳躍制限、RELRO推奨
|
||||
|
||||
### 5. 実装の段階的アプローチ
|
||||
|
||||
#### 互換レイヤー
|
||||
- 既存C ABIの`ny_*`関数は`method_dispatch`へフォールバック
|
||||
- 新ABIでは事前解決スロットがあれば直参照
|
||||
|
||||
#### 移行ツール
|
||||
- `ny-abi-gen`: ヘッダからスケルトン生成
|
||||
- `ny-abi-check`: ローディング時にABIバージョン/署名整合性を検証
|
||||
|
||||
#### バージョニング
|
||||
- `NY_ABI_VERSION`(major.minor.patch)
|
||||
- `NyBoxHeader.header_size`で前方互換
|
||||
- nyash.tomlに`min_abi`,`max_abi`を記載
|
||||
|
||||
### 技術的健全性の評価
|
||||
|
||||
**結論**: 技術的に健全。コアはCPython(PyObject)+COM(IUnknown)+Rust vtableの良いとこ取り
|
||||
- 先頭に`refcnt`/`type`/`vtable`を固定し、関数テーブルによる静的ディスパッチを基本とする設計は長期安定性が高い
|
||||
- GC協調には必須の`trace`を型契約に含め「逃げ道のない」完全列挙を強制
|
||||
- `NyValue`(tagged/immediate)導入で「Everything is Box」を性能劣化なく実現可能
|
||||
|
||||
### 最大の課題
|
||||
1. **ABI安定と最適化の両立**
|
||||
- vtable拡張、署名IDの仕様固定、JITパッチ互換などを「一度決めて長期維持」する難しさ
|
||||
2. **GC協調の完全性**
|
||||
- プラグインのtrace不備がリーク/サイクル残留を引き起こす
|
||||
3. **多様な信頼レベル混在**
|
||||
- 同一プロセスのtrusted高速経路とWasm隔離経路の整合性
|
||||
|
||||
### 他言語との比較・ベストプラクティス
|
||||
- **Python(CPython)**: ob_refcnt/ob_type/型メソッドテーブルは強力な実績
|
||||
- **COM**: IUnknownの3メソッド固定は安定ABIの黄金則
|
||||
- **Rust dyn Trait**: ABI非安定。NyashはC ABIでvtableを固定公開
|
||||
|
||||
### Everything is Boxの実現性
|
||||
可能。推奨アプローチは二段:
|
||||
- **実体**: `NyBoxHeader*`を持つヒープBox
|
||||
- **即値**: NaN-box/SMIで`NyValue.tagged`にエンコード
|
||||
|
||||
APIは常に`NyValue`受け渡し。VM/JITは即値→ヒープBox化を必要時のみ実施
|
||||
|
||||
### 具体API(抄)
|
||||
```c
|
||||
extern "C" NyStatus NyRegisterUserBox(const NyTypeSpec*, const NyMethodSpec*,
|
||||
const NySecuritySpec*, NyTypeId*);
|
||||
extern "C" NyStatus NyResolveMethodSlot(NyTypeId, NySigId, uint32_t* out_slot);
|
||||
extern "C" NyStatus NyCallSlot(NyValue self, uint32_t slot, const NyValue* args,
|
||||
uint32_t argc, NyValue* out, NyCallCtx*);
|
||||
extern "C" void NyRetain(NyValue);
|
||||
extern "C" void NyRelease(NyValue); // 即値はno-op
|
||||
```
|
||||
|
||||
### 次アクション案
|
||||
1. `nyabi.h`ドラフトと最小実装
|
||||
2. `register_user_box()`の仮実装+スモーク
|
||||
3. `ny-abi-gen`簡易版(署名→スロット表生成)
|
||||
4. ICのmonomorphic実装→PIC→JITパッチの順に段階導入
|
||||
195
docs/archive/roadmap/phases/phase-12/archive/01_roadmap_final.md
Normal file
195
docs/archive/roadmap/phases/phase-12/archive/01_roadmap_final.md
Normal file
@ -0,0 +1,195 @@
|
||||
# 埋め込みVM実装ロードマップ
|
||||
|
||||
## 🎯 目標:スクリプトプラグインのC ABI化
|
||||
|
||||
**Nyashスクリプト → C ABIプラグイン変換の完全自動化**
|
||||
|
||||
## 📊 技術スタック
|
||||
|
||||
```
|
||||
[Nyashスクリプト]
|
||||
↓ パース・型チェック
|
||||
[MIR (中間表現)]
|
||||
↓ 最適化・定数畳み込み
|
||||
[MIRバイトコード]
|
||||
↓ 埋め込み
|
||||
[Cソースコード] ← nyash-to-c ツール
|
||||
↓ コンパイル (cc/clang/gcc)
|
||||
[.so/.dll/.a] ← 通常のプラグイン!
|
||||
```
|
||||
|
||||
## 🚀 実装フェーズ
|
||||
|
||||
### Phase 12.1: 最小埋め込みVM(2-3週間)
|
||||
|
||||
#### 1. MIRバイトコード設計
|
||||
```rust
|
||||
// mir_bytecode.rs
|
||||
pub enum CompactInstruction {
|
||||
// 1バイト命令(頻出)
|
||||
LoadLocal(u8), // 0x00-0x7F
|
||||
StoreLocal(u8), // 0x80-0xFF
|
||||
|
||||
// 2バイト命令
|
||||
LoadConst(u8), // 0x01 XX
|
||||
Call(u8), // 0x02 XX
|
||||
|
||||
// 可変長
|
||||
LoadString, // 0x03 [len:u16] [data]
|
||||
Jump, // 0x04 [offset:i16]
|
||||
}
|
||||
```
|
||||
|
||||
#### 2. 埋め込みVMコア
|
||||
```c
|
||||
// nyash_embedded_vm.h
|
||||
typedef struct {
|
||||
const uint8_t* bytecode;
|
||||
size_t bytecode_len;
|
||||
|
||||
// 実行時状態(最小)
|
||||
void* stack[256];
|
||||
int sp;
|
||||
void* locals[16];
|
||||
} NyashEmbeddedVM;
|
||||
|
||||
int32_t nyash_embedded_execute(
|
||||
const uint8_t* bytecode,
|
||||
size_t bytecode_len,
|
||||
uint32_t method_id,
|
||||
const uint8_t* args,
|
||||
size_t args_len,
|
||||
uint8_t* result,
|
||||
size_t* result_len
|
||||
);
|
||||
```
|
||||
|
||||
### Phase 12.2: Nyash→Cトランスパイラー(3-4週間)
|
||||
|
||||
#### 1. 基本変換
|
||||
```bash
|
||||
$ nyash-to-c math_plugin.ny -o math_plugin.c
|
||||
Generating C plugin from Nyash script...
|
||||
- Parsing... OK
|
||||
- Type checking... OK
|
||||
- MIR generation... OK
|
||||
- Bytecode emission... OK
|
||||
- C code generation... OK
|
||||
Output: math_plugin.c (2.3KB)
|
||||
```
|
||||
|
||||
#### 2. 生成コード例
|
||||
```c
|
||||
// Generated from: math_plugin.ny
|
||||
#include <nyash_embedded.h>
|
||||
|
||||
// MIRバイトコード(最適化済み)
|
||||
static const uint8_t BYTECODE[] = {
|
||||
0x01, 0x00, // Version 1.0
|
||||
0x01, 0x00, // 1 function
|
||||
|
||||
// Function: cached_sin
|
||||
0x00, 0x08, // Function header
|
||||
0x80, 0x00, // StoreLocal 0 (x)
|
||||
0x02, 0x10, // Call sin
|
||||
0x90, // Return
|
||||
};
|
||||
|
||||
// プラグインエントリポイント
|
||||
extern "C" int32_t nyplug_math_plugin_invoke(
|
||||
uint32_t type_id,
|
||||
uint32_t method_id,
|
||||
uint32_t instance_id,
|
||||
const uint8_t* args,
|
||||
size_t args_len,
|
||||
uint8_t* result,
|
||||
size_t* result_len
|
||||
) {
|
||||
return nyash_embedded_execute(
|
||||
BYTECODE, sizeof(BYTECODE),
|
||||
method_id,
|
||||
args, args_len,
|
||||
result, result_len
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### Phase 12.3: 最適化とツールチェーン(4-6週間)
|
||||
|
||||
#### 1. ビルドシステム統合
|
||||
```toml
|
||||
# nyash.toml
|
||||
[[plugins]]
|
||||
name = "math_plugin"
|
||||
source = "plugins/math_plugin.ny" # Nyashソース
|
||||
type = "script" # 自動的にC変換
|
||||
|
||||
[[plugins]]
|
||||
name = "file_plugin"
|
||||
source = "plugins/file_plugin/Cargo.toml"
|
||||
type = "native" # 従来のRustプラグイン
|
||||
```
|
||||
|
||||
#### 2. 自動ビルドパイプライン
|
||||
```bash
|
||||
$ nyash build --plugins
|
||||
Building plugins...
|
||||
[1/2] math_plugin (script)
|
||||
- Transpiling to C... OK
|
||||
- Compiling... OK
|
||||
- Output: target/plugins/libmath_plugin.so
|
||||
[2/2] file_plugin (native)
|
||||
- Building with cargo... OK
|
||||
- Output: target/plugins/libfile_plugin.so
|
||||
Done!
|
||||
```
|
||||
|
||||
## 📈 パフォーマンス目標
|
||||
|
||||
| 操作 | ネイティブ | 埋め込みVM | 目標比率 |
|
||||
|------|-----------|------------|----------|
|
||||
| 単純計算 | 10ns | 50ns | 5x |
|
||||
| メソッド呼び出し | 20ns | 100ns | 5x |
|
||||
| 文字列操作 | 100ns | 200ns | 2x |
|
||||
| I/O操作 | 10μs | 10.1μs | 1.01x |
|
||||
|
||||
## 🔧 開発ツール
|
||||
|
||||
### 1. デバッガ
|
||||
```bash
|
||||
$ nyash-debug math_plugin.ny --method cached_sin --args "[3.14]"
|
||||
Executing cached_sin(3.14)...
|
||||
[PC:0000] LoadLocal 0 ; x = 3.14
|
||||
[PC:0002] Call sin ; sin(3.14)
|
||||
[PC:0004] Return ; 0.0015926...
|
||||
Result: 0.0015926
|
||||
```
|
||||
|
||||
### 2. プロファイラ
|
||||
```bash
|
||||
$ nyash-profile math_plugin.so
|
||||
Method statistics:
|
||||
- cached_sin: 1000 calls, avg 120ns
|
||||
- cached_cos: 500 calls, avg 115ns
|
||||
Bottlenecks: None detected
|
||||
```
|
||||
|
||||
## 🎉 最終形
|
||||
|
||||
```bash
|
||||
# 開発者の体験
|
||||
$ cat my_plugin.ny
|
||||
export box MyPlugin {
|
||||
init { cache = new MapBox() }
|
||||
process(x) { return x * 2 }
|
||||
}
|
||||
|
||||
$ nyash build my_plugin.ny
|
||||
✓ Generated: my_plugin.so
|
||||
|
||||
$ nyash run --plugin my_plugin.so test.ny
|
||||
✓ Plugin loaded (C ABI)
|
||||
✓ Result: 42
|
||||
```
|
||||
|
||||
**Nyashで書いて、どこでも動く!**
|
||||
@ -0,0 +1,164 @@
|
||||
# 解決策:埋め込みVMによるスクリプトプラグイン実現
|
||||
|
||||
## 💡 発想の転換
|
||||
|
||||
**制約は「リンク時にC ABIが必要」だけ。つまり、C ABI関数の中でVMを動かせばいい!**
|
||||
|
||||
## 🎯 アーキテクチャ
|
||||
|
||||
```c
|
||||
// C ABI関数(静的リンク可能)
|
||||
extern "C" int32_t nyplug_custom_math_invoke(
|
||||
uint32_t method_id,
|
||||
const uint8_t* args,
|
||||
size_t args_len,
|
||||
uint8_t* result,
|
||||
size_t* result_len
|
||||
) {
|
||||
// 埋め込みVM起動
|
||||
static NyashVM* embedded_vm = NULL;
|
||||
if (!embedded_vm) {
|
||||
embedded_vm = nyash_vm_create_minimal();
|
||||
nyash_vm_load_script(embedded_vm, EMBEDDED_SCRIPT);
|
||||
}
|
||||
|
||||
// スクリプト実行
|
||||
return nyash_vm_invoke(embedded_vm, method_id, args, args_len, result, result_len);
|
||||
}
|
||||
|
||||
// スクリプトは文字列リテラルとして埋め込み
|
||||
static const char* EMBEDDED_SCRIPT = R"(
|
||||
export box CustomMath {
|
||||
cached_sin(x) {
|
||||
// Nyashコード
|
||||
}
|
||||
}
|
||||
)";
|
||||
```
|
||||
|
||||
## 🔄 実現方法
|
||||
|
||||
### 1. Nyash→C トランスパイラー
|
||||
|
||||
```bash
|
||||
# Nyashスクリプト → C関数
|
||||
nyash-to-c custom_math.ny > custom_math_plugin.c
|
||||
|
||||
# 生成されるC
|
||||
// custom_math_plugin.c
|
||||
#include "nyash_embedded_vm.h"
|
||||
|
||||
static const char* SCRIPT = "..."; // Nyashコード埋め込み
|
||||
|
||||
extern "C" int32_t nyplug_custom_math_invoke(...) {
|
||||
return nyash_embedded_invoke(SCRIPT, method_id, ...);
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 最小VM実装
|
||||
|
||||
```rust
|
||||
// crates/nyash-embedded-vm
|
||||
pub struct EmbeddedVM {
|
||||
// 最小限の実行環境
|
||||
values: Vec<VMValue>,
|
||||
// スクリプトはプリコンパイル済みMIR
|
||||
mir: MirModule,
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn nyash_embedded_invoke(
|
||||
script: *const c_char,
|
||||
method_id: u32,
|
||||
// ... TLV args/result
|
||||
) -> i32 {
|
||||
// MIR実行(インタープリター)
|
||||
}
|
||||
```
|
||||
|
||||
## 📊 利点と制約
|
||||
|
||||
### ✅ 可能になること
|
||||
- **スクリプトプラグインがEXEに埋め込み可能**
|
||||
- **JIT/AOTから呼び出し可能**(C ABI経由)
|
||||
- **既存のプラグインシステムと完全互換**
|
||||
|
||||
### ⚠️ 制約
|
||||
- **パフォーマンス**: 埋め込みVMのオーバーヘッド
|
||||
- **サイズ**: 最小VMランタイムが必要(~500KB?)
|
||||
- **機能制限**: フルVMの一部機能のみ
|
||||
|
||||
## 🚀 段階的実装
|
||||
|
||||
### Phase 1: 最小埋め込みVM
|
||||
```rust
|
||||
// 必要最小限の機能
|
||||
- MIR実行(インタープリター)
|
||||
- 基本型(Integer, String, Bool)
|
||||
- メソッド呼び出し
|
||||
- TLVエンコード/デコード
|
||||
```
|
||||
|
||||
### Phase 2: Nyash→Cトランスパイラー
|
||||
```nyash
|
||||
// input: custom_math.ny
|
||||
export box CustomMath {
|
||||
sin(x) { ... }
|
||||
}
|
||||
|
||||
// output: custom_math_plugin.c
|
||||
extern "C" int32_t nyplug_custom_math_invoke(...) {
|
||||
static const uint8_t MIR_BYTECODE[] = { ... };
|
||||
return nyash_embedded_execute(MIR_BYTECODE, ...);
|
||||
}
|
||||
```
|
||||
|
||||
### Phase 3: 最適化
|
||||
- MIRプリコンパイル
|
||||
- 頻出パスのネイティブ化
|
||||
- 選択的JITコンパイル
|
||||
|
||||
## 💡 実装例
|
||||
|
||||
```c
|
||||
// 生成されたプラグイン
|
||||
#include <nyash_embedded.h>
|
||||
|
||||
// MIRバイトコード(事前コンパイル)
|
||||
static const uint8_t CUSTOM_MATH_MIR[] = {
|
||||
0x01, 0x00, // version
|
||||
0x10, 0x00, // function count
|
||||
// ... MIR instructions
|
||||
};
|
||||
|
||||
extern "C" int32_t nyplug_custom_math_abi_version() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
extern "C" int32_t nyplug_custom_math_invoke(
|
||||
uint32_t method_id,
|
||||
const uint8_t* args,
|
||||
size_t args_len,
|
||||
uint8_t* result,
|
||||
size_t* result_len
|
||||
) {
|
||||
// 埋め込みVM実行
|
||||
return nyash_mir_execute(
|
||||
CUSTOM_MATH_MIR,
|
||||
sizeof(CUSTOM_MATH_MIR),
|
||||
method_id,
|
||||
args, args_len,
|
||||
result, result_len
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## 🎯 結論
|
||||
|
||||
**「リンク時にC ABI」という制約は、埋め込みVMで解決可能!**
|
||||
|
||||
- Nyashスクリプト → MIR → Cコード → ネイティブプラグイン
|
||||
- 開発の容易さ(Nyash)と配布の利便性(C ABI)を両立
|
||||
- 既存のプラグインエコシステムと完全互換
|
||||
|
||||
これで「Everything is Box」が真に実現する!
|
||||
@ -0,0 +1,142 @@
|
||||
# 埋め込みVMでの箱引数サポート
|
||||
|
||||
## 🎯 結論:完全にサポート可能
|
||||
|
||||
現在のMIR/VM/JIT/プラグインすべてで**箱は箱を引数にできる**仕組みが確立されており、埋め込みVMでも同じパターンで実装可能です。
|
||||
|
||||
## 📊 各層での箱引数の扱い
|
||||
|
||||
### 1. Nyashスクリプトレベル
|
||||
```nyash
|
||||
// 箱を引数に取るメソッド
|
||||
box Processor {
|
||||
process(inputBox, configBox) {
|
||||
// inputBoxもconfigBoxも箱インスタンス
|
||||
local data = inputBox.getData()
|
||||
local settings = configBox.getSettings()
|
||||
return me.transform(data, settings)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. MIRレベル
|
||||
```
|
||||
; box1.process(box2, box3)
|
||||
%4 = BoxCall %1.process(%2, %3)
|
||||
```
|
||||
|
||||
### 3. 埋め込みVMでの実装
|
||||
|
||||
#### バイトコード表現
|
||||
```c
|
||||
// BoxCall命令: [op][dst][recv][method_id:2][argc][args...]
|
||||
// 例: box1.process(box2, box3)
|
||||
0x20 // OP_BOXCALL
|
||||
0x04 // dst: %4
|
||||
0x01 // recv: %1 (box1)
|
||||
0x00 0x10 // method_id: 16 (process)
|
||||
0x02 // argc: 2
|
||||
0x02 // arg[0]: %2 (box2)
|
||||
0x03 // arg[1]: %3 (box3)
|
||||
```
|
||||
|
||||
#### 実行時処理
|
||||
```c
|
||||
// 埋め込みVMでの箱引数処理
|
||||
int nyvm_execute_boxcall(NyashEmbeddedVM* vm, ...) {
|
||||
// レシーバー取得
|
||||
NyVMValue* recv = &vm->values[recv_idx];
|
||||
|
||||
// 引数をTLVエンコード
|
||||
for (int i = 0; i < argc; i++) {
|
||||
NyVMValue* arg = &vm->values[args[i]];
|
||||
|
||||
if (arg->type == NYVM_TYPE_HANDLE) {
|
||||
// 箱引数はハンドルとしてエンコード
|
||||
uint32_t type_id = get_type_id_from_handle(arg->value.h);
|
||||
uint32_t inst_id = get_instance_id_from_handle(arg->value.h);
|
||||
encode_handle(&tlv, type_id, inst_id);
|
||||
} else {
|
||||
// プリミティブ値
|
||||
encode_primitive(&tlv, arg);
|
||||
}
|
||||
}
|
||||
|
||||
// C ABIプラグイン呼び出し
|
||||
return nyash_plugin_invoke(...);
|
||||
}
|
||||
```
|
||||
|
||||
## 🔄 ハンドル管理の詳細
|
||||
|
||||
### 1. ハンドルレジストリ
|
||||
```c
|
||||
// グローバルハンドルテーブル
|
||||
typedef struct {
|
||||
uint32_t type_id; // Box型ID
|
||||
uint32_t instance_id; // インスタンスID
|
||||
uint8_t flags; // GC/所有権フラグ
|
||||
} HandleEntry;
|
||||
|
||||
static HandleEntry g_handles[MAX_HANDLES];
|
||||
|
||||
// 新しい箱インスタンスの登録
|
||||
uint64_t register_box_handle(uint32_t type_id, uint32_t instance_id) {
|
||||
uint64_t handle = allocate_handle();
|
||||
g_handles[handle] = (HandleEntry){
|
||||
.type_id = type_id,
|
||||
.instance_id = instance_id,
|
||||
.flags = HANDLE_OWNED
|
||||
};
|
||||
return handle;
|
||||
}
|
||||
```
|
||||
|
||||
### 2. プラグイン間の箱共有
|
||||
```c
|
||||
// プラグインAが箱を返す
|
||||
int plugin_a_create_box(uint8_t* result, size_t* result_len) {
|
||||
// 新しい箱を作成
|
||||
uint32_t type_id = 100; // CustomBox
|
||||
uint32_t inst_id = create_instance();
|
||||
|
||||
// TLVエンコード
|
||||
encode_handle(result, type_id, inst_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// プラグインBが箱を受け取る
|
||||
int plugin_b_process(const uint8_t* args, size_t args_len) {
|
||||
// TLVデコード
|
||||
uint32_t type_id, inst_id;
|
||||
decode_handle(args, &type_id, &inst_id);
|
||||
|
||||
// 箱を使用
|
||||
process_box(type_id, inst_id);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
## 💡 重要なポイント
|
||||
|
||||
### 1. 型安全性
|
||||
- ハンドルには型情報(type_id)が含まれる
|
||||
- 実行時の型チェックが可能
|
||||
|
||||
### 2. 所有権管理
|
||||
- ハンドルは参照カウント or GC管理
|
||||
- プラグイン間で安全に共有
|
||||
|
||||
### 3. 相互運用性
|
||||
- ネイティブBox ↔ スクリプトBox間で透過的
|
||||
- 同じハンドル機構を使用
|
||||
|
||||
## 🎯 結論
|
||||
|
||||
埋め込みVMでも:
|
||||
1. **箱は箱を引数に取れる**(ハンドル経由)
|
||||
2. **型情報を保持**(type_id)
|
||||
3. **プラグイン間で共有可能**(instance_id)
|
||||
4. **C ABIと完全互換**(TLVエンコード)
|
||||
|
||||
これにより、Nyashスクリプトで書いた高度なBoxコンポジションも、C ABIプラグインとして動作します!
|
||||
115
docs/archive/roadmap/phases/phase-12/archive/CRITICAL-ISSUE.md
Normal file
115
docs/archive/roadmap/phases/phase-12/archive/CRITICAL-ISSUE.md
Normal file
@ -0,0 +1,115 @@
|
||||
# 🚨 AI議論の誤解:存在しない問題を解決しようとした記録
|
||||
|
||||
## 誤解の本質
|
||||
|
||||
**この文書は、AIたちが「スクリプトプラグイン」という存在しない問題を作り出し、複雑な解決策を提案した記録です。**
|
||||
|
||||
### 実際の事実
|
||||
- Nyashスクリプト = 普通のユーザー定義Box
|
||||
- ユーザー定義Boxは既に完璧に動作している
|
||||
- 特別な仕組みは一切不要
|
||||
|
||||
## なぜこんな誤解をしたのか
|
||||
|
||||
**「プラグイン」という言葉に引っ張られて、C ABIの外部DLLのような特別な仕組みが必要だと思い込んでしまった。**
|
||||
|
||||
```
|
||||
現実のフロー:
|
||||
MIR → JIT → C関数呼び出し(固定アドレス)→ ネイティブコード実行
|
||||
MIR → AOT → EXE内のC関数(静的リンク)→ ネイティブコード実行
|
||||
|
||||
不可能なフロー:
|
||||
MIR → ??? → Nyashスクリプト実行(インタープリター必要)
|
||||
```
|
||||
|
||||
## なぜスクリプトプラグインは動作しないのか
|
||||
|
||||
### 1. インタープリター依存
|
||||
```nyash
|
||||
// スクリプトプラグイン
|
||||
export box CustomMath {
|
||||
sin(x) { return me._math.sin(x) }
|
||||
}
|
||||
```
|
||||
↓
|
||||
**実行にはNyash VMが必要** → EXEに埋め込めない
|
||||
|
||||
### 2. 動的型システム
|
||||
- C ABI: 静的型(i32, i64, double等)
|
||||
- Nyashスクリプト: 動的型(Box)
|
||||
- 型変換にはランタイムが必要
|
||||
|
||||
### 3. メモリ管理
|
||||
- C ABI: 手動管理またはシンプルなGC
|
||||
- Nyashスクリプト: Arc<Mutex<dyn NyashBox>>
|
||||
- GC/参照カウント管理にランタイムが必要
|
||||
|
||||
## 実例:なぜFileBoxはC ABIなのか
|
||||
|
||||
```rust
|
||||
// FileBoxプラグイン(ネイティブ)
|
||||
#[no_mangle]
|
||||
pub extern "C" fn nyash_plugin_invoke(...) -> i32 {
|
||||
// 直接システムコール可能
|
||||
// VMなしで動作
|
||||
// EXEに静的リンク可能
|
||||
}
|
||||
```
|
||||
|
||||
対して、Nyashスクリプトは:
|
||||
- VM必須
|
||||
- 動的評価
|
||||
- EXEに埋め込み不可
|
||||
|
||||
## 結論:Phase 12の方向転換が必要
|
||||
|
||||
### ❌ 不可能なこと
|
||||
- スクリプトプラグインをJIT/AOTから直接呼び出し
|
||||
- スクリプトプラグインをEXEに埋め込み
|
||||
- ネイティブプラグインと完全に透過的な利用
|
||||
|
||||
### ✅ 可能なこと
|
||||
1. **インタープリターモード限定**
|
||||
- スクリプトプラグインはインタープリター実行時のみ
|
||||
- 開発/プロトタイピング用途
|
||||
|
||||
2. **トランスパイル方式**
|
||||
- Nyashスクリプト → C/Rust → ネイティブプラグイン
|
||||
- ビルドステップが必要
|
||||
|
||||
3. **ハイブリッド実行**
|
||||
- 開発時: スクリプトプラグイン(高速イテレーション)
|
||||
- 本番時: ネイティブプラグイン(高性能)
|
||||
|
||||
## 修正された価値提案
|
||||
|
||||
### 開発フローの改善
|
||||
```
|
||||
1. アイデア → Nyashスクリプトでプロトタイプ
|
||||
2. 動作確認 → インタープリターでテスト
|
||||
3. 性能要求 → Rust/Cで再実装
|
||||
4. 配布 → ネイティブプラグインとして
|
||||
```
|
||||
|
||||
### 制限事項の明確化
|
||||
- **JIT/AOT**: ネイティブプラグインのみ
|
||||
- **インタープリター**: スクリプトプラグインも可
|
||||
- **EXE生成**: ネイティブプラグインのみ含む
|
||||
|
||||
## 推奨アクション
|
||||
|
||||
1. **Phase 12の再定義**
|
||||
- 「開発支援ツール」として位置づけ
|
||||
- JIT/AOT統合は諦める
|
||||
|
||||
2. **ドキュメント修正**
|
||||
- 制限事項を明確に記載
|
||||
- 誤解を招く「透過的利用」を削除
|
||||
|
||||
3. **代替案の検討**
|
||||
- Nyash→Rustトランスパイラー
|
||||
- プラグインテンプレート生成ツール
|
||||
|
||||
---
|
||||
|
||||
**重要な教訓:C ABIの制約は、システムプログラミングの本質的な制約である。**
|
||||
@ -0,0 +1,207 @@
|
||||
# 埋め込みVMでのBox処理設計
|
||||
|
||||
## 🎯 核心:MIRレベルでのBox処理を再現
|
||||
|
||||
### 現在のMIR/VMでのBox処理フロー
|
||||
|
||||
```
|
||||
1. MIR: BoxCall/PluginInvoke命令
|
||||
↓
|
||||
2. VM: ValueId → VMValue変換
|
||||
↓
|
||||
3. VMValue → Box<dyn NyashBox> or TLVエンコード
|
||||
↓
|
||||
4. メソッド実行
|
||||
↓
|
||||
5. 結果をVMValueに戻す
|
||||
```
|
||||
|
||||
## 📊 埋め込みVMの設計
|
||||
|
||||
### 1. 軽量VMValue定義
|
||||
|
||||
```c
|
||||
// 埋め込みVM用の値表現
|
||||
typedef enum {
|
||||
NYVM_TYPE_INT,
|
||||
NYVM_TYPE_FLOAT,
|
||||
NYVM_TYPE_BOOL,
|
||||
NYVM_TYPE_STRING,
|
||||
NYVM_TYPE_HANDLE, // Box参照(ハンドル)
|
||||
NYVM_TYPE_VOID
|
||||
} NyVMType;
|
||||
|
||||
typedef struct {
|
||||
NyVMType type;
|
||||
union {
|
||||
int64_t i;
|
||||
double f;
|
||||
uint8_t b;
|
||||
struct { const char* data; size_t len; } s;
|
||||
uint64_t h; // ハンドル(Box参照)
|
||||
} value;
|
||||
} NyVMValue;
|
||||
```
|
||||
|
||||
### 2. MIRバイトコード形式
|
||||
|
||||
```c
|
||||
// BoxCall命令のエンコード
|
||||
enum {
|
||||
OP_BOXCALL = 0x20,
|
||||
OP_PLUGIN_INVOKE = 0x21,
|
||||
// ...
|
||||
};
|
||||
|
||||
// BoxCall: [op:1] [dst:1] [box_val:1] [method_id:2] [argc:1] [args...]
|
||||
// 例: BoxCall %2 = %1.toString()
|
||||
// → 0x20 0x02 0x01 0x00 0x00 0x00
|
||||
```
|
||||
|
||||
### 3. 埋め込みVMでのBoxCall実行
|
||||
|
||||
```c
|
||||
int nyvm_execute_boxcall(
|
||||
NyashEmbeddedVM* vm,
|
||||
uint8_t dst,
|
||||
uint8_t box_val,
|
||||
uint16_t method_id,
|
||||
uint8_t argc,
|
||||
uint8_t* args
|
||||
) {
|
||||
// 1. レシーバー取得
|
||||
NyVMValue* recv = &vm->values[box_val];
|
||||
|
||||
// 2. プリミティブ型の場合
|
||||
if (recv->type != NYVM_TYPE_HANDLE) {
|
||||
// プリミティブ→TLV変換
|
||||
uint8_t tlv_buf[256];
|
||||
size_t tlv_len = encode_primitive_to_tlv(recv, tlv_buf);
|
||||
|
||||
// 組み込み実装を呼び出し
|
||||
return call_builtin_method(recv->type, method_id, tlv_buf, tlv_len);
|
||||
}
|
||||
|
||||
// 3. Box(ハンドル)の場合
|
||||
uint64_t handle = recv->value.h;
|
||||
|
||||
// 引数をTLVエンコード
|
||||
uint8_t args_tlv[1024];
|
||||
size_t args_len = 0;
|
||||
for (int i = 0; i < argc; i++) {
|
||||
NyVMValue* arg = &vm->values[args[i]];
|
||||
args_len += encode_value_to_tlv(arg, &args_tlv[args_len]);
|
||||
}
|
||||
|
||||
// 4. プラグイン呼び出し(C ABI)
|
||||
uint8_t result[4096];
|
||||
size_t result_len = sizeof(result);
|
||||
|
||||
int rc = nyash_plugin_invoke(
|
||||
get_type_id_from_handle(handle),
|
||||
method_id,
|
||||
get_instance_id_from_handle(handle),
|
||||
args_tlv, args_len,
|
||||
result, &result_len
|
||||
);
|
||||
|
||||
// 5. 結果をVMValueに変換
|
||||
if (rc == 0) {
|
||||
decode_tlv_to_value(result, result_len, &vm->values[dst]);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
```
|
||||
|
||||
## 🔄 Box引数の処理
|
||||
|
||||
### 現在のVM(Rust)
|
||||
```rust
|
||||
// VMValue → Box<dyn NyashBox>変換
|
||||
let val = self.get_value(*arg)?;
|
||||
Ok(val.to_nyash_box())
|
||||
```
|
||||
|
||||
### 埋め込みVM(C)
|
||||
```c
|
||||
// NyVMValue → TLVエンコード
|
||||
switch (value->type) {
|
||||
case NYVM_TYPE_INT:
|
||||
encode_i64(tlv, value->value.i);
|
||||
break;
|
||||
case NYVM_TYPE_HANDLE:
|
||||
encode_handle(tlv,
|
||||
get_type_id_from_handle(value->value.h),
|
||||
get_instance_id_from_handle(value->value.h)
|
||||
);
|
||||
break;
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
## 💡 実装のポイント
|
||||
|
||||
### 1. ハンドル管理
|
||||
```c
|
||||
// グローバルハンドルテーブル
|
||||
typedef struct {
|
||||
uint32_t type_id;
|
||||
uint32_t instance_id;
|
||||
void* native_ptr; // 実際のBoxポインタ(必要な場合)
|
||||
} HandleEntry;
|
||||
|
||||
static HandleEntry g_handles[MAX_HANDLES];
|
||||
static uint64_t g_next_handle = 1;
|
||||
|
||||
uint64_t register_handle(uint32_t type_id, uint32_t instance_id) {
|
||||
uint64_t h = g_next_handle++;
|
||||
g_handles[h].type_id = type_id;
|
||||
g_handles[h].instance_id = instance_id;
|
||||
return h;
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 組み込みメソッド
|
||||
```c
|
||||
// 頻出メソッドは埋め込みVMに直接実装
|
||||
int call_builtin_method(NyVMType type, uint16_t method_id, ...) {
|
||||
switch (type) {
|
||||
case NYVM_TYPE_INT:
|
||||
if (method_id == 0) { // toString
|
||||
// 整数→文字列変換
|
||||
}
|
||||
break;
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. プラグインとの統合
|
||||
```c
|
||||
// 生成されるCコード
|
||||
extern "C" int32_t nyplug_mybox_invoke(...) {
|
||||
// MIRバイトコード実行
|
||||
NyashEmbeddedVM vm;
|
||||
nyvm_init(&vm, BYTECODE, sizeof(BYTECODE));
|
||||
|
||||
// 引数をVMスタックに設定
|
||||
nyvm_decode_args(&vm, args, args_len);
|
||||
|
||||
// メソッド実行
|
||||
nyvm_execute_method(&vm, method_id);
|
||||
|
||||
// 結果をTLVエンコード
|
||||
return nyvm_encode_result(&vm, result, result_len);
|
||||
}
|
||||
```
|
||||
|
||||
## 🎯 結論
|
||||
|
||||
埋め込みVMは:
|
||||
1. **MIRのBoxCall/PluginInvoke命令を忠実に実装**
|
||||
2. **TLVエンコード/デコードでC ABIと通信**
|
||||
3. **ハンドルでBox参照を管理**
|
||||
4. **頻出処理は最適化実装**
|
||||
|
||||
これにより、Nyashスクリプトで書いたプラグインも、ネイティブプラグインと同じC ABIで動作します!
|
||||
48
docs/archive/roadmap/phases/phase-12/archive/OLD-README.md
Normal file
48
docs/archive/roadmap/phases/phase-12/archive/OLD-README.md
Normal file
@ -0,0 +1,48 @@
|
||||
# Phase 12 Archive - AIたちの誤解の記録
|
||||
|
||||
## 🚨 重要:このフォルダの内容について
|
||||
|
||||
このフォルダには、Phase 12の議論で生まれた**誤解に基づいたドキュメント**が保存されています。
|
||||
|
||||
### なぜ誤解が生まれたのか
|
||||
|
||||
AIたちは「プラグイン」という言葉から、以下のような複雑な仕組みが必要だと考えました:
|
||||
- トランスパイル(Nyash→C)
|
||||
- 埋め込みVM
|
||||
- 特別なABI変換
|
||||
- JIT/AOT統合
|
||||
|
||||
### 実際の真実
|
||||
|
||||
**Nyashスクリプト = 普通のユーザー定義Box**
|
||||
|
||||
```nyash
|
||||
# これで十分!特別な仕組みは不要
|
||||
box MyPlugin {
|
||||
init {
|
||||
me.file = new FileBox() # C ABIプラグイン使える
|
||||
}
|
||||
process(data) {
|
||||
return me.file.read(data)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 教訓として
|
||||
|
||||
これらのドキュメントは、以下の教訓を示すために残しています:
|
||||
1. シンプルな解決策を見逃してはいけない
|
||||
2. 技術用語に惑わされてはいけない
|
||||
3. Everything is Boxの哲学を忘れてはいけない
|
||||
|
||||
## 📁 アーカイブ内容
|
||||
|
||||
- `CRITICAL-ISSUE.md` - 存在しない問題を解決しようとした記録
|
||||
- `01_roadmap_final.md` - 不要なトランスパイル実装計画
|
||||
- `02_spec_embedded_vm.md` - 不要な埋め込みVM仕様
|
||||
- `03_spec_box_arguments.md` - 不要なBox受け渡し仕様
|
||||
- その他、AI会議での誤解に基づく提案
|
||||
|
||||
---
|
||||
|
||||
*「時に、最も賢い解決策は何もしないことである」*
|
||||
@ -0,0 +1,102 @@
|
||||
# プラグインBoxの箱引数宣言方法
|
||||
|
||||
## 📊 nyash_box.tomlでの宣言
|
||||
|
||||
### 1. 基本的な箱引数の宣言
|
||||
|
||||
```toml
|
||||
[HttpRequestBox.methods.respond]
|
||||
id = 3
|
||||
args = [ { name = "resp", type = "box" } ] # type = "box" で箱引数を宣言
|
||||
returns = { type = "void" }
|
||||
```
|
||||
|
||||
### 2. 引数の型一覧
|
||||
|
||||
| 型指定 | 説明 | TLVタグ |
|
||||
|--------|------|---------|
|
||||
| `"i64"` | 64ビット整数 | 3 |
|
||||
| `"f64"` | 64ビット浮動小数点 | 5 |
|
||||
| `"string"` | UTF-8文字列 | 6 |
|
||||
| `"bool"` | 真偽値 | 1 |
|
||||
| `"box"` | **箱(ハンドル)** | 8 |
|
||||
|
||||
### 3. 実際の使用例
|
||||
|
||||
#### NetプラグインのHttpRequestBox
|
||||
```toml
|
||||
[HttpRequestBox]
|
||||
type_id = 21
|
||||
|
||||
[HttpRequestBox.methods.respond]
|
||||
id = 3
|
||||
args = [ { name = "resp", type = "box" } ] # HttpResponseBoxを受け取る
|
||||
returns = { type = "void" }
|
||||
```
|
||||
|
||||
使用方法(Nyash):
|
||||
```nyash
|
||||
local request = server.accept() // HttpRequestBox
|
||||
local response = new HttpResponseBox() // 別のプラグインBox
|
||||
response.setStatus(200)
|
||||
request.respond(response) // 箱を引数として渡す!
|
||||
```
|
||||
|
||||
#### 戻り値が箱の例
|
||||
```toml
|
||||
[HttpServerBox.methods.accept]
|
||||
id = 3
|
||||
args = []
|
||||
returns = { type = "box" } # HttpRequestBoxを返す
|
||||
```
|
||||
|
||||
## 🔧 C実装側での処理
|
||||
|
||||
### TLVデコード
|
||||
```c
|
||||
// HttpRequestBox.respondの実装例
|
||||
case 3: { // respond
|
||||
// 引数をデコード
|
||||
if (args_len < 12) return -1; // header(4) + handle(8)
|
||||
|
||||
// TLVタグチェック
|
||||
uint8_t tag = args[4];
|
||||
if (tag != 8) return -1; // TAG_HANDLE = 8
|
||||
|
||||
// ハンドルデータ取得
|
||||
uint32_t resp_type_id = *(uint32_t*)&args[8];
|
||||
uint32_t resp_instance_id = *(uint32_t*)&args[12];
|
||||
|
||||
// HttpResponseBox(type_id=22)であることを確認
|
||||
if (resp_type_id != 22) return -1;
|
||||
|
||||
// レスポンス処理...
|
||||
}
|
||||
```
|
||||
|
||||
## 💡 重要なポイント
|
||||
|
||||
### 1. 型安全性
|
||||
- `type = "box"`は任意の箱を受け取れる
|
||||
- 実装側で`type_id`チェックにより型安全性を確保
|
||||
|
||||
### 2. 相互運用性
|
||||
- 異なるプラグイン間でも箱の受け渡しが可能
|
||||
- ハンドル(type_id + instance_id)により参照
|
||||
|
||||
### 3. 宣言の簡潔さ
|
||||
```toml
|
||||
# シンプルな宣言
|
||||
args = [ { name = "box_arg", type = "box" } ]
|
||||
|
||||
# 複数の箱引数も可能
|
||||
args = [
|
||||
{ name = "box1", type = "box" },
|
||||
{ name = "box2", type = "box" },
|
||||
{ name = "count", type = "i64" }
|
||||
]
|
||||
```
|
||||
|
||||
## 🎯 結論
|
||||
|
||||
プラグインBoxは`nyash_box.toml`で`type = "box"`と宣言するだけで、他の箱を引数に取ることができます。C ABIレベルではTLVハンドル(タグ8)として処理され、完全な相互運用性が実現されています。
|
||||
@ -0,0 +1,115 @@
|
||||
# プラグインBoxは既に箱を引数に取れる!
|
||||
|
||||
## 🎯 重要な発見
|
||||
|
||||
**プラグインBoxは既にC ABIレベルで箱を引数に取ることができます!**
|
||||
|
||||
## 📊 実装の詳細
|
||||
|
||||
### 1. TLVプロトコルでのハンドルサポート
|
||||
|
||||
```rust
|
||||
// TLVタグ定義
|
||||
const TAG_HANDLE: u8 = 8; // プラグインハンドル用
|
||||
|
||||
// ハンドルエンコード関数
|
||||
pub fn plugin_handle(buf: &mut Vec<u8>, type_id: u32, instance_id: u32) {
|
||||
buf.push(TAG_HANDLE);
|
||||
buf.push(0u8); // reserved
|
||||
buf.extend_from_slice(&(8u16).to_le_bytes()); // size = 8
|
||||
buf.extend_from_slice(&type_id.to_le_bytes()); // 4 bytes
|
||||
buf.extend_from_slice(&instance_id.to_le_bytes()); // 4 bytes
|
||||
}
|
||||
```
|
||||
|
||||
### 2. プラグイン呼び出し時の処理
|
||||
|
||||
```rust
|
||||
// Nyashコード
|
||||
box1.process(box2, box3)
|
||||
|
||||
// ↓ VM/プラグインローダーでの処理
|
||||
for arg in args {
|
||||
if let Some(p) = arg.as_any().downcast_ref::<PluginBoxV2>() {
|
||||
// 箱引数はハンドルとしてエンコード
|
||||
encode::plugin_handle(&mut tlv, p.type_id, p.instance_id);
|
||||
}
|
||||
// ... 他の型の処理
|
||||
}
|
||||
|
||||
// ↓ C ABIプラグイン側
|
||||
int32_t nyash_plugin_invoke(
|
||||
uint32_t type_id,
|
||||
uint32_t method_id,
|
||||
uint32_t instance_id,
|
||||
const uint8_t* args, // TLVエンコードされた引数
|
||||
size_t args_len,
|
||||
uint8_t* result,
|
||||
size_t* result_len
|
||||
) {
|
||||
// TLVデコード
|
||||
uint8_t tag;
|
||||
uint32_t arg_type_id, arg_instance_id;
|
||||
|
||||
if (decode_handle(args, &tag, &arg_type_id, &arg_instance_id)) {
|
||||
// ハンドル引数を処理
|
||||
// arg_type_id と arg_instance_id で箱を特定
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🔄 実際の使用例
|
||||
|
||||
### Nyashレベル
|
||||
```nyash
|
||||
// FileBoxがStringBoxを引数に取る例
|
||||
local file = new FileBox()
|
||||
local path = new StringBox("/tmp/test.txt")
|
||||
file.open(path) // StringBox(プラグインBox)を引数に!
|
||||
|
||||
// ArrayBoxがMapBoxを引数に取る例
|
||||
local array = new ArrayBox()
|
||||
local map = new MapBox()
|
||||
array.push(map) // MapBox(プラグインBox)を引数に!
|
||||
```
|
||||
|
||||
### プラグイン間の相互運用
|
||||
```nyash
|
||||
// NetBoxがJSONBoxを引数に取る例
|
||||
local net = new NetBox()
|
||||
local json = new JSONBox()
|
||||
json.set("url", "https://api.example.com")
|
||||
net.post(json) // JSONBoxを引数として渡す
|
||||
```
|
||||
|
||||
## 💡 重要なポイント
|
||||
|
||||
### 1. ハンドルによる間接参照
|
||||
- 箱の実体は渡さない(メモリ安全性)
|
||||
- `(type_id, instance_id)`のペアで識別
|
||||
- プラグイン側でハンドルから実体にアクセス
|
||||
|
||||
### 2. 型安全性
|
||||
- `type_id`で型を識別可能
|
||||
- 不正な型の場合はエラー返却
|
||||
|
||||
### 3. 所有権管理
|
||||
- インスタンスIDで参照管理
|
||||
- プラグイン間でも安全に共有
|
||||
|
||||
## 🎯 結論
|
||||
|
||||
**C ABIの制約があっても、ハンドル機構により箱は箱を引数に取れる!**
|
||||
|
||||
これは既に実装済みの機能であり、プラグイン間での高度な連携が可能です。
|
||||
|
||||
### 埋め込みVMへの示唆
|
||||
|
||||
既存のTLVハンドル機構をそのまま使えば、埋め込みVMでも同じように箱引数をサポートできます:
|
||||
|
||||
1. Nyashスクリプト内で箱を引数に使用
|
||||
2. MIRバイトコードにBoxCall命令を含める
|
||||
3. 埋め込みVMがTLVエンコードでC ABIプラグインを呼び出し
|
||||
4. ハンドル経由で箱を渡す
|
||||
|
||||
**Everything is Box、そしてC ABIでも箱は箱を扱える!**
|
||||
232
docs/archive/roadmap/phases/phase-12/archive/README.md
Normal file
232
docs/archive/roadmap/phases/phase-12/archive/README.md
Normal file
@ -0,0 +1,232 @@
|
||||
# Phase 12: プラグインシステムの進化 - 既存C ABIとの共存戦略
|
||||
|
||||
## 🚀 概要
|
||||
|
||||
**重要**: 既存のC ABIプラグインはそのまま使い続けられます!その上で、以下の2つの新機能を追加:
|
||||
|
||||
1. **Nyash ABIサポート** - より型安全で拡張性の高い新しいABI(オプション)
|
||||
2. **Nyashスクリプトプラグイン** - ビルド不要でプラグイン作成可能
|
||||
|
||||
### なぜ既存C ABIを残すのか?
|
||||
|
||||
- **実績と安定性**: 現在動いているFileBox、NetBox等はそのまま
|
||||
- **ゼロオーバーヘッド**: 高頻度呼び出しには最速のC ABI
|
||||
- **段階的移行**: 必要に応じて選択的にNyash ABIへ移行可能
|
||||
|
||||
## 💡 発見の経緯
|
||||
|
||||
include/export仕様の検討中に、以下の重要な気づきが:
|
||||
|
||||
```nyash
|
||||
# custom_math_plugin.ny
|
||||
export box CustomMathPlugin {
|
||||
init {
|
||||
_math = new MathBox() # 既存プラグイン活用
|
||||
_cache = new MapBox() # 結果キャッシュ
|
||||
}
|
||||
|
||||
// カスタム拡張
|
||||
cached_sin(x) {
|
||||
local key = x.toString()
|
||||
if me._cache.has(key) {
|
||||
return me._cache.get(key)
|
||||
}
|
||||
local result = me._math.sin(x)
|
||||
me._cache.set(key, result)
|
||||
return result
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
これにより、Rust/C++のビルドなしでプラグイン開発が可能に!
|
||||
|
||||
## 🎯 ABI共存戦略 - 適材適所の選択
|
||||
|
||||
### 三層構造のプラグインエコシステム
|
||||
|
||||
```
|
||||
1. C ABIプラグイン(既存・継続)
|
||||
- FileBox, NetBox, MathBox等
|
||||
- 高速・安定・実績あり
|
||||
- 変更なし!そのまま使える
|
||||
|
||||
2. Nyash ABIプラグイン(新規追加)
|
||||
- 型安全・拡張性重視の新規開発向け
|
||||
- async/await対応などの将来機能
|
||||
|
||||
3. Nyashスクリプトプラグイン(革命的)
|
||||
- ビルド不要・即座に開発
|
||||
- 上記1,2を組み合わせて利用可能
|
||||
```
|
||||
|
||||
### 使い分けの指針
|
||||
|
||||
| 用途 | 推奨ABI | 理由 |
|
||||
|------|---------|------|
|
||||
| 数値計算(高頻度) | C ABI | ゼロオーバーヘッド |
|
||||
| ファイルI/O | C ABI | 既存実装が安定 |
|
||||
| 複雑な型操作 | Nyash ABI | 型安全性重視 |
|
||||
| プロトタイプ | Nyashスクリプト | 即座に試せる |
|
||||
|
||||
### 設定例(nyash.toml v2.1)
|
||||
|
||||
```toml
|
||||
# nyash.toml v2.1
|
||||
[plugin.math]
|
||||
path = "plugins/math.so"
|
||||
abi = "c" # 高速・安定(デフォルト)
|
||||
|
||||
[plugin.advanced_math]
|
||||
path = "plugins/advanced_math.so"
|
||||
abi = "nyash" # 型安全・拡張性
|
||||
```
|
||||
|
||||
### BoxCall拡張による実装
|
||||
|
||||
**重要な発見**:MIR層の変更は不要!VM実行時の型判定で十分。
|
||||
**Phase 12での追加発見**:PluginInvokeも不要!BoxCallに統合可能。
|
||||
|
||||
```rust
|
||||
// MIR層:変更なし → さらにシンプルに(14命令へ)
|
||||
MirInstruction::BoxCall {
|
||||
receiver: Value,
|
||||
method: String,
|
||||
args: Vec<Value>,
|
||||
}
|
||||
// PluginInvoke は廃止(BoxCallに統合)
|
||||
|
||||
// VM層:賢い判定
|
||||
fn execute_boxcall(...) {
|
||||
let type_info = get_plugin_info(receiver.type_id);
|
||||
match type_info.abi {
|
||||
"c" => call_c_abi(...), // 既存プラグイン
|
||||
"nyash" => call_nyash_abi(...), // 新プラグイン
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Nyash ABI仕様
|
||||
|
||||
```c
|
||||
// 3×u64構造体による型安全な値渡し
|
||||
typedef struct NyashValue {
|
||||
uint64_t type_id; // 型識別子
|
||||
uint64_t box_handle; // Boxハンドル
|
||||
uint64_t metadata; // 拡張用(async flag等)
|
||||
} NyashValue;
|
||||
|
||||
// 統一関数シグネチャ
|
||||
typedef NyashValue (*NyashFunc)(
|
||||
uint32_t argc,
|
||||
NyashValue* args,
|
||||
void* context
|
||||
);
|
||||
```
|
||||
|
||||
### 基本インターフェース(内部)
|
||||
|
||||
```rust
|
||||
// Rust側の統一インターフェース
|
||||
trait BoxInterface {
|
||||
fn invoke(&self, method_id: u32, args: NyashValue) -> NyashValue;
|
||||
fn get_methods(&self) -> Vec<MethodInfo>;
|
||||
fn init(&mut self, ctx: Context);
|
||||
fn drop(&mut self);
|
||||
}
|
||||
```
|
||||
|
||||
### Nyashスクリプトプラグインの要件
|
||||
|
||||
```nyash
|
||||
export box MyPlugin {
|
||||
// 必須:初期化
|
||||
init { ... }
|
||||
|
||||
// 推奨:FFI互換インターフェース
|
||||
invoke(method_id, args) {
|
||||
// method_idに基づいてディスパッチ
|
||||
}
|
||||
|
||||
// オプション:メソッド情報
|
||||
get_methods() {
|
||||
return [
|
||||
{ name: "method1", id: 1 },
|
||||
{ name: "method2", id: 2 }
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📊 エコシステムへの影響
|
||||
|
||||
### 開発の民主化
|
||||
- **参入障壁の劇的低下**: Rust/C++環境不要
|
||||
- **即座の開発**: ビルド待ち時間ゼロ
|
||||
- **コミュニティ拡大**: より多くの開発者が参加可能
|
||||
|
||||
### 新しい開発パターン
|
||||
1. **プラグインの合成**: 複数のネイティブプラグインを組み合わせ
|
||||
2. **ラピッドプロトタイピング**: アイデアを即座に実装
|
||||
3. **ホットリロード**: 実行中の更新が可能
|
||||
|
||||
## 🛣️ 実装ロードマップ(2025-09-01更新)
|
||||
|
||||
**重要**: 既存のC ABIプラグインは一切変更不要!追加機能として実装します。
|
||||
|
||||
### Phase 12.1: ABI共存基盤(1週間)
|
||||
- [ ] nyash.toml v2.1仕様(abi fieldサポート、デフォルト="c")
|
||||
- [ ] プラグインローダーのABI判定実装(後方互換性保証)
|
||||
- [ ] VM execute_boxcallのABI分岐追加(C ABIは現状維持)
|
||||
- [ ] 同一機能のC ABI / Nyash ABI比較ベンチマーク
|
||||
|
||||
### Phase 12.2: Nyash ABI基盤(2週間)
|
||||
- [ ] NyashValue構造体定義(crates/nyrt/include/nyash_abi.h)
|
||||
- [ ] pack/unpack関数実装
|
||||
- [ ] 既存プラグイン1つをNyash ABI移行(実証実験)
|
||||
- [ ] JIT最適化(型既知時の特化コード生成)
|
||||
|
||||
### Phase 12.3: スクリプトプラグイン対応(3週間)
|
||||
- [ ] export box構文のパーサー実装
|
||||
- [ ] BoxInterface trait実装
|
||||
- [ ] NyashスクリプトのVM内実行環境
|
||||
- [ ] 相互運用テスト(C/Nyash/Script混在)
|
||||
|
||||
### Phase 12.4: 動的機能とエコシステム(継続的)
|
||||
- [ ] ホットリロード対応
|
||||
- [ ] プラグイン間依存関係管理
|
||||
- [ ] プラグインマーケットプレイス構想
|
||||
- [ ] セキュリティサンドボックス
|
||||
|
||||
### 実装優先順位(短期)
|
||||
1. **Week 1**: nyash.tomlのabi field + VM分岐(動作確認)
|
||||
2. **Week 2**: 性能測定 + 方向性判断
|
||||
3. **Week 3**: 本格実装 or 方針転換
|
||||
|
||||
## 📚 関連ドキュメント
|
||||
|
||||
### 初期設計
|
||||
- [Gemini先生の分析](./gemini-analysis-script-plugins.md)
|
||||
- [Codex先生の技術提案](./codex-technical-proposal.md)
|
||||
- [統合分析まとめ](./synthesis-script-plugin-revolution.md)
|
||||
|
||||
### ABI戦略議論(2025-09-01)
|
||||
- [議論まとめ](./abi-strategy-discussion/README.md)
|
||||
- [Gemini先生のABI分析](./abi-strategy-discussion/gemini-abi-analysis.md)
|
||||
- [Codex先生のABI実装戦略](./abi-strategy-discussion/codex-abi-implementation.md)
|
||||
- [Codex先生のBoxCall拡張分析](./abi-strategy-discussion/codex-boxcall-extension-analysis.md)
|
||||
- [深い分析と結論](./abi-strategy-discussion/deep-analysis-synthesis.md)
|
||||
- [最終実装決定](./abi-strategy-discussion/final-implementation-decision.md)
|
||||
|
||||
## 🎯 次のアクション(優先順位順)
|
||||
1. nyash.toml v2.1パーサーに`abi` field追加(Day 1-2)
|
||||
2. VM execute_boxcallでABI判定分岐実装(Day 3-4)
|
||||
3. SimpleMathプラグインで両ABI比較テスト(Day 5-6)
|
||||
4. ベンチマーク結果に基づく方向性判断(Day 7)
|
||||
|
||||
### 将来的なアクション
|
||||
- Nyash ABI仕様書(nyash_abi.h)作成
|
||||
- export box構文の実装
|
||||
- プラグインSDK(#[nyash_plugin]マクロ)開発
|
||||
|
||||
---
|
||||
*Everything is Box - そしてプラグインもBoxになる!*
|
||||
147
docs/archive/roadmap/phases/phase-12/archive/REVISED-PROPOSAL.md
Normal file
147
docs/archive/roadmap/phases/phase-12/archive/REVISED-PROPOSAL.md
Normal file
@ -0,0 +1,147 @@
|
||||
# Phase 12(改訂版):Nyashスクリプトプラグイン - 開発支援ツールとして
|
||||
|
||||
## 🎯 現実的な位置づけ
|
||||
|
||||
**スクリプトプラグインは、JIT/AOT/EXEとは独立した開発支援機能として実装する。**
|
||||
|
||||
## 📊 制約と可能性の整理
|
||||
|
||||
### ❌ できないこと(技術的制約)
|
||||
- MIR/VM/JIT/AOTからのスクリプトプラグイン呼び出し
|
||||
- スクリプトプラグインのEXE埋め込み
|
||||
- ネイティブプラグインとの完全な相互運用性
|
||||
|
||||
### ✅ できること(現実的な価値)
|
||||
- インタープリターモードでの高速プロトタイピング
|
||||
- 既存プラグインの組み合わせによる新機能開発
|
||||
- ビルド不要な機能拡張(開発時のみ)
|
||||
|
||||
## 🔄 修正された開発フロー
|
||||
|
||||
```
|
||||
┌─────────────────┐
|
||||
│ アイデア/要件 │
|
||||
└────────┬────────┘
|
||||
↓
|
||||
┌─────────────────┐
|
||||
│ Nyashスクリプト │ ← 高速イテレーション
|
||||
│ プラグイン作成 │ ビルド不要
|
||||
└────────┬────────┘
|
||||
↓
|
||||
┌─────────────────┐
|
||||
│ インタープリター│
|
||||
│ でテスト/検証 │
|
||||
└────────┬────────┘
|
||||
↓
|
||||
性能要求?
|
||||
↙ ↘
|
||||
No Yes
|
||||
↓ ↓
|
||||
そのまま Rust/Cで
|
||||
使用 再実装
|
||||
↓
|
||||
ネイティブ
|
||||
プラグイン
|
||||
↓
|
||||
JIT/AOT/EXE
|
||||
```
|
||||
|
||||
## 📝 実装方針
|
||||
|
||||
### 1. インタープリター専用機能として実装
|
||||
|
||||
```nyash
|
||||
// script_plugin.ny
|
||||
export box CustomLogic {
|
||||
init {
|
||||
_math = new MathBox() // ネイティブプラグイン利用
|
||||
_cache = new MapBox()
|
||||
}
|
||||
|
||||
process(data) {
|
||||
// 複雑なビジネスロジック
|
||||
// インタープリターでのみ実行
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 明確な使用場面の区別
|
||||
|
||||
```nyash
|
||||
// development.ny(開発時)
|
||||
local plugin = include("custom_logic.ny") // ✅ OK
|
||||
|
||||
// production.ny(本番時)
|
||||
local plugin = new CustomLogicBox() // ネイティブ版を使用
|
||||
```
|
||||
|
||||
### 3. トランスパイル支援ツール(将来)
|
||||
|
||||
```bash
|
||||
# Nyashスクリプト → Rustテンプレート生成
|
||||
nyash-to-rust custom_logic.ny > custom_logic_plugin/src/lib.rs
|
||||
```
|
||||
|
||||
## 🎯 価値提案(修正版)
|
||||
|
||||
### 開発者にとっての価値
|
||||
1. **探索的プログラミング** - アイデアを即座に試せる
|
||||
2. **プロトタイピング** - ビルドなしで機能検証
|
||||
3. **学習曲線の緩和** - Rust/C知識不要で拡張開発
|
||||
|
||||
### エコシステムへの貢献
|
||||
1. **アイデアの具現化** - スクリプトで検証→ネイティブで実装
|
||||
2. **コミュニティ参加** - より多くの開発者が貢献可能
|
||||
3. **ベストプラクティス** - 成功パターンの蓄積
|
||||
|
||||
## 🚀 実装計画(現実的版)
|
||||
|
||||
### Phase 12.1: 基盤構築(2週間)
|
||||
- [ ] export box構文(インタープリター専用)
|
||||
- [ ] include()関数の拡張
|
||||
- [ ] 基本的なプラグインレジストリ
|
||||
|
||||
### Phase 12.2: 開発体験向上(3週間)
|
||||
- [ ] ホットリロード(開発モード)
|
||||
- [ ] エラーメッセージ改善
|
||||
- [ ] デバッグ支援機能
|
||||
|
||||
### Phase 12.3: 移行支援(4週間)
|
||||
- [ ] パフォーマンス分析ツール
|
||||
- [ ] Rust変換テンプレート
|
||||
- [ ] 移行ガイドライン
|
||||
|
||||
## 📚 ドキュメント戦略
|
||||
|
||||
### 明確な制約の説明
|
||||
```markdown
|
||||
# Nyashスクリプトプラグイン
|
||||
|
||||
⚠️ **重要な制約**
|
||||
- インタープリターモードでのみ動作
|
||||
- JIT/AOT/EXEでは使用不可
|
||||
- 本番環境ではネイティブプラグインへの移行推奨
|
||||
```
|
||||
|
||||
### 使用例の充実
|
||||
- プロトタイピング例
|
||||
- ネイティブ移行例
|
||||
- パフォーマンス比較
|
||||
|
||||
## 🎉 期待される成果(現実的版)
|
||||
|
||||
### 短期(3ヶ月)
|
||||
- 開発効率の向上(プロトタイピング時間80%削減)
|
||||
- 新規開発者の参入(Rust不要)
|
||||
- アイデア検証の高速化
|
||||
|
||||
### 中期(1年)
|
||||
- 成功パターンの確立
|
||||
- ネイティブプラグインの品質向上
|
||||
- コミュニティ主導の機能提案増加
|
||||
|
||||
## 結論
|
||||
|
||||
**スクリプトプラグインは、C ABIの制約を認識した上で、開発支援ツールとして大きな価値を提供できる。**
|
||||
|
||||
「Everything is Box」の哲学は、実行時の制約はあれど、開発時の自由度として実現される。
|
||||
@ -0,0 +1,175 @@
|
||||
# C ABIとの整合性:Phase 12スクリプトプラグインシステム
|
||||
|
||||
## 🚨 重要な発見
|
||||
|
||||
Phase 10.1で既に**C ABI v0**が定義されており、これとPhase 12の提案を整合させる必要があります。
|
||||
|
||||
## 📊 現状のC ABI(Phase 10.1)
|
||||
|
||||
### 既存のBID-FFI(プラグイン用)
|
||||
```c
|
||||
// 現在のプラグインFFI(TLVベース)
|
||||
extern "C" fn nyash_plugin_invoke(
|
||||
type_id: u32,
|
||||
method_id: u32,
|
||||
instance_id: u32,
|
||||
args: *const u8, // TLVエンコード
|
||||
args_len: usize,
|
||||
result: *mut u8, // TLVエンコード
|
||||
result_len: *mut usize,
|
||||
) -> i32
|
||||
```
|
||||
|
||||
### 新しいNyRT C ABI v0
|
||||
```c
|
||||
// コア関数
|
||||
int32_t nyrt_abi_version(void);
|
||||
NyBox nyrt_box_new(uint64_t typeid, uint64_t size);
|
||||
void nyrt_box_free(NyBox b);
|
||||
|
||||
// プラグイン関数(例:Array)
|
||||
int32_t nyplug_array_abi_version(void);
|
||||
NyBox nyplug_array_new(void);
|
||||
int32_t nyplug_array_get(NyBox arr, uint64_t i, NyBox* out);
|
||||
```
|
||||
|
||||
## 🎯 Phase 12の修正案
|
||||
|
||||
### 問題点
|
||||
- Gemini/Codexの提案した`BoxInterface`トレイトは**Rust専用**
|
||||
- C ABIとの相互運用性が考慮されていない
|
||||
- TLVエンコーディングとの整合性が不明
|
||||
|
||||
### 解決策:C ABIラッパー戦略
|
||||
|
||||
```rust
|
||||
// ❌ 元の提案(Rust専用)
|
||||
trait BoxInterface {
|
||||
fn invoke(&self, method_id: u32, args: NyashValue) -> NyashValue;
|
||||
}
|
||||
|
||||
// ✅ 修正案(C ABI互換)
|
||||
pub struct ScriptPluginWrapper {
|
||||
// Nyashスクリプトインスタンス
|
||||
script_box: NyashValue,
|
||||
|
||||
// C ABI互換性のためのFFI関数
|
||||
ffi_invoke: extern "C" fn(
|
||||
type_id: u32,
|
||||
method_id: u32,
|
||||
instance_id: u32,
|
||||
args: *const u8,
|
||||
args_len: usize,
|
||||
result: *mut u8,
|
||||
result_len: *mut usize,
|
||||
) -> i32,
|
||||
}
|
||||
|
||||
impl ScriptPluginWrapper {
|
||||
// 既存のBID-FFIと完全互換
|
||||
pub extern "C" fn invoke_ffi(
|
||||
&self,
|
||||
type_id: u32,
|
||||
method_id: u32,
|
||||
instance_id: u32,
|
||||
args: *const u8,
|
||||
args_len: usize,
|
||||
result: *mut u8,
|
||||
result_len: *mut usize,
|
||||
) -> i32 {
|
||||
// 1. TLVデコード
|
||||
let nyash_args = decode_tlv(args, args_len);
|
||||
|
||||
// 2. Nyashスクリプト呼び出し
|
||||
let result_value = self.script_box.invoke(method_id, nyash_args);
|
||||
|
||||
// 3. TLVエンコード
|
||||
encode_tlv(result_value, result, result_len)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🔄 統合アーキテクチャ
|
||||
|
||||
```
|
||||
[JIT/AOT] ---> C ABI (nyrt_*/nyplug_*) --+--> [ネイティブプラグイン]
|
||||
|
|
||||
+--> [ScriptPluginWrapper] --> [Nyashスクリプト]
|
||||
```
|
||||
|
||||
### 利点
|
||||
1. **完全な後方互換性** - 既存のプラグインがそのまま動作
|
||||
2. **統一されたFFI** - JIT/AOT/プラグインすべて同じC ABI
|
||||
3. **透過的な利用** - 呼び出し側はネイティブ/スクリプトを区別しない
|
||||
|
||||
## 📝 実装修正案
|
||||
|
||||
### Phase 12.1(修正版)
|
||||
1. **ScriptPluginWrapperの実装**
|
||||
- BID-FFI互換のC関数エクスポート
|
||||
- TLVエンコード/デコード処理
|
||||
- Nyashスクリプトへの橋渡し
|
||||
|
||||
2. **プラグインレジストリ拡張**
|
||||
```rust
|
||||
pub struct PluginRegistry {
|
||||
// 既存のネイティブプラグイン(C ABI)
|
||||
native_plugins: HashMap<u32, PluginHandle>,
|
||||
|
||||
// スクリプトプラグイン(C ABIラッパー経由)
|
||||
script_plugins: HashMap<u32, ScriptPluginWrapper>,
|
||||
}
|
||||
```
|
||||
|
||||
3. **export box構文の実装**
|
||||
```nyash
|
||||
export box CustomMathPlugin {
|
||||
// BID-FFI互換のためのメタ情報
|
||||
__type_id__ = 100 // 動的割り当てor設定ファイル
|
||||
__methods__ = {
|
||||
"cached_sin": 1,
|
||||
"cached_cos": 2
|
||||
}
|
||||
|
||||
// 通常のNyashコード
|
||||
init { ... }
|
||||
cached_sin(x) { ... }
|
||||
}
|
||||
```
|
||||
|
||||
## 🚀 移行パス
|
||||
|
||||
### 段階1:既存プラグインの動作確認
|
||||
- FileBox、NetBox等がC ABI経由で正常動作
|
||||
- パフォーマンステスト
|
||||
|
||||
### 段階2:簡単なスクリプトプラグイン
|
||||
- MathBoxの一部機能をNyashで再実装
|
||||
- C ABIラッパー経由での動作確認
|
||||
|
||||
### 段階3:高度な統合
|
||||
- ネイティブとスクリプトの混在
|
||||
- 動的ロード/アンロード
|
||||
|
||||
## ⚡ パフォーマンス影響
|
||||
|
||||
```
|
||||
呼び出しチェーン:
|
||||
1. JIT → C ABI関数呼び出し(既存)
|
||||
2. C ABI → ScriptPluginWrapper(追加)
|
||||
3. Wrapper → TLVデコード(追加)
|
||||
4. Wrapper → Nyashスクリプト実行(追加)
|
||||
5. Wrapper → TLVエンコード(追加)
|
||||
|
||||
予想オーバーヘッド: 100-500ns/呼び出し
|
||||
```
|
||||
|
||||
## 🎯 結論
|
||||
|
||||
Phase 12のスクリプトプラグインシステムは、**C ABIを尊重**しつつ実装可能です。
|
||||
|
||||
- BoxInterfaceトレイトは内部実装詳細に留める
|
||||
- 外部インターフェースは既存のC ABI(BID-FFI)を維持
|
||||
- ScriptPluginWrapperがブリッジとして機能
|
||||
|
||||
これにより、**「Everything is Plugin」**の哲学を保ちながら、スクリプトプラグインを実現できます。
|
||||
@ -0,0 +1,334 @@
|
||||
# Codex先生の技術提案:Nyashスクリプトプラグインシステム実装
|
||||
|
||||
## エグゼクティブサマリー
|
||||
|
||||
Nyashスクリプトをプラグインとして使用する提案は、技術的に極めて実現可能であり、Nyashエコシステムに革命的な価値をもたらします。「Everything is Box」哲学の究極の実現として、実装言語に依存しない統一インターフェースを提供することで、開発の民主化とエコシステムの爆発的成長が期待できます。
|
||||
|
||||
## 技術アーキテクチャ提案
|
||||
|
||||
### 1. 統一Box ABIの詳細設計
|
||||
|
||||
```rust
|
||||
// コアインターフェース定義
|
||||
pub trait UnifiedBoxInterface: Send + Sync {
|
||||
// 基本メソッド
|
||||
fn invoke(&self, ctx: &mut Context, method_id: u32, args: &[NyashValue]) -> Result<NyashValue, BoxError>;
|
||||
fn get_metadata(&self) -> BoxMetadata;
|
||||
|
||||
// ライフサイクル管理
|
||||
fn initialize(&mut self, config: &BoxConfig) -> Result<(), BoxError>;
|
||||
fn shutdown(&mut self) -> Result<(), BoxError>;
|
||||
|
||||
// 動的機能(オプション)
|
||||
fn hot_reload(&mut self, new_code: &str) -> Result<(), BoxError> {
|
||||
Err(BoxError::NotSupported)
|
||||
}
|
||||
}
|
||||
|
||||
// メタデータ構造
|
||||
pub struct BoxMetadata {
|
||||
pub name: String,
|
||||
pub version: String,
|
||||
pub methods: Vec<MethodInfo>,
|
||||
pub capabilities: Vec<Capability>,
|
||||
pub dependencies: Vec<Dependency>,
|
||||
}
|
||||
```
|
||||
|
||||
### 2. プラグインレジストリアーキテクチャ
|
||||
|
||||
```rust
|
||||
pub struct PluginRegistry {
|
||||
// ネイティブプラグイン
|
||||
native_plugins: HashMap<u32, Arc<dyn UnifiedBoxInterface>>,
|
||||
|
||||
// スクリプトプラグイン
|
||||
script_plugins: HashMap<u32, ScriptPlugin>,
|
||||
|
||||
// 動的ID管理
|
||||
id_allocator: IdAllocator,
|
||||
|
||||
// 依存関係グラフ
|
||||
dependency_graph: DependencyGraph,
|
||||
}
|
||||
|
||||
impl PluginRegistry {
|
||||
pub fn register_native(&mut self, plugin: impl UnifiedBoxInterface + 'static) -> u32 {
|
||||
let id = self.id_allocator.allocate();
|
||||
self.native_plugins.insert(id, Arc::new(plugin));
|
||||
id
|
||||
}
|
||||
|
||||
pub fn register_script(&mut self, source: &str) -> Result<u32, RegistryError> {
|
||||
let plugin = ScriptPlugin::compile(source)?;
|
||||
let id = self.id_allocator.allocate();
|
||||
self.script_plugins.insert(id, plugin);
|
||||
Ok(id)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. スクリプトプラグインラッパー実装
|
||||
|
||||
```rust
|
||||
pub struct ScriptPlugin {
|
||||
vm: NyashVM,
|
||||
box_instance: NyashValue,
|
||||
method_cache: HashMap<u32, MethodHandle>,
|
||||
}
|
||||
|
||||
impl UnifiedBoxInterface for ScriptPlugin {
|
||||
fn invoke(&self, ctx: &mut Context, method_id: u32, args: &[NyashValue]) -> Result<NyashValue, BoxError> {
|
||||
// メソッドキャッシュから高速検索
|
||||
if let Some(handle) = self.method_cache.get(&method_id) {
|
||||
return self.vm.call_cached(handle, args);
|
||||
}
|
||||
|
||||
// 動的メソッド解決
|
||||
let method = self.resolve_method(method_id)?;
|
||||
self.vm.call_method(&self.box_instance, &method, args)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 実装戦略
|
||||
|
||||
### Phase 1: MVP実装(2-3週間)
|
||||
|
||||
1. **基本インターフェース実装**
|
||||
- UnifiedBoxInterfaceトレイトの実装
|
||||
- 既存FFIプラグイン1つを移行(MathBox推奨)
|
||||
- ScriptPluginラッパーの基本実装
|
||||
|
||||
2. **export box構文の実装**
|
||||
```nyash
|
||||
export box MyPlugin {
|
||||
init { _version = "1.0.0" }
|
||||
|
||||
// 必須:プラグインメタデータ
|
||||
get_metadata() {
|
||||
return {
|
||||
name: "MyPlugin",
|
||||
version: me._version,
|
||||
methods: ["process", "transform"]
|
||||
}
|
||||
}
|
||||
|
||||
// ビジネスロジック
|
||||
process(data) { ... }
|
||||
transform(input) { ... }
|
||||
}
|
||||
```
|
||||
|
||||
3. **基本的なレジストリ**
|
||||
- 静的登録のみ
|
||||
- 依存関係解決なし
|
||||
|
||||
### Phase 2: 動的機能(3-4週間)
|
||||
|
||||
1. **動的ロード/アンロード**
|
||||
```nyash
|
||||
local registry = new PluginRegistry()
|
||||
local id = registry.load_script("path/to/plugin.ny")
|
||||
registry.unload(id)
|
||||
```
|
||||
|
||||
2. **ホットリロード**
|
||||
```nyash
|
||||
registry.enable_hot_reload("path/to/plugin.ny")
|
||||
// ファイル変更時に自動リロード
|
||||
```
|
||||
|
||||
3. **依存関係管理**
|
||||
- 循環依存検出
|
||||
- バージョン互換性チェック
|
||||
|
||||
### Phase 3: 最適化とセキュリティ(4-6週間)
|
||||
|
||||
1. **パフォーマンス最適化**
|
||||
- メソッドキャッシング
|
||||
- JITコンパイル統合
|
||||
- プリコンパイルオプション
|
||||
|
||||
2. **セキュリティサンドボックス**
|
||||
```rust
|
||||
pub struct Sandbox {
|
||||
memory_limit: usize,
|
||||
cpu_quota: Duration,
|
||||
allowed_capabilities: HashSet<Capability>,
|
||||
}
|
||||
```
|
||||
|
||||
3. **ケイパビリティベースセキュリティ**
|
||||
- ファイルアクセス制限
|
||||
- ネットワーク制限
|
||||
- システムコール制限
|
||||
|
||||
## パフォーマンス考察
|
||||
|
||||
### ベンチマーク予測
|
||||
|
||||
```
|
||||
操作 | ネイティブ | スクリプト | 比率
|
||||
--------------------|-----------|-----------|-----
|
||||
単純メソッド呼び出し | 10ns | 100ns | 10x
|
||||
複雑な計算(1000ops) | 1μs | 5μs | 5x
|
||||
I/O操作 | 100μs | 102μs | 1.02x
|
||||
```
|
||||
|
||||
### 最適化戦略
|
||||
|
||||
1. **ホットパスの識別**
|
||||
- 頻繁に呼ばれるメソッドを自動検出
|
||||
- JITコンパイル優先度付け
|
||||
|
||||
2. **ハイブリッドアプローチ**
|
||||
- コア機能:ネイティブ実装
|
||||
- カスタマイズ層:スクリプト実装
|
||||
|
||||
## エコシステムへの影響
|
||||
|
||||
### 開発者体験の革新
|
||||
|
||||
1. **即座のフィードバックループ**
|
||||
```bash
|
||||
# 編集
|
||||
vim my_plugin.ny
|
||||
|
||||
# 即座にテスト(ビルド不要)
|
||||
nyash test_plugin.ny
|
||||
```
|
||||
|
||||
2. **プラグインマーケットプレイス**
|
||||
- GitHubから直接インストール
|
||||
- バージョン管理統合
|
||||
- 自動更新機能
|
||||
|
||||
### コミュニティ成長予測
|
||||
|
||||
- **現在**: 10-20人のコアコントリビューター(Rust必須)
|
||||
- **1年後**: 100-500人のプラグイン開発者(Nyashのみ)
|
||||
- **3年後**: 1000+のプラグインエコシステム
|
||||
|
||||
## リスクと緩和策
|
||||
|
||||
### 技術的リスク
|
||||
|
||||
1. **パフォーマンス劣化**
|
||||
- 緩和策:重要部分のネイティブ実装維持
|
||||
- プロファイリングツール提供
|
||||
|
||||
2. **セキュリティ脆弱性**
|
||||
- 緩和策:デフォルトサンドボックス
|
||||
- 署名付きプラグイン
|
||||
|
||||
### エコシステムリスク
|
||||
|
||||
1. **品質のばらつき**
|
||||
- 緩和策:公式プラグインガイドライン
|
||||
- 自動品質チェックツール
|
||||
|
||||
2. **互換性問題**
|
||||
- 緩和策:セマンティックバージョニング強制
|
||||
- 自動互換性テスト
|
||||
|
||||
## 結論と推奨事項
|
||||
|
||||
### 即時実行すべきアクション
|
||||
|
||||
1. **Box ABI仕様書の作成**(1週間)
|
||||
2. **export box構文の実装**(2週間)
|
||||
3. **MathBoxの統一インターフェース移行**(1週間)
|
||||
|
||||
### 長期ビジョン
|
||||
|
||||
Nyashスクリプトプラグインシステムは、単なる機能追加ではなく、Nyashを**プログラミング言語**から**拡張可能なプラットフォーム**へと進化させる革命的な一歩です。
|
||||
|
||||
「Everything is Box」の哲学が、実装言語の壁を超えて真に実現される時、Nyashは次世代のプログラミングエコシステムのモデルケースとなるでしょう。
|
||||
|
||||
## 付録:実装例
|
||||
|
||||
### A. 完全なスクリプトプラグイン例
|
||||
|
||||
```nyash
|
||||
# advanced_math_plugin.ny
|
||||
export box AdvancedMathPlugin {
|
||||
init {
|
||||
_math = new MathBox()
|
||||
_cache = new MapBox()
|
||||
_stats = new MapBox()
|
||||
}
|
||||
|
||||
// プラグインメタデータ(必須)
|
||||
get_metadata() {
|
||||
return {
|
||||
name: "AdvancedMathPlugin",
|
||||
version: "1.0.0",
|
||||
methods: ["cached_sin", "cached_cos", "fibonacci", "factorial"],
|
||||
capabilities: ["compute"],
|
||||
dependencies: [{
|
||||
name: "MathBox",
|
||||
version: ">=1.0.0"
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
// キャッシュ付き三角関数
|
||||
cached_sin(x) {
|
||||
local key = "sin:" + x.toString()
|
||||
if me._cache.has(key) {
|
||||
me._update_stats("cache_hit")
|
||||
return me._cache.get(key)
|
||||
}
|
||||
|
||||
local result = me._math.sin(x)
|
||||
me._cache.set(key, result)
|
||||
me._update_stats("cache_miss")
|
||||
return result
|
||||
}
|
||||
|
||||
// 再帰的フィボナッチ(メモ化)
|
||||
fibonacci(n) {
|
||||
if n <= 1 { return n }
|
||||
|
||||
local key = "fib:" + n.toString()
|
||||
if me._cache.has(key) {
|
||||
return me._cache.get(key)
|
||||
}
|
||||
|
||||
local result = me.fibonacci(n-1) + me.fibonacci(n-2)
|
||||
me._cache.set(key, result)
|
||||
return result
|
||||
}
|
||||
|
||||
// 統計情報
|
||||
get_stats() {
|
||||
return me._stats
|
||||
}
|
||||
|
||||
// プライベートメソッド
|
||||
_update_stats(event) {
|
||||
local count = me._stats.get(event) or 0
|
||||
me._stats.set(event, count + 1)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### B. ネイティブとスクリプトの透過的利用
|
||||
|
||||
```nyash
|
||||
// 使用側のコード(プラグインの実装言語を意識しない)
|
||||
local math1 = new MathBox() // ネイティブプラグイン
|
||||
local math2 = include("advanced_math_plugin.ny") // スクリプトプラグイン
|
||||
|
||||
// 同じインターフェースで利用
|
||||
print(math1.sin(3.14)) // ネイティブ実装
|
||||
print(math2.cached_sin(3.14)) // スクリプト実装
|
||||
|
||||
// 動的に切り替え可能
|
||||
local math = get_config("use_cached") ? math2 : math1
|
||||
print(math.sin(1.57))
|
||||
```
|
||||
|
||||
---
|
||||
*"Write plugins in Nyash, for Nyash, by Nyash!"*
|
||||
@ -0,0 +1,90 @@
|
||||
# Gemini先生の分析:Nyashスクリプトプラグインシステム
|
||||
|
||||
## 技術的妥当性評価
|
||||
|
||||
### 結論:極めて実現可能性は高く、技術的にも非常に妥当
|
||||
|
||||
このアプローチは、多くのモダンな言語やエンジン(Lua, JavaScript/Node.js, Pythonなど)で採用されている「ネイティブコアとスクリプト拡張」という実績あるモデルを踏襲しています。
|
||||
|
||||
### 「Everything is Box」哲学との整合性
|
||||
|
||||
このアプローチは、Boxを「外部から観測可能なインターフェースを持つオブジェクト」と定義するならば、その実装がネイティブ(Rust/C++)であろうとスクリプト(Nyash)であろうと区別しない、という哲学の究極的な現れです。
|
||||
|
||||
## 統一インターフェース設計
|
||||
|
||||
### BoxInterface Traitの提案
|
||||
|
||||
```rust
|
||||
// Rust側に、すべてのプラグインが実装すべきtraitを定義
|
||||
trait BoxInterface {
|
||||
fn invoke(&self, method_id: u32, args: NyashValue) -> NyashValue;
|
||||
// その他、初期化やメタデータ取得などの共通メソッド
|
||||
}
|
||||
```
|
||||
|
||||
### アーキテクチャ
|
||||
|
||||
```
|
||||
[Nyashコード] -> [BoxInterface Trait] --+--> [FFIラッパー] -> [ネイティブコード]
|
||||
|
|
||||
+--> [Nyashスクリプトラッパー] -> [Nyash VM実行]
|
||||
```
|
||||
|
||||
これにより、Nyashのコードからプラグインを利用する側は、相手がネイティブかスクリプトかを一切意識する必要がなくなります。
|
||||
|
||||
## エコシステムへの影響
|
||||
|
||||
### 開発の民主化
|
||||
|
||||
- **参入障壁の劇的な低下**: Rust/C++の環境構築やビルドプロセスが不要
|
||||
- **迅速なプロトタイピング**: アイデアをすぐにNyashスクリプトで形にし、テスト可能
|
||||
|
||||
### 新しいプラグインの形態
|
||||
|
||||
- **プラグインの合成**: 複数の既存プラグインを組み合わせて新しい機能を持つ「メタプラグイン」
|
||||
- **アプリケーションの「設定」としてのプラグイン**: ユーザーが自身のアプリケーションの動作をカスタマイズ
|
||||
|
||||
### 動的性の向上
|
||||
|
||||
アプリケーションの実行中に、Nyashスクリプトプラグインをリロードしたり、新しいものを追加したりすることが容易になります。
|
||||
|
||||
## 実装ロードマップ
|
||||
|
||||
### フェーズ1:コアランタイムの実現(MVP)
|
||||
1. `BoxInterface` Traitの設計と実装(Rust側)
|
||||
2. 既存FFIの`BoxInterface`への対応
|
||||
3. Nyashオブジェクトの`BoxInterface`対応
|
||||
4. `import` / `export` の実装
|
||||
|
||||
### フェーズ2:動的機能と管理
|
||||
1. プラグインレジストリの実装
|
||||
2. 動的ロード/アンロードAPIの提供
|
||||
3. ID管理の洗練
|
||||
|
||||
### フェーズ3:セキュリティと堅牢性
|
||||
1. サンドボックスの導入
|
||||
2. パフォーマンス分析ツールの提供
|
||||
|
||||
### フェーズ4:開発者体験(DX)の向上
|
||||
1. ドキュメントの整備
|
||||
2. LSP/静的解析の対応
|
||||
|
||||
## 他言語からの学び
|
||||
|
||||
### Lua
|
||||
- C APIが非常にクリーンで、Cの関数をLuaから、Luaの関数をCから呼び出すのが容易
|
||||
- **学ぶべき点**: ネイティブとスクリプト間の境界(API)をいかにシンプルで強力に保つか
|
||||
|
||||
### Node.js (JavaScript)
|
||||
- `require()`システムが、C++で書かれたネイティブアドオンも、JavaScriptで書かれたモジュールも、全く同じように読み込む
|
||||
- **学ぶべき点**: 統一されたモジュール解決システムとインターフェースの重要性
|
||||
|
||||
### Python
|
||||
- Cで書かれた拡張モジュールと、Pure Pythonで書かれたモジュールが共存
|
||||
- **学ぶべき点**: パフォーマンスが重要な部分はCで、それ以外は柔軟なPythonで書くという、実用的な使い分け
|
||||
|
||||
## 総括
|
||||
|
||||
この発見はNyashの方向性を決定づける重要なマイルストーンです。パフォーマンスが最重要視されるコアな機能はRust/C++のFFIプラグインで、それ以外の大部分の機能、ビジネスロジック、UI、ユーザーカスタマイズなどはNyashスクリプトプラグインで開発する、という美しい棲み分けが実現します。
|
||||
|
||||
これはNyashを単なるプログラミング言語から、**拡張可能なプラットフォーム**へと昇華させる可能性を秘めています。
|
||||
@ -0,0 +1,277 @@
|
||||
# C ABI TypeBox 設計仕様書 v2.0 (2025-09-01)
|
||||
|
||||
## 🎯 概要
|
||||
|
||||
**重要な設計変更**: 複雑なFactory設計から、極限までシンプルなTypeBoxアプローチへ移行しました。
|
||||
|
||||
TypeBoxは、C ABIプラグイン間でBox型情報を受け渡すための最小限の仕組みです。「Everything is Box」の哲学に従い、型情報すらBoxとして扱います。
|
||||
|
||||
### 解決する問題
|
||||
1. **相互依存問題**: C ABIプラグインは他プラグインのヘッダーを直接参照できない
|
||||
2. **循環依存**: MapBox→ArrayBox→StringBoxのような依存関係
|
||||
3. **ABI境界**: 異なるコンパイラ/バージョンでビルドされたプラグイン間の互換性
|
||||
4. **シンプルさ**: MIR層への影響を最小限に抑える
|
||||
|
||||
## 📐 基本設計:TypeBoxアプローチ
|
||||
|
||||
### TypeBox構造体(極限までシンプル)
|
||||
|
||||
```c
|
||||
// nyrt_typebox.h - すべてのプラグインが共有する最小限のヘッダ
|
||||
typedef struct NyrtTypeBox {
|
||||
uint32_t abi_tag; // 'TYBX' (0x58425954) マジックナンバー
|
||||
const char* name; // "ArrayBox", "StringBox" など
|
||||
void* (*create)(void); // Box生成関数(引数なし版)
|
||||
} NyrtTypeBox;
|
||||
|
||||
// オプション:コンテキスト付き版(将来拡張用)
|
||||
typedef struct NyrtTypeBoxV2 {
|
||||
uint32_t abi_tag; // 'TYB2' (0x32425954)
|
||||
uint16_t abi_major; // 1
|
||||
uint16_t abi_minor; // 0
|
||||
const char* name; // 型名
|
||||
void* (*create)(void* context); // コンテキスト付き生成
|
||||
uint32_t size; // sizeof(NyrtTypeBoxV2)
|
||||
} NyrtTypeBoxV2;
|
||||
```
|
||||
|
||||
### 設計原則
|
||||
|
||||
1. **静的メタデータ**: TypeBoxは不変の型情報(参照カウント不要)
|
||||
2. **引数として渡す**: 明示的な依存関係を保つ
|
||||
3. **グローバル変数なし**: すべて引数経由で受け渡し
|
||||
4. **ファクトリーなし**: 直接関数ポインタを呼ぶシンプルさ
|
||||
|
||||
### Rust側実装(ランタイム)
|
||||
|
||||
```rust
|
||||
// src/runtime/type_boxes.rs
|
||||
use std::os::raw::c_void;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NyrtTypeBox {
|
||||
pub abi_tag: u32,
|
||||
pub name: *const std::os::raw::c_char,
|
||||
pub create: extern "C" fn() -> *mut c_void,
|
||||
}
|
||||
|
||||
// ArrayBox用の静的TypeBox定義
|
||||
#[no_mangle]
|
||||
pub static ARRAY_TYPE_BOX: NyrtTypeBox = NyrtTypeBox {
|
||||
abi_tag: 0x58425954, // 'TYBX'
|
||||
name: b"ArrayBox\0".as_ptr() as *const _,
|
||||
create: create_array_box_impl,
|
||||
};
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn create_array_box_impl() -> *mut c_void {
|
||||
// ArrayBoxインスタンスを作成
|
||||
let array = ArrayBox::new();
|
||||
let boxed = Box::new(array);
|
||||
Box::into_raw(boxed) as *mut c_void
|
||||
}
|
||||
|
||||
// オプション:型検証ヘルパー
|
||||
#[no_mangle]
|
||||
pub extern "C" fn nyrt_validate_typebox(tb: *const NyrtTypeBox) -> bool {
|
||||
if tb.is_null() { return false; }
|
||||
unsafe {
|
||||
(*tb).abi_tag == 0x58425954
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🔄 プラグイン側実装例
|
||||
|
||||
### MapBoxプラグイン(keys()実装)
|
||||
|
||||
```c
|
||||
// plugins/map/map_box.c
|
||||
#include "nyrt_typebox.h"
|
||||
|
||||
// MapBox.keys()の実装 - TypeBoxを引数で受け取る
|
||||
void* map_keys(void* self, void* array_type_box) {
|
||||
MapBox* map = (MapBox*)self;
|
||||
NyrtTypeBox* array_type = (NyrtTypeBox*)array_type_box;
|
||||
|
||||
// 最小限の検証
|
||||
if (!array_type || array_type->abi_tag != 0x58425954) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// ArrayBoxを作成(直接関数ポインタを呼ぶ)
|
||||
void* array = array_type->create();
|
||||
if (!array) return NULL;
|
||||
|
||||
// キーをArrayBoxに追加
|
||||
// 注:ArrayBoxのpushメソッドは別途C API経由で呼ぶ必要あり
|
||||
for (size_t i = 0; i < map->size; i++) {
|
||||
// ArrayBox固有のAPIを使用(プラグイン間の取り決め)
|
||||
// array_push(array, map->entries[i].key);
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
// 呼び出し側の例
|
||||
void example_usage(void* map) {
|
||||
// ランタイムから型情報を取得(または静的に保持)
|
||||
extern NyrtTypeBox ARRAY_TYPE_BOX; // ランタイムが提供
|
||||
|
||||
void* keys = map_keys(map, &ARRAY_TYPE_BOX);
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
## 🌟 なぜTypeBoxアプローチが優れているか
|
||||
|
||||
### 専門家による分析結果
|
||||
|
||||
GeminiとCodexによる深い技術分析の結果、以下の結論に至りました:
|
||||
|
||||
1. **極限のシンプルさ**
|
||||
- 構造体1つ、関数ポインタ1つ
|
||||
- C言語の基本機能のみ使用
|
||||
- 特別なライブラリ不要
|
||||
|
||||
2. **明示的な依存関係**
|
||||
- TypeBoxを引数で渡すことで依存が明確
|
||||
- グローバル状態なし
|
||||
- テスト容易性の向上
|
||||
|
||||
3. **MIR層への影響最小**
|
||||
- 型情報を単なる値として扱う
|
||||
- 新しいディスパッチルール不要
|
||||
- 既存の仕組みで実現可能
|
||||
|
||||
4. **拡張性**
|
||||
- 構造体の末尾に新フィールド追加可能
|
||||
- バージョニングによる互換性維持
|
||||
- 将来の要求に対応可能
|
||||
|
||||
### 代替案の比較
|
||||
|
||||
| アプローチ | 複雑さ | MIR影響 | 保守性 |
|
||||
|-----------|--------|---------|--------|
|
||||
| TypeBox(採用) | ★☆☆☆☆ | 最小 | 優秀 |
|
||||
| Factory Pattern | ★★★★☆ | 中 | 困難 |
|
||||
| COM/JNI風 | ★★★★★ | 大 | 複雑 |
|
||||
| サービスレジストリ | ★★★☆☆ | 中 | 良好 |
|
||||
|
||||
## 💾 メモリ管理とセキュリティ
|
||||
|
||||
### TypeBoxのライフサイクル
|
||||
|
||||
```c
|
||||
// TypeBoxは静的メタデータ(参照カウント不要)
|
||||
// ランタイムが提供する不変のデータとして扱う
|
||||
extern const NyrtTypeBox ARRAY_TYPE_BOX; // 'static lifetime
|
||||
extern const NyrtTypeBox STRING_TYPE_BOX; // 'static lifetime
|
||||
|
||||
// 生成されたBoxインスタンスは通常通り参照カウント管理
|
||||
void* array = array_type->create();
|
||||
// 使用...
|
||||
nyrt_release(array); // 既存の参照カウントAPI
|
||||
```
|
||||
|
||||
### セキュリティ考慮事項
|
||||
|
||||
```c
|
||||
// 最小限の検証で安全性を確保
|
||||
bool is_valid_typebox(const NyrtTypeBox* tb) {
|
||||
return tb != NULL &&
|
||||
tb->abi_tag == 0x58425954 && // 'TYBX'
|
||||
tb->name != NULL &&
|
||||
tb->create != NULL;
|
||||
}
|
||||
|
||||
// 使用例
|
||||
if (!is_valid_typebox(array_type)) {
|
||||
return NULL; // 不正なTypeBoxを拒否
|
||||
}
|
||||
```
|
||||
|
||||
## 🚀 実装ロードマップ
|
||||
|
||||
### Phase 1: TypeBox基本実装(3日)
|
||||
- [ ] nyrt_typebox.h定義
|
||||
- [ ] 基本型(Array/String/Map)のTypeBox定義
|
||||
- [ ] 検証関数の実装
|
||||
|
||||
### Phase 2: プラグイン統合(1週間)
|
||||
- [ ] MapBox.keys()のTypeBox対応
|
||||
- [ ] ArrayBox APIの整備
|
||||
- [ ] サンプル実装
|
||||
|
||||
### Phase 3: 完全移行(1週間)
|
||||
- [ ] 全プラグインのTypeBox対応
|
||||
- [ ] ドキュメント更新
|
||||
- [ ] テストスイート
|
||||
|
||||
## 📊 パフォーマンス分析
|
||||
|
||||
### TypeBoxアプローチのオーバーヘッド
|
||||
```
|
||||
直接生成: ~50ns
|
||||
TypeBox経由: ~60ns(関数ポインタ1回)
|
||||
→ ほぼ無視できるレベル
|
||||
```
|
||||
|
||||
### メモリ効率
|
||||
```
|
||||
TypeBox構造体: 24bytes(最小構成)
|
||||
グローバル変数: 0(すべて引数渡し)
|
||||
→ 極めて効率的
|
||||
```
|
||||
|
||||
## 🎯 実装例:MapBox.keys()の完全な実装
|
||||
|
||||
```c
|
||||
// map_box.c
|
||||
void* map_keys(void* self, void* array_type_box, void* string_type_box) {
|
||||
MapBox* map = (MapBox*)self;
|
||||
NyrtTypeBox* array_type = (NyrtTypeBox*)array_type_box;
|
||||
NyrtTypeBox* string_type = (NyrtTypeBox*)string_type_box;
|
||||
|
||||
// TypeBox検証
|
||||
if (!is_valid_typebox(array_type) || !is_valid_typebox(string_type)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// ArrayBox作成
|
||||
void* array = array_type->create();
|
||||
if (!array) return NULL;
|
||||
|
||||
// 各キーをStringBoxとして追加
|
||||
for (size_t i = 0; i < map->size; i++) {
|
||||
// 注:実際の実装では、ArrayBoxのpush APIを
|
||||
// 別途定義された方法で呼び出す必要があります
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
```
|
||||
|
||||
## 📝 まとめ:なぜTypeBoxが最適解なのか
|
||||
|
||||
### Geminiの結論
|
||||
> 「ご提案のTypeBoxアプローチは、NyashのC ABIにおけるBox生成ファクトリの設計として、これ以上ないほどシンプルかつ強力なものです。」
|
||||
|
||||
### Codexの結論
|
||||
> 「Keep the concept, refine it: the TypeBox pointer is the sweet spot — explicit, cheap, zero global cache thrash, and one function pointer."
|
||||
|
||||
### 設計の核心
|
||||
- **Everything is Box**: 型情報すらBoxとして扱う
|
||||
- **極限のシンプルさ**: 構造体1つ、関数ポインタ1つ
|
||||
- **明示的な依存**: すべて引数で渡す
|
||||
|
||||
## 🎯 成功指標
|
||||
|
||||
1. **機能性**: MapBox.keys()のようなクロスプラグインBox生成が動作
|
||||
2. **パフォーマンス**: 直接生成比1.2倍以内のオーバーヘッド(実測値)
|
||||
3. **シンプルさ**: 20行以内のコードで実装可能
|
||||
4. **保守性**: MIR層の変更不要
|
||||
|
||||
---
|
||||
|
||||
*「Everything is Box - 型情報すらBoxとして扱う」- TypeBoxアプローチ*
|
||||
@ -0,0 +1,13 @@
|
||||
# Nyash ABI 概要(統合ABIダイジェスト)
|
||||
|
||||
本ドキュメントは `UNIFIED-ABI-DESIGN.md` の要約です。詳細は統合仕様を参照してください。
|
||||
|
||||
- 目的: C ABI を維持しつつ、NyashValue(3×u64相当)でのゼロコピー呼び出しを段階導入
|
||||
- TypeBox: FQN/stable_id/vtable(C/Nyash) を束ねるディスクリプタ
|
||||
- 所有権: BORROW/TRANSFER/CLONE を明示(release責務の所在を固定)
|
||||
- 例外: C ABIはnothrow。越境例外は nyrt_err へ変換
|
||||
- ディスパッチ: Nyash vtable優先→C vtable/TLVフォールバック(VM/JIT共通)
|
||||
- 導入順序: TypeBoxレジストリ→統一ディスパッチ→Nyash ABI サンプル→最適化
|
||||
|
||||
このフェーズの実装タスクは [TASKS.md](./TASKS.md) を参照。
|
||||
|
||||
@ -0,0 +1,191 @@
|
||||
# C ABI プラグインシステム
|
||||
|
||||
## 📦 概要
|
||||
|
||||
C ABIは、Nyashの**基本プラグインシステム**です。C言語の標準的な関数呼び出し規約を使用し、高速かつ軽量な実装を提供します。
|
||||
|
||||
## 🎯 特徴
|
||||
|
||||
### シンプルさ
|
||||
- **たった3つの関数**で完全なプラグインが作れる
|
||||
- 複雑な型システムや継承は不要
|
||||
- C言語の知識があれば誰でも書ける
|
||||
|
||||
### 高速性
|
||||
- 直接的な関数ポインタ呼び出し
|
||||
- オーバーヘッドがほぼゼロ
|
||||
- JITコンパイラとの相性も抜群
|
||||
|
||||
### 安定性
|
||||
- C ABIは数十年の実績がある標準規格
|
||||
- プラットフォーム間での互換性が高い
|
||||
- バージョン間の互換性も維持しやすい
|
||||
|
||||
## 📝 基本実装
|
||||
|
||||
### 1. 最小限のプラグイン(3つの関数)
|
||||
|
||||
```c
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// 1. create関数:Boxを作成
|
||||
void* string_create(const char* initial_value) {
|
||||
char* str = malloc(strlen(initial_value) + 1);
|
||||
strcpy(str, initial_value);
|
||||
return str;
|
||||
}
|
||||
|
||||
// 2. method関数:メソッドを実行
|
||||
void* string_method(void* self, const char* method_name, void** args, int arg_count) {
|
||||
char* str = (char*)self;
|
||||
|
||||
if (strcmp(method_name, "length") == 0) {
|
||||
int* result = malloc(sizeof(int));
|
||||
*result = strlen(str);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (strcmp(method_name, "toUpperCase") == 0) {
|
||||
char* upper = malloc(strlen(str) + 1);
|
||||
for (int i = 0; str[i]; i++) {
|
||||
upper[i] = toupper(str[i]);
|
||||
}
|
||||
upper[strlen(str)] = '\0';
|
||||
return upper;
|
||||
}
|
||||
|
||||
return NULL; // メソッドが見つからない
|
||||
}
|
||||
|
||||
// 3. destroy関数:メモリを解放
|
||||
void string_destroy(void* self) {
|
||||
free(self);
|
||||
}
|
||||
```
|
||||
|
||||
### 2. プラグイン設定(nyash.toml)
|
||||
|
||||
```toml
|
||||
[[plugins]]
|
||||
name = "StringBox"
|
||||
path = "./string_plugin.so"
|
||||
type = "c-abi"
|
||||
version = 1
|
||||
|
||||
# メソッドの戻り値型を指定
|
||||
[plugins.methods]
|
||||
length = { returns = "integer" }
|
||||
toUpperCase = { returns = "string" }
|
||||
```
|
||||
|
||||
## 🔧 TLV(Type-Length-Value)形式
|
||||
|
||||
### 構造化データのやり取り
|
||||
|
||||
C ABIでは、複雑なデータをTLV形式でやり取りします:
|
||||
|
||||
```c
|
||||
// TLVヘッダー
|
||||
typedef struct {
|
||||
uint8_t type; // 1=bool, 2=i64, 3=f64, 5=string, 6=handle
|
||||
uint32_t length; // データ長
|
||||
// この後にデータが続く
|
||||
} TLVHeader;
|
||||
|
||||
// 複数の値を返す例
|
||||
void* math_stats(void* self, const char* method_name, void** args, int arg_count) {
|
||||
if (strcmp(method_name, "calculate") == 0) {
|
||||
// 3つの値を返す: [min, max, average]
|
||||
size_t total_size = sizeof(TLVHeader) * 3 + sizeof(double) * 3;
|
||||
uint8_t* buffer = malloc(total_size);
|
||||
uint8_t* ptr = buffer;
|
||||
|
||||
// min値
|
||||
TLVHeader* hdr1 = (TLVHeader*)ptr;
|
||||
hdr1->type = 3; // f64
|
||||
hdr1->length = sizeof(double);
|
||||
ptr += sizeof(TLVHeader);
|
||||
*(double*)ptr = 1.0;
|
||||
ptr += sizeof(double);
|
||||
|
||||
// 以下同様にmax値、average値を追加...
|
||||
|
||||
return buffer;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
```
|
||||
|
||||
## 🚀 TypeBox:C ABIの拡張メカニズム
|
||||
|
||||
### C ABIの限界を超える
|
||||
|
||||
C ABIだけでは、プラグイン間でBoxを生成することができません。例えば、MapBoxがArrayBoxを返したい場合、MapBoxはArrayBoxの実装を知らないため直接作成できません。
|
||||
|
||||
この問題を解決するのが**TypeBox**です。
|
||||
|
||||
### TypeBoxとは?
|
||||
|
||||
TypeBoxは「**型情報をBoxとして扱う**」という概念です。型の生成方法をBoxとして渡すことで、プラグイン間の連携を可能にします。
|
||||
|
||||
```c
|
||||
// TypeBox構造体:型情報をBoxとして扱う
|
||||
typedef struct {
|
||||
uint32_t abi_tag; // 'TYBX' (0x54594258)
|
||||
const char* name; // "ArrayBox"
|
||||
void* (*create)(void); // Box生成関数
|
||||
} TypeBox;
|
||||
|
||||
// MapBox.keys()の実装 - ArrayBoxのTypeBoxを引数で受け取る
|
||||
void* map_keys(void* self, void* array_type_box) {
|
||||
MapBox* map = (MapBox*)self;
|
||||
TypeBox* array_type = (TypeBox*)array_type_box;
|
||||
|
||||
// 検証
|
||||
if (!array_type || array_type->abi_tag != 0x54594258) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// ArrayBoxを生成(TypeBox経由)
|
||||
void* array = array_type->create();
|
||||
if (!array) return NULL;
|
||||
|
||||
// MapのキーをArrayに追加
|
||||
// (ArrayBoxのメソッドは別途C API経由で呼ぶ)
|
||||
|
||||
return array;
|
||||
}
|
||||
```
|
||||
|
||||
### TypeBoxの利点
|
||||
|
||||
1. **プラグイン間の疎結合**: 直接的な依存関係なし
|
||||
2. **型安全性**: abi_tagによる検証
|
||||
3. **拡張可能**: 新しいBox型の追加が容易
|
||||
4. **シンプル**: 構造体1つ、関数ポインタ1つ
|
||||
|
||||
## 💡 いつC ABIを使うべきか?
|
||||
|
||||
### C ABIが最適な場合
|
||||
- ✅ **シンプルな機能**を追加したい
|
||||
- ✅ **高速性**が重要
|
||||
- ✅ **安定性**を重視する
|
||||
- ✅ 既存のC/C++ライブラリをラップしたい
|
||||
|
||||
### C ABIでは難しい場合
|
||||
- ❌ 複雑な継承関係が必要
|
||||
- ❌ 他言語(Python/Go等)との相互運用
|
||||
- ❌ 動的な型変換が頻繁に必要
|
||||
|
||||
これらの場合は、C ABI + TypeBoxをベースに構築された**Nyash ABI**を検討してください。
|
||||
|
||||
## 📊 まとめ
|
||||
|
||||
C ABIは「**シンプル・高速・安定**」の3拍子が揃った、Nyashの基本プラグインシステムです。
|
||||
|
||||
- 最小3関数で実装可能
|
||||
- オーバーヘッドがほぼゼロ
|
||||
- TypeBoxによる拡張で、プラグイン間連携も可能
|
||||
|
||||
**迷ったらC ABIから始める**のが正解です!
|
||||
@ -0,0 +1,202 @@
|
||||
# Nyash ABI プラグインシステム
|
||||
|
||||
## 📦 概要
|
||||
|
||||
Nyash ABIは、**C ABI + TypeBoxをベースに構築された高度なプラグインシステム**です。C ABIの限界を超えて、より豊富な機能と言語間相互運用を提供します。
|
||||
|
||||
## 🏗️ アーキテクチャ
|
||||
|
||||
```
|
||||
基本層:C ABI(シンプル・高速・安定)
|
||||
↓
|
||||
拡張層:TypeBox(プラグイン間連携)
|
||||
↓
|
||||
高度層:Nyash ABI(言語間相互運用・拡張性)
|
||||
```
|
||||
|
||||
Nyash ABIは、C ABIとTypeBoxの上に構築されているため、既存のC ABIプラグインとの互換性を保ちながら、より高度な機能を提供できます。
|
||||
|
||||
## 🎯 特徴
|
||||
|
||||
### C ABIからの進化点
|
||||
|
||||
1. **セレクターベースの高速ディスパッチ**
|
||||
- 文字列比較ではなく、事前計算されたハッシュ値を使用
|
||||
- メソッド呼び出しの高速化
|
||||
|
||||
2. **NyashValue型による統一的な値表現**
|
||||
- 16バイトに最適化された値表現
|
||||
- インライン値サポート(小さな整数やboolは直接格納)
|
||||
|
||||
3. **言語間相互運用**
|
||||
- Python、Go、JavaScript等との連携が可能
|
||||
- 共通のオブジェクトモデルを提供
|
||||
|
||||
4. **高度なメモリ管理**
|
||||
- アトミック参照カウント
|
||||
- 弱参照による循環参照回避
|
||||
|
||||
## 📝 実装例
|
||||
|
||||
### 基本的なNyash ABIプラグイン
|
||||
|
||||
```c
|
||||
#include "nyash_abi.h"
|
||||
|
||||
// Nyash ABIオブジェクト構造体
|
||||
typedef struct {
|
||||
nyash_obj_header header; // 共通ヘッダー(参照カウント等)
|
||||
int value; // カスタムデータ
|
||||
} CounterBox;
|
||||
|
||||
// メソッドディスパッチャー(セレクターベース)
|
||||
nyash_status counter_call(
|
||||
nyash_ctx* ctx,
|
||||
void* self,
|
||||
nyash_selector selector,
|
||||
nyash_value* args,
|
||||
size_t arg_count,
|
||||
nyash_value* result
|
||||
) {
|
||||
CounterBox* counter = (CounterBox*)self;
|
||||
|
||||
// セレクターに基づいて高速ディスパッチ
|
||||
switch(selector) {
|
||||
case NYASH_SEL_INCREMENT: // 事前計算されたハッシュ値
|
||||
counter->value++;
|
||||
*result = nyash_make_int(counter->value);
|
||||
return NYASH_OK;
|
||||
|
||||
case NYASH_SEL_GET_VALUE:
|
||||
*result = nyash_make_int(counter->value);
|
||||
return NYASH_OK;
|
||||
|
||||
default:
|
||||
return NYASH_ERROR_METHOD_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### NyashValue - 統一的な値表現
|
||||
|
||||
```c
|
||||
// 16バイトに最適化された値構造(JIT/LLVM最適化を考慮)
|
||||
typedef struct __attribute__((aligned(16))) {
|
||||
uint64_t type_id; // 型識別子
|
||||
uint64_t payload; // ポインタまたはインライン値
|
||||
uint64_t metadata; // フラグ・追加情報
|
||||
} nyash_value;
|
||||
|
||||
// インライン値の例
|
||||
nyash_value nyash_make_int(int64_t value) {
|
||||
return (nyash_value){
|
||||
.type_id = NYASH_TYPE_INTEGER,
|
||||
.payload = (uint64_t)value,
|
||||
.metadata = NYASH_TAG_SMALL_INT // インライン整数タグ
|
||||
};
|
||||
}
|
||||
|
||||
// Boxオブジェクトの例
|
||||
nyash_value nyash_make_box(void* box_ptr) {
|
||||
return (nyash_value){
|
||||
.type_id = ((nyash_obj_header*)box_ptr)->type_id,
|
||||
.payload = (uint64_t)box_ptr,
|
||||
.metadata = NYASH_TAG_POINTER // ヒープポインタタグ
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## 🌐 言語間相互運用
|
||||
|
||||
### Python連携
|
||||
|
||||
```python
|
||||
# Python側のNyash ABIラッパー
|
||||
import nyash
|
||||
|
||||
# Nyashプラグインをロード
|
||||
counter = nyash.load_plugin("counter.so")
|
||||
|
||||
# セレクターベースの呼び出し
|
||||
result = counter.call("increment") # 内部でセレクターに変換
|
||||
print(f"Counter value: {result}")
|
||||
```
|
||||
|
||||
### Go連携
|
||||
|
||||
```go
|
||||
// Go側のNyash ABIバインディング
|
||||
package main
|
||||
|
||||
import "github.com/nyash/go-bindings"
|
||||
|
||||
func main() {
|
||||
counter := nyash.LoadPlugin("counter.so")
|
||||
|
||||
// 型安全な呼び出し
|
||||
value, err := counter.Call("increment")
|
||||
if err == nil {
|
||||
fmt.Printf("Counter value: %d\n", value.(int64))
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🚀 Nyash ABIがTypeBoxとして実装される仕組み
|
||||
|
||||
Nyash ABIの革新的な点は、**ABIそのものがTypeBoxとして実装される**ことです:
|
||||
|
||||
```c
|
||||
// Nyash ABIプロバイダーもTypeBox(C ABI)として提供
|
||||
typedef struct {
|
||||
// TypeBox標準ヘッダ
|
||||
uint32_t abi_tag; // 'NABI'
|
||||
const char* name; // "NyashABIProvider"
|
||||
void* (*create)(void); // ABIプロバイダ生成
|
||||
|
||||
// Nyash ABI専用操作
|
||||
struct {
|
||||
nyash_status (*call)(nyash_ctx*, void* obj, nyash_selector, ...);
|
||||
void (*retain)(void* obj);
|
||||
void (*release)(void* obj);
|
||||
} nyash_ops;
|
||||
} NyashABITypeBox;
|
||||
```
|
||||
|
||||
これにより:
|
||||
1. **段階的移行**: C ABIプラグインからNyash ABIへの移行が容易
|
||||
2. **相互運用**: C ABIとNyash ABIプラグインが同じシステムで共存
|
||||
3. **セルフホスティング**: 最終的にNyash自身でNyashを実装可能
|
||||
|
||||
## 💡 いつNyash ABIを使うべきか?
|
||||
|
||||
### Nyash ABIが最適な場合
|
||||
- ✅ **他言語との相互運用**が必要(Python/Go/JS等)
|
||||
- ✅ **高度なメソッドディスパッチ**が必要(セレクター方式)
|
||||
- ✅ **複雑な型システム**を扱う
|
||||
- ✅ **将来の拡張性**を重視
|
||||
|
||||
### C ABIで十分な場合
|
||||
- ✅ シンプルな機能のみ必要
|
||||
- ✅ 最高速度を求める(直接関数呼び出し)
|
||||
- ✅ 既存のC/C++ライブラリの単純なラップ
|
||||
|
||||
## 📊 3つのABIの比較
|
||||
|
||||
| 特徴 | C ABI | C ABI + TypeBox | Nyash ABI |
|
||||
|------|-------|-----------------|-----------|
|
||||
| シンプルさ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ |
|
||||
| 速度 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
|
||||
| プラグイン間連携 | ❌ | ✅ | ✅ |
|
||||
| 言語間連携 | ⭐⭐ | ⭐⭐ | ⭐⭐⭐⭐⭐ |
|
||||
| 拡張性 | ⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
|
||||
|
||||
## 📚 まとめ
|
||||
|
||||
Nyash ABIは「**C ABI + TypeBoxの上に構築された高度なプラグインシステム**」です。
|
||||
|
||||
- C ABIの安定性とシンプルさを継承
|
||||
- TypeBoxによるプラグイン間連携をサポート
|
||||
- セレクター方式による高速メソッドディスパッチ
|
||||
- 言語間相互運用による無限の可能性
|
||||
|
||||
**高度な機能や将来の拡張性が必要ならNyash ABI**を選びましょう!
|
||||
@ -0,0 +1,172 @@
|
||||
# Nyashスクリプトプラグイン革命:統合分析まとめ
|
||||
|
||||
## 🚀 革命的発見の本質
|
||||
|
||||
Nyashスクリプト自体でプラグインを作成できるという発見は、単なる機能追加ではなく、**Nyashの本質的な進化**を意味します。
|
||||
|
||||
### Everything is Boxの究極形
|
||||
|
||||
```
|
||||
従来: Box = Rust/C++実装のオブジェクト
|
||||
革命: Box = 実装言語を問わないインターフェース
|
||||
```
|
||||
|
||||
この発見により、「Everything is Box」哲学が実装レイヤーの制約から解放され、真の意味で実現されます。
|
||||
|
||||
## 🎯 両先生の分析の統合
|
||||
|
||||
### 共通の評価ポイント
|
||||
|
||||
1. **技術的妥当性**: 極めて高い実現可能性
|
||||
2. **エコシステムへの影響**: 開発者数の爆発的増加が期待
|
||||
3. **実装アプローチ**: 統一インターフェースによる透過的利用
|
||||
|
||||
### 相補的な視点
|
||||
|
||||
| 観点 | Gemini先生 | Codex先生 |
|
||||
|------|-----------|-----------|
|
||||
| 焦点 | 哲学的整合性・他言語事例 | 具体的実装・パフォーマンス |
|
||||
| 強み | エコシステム影響分析 | 技術アーキテクチャ設計 |
|
||||
| 提案 | 段階的ロードマップ | 詳細な実装戦略 |
|
||||
|
||||
## 📊 統合実装計画
|
||||
|
||||
### 即時着手(1-2週間)
|
||||
|
||||
1. **Box ABI仕様策定**
|
||||
- Gemini案のBoxInterfaceトレイト
|
||||
- Codex案のUnifiedBoxInterface
|
||||
- 両案を統合した最終仕様
|
||||
|
||||
2. **export box構文実装**
|
||||
```nyash
|
||||
export box PluginName {
|
||||
// 必須:メタデータ提供
|
||||
get_metadata() { ... }
|
||||
|
||||
// ビジネスロジック
|
||||
method1() { ... }
|
||||
method2() { ... }
|
||||
}
|
||||
```
|
||||
|
||||
3. **プロトタイプ実装**
|
||||
- MathBoxを統一インターフェースに移行
|
||||
- 簡単なNyashスクリプトプラグイン作成
|
||||
|
||||
### 中期目標(1-2ヶ月)
|
||||
|
||||
1. **動的プラグインシステム**
|
||||
- ホットリロード機能
|
||||
- 依存関係管理
|
||||
- バージョン互換性
|
||||
|
||||
2. **開発ツール整備**
|
||||
- プラグインテンプレート
|
||||
- デバッグツール
|
||||
- パフォーマンスプロファイラ
|
||||
|
||||
3. **セキュリティ基盤**
|
||||
- サンドボックス実装
|
||||
- ケイパビリティベース権限
|
||||
|
||||
### 長期ビジョン(6ヶ月-1年)
|
||||
|
||||
1. **プラグインエコシステム**
|
||||
- マーケットプレイス構築
|
||||
- 自動品質チェック
|
||||
- コミュニティガイドライン
|
||||
|
||||
2. **高度な最適化**
|
||||
- JIT統合
|
||||
- プリコンパイル機能
|
||||
- ネイティブ/スクリプトハイブリッド
|
||||
|
||||
## 🔑 成功の鍵
|
||||
|
||||
### 技術的成功要因
|
||||
|
||||
1. **シンプルな統一インターフェース**
|
||||
- 学習コストを最小化
|
||||
- 既存プラグインの移行を容易に
|
||||
|
||||
2. **段階的移行パス**
|
||||
- 既存のFFIプラグインと共存
|
||||
- 破壊的変更を避ける
|
||||
|
||||
3. **パフォーマンス配慮**
|
||||
- ホットパスはネイティブ維持
|
||||
- I/O boundタスクから適用
|
||||
|
||||
### エコシステム成功要因
|
||||
|
||||
1. **開発体験の劇的改善**
|
||||
- ビルド不要
|
||||
- 即座のフィードバック
|
||||
- 豊富なサンプル
|
||||
|
||||
2. **コミュニティ形成**
|
||||
- 初心者に優しいドキュメント
|
||||
- アクティブなサポート
|
||||
- 貢献への明確なパス
|
||||
|
||||
## 🎊 期待される成果
|
||||
|
||||
### 短期(3-6ヶ月)
|
||||
- プラグイン開発者: 10→100人
|
||||
- プラグイン数: 20→200個
|
||||
- 開発速度: 10倍向上
|
||||
|
||||
### 中期(1年)
|
||||
- 主要機能の8割がプラグイン化
|
||||
- サードパーティエコシステム確立
|
||||
- 企業採用事例の出現
|
||||
|
||||
### 長期(3年)
|
||||
- デファクトスタンダード化
|
||||
- 1000+のプラグイン
|
||||
- 自立的エコシステム
|
||||
|
||||
## 🏁 結論
|
||||
|
||||
Nyashスクリプトプラグインシステムは、**技術的に実現可能**であり、**戦略的に必須**の進化です。
|
||||
|
||||
「Everything is Box」哲学の真の実現により、Nyashは単なるプログラミング言語から、**次世代の拡張可能プラットフォーム**へと進化します。
|
||||
|
||||
### 合言葉
|
||||
|
||||
> **"Write plugins in Nyash, for Nyash, by Nyash!"**
|
||||
|
||||
この革命により、Nyashコミュニティは爆発的な成長を遂げ、真に民主的なプログラミングエコシステムが誕生するでしょう。
|
||||
|
||||
---
|
||||
|
||||
## 📎 付録:クイックスタートガイド
|
||||
|
||||
### 最初のスクリプトプラグイン(5分で作成)
|
||||
|
||||
```nyash
|
||||
# my_first_plugin.ny
|
||||
export box MyFirstPlugin {
|
||||
init {
|
||||
_name = "My First Plugin"
|
||||
_count = 0
|
||||
}
|
||||
|
||||
greet(name) {
|
||||
me._count = me._count + 1
|
||||
return "Hello, " + name + "! (call #" + me._count.toString() + ")"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 使用例
|
||||
|
||||
```nyash
|
||||
# main.ny
|
||||
local plugin = include("my_first_plugin.ny")
|
||||
print(plugin.greet("World")) // "Hello, World! (call #1)"
|
||||
print(plugin.greet("Nyash")) // "Hello, Nyash! (call #2)"
|
||||
```
|
||||
|
||||
**ビルド不要、即実行!** これがNyashスクリプトプラグインの力です。
|
||||
@ -0,0 +1,229 @@
|
||||
# Nyash ABIをC実装TypeBoxで提供する設計仕様書
|
||||
|
||||
## 🎯 概要
|
||||
|
||||
「Everything is Box」哲学の究極形:**ABIすらBoxとして扱う**
|
||||
|
||||
本設計は、Nyash ABIをTypeBox(C ABI)として実装することで、Rust依存を排除し、完全なセルフホスティングを実現する革新的アプローチです。
|
||||
|
||||
**3大AI専門家の評価:**
|
||||
- **Gemini**: 「技術的妥当性が高く、言語哲学とも合致した、極めて優れた設計」
|
||||
- **Codex**: 「Feasible and attractive: ABI-as-Box completes the idea」
|
||||
- **ChatGPT5**: 「実装に耐える設計。10の改善点で完璧」(統合ABI設計に反映済み)
|
||||
|
||||
## 📐 技術設計
|
||||
|
||||
### 基本アーキテクチャ
|
||||
|
||||
```c
|
||||
// nyash_abi_provider.h - Codex推奨の16バイトアライメント版
|
||||
typedef struct __attribute__((aligned(16))) {
|
||||
// TypeBox標準ヘッダ(バージョニング対応)
|
||||
uint32_t abi_tag; // 'NABI' (0x4942414E)
|
||||
uint16_t api_version; // APIバージョン
|
||||
uint16_t struct_size; // 構造体サイズ(互換性チェック用)
|
||||
const char* name; // "NyashABIProvider"
|
||||
void* (*create)(void); // プロバイダインスタンス生成
|
||||
|
||||
// Nyash ABI専用拡張(コンテキストベース)
|
||||
struct {
|
||||
// セレクターキャッシング対応
|
||||
nyash_status (*lookup_selector)(nyash_ctx*, uint64_t type_id, const char* name, nyash_selector* out);
|
||||
nyash_status (*call)(nyash_ctx*, void* obj, nyash_selector sel, nyash_value* argv, int argc, nyash_value* out);
|
||||
|
||||
// 基本操作
|
||||
nyash_status (*create_value)(nyash_ctx*, uint64_t type_id, void* data, uint64_t flags, nyash_value* out);
|
||||
void (*retain)(void* obj);
|
||||
void (*release)(void* obj);
|
||||
|
||||
// 型情報
|
||||
uint64_t (*type_of)(nyash_value value);
|
||||
bool (*is_null)(nyash_value value);
|
||||
bool (*eq)(nyash_value a, nyash_value b);
|
||||
uint64_t (*hash)(nyash_value value);
|
||||
} nyash_ops;
|
||||
|
||||
// 機能ビット(将来拡張用)
|
||||
uint64_t capabilities; // NYASH_CAP_ASYNC | NYASH_CAP_WEAKREF等
|
||||
void* reserved[4]; // 将来拡張用
|
||||
} NyashABITypeBox;
|
||||
```
|
||||
|
||||
### NyashValue - 16バイト最適化構造(Codex提案)
|
||||
|
||||
```c
|
||||
// JIT/LLVM最適化を考慮した16バイトアライメント
|
||||
typedef struct __attribute__((aligned(16))) {
|
||||
uint64_t type_id; // 型識別子(上位16bit: vendor, 8bit: kind)
|
||||
uint64_t payload; // ポインタまたはインライン値
|
||||
uint64_t metadata; // フラグ・追加情報(下位3bit: タグ)
|
||||
} nyash_value;
|
||||
|
||||
// メタデータタグ(Gemini提案のTagged Pointers)
|
||||
#define NYASH_TAG_POINTER 0x0 // ヒープオブジェクトへのポインタ
|
||||
#define NYASH_TAG_SMALL_INT 0x1 // 61ビット整数(符号付き)
|
||||
#define NYASH_TAG_BOOL 0x2 // 真偽値
|
||||
#define NYASH_TAG_NULL 0x3 // null
|
||||
#define NYASH_TAG_SMALL_ENUM 0x4 // 小さな列挙型
|
||||
```
|
||||
|
||||
### メモリ管理 - Intrusive参照カウント(Gemini詳細提案)
|
||||
|
||||
```c
|
||||
// すべてのヒープBoxの共通ヘッダ
|
||||
typedef struct {
|
||||
atomic_size_t ref_count; // アトミック参照カウント
|
||||
const nyash_obj_vtable* vtable; // メソッドテーブル
|
||||
uint64_t type_id; // 型識別子
|
||||
uint64_t flags; // THREAD_AFFINE等のフラグ
|
||||
|
||||
// 弱参照サポート(循環参照対策)
|
||||
struct weak_ref_list* weak_refs; // 弱参照リスト(オプション)
|
||||
} nyash_obj_header;
|
||||
|
||||
// Gemini推奨:弱参照による循環参照回避
|
||||
typedef struct {
|
||||
nyash_obj_header* target; // 対象オブジェクト(NULL可能)
|
||||
atomic_bool is_valid; // 有効性フラグ
|
||||
} nyash_weak_ref;
|
||||
```
|
||||
|
||||
### コンテキストベースAPI(Codex推奨)
|
||||
|
||||
```c
|
||||
// グローバル状態を避けるコンテキスト構造
|
||||
typedef struct {
|
||||
nyash_allocator* allocator; // カスタムアロケータ
|
||||
nyash_scheduler* scheduler; // スケジューラ(async用)
|
||||
void* tls; // スレッドローカルストレージ
|
||||
uint64_t feature_flags; // 機能フラグ
|
||||
nyash_error* last_error; // 最後のエラー
|
||||
} nyash_ctx;
|
||||
|
||||
// ステータスコード(例外を使わない)
|
||||
typedef enum {
|
||||
NYASH_OK = 0,
|
||||
NYASH_E_TYPE, // 型エラー
|
||||
NYASH_E_NULL, // NULL参照
|
||||
NYASH_E_BOUNDS, // 境界外アクセス
|
||||
NYASH_E_MEMORY, // メモリ不足
|
||||
NYASH_E_NOT_FOUND, // メソッド/プロパティ未定義
|
||||
} nyash_status;
|
||||
```
|
||||
|
||||
## 🚀 実装戦略(3段階)
|
||||
|
||||
### Phase 1: C Shim実装(1-2週間)
|
||||
既存Rust実装へのCラッパーとして開始:
|
||||
|
||||
```c
|
||||
// plugins/nyash_abi_c/src/shim.c
|
||||
nyash_status nyash_call_shim(nyash_ctx* ctx, void* obj,
|
||||
nyash_selector sel, nyash_value* argv,
|
||||
int argc, nyash_value* out) {
|
||||
// Rust FFI経由で既存実装を呼び出し
|
||||
extern nyash_status rust_nyash_call(/* ... */);
|
||||
return rust_nyash_call(ctx, obj, sel, argv, argc, out);
|
||||
}
|
||||
```
|
||||
|
||||
### Phase 2: フルC実装(1ヶ月)
|
||||
- 基本型(Integer/String/Bool/Array/Map)の完全実装
|
||||
- セレクターキャッシング機構
|
||||
- アトミック参照カウント + 弱参照
|
||||
- 型情報レジストリ
|
||||
|
||||
### Phase 3: Nyash再実装(2ヶ月)
|
||||
- C実装をNyashで書き直し
|
||||
- AOTコンパイルで同じC ABIを公開
|
||||
- セルフホスティング達成!
|
||||
|
||||
## 🔧 パフォーマンス最適化
|
||||
|
||||
### セレクターキャッシング(Codex提案)
|
||||
```c
|
||||
// 文字列ルックアップは初回のみ
|
||||
typedef struct {
|
||||
uint32_t vtable_slot; // 解決済みvtableスロット
|
||||
uint64_t cache_cookie; // インラインキャッシュ用
|
||||
} nyash_selector;
|
||||
|
||||
// JITは直接vtable_slotを使用可能
|
||||
```
|
||||
|
||||
### Tagged Pointers(Gemini提案)
|
||||
- 64bitポインタの下位3bitをタグとして活用
|
||||
- 小さな整数(61bit)、真偽値、nullをヒープ確保なしで表現
|
||||
- `metadata & 0x7`でタグ判定、分岐なしアンボックス可能
|
||||
|
||||
## 📊 テスト戦略
|
||||
|
||||
### 適合性テストスイート
|
||||
```bash
|
||||
tests/abi/
|
||||
├── conformance/ # ABI適合性テスト
|
||||
├── memory/ # 参照カウント・弱参照テスト
|
||||
├── threading/ # マルチスレッド安全性
|
||||
├── performance/ # ベンチマーク(1.5x以内目標)
|
||||
└── compatibility/ # Rust/C実装の差分テスト
|
||||
```
|
||||
|
||||
### ファジング(Codex提案)
|
||||
- `nyash_value`エンコード/デコード
|
||||
- `type_id`正規化
|
||||
- 循環参照パターン
|
||||
|
||||
## 🌟 技術的革新性
|
||||
|
||||
### 1. ABI as a Box
|
||||
「Everything is Box」哲学の完成形。ABIそのものがBoxとして扱われることで:
|
||||
- 実行時のABI切り替えが可能
|
||||
- デバッグ用ABI、プロファイリング用ABIの動的ロード
|
||||
- 異なるメモリ管理モデル(GC等)の実験が容易
|
||||
|
||||
### 2. セルフホスティングへの明確な道筋
|
||||
1. **Rust製コンパイラ** → **C ABI上のNyashコンパイラ**をビルド
|
||||
2. **Nyashコンパイラ** → **自分自身を再コンパイル**
|
||||
3. Rust依存完全排除!
|
||||
|
||||
### 3. 長期的保守性
|
||||
- C ABIは最も安定した普遍的インターフェース
|
||||
- プラットフォーム非依存
|
||||
- 30年後も動作する設計
|
||||
|
||||
## 📝 配布と使用
|
||||
|
||||
### nyash.toml設定
|
||||
```toml
|
||||
[plugins.hako_abi_provider]
|
||||
path = "plugins/nyash_abi_provider.so"
|
||||
abi = "c"
|
||||
types = ["NyashABIProvider"]
|
||||
capabilities = ["async", "weakref", "selector_cache"]
|
||||
```
|
||||
|
||||
### Nyashコードでの使用
|
||||
```nyash
|
||||
// ABIプロバイダーの取得
|
||||
local abiType = getTypeBox("NyashABIProvider")
|
||||
local abi = abiType.create()
|
||||
|
||||
// セレクターキャッシングを活用した高速呼び出し
|
||||
local strType = abi.lookupType("StringBox")
|
||||
local lengthSel = abi.lookupSelector(strType, "length")
|
||||
|
||||
local str = abi.createValue(strType, "Hello World")
|
||||
local len = abi.call(str, lengthSel, [])
|
||||
print(len) // 11
|
||||
```
|
||||
|
||||
## 🎯 まとめ
|
||||
|
||||
本設計により、Nyashは:
|
||||
- **Rust非依存**でセルフホスティング可能に
|
||||
- **「Everything is Box」哲学**を完全実現
|
||||
- **高性能**(Tagged Pointers、セレクターキャッシング)
|
||||
- **安全**(アトミック参照カウント、弱参照)
|
||||
- **拡張可能**(バージョニング、機能ビット)
|
||||
|
||||
これは単なる実装の変更ではなく、言語の哲学を技術で体現する、美しいアーキテクチャの完成です。
|
||||
@ -0,0 +1,356 @@
|
||||
# 統合ABI設計仕様書 v1.0 (2025-09-01)
|
||||
|
||||
## 🎯 概要
|
||||
|
||||
**革命的発見**: TypeBoxブリッジにより、C ABI + Nyash ABI統合プラグインシステムが実現可能!
|
||||
|
||||
Codex専門家分析により、既存のC ABIプラグインを維持しながら、型安全で高性能なNyash ABIプラグインを同一システムで運用する統合設計が確立されました。
|
||||
|
||||
### 設計哲学
|
||||
1. **既存を壊さない**: C ABIプラグインはそのまま動作
|
||||
2. **段階的進化**: プラグインごとに個別でABI選択可能
|
||||
3. **パフォーマンス**: Nyash ABI優先、必要時のみC ABIブリッジ
|
||||
4. **Everything is Box**: TypeBox自体もBox哲学に従う
|
||||
|
||||
## 📐 核心設計:統一TypeBoxディスクリプタ
|
||||
|
||||
### UnifiedTypeBox構造体(ChatGPT5改善版)
|
||||
|
||||
```c
|
||||
// crates/nyrt/include/nyrt_typebox.h
|
||||
#pragma pack(push, 8) // ABIアライメント固定
|
||||
|
||||
typedef struct {
|
||||
// ヘッダー(バージョン管理・互換性)
|
||||
uint32_t abi_tag; // 'TYBX' (0x54594258)
|
||||
uint16_t ver_major; // 1
|
||||
uint16_t ver_minor; // 0
|
||||
uint32_t size; // sizeof(nyrt_typebox) - 拡張互換性
|
||||
nyrt_abi_kind_t abi_kind; // C/Nyash/統合
|
||||
uint32_t callconv; // 呼び出し規約(Win/Linux差分)
|
||||
|
||||
// 型識別(衝突安全性強化)
|
||||
const char* name; // "nyash.core.Array" - FQN
|
||||
uint8_t stable_id[32]; // SHA-256ハッシュ(衝突耐性)
|
||||
uint64_t fast_key; // 高速ルックアップ用64bitキー
|
||||
|
||||
// スレッド安全性・最適化ヒント
|
||||
uint32_t flags; // THREAD_SAFE/IMMUTABLE/REENTRANT/MAY_BLOCK
|
||||
uint32_t align; // アライメントヒント
|
||||
|
||||
// ABI別vtable(nullable)
|
||||
const nyrt_c_vtable* c; // C ABI vtable
|
||||
const nyrt_ny_vtable* ny; // Nyash ABI vtable
|
||||
|
||||
// メタデータ
|
||||
nyrt_type_meta meta; // JSON/CBOR形式
|
||||
const void* user_data; // プラグイン定義データ
|
||||
} nyrt_typebox;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
// ABIサイズ検証(コンパイル時)
|
||||
_Static_assert(sizeof(nyrt_typebox) <= 128, "TypeBox size too large");
|
||||
```
|
||||
|
||||
### ABI種別とvtable(ChatGPT5強化版)
|
||||
|
||||
```c
|
||||
// ABI種別定義
|
||||
typedef enum {
|
||||
NYRT_ABI_NONE = 0,
|
||||
NYRT_ABI_C = 1, // C ABIのみ
|
||||
NYRT_ABI_NYASH = 2, // Nyash ABIのみ
|
||||
NYRT_ABI_UNIFIED = 3 // 両方サポート
|
||||
} nyrt_abi_kind_t;
|
||||
|
||||
// 呼び出し規約(プラットフォーム差分対応)
|
||||
typedef enum {
|
||||
NYRT_CALLCONV_SYSTEMV = 1, // Linux/Unix標準
|
||||
NYRT_CALLCONV_WIN64 = 2, // Windows x64
|
||||
NYRT_CALLCONV_FASTCALL = 3 // Windows最適化
|
||||
} nyrt_callconv_t;
|
||||
|
||||
// エラーコード(厳密化)
|
||||
typedef int32_t nyrt_err;
|
||||
#define NYRT_OK 0
|
||||
#define NYRT_E_ARG 1 // 引数エラー
|
||||
#define NYRT_E_TYPE 2 // 型エラー
|
||||
#define NYRT_E_STATE 3 // 状態エラー
|
||||
#define NYRT_E_OOM 4 // メモリ不足
|
||||
#define NYRT_E_ABORT 5 // 致命的エラー
|
||||
|
||||
// 所有権契約(明文化)
|
||||
typedef enum {
|
||||
NYRT_OWN_BORROW = 0, // 借用(呼び出し期間のみ有効)
|
||||
NYRT_OWN_TRANSFER = 1, // 所有権移譲(受け取り側がrelease)
|
||||
NYRT_OWN_CLONE = 2 // クローン(コピー、独立管理)
|
||||
} nyrt_ownership;
|
||||
|
||||
// スレッド安全性フラグ
|
||||
#define NYRT_FLAG_THREAD_SAFE 0x0001 // スレッドセーフ
|
||||
#define NYRT_FLAG_IMMUTABLE 0x0002 // 不変オブジェクト
|
||||
#define NYRT_FLAG_REENTRANT 0x0004 // 再帰呼び出し可能
|
||||
#define NYRT_FLAG_MAY_BLOCK 0x0008 // 長時間処理(GCセーフポイント必要)
|
||||
|
||||
// C ABI vtable: nothrow保証・所有権明確化
|
||||
typedef struct {
|
||||
// ライフサイクル(すべてnothrow)
|
||||
void* (*create)(void* env); // 例外禁止
|
||||
void (*retain)(void* instance); // 参照カウント増加
|
||||
void (*release)(void* instance); // 参照カウント減少
|
||||
|
||||
// NyashValue ↔ void* 変換(所有権明示)
|
||||
nyrt_err (*to_nyash)(const void* instance, nyrt_nyash_value* out, nyrt_ownership* own);
|
||||
nyrt_err (*from_nyash)(nyrt_nyash_value val, void** out, nyrt_ownership* own);
|
||||
|
||||
// メソッド呼び出し(nothrow、GCセーフポイント配慮)
|
||||
nyrt_err (*invoke_by_id)(void* instance, nyrt_method_id method,
|
||||
const void* const* argv, size_t argc,
|
||||
void** ret_out, nyrt_ownership* ret_own);
|
||||
|
||||
// フォールバック(ID不明時)
|
||||
nyrt_err (*invoke_by_name)(void* instance, const char* method_name,
|
||||
const void* const* argv, size_t argc,
|
||||
void** ret_out, nyrt_ownership* ret_own);
|
||||
} nyrt_c_vtable;
|
||||
|
||||
// Nyash ABI vtable: ネイティブNyashValue
|
||||
typedef struct {
|
||||
// ライフサイクル
|
||||
nyrt_nyash_value (*create)(void* ctx);
|
||||
void (*retain)(nyrt_nyash_value v);
|
||||
void (*release)(nyrt_nyash_value v);
|
||||
|
||||
// 直接NyashValueでメソッド呼び出し
|
||||
nyrt_err (*invoke_by_id)(nyrt_nyash_value* this_val, nyrt_method_id method,
|
||||
const nyrt_nyash_value* args, size_t argc,
|
||||
nyrt_nyash_value* ret_out);
|
||||
|
||||
nyrt_err (*invoke_by_name)(nyrt_nyash_value* this_val, const char* method_name,
|
||||
const nyrt_nyash_value* args, size_t argc,
|
||||
nyrt_nyash_value* ret_out);
|
||||
} nyrt_ny_vtable;
|
||||
```
|
||||
|
||||
## 🛡️ ChatGPT5安全性強化(10の重要改善)
|
||||
|
||||
### 1. ID衝突安全性
|
||||
- **SHA-256ハッシュ**: 64bitから256bitへ強化(衝突耐性)
|
||||
- **高速キー併用**: 64bit fast_keyでホットパス最適化
|
||||
- **重複登録拒否**: 同一type_idの重複をランタイムで検出・拒否
|
||||
|
||||
### 2. 所有権契約の明文化
|
||||
```c
|
||||
// 所有権と解放責務の明確な定義
|
||||
NYRT_OWN_BORROW = 0, // 呼び出し期間のみ有効、releaseしない
|
||||
NYRT_OWN_TRANSFER = 1, // 受け取り側がrelease責務を負う
|
||||
NYRT_OWN_CLONE = 2 // 独立コピー、各々がrelease
|
||||
```
|
||||
|
||||
### 3. 例外/パニック越境禁止
|
||||
- **C ABIは完全nothrow**: すべての関数で例外禁止
|
||||
- **Nyash側例外捕捉**: パニック → nyrt_err変換
|
||||
- **境界ガード**: `try-catch`でC/Nyash境界を保護
|
||||
|
||||
### 4. GC/セーフポイント規則
|
||||
```rust
|
||||
// MAY_BLOCKフラグ付きC ABI呼び出し前後
|
||||
if type_info.flags & NYRT_FLAG_MAY_BLOCK != 0 {
|
||||
vm.gc_safepoint_enter();
|
||||
let result = c_vtable.invoke_by_id(...);
|
||||
vm.gc_safepoint_exit();
|
||||
}
|
||||
```
|
||||
|
||||
### 5. プラグイン初期化と互換性交渉
|
||||
```c
|
||||
// プラグインエントリーポイント
|
||||
NYRT_EXPORT nyrt_err nyash_plugin_init(const nyrt_host*, const nyrt_runtime_info*);
|
||||
NYRT_EXPORT const nyrt_typebox** nyash_typeboxes(size_t* count);
|
||||
|
||||
// バージョン確認必須
|
||||
typedef struct {
|
||||
uint16_t size; // 構造体サイズ
|
||||
uint16_t ver_major; // メジャーバージョン
|
||||
uint16_t ver_minor; // マイナーバージョン
|
||||
uint16_t reserved;
|
||||
} nyrt_runtime_info;
|
||||
```
|
||||
|
||||
### 6. NyashValueインライン表現
|
||||
```c
|
||||
// インライン値エンコーディング規則
|
||||
typedef struct {
|
||||
uint64_t type_id; // 型識別子
|
||||
uint64_t box_handle; // ポインタ or インライン値
|
||||
uint64_t metadata; // INLINEフラグ + 追加情報
|
||||
} nyrt_nyash_value;
|
||||
|
||||
#define NYASH_META_INLINE 0x0001 // box_handleがインライン値
|
||||
#define NYASH_META_ASYNC 0x0002 // 非同期結果
|
||||
#define NYASH_META_ERROR 0x0010 // エラー値
|
||||
```
|
||||
|
||||
## 🔄 統一ディスパッチ戦略
|
||||
|
||||
### VM層での透明なABI選択
|
||||
|
||||
```rust
|
||||
// src/runtime/unified_dispatch.rs
|
||||
pub fn call_with_typebox(
|
||||
method: MethodId,
|
||||
this_ty: &TypeBoxInfo,
|
||||
this_val: NyashValue,
|
||||
args: &[NyashValue],
|
||||
) -> Result<NyashValue, NyError> {
|
||||
// Nyash ABI優先(ゼロコストパス)
|
||||
if let Some(ny) = &this_ty.ny {
|
||||
return ny.invoke_by_id(this_val, method, args);
|
||||
}
|
||||
|
||||
// C ABIブリッジ(必要時のみ)
|
||||
let c = this_ty.c.as_ref().ok_or(NyError::MissingVTable)?;
|
||||
let (this_ptr, this_own) = c.from_nyash(this_val)?;
|
||||
let (argv, arena) = marshal_args_to_c(args, c)?;
|
||||
let (ret_ptr, ret_own) = c.invoke_by_id(this_ptr, method, &argv)?;
|
||||
let ret = c.to_nyash(ret_ptr, ret_own)?;
|
||||
|
||||
Ok(ret)
|
||||
}
|
||||
```
|
||||
|
||||
### 7. ホストコールバック(プラグイン支援)
|
||||
```c
|
||||
// プラグインが使える安全なホスト機能
|
||||
typedef struct {
|
||||
uint16_t size; // 構造体サイズ
|
||||
void* (*host_alloc)(size_t); // メモリ確保
|
||||
void (*host_free)(void*); // メモリ解放
|
||||
void (*log)(int level, const char* msg); // ログ出力
|
||||
nyrt_err (*gc_safepoint)(void); // GCセーフポイント
|
||||
} nyrt_host;
|
||||
```
|
||||
|
||||
### 8. セキュリティ/不正プラグイン対策
|
||||
- **TypeBox検証**: abi_tag、サイズ、バージョンの完全性確認
|
||||
- **重複登録拒否**: 同一名前・type_idの重複を検出
|
||||
- **境界チェック**: user_dataのサイズ・内容検証
|
||||
- **Capability予約**: 将来のファイル/ネット権限制御用フラグ
|
||||
|
||||
### 9. プラグインアンロード安全性
|
||||
```rust
|
||||
// プラグインアンロード前の安全確認
|
||||
fn can_unload_plugin(plugin_id: &str) -> bool {
|
||||
let live_instances = registry.count_live_instances(plugin_id);
|
||||
live_instances == 0 // 生存インスタンスがない場合のみアンロード可能
|
||||
}
|
||||
```
|
||||
|
||||
### 10. テスト戦略(ChatGPT5推奨)
|
||||
- **ABIクロスパリティ**: 同一Box実装(C/Nyash/Unified)で結果一致
|
||||
- **所有権ファズ**: Borrow/Transfer/Clone組み合わせでリーク検出
|
||||
- **呼び出し規約クロス**: Win(Fastcall)↔Linux(SystemV)結果一致
|
||||
- **性能目標**: Nyash ABI = 1.0x、C ABIブリッジ ≤ 1.5x
|
||||
|
||||
## 📝 nyash.toml v3.0設定
|
||||
|
||||
```toml
|
||||
# 統一プラグイン設定
|
||||
[plugins.map_simple]
|
||||
path = "plugins/map.so"
|
||||
abi = "c" # C ABIのみ
|
||||
types = ["nyash.core.Map"]
|
||||
|
||||
[plugins.map_advanced]
|
||||
path = "plugins/advanced_map.so"
|
||||
abi = "nyash" # Nyash ABIのみ
|
||||
types = ["nyash.core.Map"]
|
||||
|
||||
[plugins.map_hybrid]
|
||||
path = "plugins/hybrid_map.so"
|
||||
abi = "unified" # 両方サポート(Nyash優先)
|
||||
types = ["nyash.core.Map", "nyash.core.Array"]
|
||||
symbols.boxes = "nyash_typeboxes"
|
||||
symbols.init = "nyash_plugin_init"
|
||||
```
|
||||
|
||||
## ⚡ パフォーマンス最適化
|
||||
|
||||
### 1. IDベースディスパッチ
|
||||
- 型ID: 64bit安定ハッシュ(FQN + 型引数)
|
||||
- メソッドID: 64bitハッシュ(シグネチャ)
|
||||
- ホットパスで文字列ハッシュ回避
|
||||
|
||||
### 2. インライン値サポート
|
||||
```c
|
||||
// NyashValue(Nyash ABI)
|
||||
typedef struct {
|
||||
uint64_t type_id; // 型識別子
|
||||
uint64_t box_handle; // Arc<Box>ポインタ or インライン値
|
||||
uint64_t metadata; // INLINEフラグ等
|
||||
} NyashValue;
|
||||
|
||||
#define NYASH_META_INLINE 0x0001 // box_handleがインライン値
|
||||
```
|
||||
|
||||
### 3. ゼロコピーブリッジ
|
||||
- 所有権フラグ(BORROW/PLUGIN/HOST)で適切な参照管理
|
||||
- 不要なコピー回避
|
||||
- retain/releaseの最適化
|
||||
|
||||
## 🏗️ 実装ロードマップ
|
||||
|
||||
### Phase 1: TypeBox統合基盤(1週間)
|
||||
- [ ] nyrt_typebox.h完全定義
|
||||
- [ ] Rust FFIミラー(crates/nyrt/src/typebox.rs)
|
||||
- [ ] UnifiedPluginRegistry実装
|
||||
|
||||
### Phase 2: 実証実装(2週間)
|
||||
- [ ] MapBoxの両ABI実装
|
||||
- [ ] 統一ディスパッチテスト
|
||||
- [ ] パフォーマンスベンチマーク
|
||||
|
||||
### Phase 3: プロダクション化(3週間)
|
||||
- [ ] nyash.toml v3.0パーサー
|
||||
- [ ] プラグイン移行ガイドライン
|
||||
- [ ] デバッグツール整備
|
||||
|
||||
## 🎯 成功指標
|
||||
|
||||
1. **機能性**: MapBox.keys()がArrayBoxを返す(両ABI対応)
|
||||
2. **パフォーマンス**: Nyash ABIで直接呼び出し、C ABIで1.5倍以内
|
||||
3. **互換性**: 既存C ABIプラグインがそのまま動作
|
||||
4. **拡張性**: 新しいABI追加が容易
|
||||
|
||||
## 🌟 なぜ統合が可能になったのか
|
||||
|
||||
### TypeBoxの革命的価値
|
||||
1. **型情報の統一表現**: Everything is Box哲学の完全実現
|
||||
2. **ABI間ブリッジ**: 異なるABI間の透明な変換
|
||||
3. **バージョン管理**: 前方互換性のある拡張メカニズム
|
||||
4. **段階的移行**: 破壊的変更なしの進化
|
||||
|
||||
### 3大AI専門家の一致した結論
|
||||
|
||||
**Codex専門家分析**:
|
||||
> 「TypeBoxを汎用ブリッジとして使用する統合設計は、
|
||||
> 安定性・パフォーマンス・拡張性のすべてを満たす理想的なアーキテクチャ」
|
||||
|
||||
**ChatGPT5専門家分析**:
|
||||
> 「方向性は合ってるし、実装に耐える設計。10の改善点で
|
||||
> 衝突安全性・所有権・セキュリティが完璧になる」
|
||||
|
||||
**設計の確実性**: 3つのAIシステムが独立に同じ結論に到達
|
||||
|
||||
## 🚀 次のステップ(ChatGPT5推奨)
|
||||
|
||||
1. **nyrt_typebox.h実装** - 完全なヘッダー定義
|
||||
2. **MapBox両ABI実装** - 実証実装でパリティ確認
|
||||
3. **所有権ファズテスト** - メモリリーク検出
|
||||
4. **パフォーマンス測定** - 1.5x以内目標達成確認
|
||||
|
||||
---
|
||||
|
||||
*Everything is Box - 型情報も、ABI情報も、すべてがBoxとして統一される世界*
|
||||
*3大AI専門家による完全検証済み設計 ✅*
|
||||
131
docs/archive/roadmap/phases/phase-12/design/WHY-AIS-FAILED.md
Normal file
131
docs/archive/roadmap/phases/phase-12/design/WHY-AIS-FAILED.md
Normal file
@ -0,0 +1,131 @@
|
||||
# なぜ天才AIたちは間違えたのか - Phase 12の教訓
|
||||
|
||||
## 🤔 根本的な誤解
|
||||
|
||||
### AIたちの誤解
|
||||
```
|
||||
「スクリプトプラグイン」という特別な仕組みが必要
|
||||
→ JIT/AOTから呼び出せない問題がある
|
||||
→ 複雑な解決策が必要
|
||||
```
|
||||
|
||||
### 実際の真実
|
||||
```
|
||||
Nyashスクリプト = 普通のユーザー定義Box
|
||||
→ すでに動いている
|
||||
→ 何も問題ない
|
||||
```
|
||||
|
||||
## 💡 なぜこんな誤解が生まれたのか
|
||||
|
||||
### 1. 「プラグイン」という言葉の罠
|
||||
- AI思考:「プラグイン = 外部DLL/SO = 特別な仕組み」
|
||||
- 実際:「プラグイン = 再利用可能なBox = 普通のユーザー定義Box」
|
||||
|
||||
### 2. 実装レイヤーの混同
|
||||
```
|
||||
AIの頭の中:
|
||||
┌─────────────────────┐
|
||||
│ JIT/AOT (最適化層) │ ← ここに固執
|
||||
├─────────────────────┤
|
||||
│ C ABI プラグイン │
|
||||
├─────────────────────┤
|
||||
│ スクリプトプラグイン │ ← 新しい層を作ろうとした
|
||||
└─────────────────────┘
|
||||
|
||||
実際のNyash:
|
||||
┌─────────────────────┐
|
||||
│ Nyash VM/インタープリター │
|
||||
├─────────────────────┤
|
||||
│ すべてがBox(統一層)│
|
||||
│ - ビルトインBox │
|
||||
│ - C ABIプラグイン │
|
||||
│ - ユーザー定義Box │ ← これだけで十分!
|
||||
└─────────────────────┘
|
||||
```
|
||||
|
||||
### 3. 過度な最適化思考
|
||||
- AI:「JIT/AOTで高速化しなければ!」
|
||||
- 実際:「インタープリター言語として十分高速」
|
||||
|
||||
### 🚀 なぜスクリプトファイルでも高速なのか
|
||||
|
||||
**重要な真実:NyashはAOT/JITをサポートしている!**
|
||||
|
||||
```bash
|
||||
# スクリプトファイルをAOTコンパイル可能
|
||||
./nyash --aot script.hako -o script.exe
|
||||
|
||||
# JITで実行(ホットコードを自動最適化)
|
||||
./nyash --backend vm --jit script.hako
|
||||
```
|
||||
|
||||
つまり:
|
||||
1. **開発時**: スクリプトファイルで即座に実行・修正
|
||||
2. **本番時**: AOTコンパイルで最高速度
|
||||
3. **中間**: JITで自動的に最適化
|
||||
|
||||
**スクリプト言語の利便性 + ネイティブコードの速度 = 両方手に入る!**
|
||||
|
||||
### 4. Everything is Boxの哲学を忘れた
|
||||
```nyash
|
||||
# これが既に「スクリプトプラグイン」!
|
||||
box DataProcessor {
|
||||
init {
|
||||
me.file = new FileBox() # C ABIプラグイン
|
||||
me.math = new MathBox() # C ABIプラグイン
|
||||
me.cache = new MapBox() # ビルトインBox
|
||||
}
|
||||
|
||||
process(data) {
|
||||
# 全部普通に動く!
|
||||
local result = me.math.sin(data)
|
||||
me.file.write("log.txt", result.toString())
|
||||
return result
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🎓 教訓
|
||||
|
||||
### 1. シンプルな解決策を見逃すな
|
||||
- 複雑な問題に見えても、既存の仕組みで解決できることが多い
|
||||
- 「Everything is Box」は強力な統一原理
|
||||
|
||||
### 2. 言葉に惑わされるな
|
||||
- 「プラグイン」→「特別な仕組み」という連想を避ける
|
||||
- 本質を見る:「再利用可能なコード」
|
||||
|
||||
### 3. ユーザー視点を忘れるな
|
||||
```nyash
|
||||
# ユーザーから見れば、これで十分!
|
||||
local processor = new DataProcessor()
|
||||
local result = processor.process(3.14)
|
||||
```
|
||||
|
||||
### 4. AIの弱点
|
||||
- 技術用語から過度に複雑な解釈をしがち
|
||||
- 既存の解決策より新しい仕組みを作りたがる
|
||||
- レイヤーを増やしたがる傾向
|
||||
|
||||
## 📝 Phase 12の本当の価値
|
||||
|
||||
### 実は必要なのは
|
||||
1. **export/import構文**(ファイル間でBoxを共有)
|
||||
2. **パッケージマネージャー**(Boxの配布・インストール)
|
||||
3. **ドキュメント生成**(Boxの使い方を共有)
|
||||
|
||||
### 必要ないもの
|
||||
- 特別な「スクリプトプラグイン」層
|
||||
- JIT/AOT統合
|
||||
- 複雑なトランスパイル
|
||||
|
||||
## 🚀 結論
|
||||
|
||||
**Nyashは最初から正しかった。Everything is Boxだから、すべてが統一的に動く。**
|
||||
|
||||
AIたちは「プラグイン」という言葉に惑わされて、存在しない問題を解決しようとしていた。
|
||||
|
||||
---
|
||||
|
||||
*時に、最も賢い解決策は「何もしないこと」である。*
|
||||
@ -0,0 +1,87 @@
|
||||
# Nyash ABI戦略議論まとめ (2025-09-01)
|
||||
|
||||
## 📋 概要
|
||||
|
||||
Phase 12のプラグインシステム実装において、C ABIとNyash ABIの選択について、AI先生方と深い技術議論を行いました。
|
||||
|
||||
## 🗂️ ドキュメント一覧
|
||||
|
||||
1. **[gemini-abi-analysis.md](gemini-abi-analysis.md)**
|
||||
- Gemini先生の長期エコシステム視点
|
||||
- ABI安定性の重要性
|
||||
- 段階的進化戦略(C ABI → SDK → WASM)
|
||||
|
||||
2. **[codex-abi-implementation.md](codex-abi-implementation.md)**
|
||||
- Codex先生の実装最適化視点
|
||||
- C呼出規約×Nyash値表現の提案
|
||||
- VM/JIT最適化の具体策
|
||||
|
||||
3. **[deep-analysis-synthesis.md](deep-analysis-synthesis.md)**
|
||||
- なぜ正解が難しいのかの深い分析
|
||||
- 時間軸のジレンマ
|
||||
- 「正解がない」ことが答え
|
||||
|
||||
## 🎯 結論:BoxCall拡張による統合案
|
||||
|
||||
### 最終的な実装方針
|
||||
|
||||
```rust
|
||||
// MIRレベル:BoxCallをちょっと拡張
|
||||
MirInstruction::BoxCall {
|
||||
receiver: Value,
|
||||
method: String,
|
||||
args: Vec<Value>,
|
||||
abi_hint: Option<AbiType>, // ← これだけ追加
|
||||
}
|
||||
```
|
||||
|
||||
### 利点
|
||||
|
||||
1. **MIR命令数は15個のまま**(美しさ維持)
|
||||
2. **既存コードは変更不要**(後方互換)
|
||||
3. **プラグインごとにABI選択可能**(段階的移行)
|
||||
4. **Everything is Box哲学の体現**
|
||||
|
||||
### 実装計画
|
||||
|
||||
```yaml
|
||||
Week 1: 基盤整備
|
||||
- PluginABI enum定義
|
||||
- nyash.tomlのabi field追加
|
||||
- NyashValue構造体作成
|
||||
|
||||
Week 2: VM統合
|
||||
- プラグインローダー拡張
|
||||
- VM実行時のABI分岐
|
||||
- pack/unpack実装
|
||||
|
||||
Week 3: 検証
|
||||
- 比較ベンチマーク
|
||||
- ドキュメント作成
|
||||
- 方向性判断
|
||||
```
|
||||
|
||||
## 🔑 重要な洞察
|
||||
|
||||
1. **両ABI共存が現実的**
|
||||
- C ABI:既存資産・高速・安定
|
||||
- Nyash ABI:型安全・拡張性・将来性
|
||||
|
||||
2. **適応的戦略の採用**
|
||||
- 3ヶ月ごとに測定・評価
|
||||
- データに基づく進化
|
||||
|
||||
3. **箱理論による差し替え可能性**
|
||||
- 実装を箱に切り出す
|
||||
- いつでも戻せる安心感
|
||||
|
||||
## 📊 次のステップ
|
||||
|
||||
1. このREADMEを起点に実装開始
|
||||
2. 最小限のプロトタイプ作成
|
||||
3. 性能・開発体験の比較データ収集
|
||||
4. Phase 12本実装への反映
|
||||
|
||||
---
|
||||
|
||||
*「間に挟むだけ」が最も難しい設計判断だった。しかし、BoxCall拡張という自然な解決策にたどり着いた。*
|
||||
@ -0,0 +1,124 @@
|
||||
# Codex先生のNyash ABI実装戦略 (2025-09-01)
|
||||
|
||||
## 質問内容
|
||||
|
||||
Nyashプラグインシステムの ABI戦略について技術的相談です。
|
||||
|
||||
【背景】
|
||||
Phase 12でNyashスクリプトプラグインシステムを実装中です。現在、プラグインインターフェースの設計で重要な判断が必要です。
|
||||
|
||||
【現状】
|
||||
- 既存: C ABI(シンプル、高速、実績あり)
|
||||
- 提案: Nyash ABI(3×u64構造体、型情報付き、拡張性高い)
|
||||
|
||||
【トレードオフ】
|
||||
C ABI:
|
||||
- 利点: ゼロオーバーヘッド、既存資産活用、シンプル
|
||||
- 欠点: 型情報なし、拡張性限定、エラー処理が原始的
|
||||
|
||||
Nyash ABI:
|
||||
- 利点: 型安全、メタデータ活用、将来性(async等)
|
||||
- 欠点: pack/unpackのオーバーヘッド、新規学習コスト
|
||||
|
||||
【具体的な選択肢】
|
||||
1. Nyash ABIのみ(統一性重視)
|
||||
2. C ABI + Nyash ABI両方(実用性重視)
|
||||
3. その他の革新的アプローチ?
|
||||
|
||||
【質問】
|
||||
1. どちらの戦略が長期的に見て賢明でしょうか?
|
||||
2. 両方サポートする場合の複雑性は管理可能でしょうか?
|
||||
3. 他の言語での成功例・失敗例から学べることは?
|
||||
4. VM/JIT最適化の観点から、どちらが有利でしょうか?
|
||||
|
||||
実装の実践的観点から、C ABIとNyash ABIの選択について深く分析してください。特にVM/JIT最適化や実装の複雑性を考慮して。
|
||||
|
||||
## Codex先生の回答
|
||||
|
||||
**結論**
|
||||
- 長期的には「C呼出規約 × Nyash値表現(3×u64)」を中核に、C ABIとNyash ABIの両方をサポートする二層戦略が最も堅実。
|
||||
- まずは二者併存で運用し、JIT/VMでの最適化余地と実用性を確保しながら、将来的にNyash ABIを第一級に育てるのが現実的。
|
||||
|
||||
**推奨戦略**
|
||||
- 両対応(2)を採用。ただし"呼出規約はC、値表現はNyash"を共通土台にする。
|
||||
- 共通の値ABI: `#[repr(C)] struct NyValue { u64 tag; u64 payload; u64 aux; }`
|
||||
- C ABI関数でもNyValueを受け渡しできるため、型安全・メタデータ拡張の道を確保しつつ、Cの安定性・高速性を得る。
|
||||
- プラグイン初期化は「バージョン付き関数テーブル(vtable)+機能フラグ」の交渉型にする。
|
||||
- 例: `NyPluginInitV1(NyRtFnsV1* rt, NyPluginV1* out)` → `NyPluginV1 { u32 abi_mask; u32 size; NyFnDesc* fns; ... }`
|
||||
- `abi_mask`で `NY_ABI_C` と `NY_ABI_NYV1` の両方可否を示す。将来の `NY_ABI_NYV2` も追加可能。
|
||||
- エラーモデルは二段階:
|
||||
- 速経路: `NyStatus`(enum, small int)を戻す。失敗時は`NyValue`でエラーオブジェクトをout-param返却。
|
||||
- 詳細情報は`NyError`ヘルパ(`NyValue`として表現)に格納。FFI境界でpanic禁止・例外横断なし。
|
||||
- メモリ/所有権はハンドル/関数テーブル経由で統一(NyRTのalloc/free、string/slice作成API)。内部構造体への直接依存は不可。
|
||||
|
||||
**複雑性と管理**
|
||||
- 追加コストは主にローダとアダプタ(トランポリン)実装+テスト行列の増加。ただし次の工夫で管理可能:
|
||||
- 機能交渉を一本化(init関数とマニフェスト/nyash.tomlで表明)。ロード時に一度だけ決定。
|
||||
- 呼出アダプタをテンプレート化/JIT時に生成・キャッシュ(型配列→シグネチャ→thunkアドレス)。
|
||||
- 型表(`NyFnDesc`に引数/戻りの型ID配列、純関数/readonly/aliasing属性)を持ち、最適化と検証を兼用。
|
||||
- 見積り:ローダ+vtable+アダプタの骨格は数百行〜千行弱で収まり、以降は関数種別追加が足し算。
|
||||
|
||||
**他言語の事例からの学び**
|
||||
- 成功例
|
||||
- Node N-API: バージョン化された関数テーブルでABIを安定化。実装側の進化と互換の両立に有効。
|
||||
- Lua C API: C呼出規約+独自値表現で長期安定。ただしstackベースは学習コストあり。
|
||||
- 反省点
|
||||
- CPython C API: 内部構造体露出で進化の足枷に。HPyはハンドル化で再設計。
|
||||
- JNI: 汎用だが冗長・低速傾向。最適化しづらい。
|
||||
- 教訓
|
||||
- 内部レイアウト非公開(ハンドル/関数経由)・バージョン化vtable・拡張フラグが長期安定の鍵。
|
||||
- 値ABIは固定サイズ・レジスタ渡し最適化可能な形が吉(3×u64は合理的)。
|
||||
|
||||
**VM/JIT最適化の観点**
|
||||
- 呼出オーバーヘッド
|
||||
- 3×u64はSysV/Win64いずれもレジスタ渡しが効きやすく、C ABIと同等のコールコストに収束。
|
||||
- 本質的ボトルネックは間接呼出ミス予測と型検査。JITで型が既知ならチェックを埋め込み/削減可能。
|
||||
- 直呼 vs トランポリン
|
||||
- 署名が一致する場合は直接呼出(JITに外部シンボルとして登録)。
|
||||
- 型昇降/借用が必要な時のみthunkを噛ませる。JITでモノモーフィック化・デッドパス除去。
|
||||
- 最適化ヒント(Cranelift/LLVM)
|
||||
- 関数属性: `nounwind`, `readonly`/`readnone`, `nocapture`, `nonnull`, `cold`(エラーパス)
|
||||
- 戻り値はout-paramにしてtailcall最適化(`musttail`適用可否は要検証)。
|
||||
- シンボルはAOT時`dso_local`、JITは`CallConv::SystemV/WindowsFast`で3×i64に整合。
|
||||
- ホットループ対策
|
||||
- スカラー跨ぎは避け、スライス/バルクAPIを定義(例: vector add)。boundary跨ぎ回数を削減。
|
||||
- 将来は静的リンクモード(first-party plugins)でLTO許可→AOTでインライン・DCE可。
|
||||
|
||||
**Nyash ABIのみ vs 併存の比較**
|
||||
- Nyash ABIのみ(1)
|
||||
- 一貫性と将来性は高いが、既存C資産/ツール連携コストと立上げ摩擦が大きい。
|
||||
- 併存(2, 推奨)
|
||||
- 早期エコシステム拡大と最適化の両取り。複雑性はvtable+アダプタの設計で抑え込み可能。
|
||||
- その他(3)
|
||||
- N-API風ハンドル専一は安定するが、オーバーヘッド/冗長性が増える。Nyashのパフォーマンス志向には過剰。
|
||||
|
||||
**実装メモ(具体)**
|
||||
- 値ABI
|
||||
- `tag`: 上位ビットに種別・フラグ(own/borrow、small/heap、nullable等)
|
||||
- `payload`: ポインタor即値、`aux`: len/stride/arena_id等
|
||||
- `NySlice`: `tag=SLICE`で`payload=ptr`, `aux=len`。borrow時は生存期間制約、必要なら`nyrt_clone_slice`で所有権取得。
|
||||
- 初期化/交渉
|
||||
- `NyPluginInitV1(NyRtFnsV1*, NyPluginV1*) -> NyStatus`
|
||||
- `NyRtFnsV1`: alloc/free、string/slice/future、log、error造作API。
|
||||
- `NyPluginV1`: `abi_mask`, `size`, `features`, `fn_count`, `NyFnDesc*`.
|
||||
- エラー/非同期
|
||||
- `NyStatus` + `NyValue err_out`。非同期は `NyFuture*`を返却、`NyRtFnsV1`で`poll/wake`を橋渡し。
|
||||
- VMのスケジューラとWakerのブリッジはvtableで隠蔽(ABI非依存)。
|
||||
- 安定性
|
||||
- すべての公開構造体に`size`を先頭フィールドに持たせ将来拡張。未理解フィールドは無視。
|
||||
- ABIバージョンは数値+機能フラグで条件分岐(ビルド時にも`#[cfg(feature)]`で絞る)。
|
||||
|
||||
**質問への回答**
|
||||
- 1) 長期的に賢明か: 併存+共通値ABIが最善。Cの互換性とNyashの型安全/拡張性を両立。
|
||||
- 2) 複雑性は管理可能か: はい。vtableの一本化、JIT生成thunk、機能交渉で抑制できる。
|
||||
- 3) 学び: 内部構造体を外部に晒さない・ハンドル経由・バージョン化テーブル・豊富な属性メタデータ。CPythonの反省とN-APIの成功を取り込む。
|
||||
- 4) VM/JIT最適化: 3×u64のNyash値はレジスタ渡しでC ABIと同等に速く、型既知箇所はJITで直呼/チェック省略可能。最適化の自由度はNyash ABIの方が高い。
|
||||
|
||||
**次のアクション**
|
||||
- 値ABIと関数テーブル仕様を`crates/nyrt/include/nyrt.h`に最小ドラフト化(`NyValue`, `NyStatus`, `NyRtFnsV1`, `NyPluginV1`, `NyFnDesc`)。
|
||||
- ローダにinit/交渉実装(`nyash.toml`のabi種別・型情報読み込み→関数登録)。
|
||||
- JIT/VMに外部関数署名登録とthunk生成を追加(Cranelift/LLVM兼用)。
|
||||
- バルク演算プラグインのスモークを作成(C ABI版とNyash ABI版を比較ベンチ)。
|
||||
- ドキュメント化(`docs/plugins/abi.md`)とサンプル(`plugins/`、`apps/`)追加。
|
||||
|
||||
必要なら、ドラフトの`NyValue`と`NyPluginInitV1`の最小Cヘッダ案もすぐ出します。
|
||||
@ -0,0 +1,188 @@
|
||||
# Codex先生のBoxCall拡張分析 (2025-09-01)
|
||||
|
||||
## 質問内容
|
||||
|
||||
Nyash ABI実装の具体的アプローチについて技術相談です。
|
||||
|
||||
【背景】
|
||||
前回の議論で、C ABIとNyash ABIの両方をサポートする方向性が見えました。実装方法について新しいアイデアがあります。
|
||||
|
||||
【BoxCall拡張による統合案】
|
||||
MIR命令を増やさず、既存のBoxCallを自然に拡張する案です:
|
||||
|
||||
```rust
|
||||
// 現在のBoxCall
|
||||
MirInstruction::BoxCall {
|
||||
receiver: Value,
|
||||
method: String,
|
||||
args: Vec<Value>,
|
||||
}
|
||||
|
||||
// 提案:最小限の拡張
|
||||
MirInstruction::BoxCall {
|
||||
receiver: Value,
|
||||
method: String,
|
||||
args: Vec<Value>,
|
||||
abi_hint: Option<AbiType>, // 追加
|
||||
}
|
||||
```
|
||||
|
||||
【実装の流れ】
|
||||
1. MIRビルダー:プラグインBoxならABIヒント付与
|
||||
2. VM実行時:receiver.type_idから適切なABI選択
|
||||
3. プラグインローダー:nyash.tomlでABI指定可能
|
||||
|
||||
【この案の利点】
|
||||
- MIR命令数は15個維持(Everything is Box哲学)
|
||||
- 既存コード無変更(後方互換)
|
||||
- プラグインごとに段階的移行可能
|
||||
- JITでABI別最適化も可能
|
||||
|
||||
【質問】
|
||||
1. このBoxCall拡張案は設計として健全でしょうか?
|
||||
2. abi_hintは本当に必要?VM実行時の型判定で十分?
|
||||
3. 将来的な拡張(WASM等)にも対応できる設計か?
|
||||
4. パフォーマンス影響をどう評価すべきか?
|
||||
|
||||
実装の観点から、MIR層でのabi_hint追加とVM層でのABI判定について深く分析してください。特に既存実装への影響を最小化する方法を考慮して。
|
||||
|
||||
## Codex先生の回答
|
||||
|
||||
### コードベース分析
|
||||
|
||||
まず、現在のMIR/VM実装を確認:
|
||||
|
||||
```rust
|
||||
// 現在のMirInstruction::BoxCall定義
|
||||
BoxCall {
|
||||
dst: Option<ValueId>,
|
||||
box_val: ValueId,
|
||||
method: String,
|
||||
method_id: Option<u16>, // Universal method用
|
||||
args: Vec<ValueId>,
|
||||
effects: EffectMask,
|
||||
}
|
||||
```
|
||||
|
||||
プラグインローダーはすでにnyash.tomlから型情報を読み込んでおり、VM実行時に利用可能。
|
||||
|
||||
### 核心的な洞察
|
||||
|
||||
**abi_hintは実は不要かもしれない!**
|
||||
|
||||
理由:
|
||||
1. VM実行時にreceiver.type_idから型情報を取得可能
|
||||
2. プラグインローダーが既にABI情報を保持している
|
||||
3. MIR層を変更せずに済む(15命令維持)
|
||||
|
||||
### 実装提案
|
||||
|
||||
#### Option A: 最小限実装(MIR無変更)
|
||||
|
||||
```rust
|
||||
// VM層での実装
|
||||
fn execute_boxcall(&mut self, dst: Option<ValueId>, box_val: ValueId, method: &str, args: &[ValueId]) -> Result<ControlFlow, VMError> {
|
||||
let receiver = self.get_value(box_val)?;
|
||||
let type_id = receiver.get_type_id();
|
||||
|
||||
// プラグインローダーから型情報取得
|
||||
if let Some(plugin_info) = self.runtime.get_plugin_info(type_id) {
|
||||
match plugin_info.abi.as_str() {
|
||||
"c" => self.call_c_abi_plugin(plugin_info, method, args),
|
||||
"nyash" => self.call_nyash_abi_plugin(plugin_info, method, args),
|
||||
_ => self.call_c_abi_plugin(plugin_info, method, args), // fallback
|
||||
}
|
||||
} else {
|
||||
// ビルトインBox処理(既存のまま)
|
||||
self.execute_builtin_method(receiver, method, args)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Option B: 将来の拡張性を考慮
|
||||
|
||||
```rust
|
||||
// MIRに汎用メタデータ追加(ABIに限定しない)
|
||||
MirInstruction::BoxCall {
|
||||
receiver: Value,
|
||||
method: String,
|
||||
args: Vec<Value>,
|
||||
metadata: Option<u32>, // 汎用的な最適化ヒント
|
||||
}
|
||||
```
|
||||
|
||||
### JIT/AOT最適化の観点
|
||||
|
||||
```rust
|
||||
// JIT時の特化
|
||||
match type_info.abi {
|
||||
Some("c") => {
|
||||
// 直接call命令生成
|
||||
builder.emit_direct_call(symbol, args);
|
||||
}
|
||||
Some("nyash") => {
|
||||
// NyashValue pack/unpackを含めてインライン化
|
||||
let packed = builder.emit_pack_nyash_values(args);
|
||||
builder.emit_call_with_abi(symbol, packed);
|
||||
}
|
||||
_ => {
|
||||
// 汎用パス(VM呼び出し)
|
||||
builder.emit_vm_boxcall(receiver, method, args);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### パフォーマンス評価方法
|
||||
|
||||
```rust
|
||||
// ベンチマーク設計
|
||||
fn benchmark_abi_comparison() {
|
||||
// 1. 高頻度呼び出し(math operations)
|
||||
measure_time("C ABI", || {
|
||||
for _ in 0..1_000_000 {
|
||||
math_add_c_abi(1.0, 2.0);
|
||||
}
|
||||
});
|
||||
|
||||
measure_time("Nyash ABI", || {
|
||||
for _ in 0..1_000_000 {
|
||||
math_add_nyash_abi(pack(1.0), pack(2.0));
|
||||
}
|
||||
});
|
||||
|
||||
// 2. 複雑な型(string operations)
|
||||
// 3. プラグイン初期化コスト
|
||||
}
|
||||
```
|
||||
|
||||
### 結論と推奨事項
|
||||
|
||||
1. **abi_hintは不要** - VM実行時の型判定で十分
|
||||
2. **MIR層は無変更** - 15命令の美しさ維持
|
||||
3. **将来拡張は型システム経由** - WASMもプラグイン型として追加
|
||||
4. **段階的実装**:
|
||||
- Week 1: nyash.toml拡張 + VM分岐
|
||||
- Week 2: ベンチマーク + 最適化
|
||||
- Week 3: JIT特化(必要なら)
|
||||
|
||||
### 実装の具体的ステップ
|
||||
|
||||
```yaml
|
||||
Step 1: nyash.toml拡張
|
||||
- LibraryDefinition に abi: Option<String> 追加
|
||||
- デフォルトは "c"
|
||||
|
||||
Step 2: プラグインローダー
|
||||
- PluginInfo 構造体に abi フィールド追加
|
||||
- ロード時に保存
|
||||
|
||||
Step 3: VM execute_boxcall
|
||||
- 型判定でABI分岐
|
||||
- call_c_abi / call_nyash_abi メソッド追加
|
||||
|
||||
Step 4: テスト
|
||||
- 同一機能の C/Nyash 両実装
|
||||
- 性能比較測定
|
||||
```
|
||||
|
||||
この最小限アプローチなら、既存コードへの影響を最小化しつつ、将来の拡張性も確保できます。
|
||||
@ -0,0 +1,164 @@
|
||||
# Nyash ABI戦略の深い分析 - なぜ正解が難しいのか (2025-09-01)
|
||||
|
||||
## 🤔 両先生の回答から見えた根本的な難しさ
|
||||
|
||||
### 1. 時間軸のジレンマ
|
||||
|
||||
**Gemini先生の視点**(長期エコシステム):
|
||||
- 10年後も動くプラグインを作りたい
|
||||
- 破壊的変更は絶対避けたい
|
||||
- 開発者の信頼が最重要
|
||||
|
||||
**Codex先生の視点**(現実的最適化):
|
||||
- 今すぐ高速に動かしたい
|
||||
- JIT/VMの最適化余地を残したい
|
||||
- 実装の複雑性を抑えたい
|
||||
|
||||
→ **この2つは本質的に矛盾する!**
|
||||
|
||||
### 2. 抽象化レベルの選択
|
||||
|
||||
```
|
||||
高レベル抽象化(Gemini案)
|
||||
↑
|
||||
SDK層
|
||||
↑
|
||||
C ABI(安定境界)
|
||||
|
||||
vs
|
||||
|
||||
低レベル統合(Codex案)
|
||||
↓
|
||||
共通値表現(3×u64)
|
||||
↓
|
||||
C呼出規約で統一
|
||||
```
|
||||
|
||||
どちらが正解? **状況による!**
|
||||
|
||||
### 3. 隠れた複雑性の罠
|
||||
|
||||
**表面的には単純に見える選択**:
|
||||
- C ABI only → シンプル!
|
||||
- Nyash ABI only → 統一的!
|
||||
- 両方サポート → 柔軟!
|
||||
|
||||
**実際の複雑さ**:
|
||||
- C ABI only → 型情報なし、拡張困難
|
||||
- Nyash ABI only → 既存資産切り捨て
|
||||
- 両方サポート → **複雑性が2倍...ではなく4倍!**
|
||||
|
||||
### 4. なぜ複雑性が爆発するのか
|
||||
|
||||
```
|
||||
組み合わせ爆発:
|
||||
- 2つのABI ×
|
||||
- 3つのバックエンド(Interpreter/VM/JIT) ×
|
||||
- N個のプラグイン型 ×
|
||||
- M個の最適化レベル
|
||||
= 指数関数的複雑性
|
||||
```
|
||||
|
||||
## 🎯 深い洞察:本当の問題は何か
|
||||
|
||||
### 技術的正解 vs ビジネス的正解
|
||||
|
||||
**技術的に美しい解**:
|
||||
- Nyash ABI一本化
|
||||
- 型安全、拡張可能、統一的
|
||||
|
||||
**ビジネス的に賢い解**:
|
||||
- C ABI + 段階的移行
|
||||
- 既存資産活用、リスク分散
|
||||
|
||||
→ **どちらも「正解」であり「不正解」**
|
||||
|
||||
### 隠れた第3の選択肢
|
||||
|
||||
両先生が暗黙的に示唆している:
|
||||
|
||||
```
|
||||
時期による使い分け:
|
||||
Phase 1: C ABIで素早くエコシステム立ち上げ
|
||||
Phase 2: SDK層で開発体験向上
|
||||
Phase 3: Nyash ABIで技術的優位性確立
|
||||
Phase 4: 統合または選択的廃止
|
||||
```
|
||||
|
||||
## 💡 究極の洞察:「正解がない」ことが答え
|
||||
|
||||
### なぜ正解が難しいのか
|
||||
|
||||
1. **未来は予測不可能**
|
||||
- NyashがRustを超えるか?
|
||||
- WASMが世界標準になるか?
|
||||
- 新しいABI標準が生まれるか?
|
||||
|
||||
2. **トレードオフは価値観次第**
|
||||
- 速度 vs 安全性
|
||||
- シンプル vs 機能性
|
||||
- 互換性 vs 革新性
|
||||
|
||||
3. **成功の定義が人による**
|
||||
- 多くのプラグイン?
|
||||
- 高速な実行?
|
||||
- 美しいコード?
|
||||
|
||||
## 🚀 実践的な答え:適応的戦略
|
||||
|
||||
### 推奨アプローチ
|
||||
|
||||
```rust
|
||||
// 初期実装:両対応だが内部統一
|
||||
enum PluginABI {
|
||||
C(CPlugin), // 既存資産
|
||||
Nyash(NyashPlugin), // 新規開発
|
||||
}
|
||||
|
||||
// 共通インターフェース
|
||||
trait Plugin {
|
||||
fn invoke(&self, args: &[Value]) -> Result<Value>;
|
||||
}
|
||||
|
||||
// 将来の拡張ポイント
|
||||
impl PluginABI {
|
||||
fn optimize_for_jit(&self) -> Option<DirectCall> {
|
||||
// JIT時に最適化可能なら直接呼び出しに変換
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 段階的進化の道筋
|
||||
|
||||
1. **観察期間**(6ヶ月)
|
||||
- 両ABI並行運用
|
||||
- 使用パターン分析
|
||||
- パフォーマンス測定
|
||||
|
||||
2. **最適化期間**(次の6ヶ月)
|
||||
- 頻出パターンの高速化
|
||||
- SDK層の洗練
|
||||
- ドキュメント充実
|
||||
|
||||
3. **判断期間**(1年後)
|
||||
- データに基づく選択
|
||||
- 片方を非推奨に?
|
||||
- それとも永続的共存?
|
||||
|
||||
## 🌟 結論:「正解がない」を受け入れる勇気
|
||||
|
||||
**Nyashの哲学**:
|
||||
- Everything is Box → Everything has Trade-offs
|
||||
- 完璧より進捗(80/20ルール)
|
||||
- 箱理論で差し替え可能に
|
||||
|
||||
**最終提案**:
|
||||
1. 両方実装するが、**内部アーキテクチャは統一**
|
||||
2. **測定可能な成功指標**を先に定義
|
||||
3. **3ヶ月ごとに振り返り**、方向修正
|
||||
|
||||
正解がないからこそ、**適応し続けることが正解**。
|
||||
|
||||
---
|
||||
|
||||
*「間に挟むだけ」のABI層が、実は最も難しい設計判断の一つだった。*
|
||||
@ -0,0 +1,121 @@
|
||||
# BoxCall拡張によるABI戦略 - 最終実装決定 (2025-09-01)
|
||||
|
||||
## 🎯 両先生の回答から得た重要な洞察
|
||||
|
||||
### Gemini先生の誤解が示す重要な点
|
||||
- 先生は「BoxCall = Box<dyn Trait>を渡す」と誤解
|
||||
- しかし、この誤解が**abi_stable**の重要性を教えてくれた
|
||||
- 将来的にRustトレイトオブジェクトを扱う際の指針に
|
||||
|
||||
### Codex先生の実践的分析
|
||||
1. **abi_hintは実は不要かもしれない**
|
||||
- VM実行時にtype_idから判定可能
|
||||
- プラグインローダーが型情報を保持
|
||||
- MIR層を汚さない
|
||||
|
||||
2. **既存実装への影響最小化**
|
||||
- TypeMetaにABI情報を含める
|
||||
- nyash.tomlから読み込み済み
|
||||
- VM側で判定するだけ
|
||||
|
||||
## 🚀 最終実装方針
|
||||
|
||||
### Option A: 最小限実装(推奨)
|
||||
|
||||
```rust
|
||||
// MIR層:変更なし!
|
||||
MirInstruction::BoxCall {
|
||||
receiver: Value,
|
||||
method: String,
|
||||
args: Vec<Value>,
|
||||
// abi_hint不要!
|
||||
}
|
||||
|
||||
// VM層:型判定でABI選択
|
||||
fn execute_boxcall(...) {
|
||||
let type_id = receiver.get_type_id();
|
||||
|
||||
// プラグインローダーから型情報取得
|
||||
if let Some(plugin_info) = get_plugin_info(type_id) {
|
||||
match plugin_info.abi {
|
||||
"c" => call_c_abi(...),
|
||||
"nyash" => call_nyash_abi(...),
|
||||
_ => fallback_to_c_abi(...),
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Option B: 明示的ヒント(将来の拡張性)
|
||||
|
||||
```rust
|
||||
// MIR層:最小限の拡張
|
||||
MirInstruction::BoxCall {
|
||||
receiver: Value,
|
||||
method: String,
|
||||
args: Vec<Value],
|
||||
metadata: Option<u32>, // 汎用メタデータ(ABIヒント含む)
|
||||
}
|
||||
```
|
||||
|
||||
## 📊 比較表
|
||||
|
||||
| 観点 | Option A(最小限) | Option B(ヒント付き) |
|
||||
|------|------------------|---------------------|
|
||||
| MIR変更 | なし ✅ | 最小限 |
|
||||
| 実装工数 | 1週間 | 2週間 |
|
||||
| JIT最適化 | VM時判定 | ビルド時判定可能 |
|
||||
| 将来拡張 | 型情報経由 | メタデータ活用 |
|
||||
|
||||
## 🎯 結論:Option Aで始める
|
||||
|
||||
### 理由
|
||||
1. **80/20ルール**: まず動くものを作る
|
||||
2. **MIR無変更**: 15命令の美しさ維持 → さらに14命令へ(PluginInvoke統合)
|
||||
3. **段階的進化**: 必要になったらOption Bへ
|
||||
|
||||
### Phase 12での追加統合
|
||||
- **PluginInvoke → BoxCall 完全統合**
|
||||
- ビルトインBox廃止により区別が不要
|
||||
- VM層でのABI判定で十分
|
||||
- Core-15 → Core-14 への削減
|
||||
|
||||
### 実装ステップ(1週間)
|
||||
|
||||
```yaml
|
||||
Day 1-2: nyash.toml拡張
|
||||
- abi: "c" | "nyash" field追加
|
||||
- プラグインローダー対応
|
||||
|
||||
Day 3-4: VM実行時分岐
|
||||
- execute_boxcall内でABI判定
|
||||
- NyashValue pack/unpack実装
|
||||
|
||||
Day 5-6: テスト・ベンチマーク
|
||||
- 同一機能の2種類プラグイン
|
||||
- 性能比較測定
|
||||
|
||||
Day 7: 判断
|
||||
- データに基づく方向性決定
|
||||
- Option B移行の必要性評価
|
||||
```
|
||||
|
||||
## 💡 深い洞察
|
||||
|
||||
**「abi_hintは不要」という発見が示すもの**:
|
||||
- 型システムが既に十分な情報を持っている
|
||||
- MIRは純粋な意図の表現で良い
|
||||
- 実行時の賢い判断に任せる
|
||||
|
||||
これこそ「Everything is Box」の真髄 - Boxが自分の実装方法を知っている!
|
||||
|
||||
## 🚀 次のアクション
|
||||
|
||||
1. nyash.tomlパーサーに`abi` field追加
|
||||
2. プラグインローダーでABI情報保持
|
||||
3. VM execute_boxcallで分岐実装
|
||||
4. 最小限のテストプラグイン作成
|
||||
|
||||
---
|
||||
|
||||
*最小限から始めて、データで判断する。これがNyashの道。*
|
||||
@ -0,0 +1,179 @@
|
||||
# Gemini先生のNyash ABI戦略分析 (2025-09-01)
|
||||
|
||||
## 質問内容
|
||||
|
||||
Nyashプラグインシステムの ABI戦略について技術的相談です。
|
||||
|
||||
【背景】
|
||||
Phase 12でNyashスクリプトプラグインシステムを実装中です。現在、プラグインインターフェースの設計で重要な判断が必要です。
|
||||
|
||||
【現状】
|
||||
- 既存: C ABI(シンプル、高速、実績あり)
|
||||
- 提案: Nyash ABI(3×u64構造体、型情報付き、拡張性高い)
|
||||
|
||||
【トレードオフ】
|
||||
C ABI:
|
||||
- 利点: ゼロオーバーヘッド、既存資産活用、シンプル
|
||||
- 欠点: 型情報なし、拡張性限定、エラー処理が原始的
|
||||
|
||||
Nyash ABI:
|
||||
- 利点: 型安全、メタデータ活用、将来性(async等)
|
||||
- 欠点: pack/unpackのオーバーヘッド、新規学習コスト
|
||||
|
||||
【具体的な選択肢】
|
||||
1. Nyash ABIのみ(統一性重視)
|
||||
2. C ABI + Nyash ABI両方(実用性重視)
|
||||
3. その他の革新的アプローチ?
|
||||
|
||||
【質問】
|
||||
1. どちらの戦略が長期的に見て賢明でしょうか?
|
||||
2. 両方サポートする場合の複雑性は管理可能でしょうか?
|
||||
3. 他の言語での成功例・失敗例から学べることは?
|
||||
4. VM/JIT最適化の観点から、どちらが有利でしょうか?
|
||||
|
||||
## Gemini先生の回答
|
||||
|
||||
### NyashプラグインシステムにおけるABI戦略の技術的考察
|
||||
|
||||
Nyashプラグインシステムの長期的なエコシステム発展を見据えたABI(Application Binary Interface)戦略について、深く技術的に考察します。
|
||||
|
||||
### 1. ABI安定性の重要性:エコシステム成功の礎
|
||||
|
||||
プラグインシステムの成功は、**ABIの鉄壁の安定性**にかかっています。ホストアプリケーション(Nyash)とプラグインは、別々にコンパイル・配布されるバイナリです。両者が正しく協調動作できるのは、関数呼び出し規約、データ型表現、メモリアロケーションといった低レベルな規約、すなわちABIが厳密に一致しているからです。
|
||||
|
||||
もしNyashのバージョンアップでABIに破壊的変更が生じれば、既存の全プラグインは動作しなくなり、再コンパイルが必要になります。これはエコシステムにとって致命的です。開発者は追従を諦め、ユーザーはプラグインが使えなくなることを恐れてNyashのアップデートをためらうでしょう。
|
||||
|
||||
したがって、ABI戦略の最優先目標は**「前方互換性(新しいNyashが古いプラグインを動かせる)と、可能な限りの後方互換性(古いNyashが新しいプラグインの機能を限定的にでも利用できる)」**を保証することです。
|
||||
|
||||
### 2. 現状の分析と潜在的リスク
|
||||
|
||||
現在のNyashのコードベースを調査し、プラグイン関連の実装を特定する必要があります。`Cargo.toml`やソースコードから、おそらくRustのダイナミックライブラリ(`.so`, `.dll`, `.dylib`)を動的に読み込む形式が採用されていると推測されます。
|
||||
|
||||
ここで最も警戒すべきは、**Rust固有のABIに依存することのリスク**です。Rustコンパイラは、パフォーマンス最適化のために、構造体のメモリレイアウトや関数呼び出し規約をバージョン間で予告なく変更します。したがって、`extern "Rust"`(デフォルト)の関数をプラグイン境界として公開するのは、エコシステムの観点からは**絶対に避けなければなりません**。
|
||||
|
||||
素晴らしい!検索結果から、Nyashはすでに `extern "C"` を広範囲に利用していることが明確にわかります。これは非常に良い出発点です。`plugin_loader_v2.rs` や `bid/plugin_api.rs` などを見ると、プラグインの初期化(`nyash_plugin_init`)や関数呼び出し(`invoke_fn`)のシグネチャがC ABIで定義されています。
|
||||
|
||||
これは、ABI安定性に対する基本的な理解がプロジェクトに既に存在することを示しています。しかし、長期的なエコシステムを築くには、これをさらに推し進め、より洗練された戦略を立てる必要があります。
|
||||
|
||||
### 3. 長期的な発展のためのABI戦略提案
|
||||
|
||||
現在の `extern "C"` ベースのアプローチを基礎としつつ、以下の戦略を段階的に導入することを提案します。
|
||||
|
||||
#### 戦略1:C ABIを「公式な安定境界」として厳格に定義・文書化する
|
||||
|
||||
これは最も重要です。`extern "C"` を使っているというだけでは不十分で、それを**公式な規約**として確立する必要があります。
|
||||
|
||||
**具体的なアクション:**
|
||||
|
||||
1. **ABI仕様書の作成:**
|
||||
- `nyash-abi.h`のようなCヘッダーファイル形式で、プラグインが実装すべき関数シグネチャと、Nyashが提供するホスト関数(コールバック)をすべて定義します。
|
||||
- `invoke_fn` で使われている `*const u8`, `*mut u8` のようなバイトポインタが、具体的にどのようなデータを指すのか(シリアライズ形式、レイアウトなど)を厳密に文書化します。
|
||||
- `NyashHostVtable` のような構造体は、フィールドの順序と型が未来永劫変わらないことを保証しなければなりません。新しいホスト関数を追加する場合は、末尾にのみ追加します。
|
||||
- エラー報告の規約(戻り値の `i32` が何を意味するのか)を定義します。
|
||||
|
||||
2. **FFI(Foreign Function Interface)層の明確化:**
|
||||
- Nyash内部のRustコードと、C ABI境界を明確に分離します。`plugin_loader_v2.rs` はこの役割を担っているようですが、この層は「ABI変換」にのみ責任を持つべきです。内部的なリファクタリングがABIに影響を与えないようにします。
|
||||
|
||||
**利点:**
|
||||
- **言語非依存:** C ABIはあらゆる主要言語(C++, Zig, Go, Python, etc.)から利用可能で、プラグイン開発者の裾野を広げます。
|
||||
- **究極の安定性:** C ABIは数十年にわたり安定しています。
|
||||
|
||||
**欠点:**
|
||||
- **表現力の低さ:** Rustの`Result`や`Option`、ライフタイムといった豊かな型情報を直接渡せず、`i32`のエラーコードやポインタのNULLチェックといったプリミティブな方法に頼らざるを得ません。
|
||||
- **手作業と`unsafe`:** データのシリアライズ・デシリアライズやポインタ操作が必須となり、`unsafe`コードが増え、バグの温床になりやすいです。
|
||||
|
||||
#### 戦略2:高レベルな「Rust向けラッパーSDK」を提供する
|
||||
|
||||
C ABIの欠点を補うため、プラグイン開発者が直接C ABIを触らなくても済むように、公式のRust製SDK(クレート)を提供します。
|
||||
|
||||
**具体的なアクション:**
|
||||
|
||||
1. **`nyash-plugin-sdk` クレートの作成:**
|
||||
- このSDKは、低レベルなC ABIのやり取りをすべてカプセル化します。
|
||||
- プラグイン開発者は、`Result<MyData, MyError>` のような自然なRustの型を扱うだけで、SDKが自動的にC ABI準拠のデータ(バイト列やエラーコード)との相互変換を行います。
|
||||
- 定型的なコードを自動生成するマクロ(例: `#[nyash_plugin]`)を提供し、開発体験を向上させます。
|
||||
|
||||
**SDK利用者のコード(イメージ):**
|
||||
```rust
|
||||
// プラグイン開発者が書くコード
|
||||
use nyash_plugin_sdk::{plugin, NyashResult, NyashError};
|
||||
|
||||
struct MyPlugin;
|
||||
|
||||
#[plugin]
|
||||
impl Plugin for MyPlugin {
|
||||
fn handle_request(&self, input: &str) -> NyashResult<String> {
|
||||
if input == "hello" {
|
||||
Ok("world".to_string())
|
||||
} else {
|
||||
Err(NyashError::new("Invalid input"))
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**SDK内部の実装(イメージ):**
|
||||
```rust
|
||||
// #[plugin] マクロが生成するコード
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn nyash_plugin_invoke(
|
||||
/* C ABI引数 */
|
||||
) -> i32 {
|
||||
// 1. C ABIのバイト列から &str へデシリアライズ
|
||||
// 2. MyPlugin::handle_request を呼び出し
|
||||
// 3. 結果の Result<String, NyashError> をC ABIのエラーコードとバイト列にシリアライズ
|
||||
// 4. 結果を返す
|
||||
// ... この部分はSDKが隠蔽する ...
|
||||
}
|
||||
```
|
||||
|
||||
**利点:**
|
||||
- **高い開発者体験:** Rust開発者は、安全で慣用的なRustコードを書くことに集中できます。
|
||||
- **安全性の向上:** `unsafe`コードをSDKに集約させることで、プラグイン開発者がメモリ安全性を破壊するリスクを大幅に低減できます。
|
||||
|
||||
#### 戦略3:データ交換フォーマットの標準化
|
||||
|
||||
`invoke_fn` でやり取りされる `*const u8` の中身を標準化します。これにより、堅牢性と前方互換性が向上します。
|
||||
|
||||
**候補:**
|
||||
|
||||
- **Protocol Buffers / FlatBuffers:**
|
||||
- **利点:** スキーマ定義が明確で、前方・後方互換性を考慮した設計が容易。多言語対応のコード生成ツールが豊富。パフォーマンスも高い。
|
||||
- **欠点:** ビルドプロセスに一手間加わる。
|
||||
|
||||
- **JSON / MessagePack:**
|
||||
- **利点:** 動的で柔軟。デバッグが容易。
|
||||
- **欠点:** スキーマがないため、実行時エラーになりやすい。シリアライズ・デシリアライズのオーバーヘッドが比較的多きい。
|
||||
|
||||
**推奨:**
|
||||
長期的なエコシステムの安定性を考えると、スキーマベースの **Protocol Buffers** または **FlatBuffers** が最適です。
|
||||
|
||||
#### 戦略4:WebAssembly (Wasm) の採用検討
|
||||
|
||||
究極の目標として、プラグインをWebAssemblyモジュールとして実行する方式を検討する価値があります。
|
||||
|
||||
**利点:**
|
||||
- **サンドボックス化:** Wasmランタイム(Wasmtimeなど)上でプラグインを実行することで、Nyash本体から完全に隔離された安全な環境を提供できます。悪意のあるプラグインやバグのあるプラグインがホストをクラッシュさせるのを防ぎます。
|
||||
- **真の言語非依存:** C ABIよりもさらに多くの言語(コンパイルターゲットにWASIを持つもの)がプラグイン開発に利用可能になります。
|
||||
- **WASIとコンポーネントモデル:** WASI(WebAssembly System Interface)やWasm Component Modelの標準化が進むことで、ファイルアクセスやネットワークなどのホスト機能へのアクセスが標準化され、より洗練されたABIを構築できます。
|
||||
|
||||
**欠点:**
|
||||
- **パフォーマンスオーバーヘッド:** C ABIのダイナミックライブラリ呼び出しに比べ、Wasmランタイムを介在させることによるオーバーヘッドが存在します。
|
||||
- **実装の複雑さ:** Wasmランタイムの組み込みと、ホスト・ゲスト間のデータ共有(特に複雑なデータ構造)の実装は複雑になります。
|
||||
|
||||
### まとめと提言
|
||||
|
||||
Nyashは `extern "C"` の採用により、ABI安定化への正しい一歩を踏み出しています。長期的なエコシステムの繁栄のため、以下のロードマップを提案します。
|
||||
|
||||
1. **短期(すぐ着手すべき):**
|
||||
- **C ABIの公式化:** `nyash-abi.h`相当の仕様を定義し、文書化する。
|
||||
- **データフォーマットの選定:** `invoke_fn` で交換されるデータのシリアライズ形式としてProtocol Buffers等を導入する。
|
||||
|
||||
2. **中期(エコシステムの成長期):**
|
||||
- **Rust向けSDKの提供:** `nyash-plugin-sdk` クレートを開発し、Rust開発者の体験を向上させる。
|
||||
- **他言語向けSDKの提供:** 需要に応じて、PythonやGo向けのラッパーライブラリを提供する。
|
||||
|
||||
3. **長期(未来のビジョン):**
|
||||
- **WebAssemblyへの移行:** パフォーマンス要件とセキュリティ要件を天秤にかけ、プラグイン実行環境をWasmに移行することを検討する。これにより、究極の安全性と移植性を獲得できる。
|
||||
|
||||
この戦略により、Nyashは安定性、開発者体験、安全性を段階的に向上させ、活発で持続可能なプラグインエコシステムを構築できると確信します。
|
||||
@ -0,0 +1,37 @@
|
||||
# Nyash ABI議論アーカイブ
|
||||
|
||||
このディレクトリには、Nyash ABIの設計に関する重要な議論や考察が保存されています。
|
||||
|
||||
## 📚 ドキュメント一覧
|
||||
|
||||
### 🌟 AI専門家の深い考察
|
||||
- **[gemini-codex-deep-thoughts.md](gemini-codex-deep-thoughts.md)** - Gemini先生とCodex先生によるNyash ABI C実装の深い考察(2025年9月2日)
|
||||
- セルフホスティング実現への技術的妥当性
|
||||
- 具体的な実装提案(16バイトアライメント、セレクターキャッシング等)
|
||||
- 哲学的観点からの分析
|
||||
|
||||
### 🎯 設計の進化過程
|
||||
- 初期提案: 複雑なFactory設計
|
||||
- 転換点: 「型をC ABIの箱として渡す共通ルール」という洞察
|
||||
- 最終形: TypeBox + Nyash ABI C実装による統一設計
|
||||
|
||||
## 💡 重要な洞察
|
||||
|
||||
### 「Everything is Box」の究極形
|
||||
ABIそのものをBoxとして扱うことで、言語の哲学が技術的実装と完全に一致しました。
|
||||
|
||||
### セルフホスティングへの道
|
||||
1. C Shim実装(既存Rustへのラッパー)
|
||||
2. フルC実装(基本型・参照カウント)
|
||||
3. Nyashで再実装(AOTでC ABI公開)
|
||||
4. Nyashコンパイラ自身をNyashで実装
|
||||
|
||||
### AI専門家の評価
|
||||
- **Gemini**: 「技術的妥当性が高く、言語哲学とも合致した、極めて優れた設計」
|
||||
- **Codex**: 「Feasible and attractive: ABI-as-Box completes the idea」
|
||||
- **ChatGPT5**: 「実装に耐える設計。10の改善点で完璧」
|
||||
|
||||
## 📝 関連ドキュメント
|
||||
- [../NYASH-ABI-C-IMPLEMENTATION.md](../NYASH-ABI-C-IMPLEMENTATION.md) - 実装仕様書
|
||||
- [../UNIFIED-ABI-DESIGN.md](../UNIFIED-ABI-DESIGN.md) - 統合ABI設計
|
||||
- [../README.md](../README.md) - Phase 12概要
|
||||
@ -0,0 +1,113 @@
|
||||
# Codex先生のNyash ABI実装戦略 (2025-09-01)
|
||||
|
||||
## 質問内容
|
||||
|
||||
Nyash ABIという統一ブリッジ規格の実装について技術的相談です。
|
||||
|
||||
【背景】
|
||||
Gemini先生から以下の評価をいただきました:
|
||||
- COM/GObject/WASM Component Modelとの類似性
|
||||
- 3つのu64は十分な表現力
|
||||
- GC言語との循環参照が最大の課題
|
||||
- 非同期処理はmetadataフラグで統一可能
|
||||
- 「間に挟むだけ」だが世界を変える可能性あり
|
||||
|
||||
【Nyash ABIの基本設計】
|
||||
```c
|
||||
typedef struct NyashValue {
|
||||
uint64_t type_id; // 型識別子
|
||||
uint64_t box_handle; // Arc<T>のポインタ
|
||||
uint64_t metadata; // フラグ・インライン値
|
||||
} NyashValue;
|
||||
|
||||
typedef NyashValue (*NyashFunc)(
|
||||
uint32_t argc,
|
||||
NyashValue* args,
|
||||
void* context
|
||||
);
|
||||
```
|
||||
|
||||
【具体的な実装相談】
|
||||
1. MIR統合: ExternCallにabi_type追加で十分?それとも新命令?
|
||||
2. バインディング生成: #[nyash_abi]マクロの実装戦略は?
|
||||
3. 型レジストリ: type_idの生成と管理方法(ハッシュ?連番?)
|
||||
4. インライン最適化: metadata活用で整数をbox化回避する設計
|
||||
5. 移行戦略: 既存のC ABIプラグインとの共存方法
|
||||
|
||||
実装の観点から、最もシンプルで段階的に導入できる方法を教えてください。
|
||||
|
||||
## Codex先生の回答
|
||||
|
||||
以下は「まず壊さず、少しずつ置き換える」ための、最小実装から拡張していく導入方針です。現行の MIR/ランタイム構成を踏まえ、後方互換を維持しつつ Nyash ABI を段階導入できます。
|
||||
|
||||
**最小導入方針**
|
||||
- 入口統一: ランタイム側で常に `NyashFunc`(3×u64)に呼び出しを揃える。既存C ABIはランタイム内の薄いトランポリンで包んで `NyashFunc` に見せる。
|
||||
- MIRは無変更: まずは `MirInstruction::ExternCall` のままで十分。ABI種別はレジストリが関数ポインタ解決時に吸収。
|
||||
- 段階移行: プラグインが新旧どちらでも動くよう、`nyash.toml` で ABI 種別を宣言。未宣言は旧C ABI扱いにし、ランタイムが自動でトランポリン生成。
|
||||
|
||||
**1. MIR統合(ExternCallの扱い)**
|
||||
- 現状の `MirInstruction::ExternCall { iface_name, method_name, args, effects }` と `Semantics::extern_call(&str, &str, &[Val])` をそのまま使用。
|
||||
- ランタイムの「外部呼び出し解決レイヤ(ユニファイドレジストリ)」で `(iface, method)` → 事前に登録済みの「NyashFuncポインタ」を返す。
|
||||
- 既存C ABI実装はロード時に「C→Nyash ABI 変換トランポリン」を自動作成し、そのポインタを登録。JIT/LLVM/VM の各バックエンドは常に同じ `NyashFunc` 呼び出しシグネチャだけを生成すればよい。
|
||||
- 将来的に ABI ヒントが必要なら、`ExternCall` にオプショナルな `abi: AbiKind` 追加は可能だが、初期段階では不要。
|
||||
|
||||
**2. バインディング生成(#[nyash_abi])**
|
||||
- 戦略: プロシージャルマクロで「Rust普通関数 ↔ NyashFuncシグネチャ」間の自動ラッパを生成。
|
||||
- 生成内容:
|
||||
- `#[no_mangle] extern "C" fn exported(argc, *args, ctx) -> NyashValueABI` の外側関数(NyashFunc)。
|
||||
- 内側で ABI 配列 `NyashValueABI` を内部 `crate::value::NyashValue` にデコード、Rust関数を呼び、戻りを再度 ABI へエンコード。
|
||||
- 型境界は `FromAbi/ToAbi` トレイトで実装(i64/bool/string/box など)し、`#[nyash_abi] fn f(a: i64, b: String) -> bool` のような自然な記述で書けるようにする。
|
||||
- 配布: `crates/nyrt/` に `nyash_abi.h`(C向けヘッダ)と `abi.rs`(Rust向け)を置く。プラグインはこのヘッダ/クレートにだけ依存。
|
||||
|
||||
**3. 型レジストリ(type_idの生成と管理)**
|
||||
- 方式: 64bit固定ハッシュ(安定化のための固定シード)で「完全修飾名」をハッシュ。
|
||||
- 例: `"nyash.core/Integer"`, `"plugin.math/BigInt@1"` のように namespace + 型名 + バージョンを連結して xxhash/siphash で 64bit に。
|
||||
- 衝突対策: 初回登録時に「同一IDだが異なる完全名」の場合は起動時に失敗(CIで検知)。内蔵型は予約IDを定数定義(Null, Void, Bool, I64, String など)。
|
||||
- レジストリ: 既存の `src/runtime/unified_registry.rs` に統合、あるいは `abi_registry.rs` を新設。
|
||||
- `id -> vtable`(dtor/trace/to_string/cast)と `name -> id` を保持。
|
||||
- `nyash.toml` で型やメソッドの宣言を受け取り、ロード時に登録。プラグイン側も `#[nyash_abi(type = "...")]` で露出。
|
||||
|
||||
**4. インライン最適化(metadataの使い方)**
|
||||
- 目的: 小さい値は box を避け、`box_handle=0` で `metadata` に即値を入れる。
|
||||
- 提案レイアウト(初期版・シンプル):
|
||||
- 最上位4bit: タグ(0=Boxed, 1=I63, 2=Bool, 3=Null, 4=Void, 5=Reserved(Future/Async))
|
||||
- `I63`: 下位63bitに符号付き整数。`type_id=NYASH_TID_I64`, `box_handle=0`。
|
||||
- `Bool`: bit0 に値。`type_id=NYASH_TID_BOOL`, `box_handle=0`。
|
||||
- `Null/Void`: `box_handle=0`。`type_id` はそれぞれの予約ID。
|
||||
- `Boxed`: `box_handle` に `Arc<T>` のアドレス(生ポインタまたはハンドル値)。`metadata` の低位にフラグ(weak/async/readonly 等)を拡張可能。
|
||||
- 浮動小数は第1段では Boxed のまま(安全優先)。将来 NaN-boxing 等は別フェーズで検討。
|
||||
|
||||
**5. 移行戦略(既存C ABIとの共存)**
|
||||
- プラグイン宣言: `nyash.toml` に `abi = "c" | "nyash"` を追加。未指定は `"c"` と見做す。
|
||||
- ローダ:
|
||||
- `"nyash"`: 直接 `NyashFunc` を dlsym。
|
||||
- `"c"`: 既存C関数を dlsym → ランタイム側トランポリンを生成(呼び出し前後で ABI <-> 旧C の変換)。
|
||||
- 呼び出し側(MIR/バックエンド): 常に `NyashFunc` を呼ぶのでコード生成は単純化。JIT/LLVM/VM の差異を ABI 解決層が吸収。
|
||||
- 段階移行:
|
||||
- Phase 1: トランポリンで全プラグインが動く状態を作る(MIR無変更)。
|
||||
- Phase 2: 新規プラグインは `#[nyash_abi]` を使うガイドを提示。
|
||||
- Phase 3: ホットパスのプラグインだけ順次Nyash ABIネイティブ化(ボックス回避の恩恵)。
|
||||
|
||||
**GC/循環参照(要点)**
|
||||
- 既定は「外部境界のエッジは弱参照扱い」。強参照を持つ場合のみ明示 pin/unpin API(`metadata` の weak/pinned フラグで伝達)を導入。
|
||||
- レジストリの vtable に `trace()`/`finalize()` を用意し、GC 言語ブリッジは自前 GC へ協調(Mark 時にクロス境界を報告)。
|
||||
- 非同期や Future は、「Boxed + asyncフラグ(or 専用 type_id=Future)」で統一し、`await` 時に解決。メタデータビットで「非同期値(未解決)」を示す。
|
||||
|
||||
**実装ステップ(具体)**
|
||||
- NyRT:
|
||||
- `crates/nyrt/include/nyash_abi.h` と `crates/nyrt/src/abi.rs` を追加(`NyashValueABI`、エンコード/デコード、予約 type_id、タグ定義)。
|
||||
- `FromAbi/ToAbi` トレイトと安全ヘルパ。
|
||||
- レジストリ:
|
||||
- `src/runtime/abi_registry.rs`(または既存の unified_registry に統合)で `(iface, method) -> NyashFunc*` を解決。
|
||||
- `nyash.toml` から ABI 種別と型宣言を読み取り登録。
|
||||
- ローダ/トランポリン:
|
||||
- `"c"` プラグイン呼び出しを包む小さな C→Nyash ラッパ(呼出前後で値配列を変換)。
|
||||
- マクロ:
|
||||
- `crates/nyash-macros` に `#[nyash_abi]` を実装。Rust関数に対して NyashFunc エクスポート+型ID登録。
|
||||
|
||||
**最小で得られる効果**
|
||||
- MIRやバックエンドは変更最小(もしくは無変更)で、呼出境界が統一。
|
||||
- まず整数/真偽/null/void が即値で走り、箱化コストが減少。
|
||||
- 既存プラグインは壊れず、徐々に `#[nyash_abi]` へ移行可能。
|
||||
|
||||
必要なら、この方針で最初のスケルトン(`nyash_abi.h/abi.rs`、トランポリン、レジストリ拡張)の差分案まで作ります。どの順から着手しますか?
|
||||
@ -0,0 +1,235 @@
|
||||
# Gemini先生とCodex先生のNyash ABI C実装についての深い考察
|
||||
|
||||
2025年9月2日、Nyashのセルフホスティング実現に向けて、2人のAI専門家が深い考察を提供しました。
|
||||
|
||||
## 🌟 Gemini先生の考察
|
||||
|
||||
### 総評
|
||||
**「技術的妥当性が高く、言語哲学とも合致した、極めて優れた設計」**
|
||||
|
||||
### 1. 技術的妥当性
|
||||
|
||||
#### C言語によるNyash ABI実装の現実性
|
||||
- **現実的です。** C言語は、OSのカーネルから他のプログラミング言語のランタイムまで、システムコンポーネントを記述するためのデファクトスタンダードです。
|
||||
- 参照カウント、動的な型情報(メソッドテーブルなど)の管理、メモリレイアウトの精密な制御といった、ABIの実装に必要な低レベルな操作は、すべてC言語の得意分野です。
|
||||
|
||||
#### TypeBoxシステムとの統合の自然さ
|
||||
- **極めて自然です。** TypeBoxがC ABIベースのプラグインシステムであるため、Cで実装されたNyash ABIをTypeBoxの一種として動的にロードする、というアイデアは既存の仕組みに完璧に乗っかります。
|
||||
- `abi_tag: 'NABI'` のような識別子で他のTypeBoxと区別するのも、クリーンで拡張性の高い方法です。
|
||||
- これは、システムの複雑性を爆発させることなく、コア機能の差し替えを実現するエレガントなソリューションです。
|
||||
|
||||
#### セルフホスティングへの道筋の明確さ
|
||||
- **明確かつ論理的です。** 提示された3段階の移行戦略は、セルフホスティングを達成するための古典的かつ実績のあるブートストラップ手順を踏んでいます。
|
||||
1. **Rust製コンパイラ** を使って、**C実装ABI**上で動く **Nyash製コンパイラ** をコンパイルする。
|
||||
2. 生成された **Nyash製コンパイラ** を使って、**それ自身を再度コンパイル**する。
|
||||
- この時点でRustツールチェインへの依存が切れ、セルフホスティングが達成されます。
|
||||
|
||||
### 2. 実装上の課題と解決策
|
||||
|
||||
#### メモリ管理の具体的な実装方法
|
||||
- **参照カウント:** 提案通り、参照カウントが基本になります。
|
||||
- 具体的には、Nyashの各Box(オブジェクト)が確保するメモリブロックのヘッダ部分に、参照カウント数を格納するフィールド(例: `atomic_size_t ref_count;`)を設けます。
|
||||
- `retain` / `release` は、このカウンタを**アトミック操作**で増減させる必要があります。これにより、マルチスレッド環境下でも安全なメモリ管理が保証されます。(C11の `<stdatomic.h>` が利用できます)
|
||||
- **循環参照への対策:** 初期段階では「循環参照は未定義動作(メモリリーク)」と割り切ることも可能ですが、長期的には**弱参照(Weak Reference)**の仕組みをABIレベルで導入することを強く推奨します。
|
||||
|
||||
#### 型安全性をどう保証するか
|
||||
- `type_id` が鍵となります。これは単なる整数ではなく、**グローバルな型情報テーブルへのインデックス(またはポインタ)**として機能させるべきです。
|
||||
- このテーブルには、型名、メソッドテーブル(メソッド名と関数ポインタのマップ)、親の型への参照などの情報が含まれます。
|
||||
- `invoke_method` を実行する際は、まずオブジェクトの `type_id` から型情報を引き、メソッドテーブル内に要求されたメソッドが存在するかを検証します。
|
||||
|
||||
#### パフォーマンスへの影響
|
||||
- **ディスパッチのオーバーヘッド:** 文字列比較によるメソッド検索は遅延の原因になります。これを緩和するため、コンパイル時にメソッド名をハッシュ化し、ランタイムでは整数(ハッシュ値)で比較する方法が効果的です。
|
||||
- **インライン値(Tagged Pointers):** `NyashValue_C` の設計はパフォーマンスの鍵です。64bit環境では、ポインタの下位ビットがアラインメントにより常に0であることを利用し、このビットを「タグ」として使うことで、小さな整数や真偽値などをポインタに直接埋め込めます。
|
||||
|
||||
### 3. 段階的移行戦略
|
||||
|
||||
#### 既存Rust実装との共存方法
|
||||
- 移行期間中、Nyashランタイムは**2種類のBox表現(Rustネイティブ版とC ABI版)を同時に扱える**必要があります。
|
||||
- 両者の間で値をやり取りするための**ブリッジ(変換層)**が不可欠です。
|
||||
- 最初は、コアな組み込み型はRust実装のまま、新しいプラグインや一部のモジュールをC ABI版で実装していくのが安全な進め方でしょう。
|
||||
|
||||
#### 互換性維持とテスト戦略
|
||||
- **ABIインターフェースの仕様固定:** `nyash_ops` の関数シグネチャとセマンティクス(所有権のルールなど)を一度定義したら、それを厳格に守ることが極めて重要です。
|
||||
- **大規模なテストスイート:** 移行を成功させるには、テストがすべてを決定します。
|
||||
1. **振る舞いの一致テスト:** 同じNyashソースコードを「Rust ABIのみ」「C ABIのみ」「両者混在」の3つのモードで実行し、出力や結果が完全に一致することを検証するテストスイートを構築します。
|
||||
2. **ユニットテスト:** Cで実装されたABIの各関数(`create_value`, `retain`, `release`など)を、Cのテストフレームワーク(例: `check`)で徹底的にテストします。
|
||||
3. **ベンチマーク:** 各フェーズでパフォーマンスを計測し、意図しない性能劣化(リグレッション)が起きていないかを常に監視します。
|
||||
|
||||
### 4. 哲学的な観点
|
||||
|
||||
#### 「Everything is Box」哲学との整合性
|
||||
- **完璧に整合しています。** これは「Everything is Box」という哲学の究極的な表現です。
|
||||
- 言語を構成するユーザーレベルのオブジェクトだけでなく、言語の実行基盤であるABIそのものまでもが「Box」という統一された概念で扱われる。
|
||||
- これは、LISPがコードとデータをS式で統一的に扱う美しさに通じる、自己言及的なエレガンスを持っています。
|
||||
|
||||
#### ABIをBoxとして扱うことの意味
|
||||
- これは、**言語の振る舞いを定義する「メタオブジェクト」**を導入することに他なりません。
|
||||
- これにより、Nyashは自分自身の実行セマンティクスすら、理論上は動的に差し替えたり拡張したりできる可能性を秘めることになります。
|
||||
- 例えば、デバッグ用のABI、プロファイリング用のABI、あるいは全く異なるメモリ管理モデル(例: GC)を持つABIを、同じTypeBoxの仕組みでロードすることも夢ではありません。
|
||||
|
||||
### 5. 他の選択肢との比較
|
||||
|
||||
#### Rust依存を維持する場合
|
||||
- 実装は楽ですが、言語としての独立性を永遠に失います。
|
||||
- Nyashをビルドするのに常にRustが必要というのは、言語のポータビリティと自己完結性を著しく損ないます。
|
||||
|
||||
#### 他のセルフホスティング戦略(例: LLVMへのコンパイル)
|
||||
- LLVM IRのような中間言語にコンパイルするのも強力な戦略です。
|
||||
- しかし、それはNyashの実行モデルをLLVMのモデルにマッピングする作業であり、依存先がRustからLLVMに変わるだけとも言えます。
|
||||
- ご提案の「ABIのBox化」は、**Nyash自身の実行モデルを維持したまま独立を果たす**という点で、より自己完結的で野心的なアプローチです。
|
||||
|
||||
#### 長期的な保守性
|
||||
- C ABIは、コンピューティングの世界で最も安定し、普遍的なインターフェースです。
|
||||
- ここに基盤を置くことで、Nyashは将来にわたって非常に高い安定性とポータビリティを獲得できます。
|
||||
|
||||
### 結論と最終的なアドバイス
|
||||
|
||||
ご提案の設計は、Nyashを真に独立した言語へと飛躍させ、その哲学を完成させるための、**実装可能かつ美しいブループリント**です。この方向性で進むことを強く推奨します。
|
||||
|
||||
**追加のアドバイス:**
|
||||
- **所有権ルールの厳密な定義:** ABIの関数呼び出しにおける値の所有権(誰が`release`の責任を持つか)を、ドキュメントで厳密に定義してください。
|
||||
- **エラーハンドリング:** `invoke_method`などが失敗した場合に、どのようにエラー情報(型ミスマッチ、メソッド未定義など)を呼び出し元に伝えるか。
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Codex先生の考察
|
||||
|
||||
### Executive Summary
|
||||
- Feasible and attractive: treating the Nyash ABI itself as a TypeBox (C ABI) is a clean way to de‑Rust the runtime boundary while aligning with "Everything is Box".
|
||||
- Key to success: keep the ABI surface minimal, versioned, allocator/context‑centric, and future‑proofed; treat reflection, invocation, and async as Boxes too.
|
||||
- Migration: start as a C shim over current Rust NyRT, run conformance tests in parallel, then swap implementations behind the same ABI, and finally reimplement in Nyash.
|
||||
|
||||
### Technical Feasibility
|
||||
- C implementation: realistic if the ABI is small, pure C (no exceptions), with explicit lifetimes, error/status returns, and allocator control. Similar precedents exist (CPython C-API, Lua C API, COM‑style vtables).
|
||||
- TypeBox integration: natural fit if the ABI object is "just another Box" exposing a stable vtable plus discovery via `nyash.toml`/plugin loader.
|
||||
- Self‑hosting path: clear when the compiler and runtime only depend on the C ABI Box; the compiler written in Nyash can build itself by linking against that Box.
|
||||
|
||||
### ABI Shape: Recommended Adjustments
|
||||
- Versioning and size: include `api_version` and `struct_size` in the TypeBox header so older loaders can detect compatibility.
|
||||
- Context first: most functions accept a `nyash_ctx*` holding allocator, scheduler, TLS, and feature flags; this avoids global state.
|
||||
- Status + out‑params: adopt `nyash_status` enum return, with outputs via out‑params; do not return ownership in a raw return position.
|
||||
- Object model: make every heap object implement retain/release via a common header/layout and expose a `nyash_obj_vtable` for method lookup.
|
||||
- Method invocation: prefer selector/handle lookup over raw string calls. Pattern:
|
||||
- `nyash_status lookup_selector(ctx, type_id, name, out nyash_selector*)`
|
||||
- `nyash_status call(ctx, obj, selector, argv, argc, out result)`
|
||||
- Allows caching and JIT fast paths; string lookup happens at most once per call‑site.
|
||||
|
||||
### Minimal core surface:
|
||||
- `retain(obj)`, `release(obj)`
|
||||
- `type_of(value) -> type_id`
|
||||
- `is_null`, `eq`, `hash`
|
||||
- `lookup_selector`, `call`
|
||||
- `create_value(type_id, data, flags)`
|
||||
- `alloc`, `free`, `mem_stats` via `nyash_allocator`
|
||||
- `error_new`, `error_code`, `error_message` (errors are Boxes)
|
||||
- Async primitives as Boxes (see below)
|
||||
- Binary hygiene: add `vendor_tag`, `abi_tag = 'NABI'`, reserved fields, and explicit alignment requirements.
|
||||
|
||||
### Value Layout and Type Identity
|
||||
- `nyash_value`: 16‑byte payload recommended for portability and JIT friendliness:
|
||||
- `u64 type_id; u64 payload; u64 meta;` or `u64[2] payload` if you want 128‑bit immediates later. Ensure 16‑byte alignment for vector ops and stable lowering in LLVM.
|
||||
- Inline vs heap:
|
||||
- Use low meta bits for immediate tags (small int, bool, null, small enum).
|
||||
- Heap payloads are opaque pointers to refcounted objects with a common header.
|
||||
- `type_id`: stable 64‑bit value with namespacing: top 16 bits vendor, 8 bits kind (struct, enum, trait/interface, array, func), remaining bits a stable hash of the fully‑qualified name + version.
|
||||
|
||||
### Memory Model
|
||||
- Intrusive refcount header: for all heap Boxes:
|
||||
- `struct header { atomic_uintptr_t rc; const nyash_obj_vtable* vtable; u64 type_id; u64 flags; }`
|
||||
- Thread safety: use atomic increments/decrements; defer destruction on the owning scheduler thread if the vtable marks "affine".
|
||||
- Cycle handling: three options; pick one early and document:
|
||||
- No cross‑cycle guarantee, plus "weakref" Boxes and explicit `close()` for graph owners (lowest complexity).
|
||||
- Trial‑deferred cycle detection (Bacon–Rajan) at safepoints.
|
||||
- Arena/region Boxes for compiler/IR lifetimes (good for self‑hosting).
|
||||
- Allocation: `nyash_allocator` in `nyash_ctx` allows embedding, custom arenas, and leak accounting. Every allocation path must route through it.
|
||||
|
||||
### Type Safety Guarantees
|
||||
- Validate `type_id` on every API entry that consumes a `nyash_value`. Return `NYASH_E_TYPE`.
|
||||
- Provide `nyash_cast(ctx, value, target_type_id, out value2)` that performs runtime checks (and potentially conversion) in one place.
|
||||
- For generics/parametric types, define a "type constructor" `type_id` plus encoded parameters hashed into a derived `type_id`.
|
||||
|
||||
### Performance Considerations
|
||||
- Selector caching: make `nyash_selector` a stable handle (contains resolved vtable slot + inline cache cookie). JIT can inline calls directly via the slot.
|
||||
- Avoid string dispatch in hot paths: strings resolve only once per call‑site; ABI preserves handles to avoid repeated lookups.
|
||||
- Small immediates: keep i31/i61, bool, small enum as immediates; `meta` carries tag; JIT emits zero‑branch unbox.
|
||||
- Error handling: status codes + separate error Box avoids exceptions; zero‑overhead fast path.
|
||||
- Marshaling: keep `argv` as a flat `nyash_value*` slice; for varargs heavy sites, support `nyash_tuple` Box to amortize allocations.
|
||||
- Layout stability: document alignment and endianness; avoid bitfields in the ABI; use masks and shifts.
|
||||
|
||||
### Async and Errors
|
||||
- Async as Box: define `nyash_future` TypeBox with
|
||||
- `poll(ctx, self, out ready, out result_or_err)`
|
||||
- `awaitable` integration at the language level; scheduler belongs to `nyash_ctx`.
|
||||
- Cancellation: `cancel(ctx, self, reason)`; guarantee idempotence.
|
||||
- Errors as Box: `nyash_error` carries `code`, `message`, `data` (Box). Every API returning non‑OK can also optionally fill an out error Box.
|
||||
|
||||
### Versioning and Compatibility
|
||||
- Feature negotiation: `supports(ctx, feature_id)` and a `capabilities` bitmask in the provider header.
|
||||
- Semantic version in header, strict size check: reject if `struct_size < required`.
|
||||
- Reserved fields: pad both the provider and object vtables with reserved pointers for forward extension.
|
||||
- Cross‑platform: define `NYASH_ABI_API` macro for visibility/calling convention; test x86_64 Linux, macOS, Windows (MSVC) early.
|
||||
|
||||
### Coexistence and Migration
|
||||
- Phase 1 (C shim over Rust):
|
||||
- Implement the C TypeBox provider whose functions forward to existing Rust NyRT via `extern "C"` glue. This validates the ABI without rewriting runtime logic.
|
||||
- Place under `plugins/nyash_abi_c/` and add mapping in `nyash.toml`.
|
||||
- Phase 2 (feature parity in C):
|
||||
- Incrementally reimplement hot paths: small immediates, retain/release, allocator, string, array. Keep complex features (async, reflection) temporarily forwarded to Rust until replaced.
|
||||
- Phase 3 (Nyash reimplementation):
|
||||
- Recode the C provider in Nyash, but keep the exact same C ABI surface via an AOT target producing the same symbols.
|
||||
- Coexistence:
|
||||
- Loader picks provider by name and version from `nyash.toml`. Keep Rust and C providers shippable concurrently; choose via env (`NYASH_ABI_IMPL=c,rust`).
|
||||
- Compatibility:
|
||||
- Add a conformance suite that exercises only the ABI; run it against both providers until results match.
|
||||
|
||||
### Testing Strategy
|
||||
- Conformance tests under `tests/abi/`:
|
||||
- Retain/release semantics, cross‑thread retain, immediate encoding, selector lookup caching, error propagation, async poll semantics.
|
||||
- Fuzz/property tests for `nyash_value` encode/decode and `type_id` canonicalization.
|
||||
- ABI stability:
|
||||
- Generate a C header from a single source of truth; forbid breaking changes unless version bumps.
|
||||
- Integration smokes:
|
||||
- Use `tools/llvm_smoke.sh` with `NYASH_C_ABI=1` to validate JIT/AOT end‑to‑end with the C provider loaded.
|
||||
|
||||
### Philosophical Fit
|
||||
- ABI‑as‑Box completes the idea that "runtime powers" are themselves values. It turns reflection, invocation, and scheduling into first‑class participants rather than privileged side channels.
|
||||
- Beauty comes from uniform dispatch: the compiler, runtime, and plugins all talk through the same Box vocabulary with selectors and capabilities.
|
||||
|
||||
### Alternatives and Trade‑offs
|
||||
- Keep Rust dependency:
|
||||
- Pro: faster to evolve; borrow‑checker catches many bugs.
|
||||
- Con: self‑hosting depends on Rust toolchain; ABI surface must still be C for plugins; harder for other ecosystems to embed.
|
||||
- WASM/WASI ABI:
|
||||
- Pro: portable sandbox, good for plugins.
|
||||
- Con: host interop and low‑latency GC/RC semantics are harder; JIT integration overhead.
|
||||
- Minimal micro‑kernel runtime in C + high‑level services in Rust:
|
||||
- Pro: balance; critical ABI in C, complex features in Rust behind handles.
|
||||
- Con: more moving parts, boundary crossings remain.
|
||||
|
||||
### Concrete Next Steps
|
||||
- Define and fix (freeze) a v0 ABI header:
|
||||
- Add `api_version`, `struct_size`, `nyash_ctx*`, `nyash_allocator*`, `nyash_status`, `nyash_value` 16‑byte layout, `retain/release`, `lookup_selector`, `call`, `error` primitives, and capability bits.
|
||||
- Scaffold `plugins/nyash_abi_c/`:
|
||||
- Provide a stub provider that returns `NYASH_E_NOT_IMPL` but passes header/version checks; wire it in `nyash.toml`.
|
||||
- Add a conformance test crate in `tests/abi/` that loads the provider by name and validates the header, alloc, retain/release, and immediate encodes.
|
||||
- Implement small immediates + retain/release + strings:
|
||||
- Backed by a simple thread‑safe RC and arena allocator in C.
|
||||
- Introduce selector caching in the VM/JIT:
|
||||
- Plumb `nyash_selector` handles in the call path; deopt to string lookup on cache miss.
|
||||
|
||||
If you want, I can draft the minimal v0 header (with versioning/capabilities and 16‑byte value layout) and a stub `plugins/nyash_abi_c` skeleton that loads in the current repo, plus a small conformance test to exercise header negotiation.
|
||||
|
||||
---
|
||||
|
||||
## まとめ
|
||||
|
||||
両AI専門家が一致して、Nyash ABIをC実装TypeBoxとして提供する設計案を高く評価しています。
|
||||
|
||||
共通する重要ポイント:
|
||||
1. **技術的に実現可能** - C言語でのABI実装は現実的で実績もある
|
||||
2. **哲学的に美しい** - Everything is Boxの究極的表現
|
||||
3. **段階的移行が鍵** - C Shim → フル実装 → Nyash再実装
|
||||
4. **パフォーマンス最適化** - Tagged Pointers、セレクターキャッシング
|
||||
5. **セルフホスティング実現** - Rust依存を完全に排除可能
|
||||
|
||||
この深い考察により、Nyashのセルフホスティングへの道筋が明確になりました。
|
||||
@ -0,0 +1,141 @@
|
||||
# Gemini先生のNyash ABI分析 (2025-09-01)
|
||||
|
||||
## 質問内容
|
||||
|
||||
Nyash ABIという統一ブリッジ規格について技術的相談です。
|
||||
|
||||
【背景】
|
||||
Nyashプログラミング言語で、あらゆる言語を繋ぐ統一的なABIを作る構想です。
|
||||
|
||||
【Nyash ABIの基本設計】
|
||||
```c
|
||||
// C ABIベースだが、Nyash型システムを載せる
|
||||
typedef struct NyashValue {
|
||||
uint64_t type_id; // 型識別子
|
||||
uint64_t box_handle; // Boxハンドル(Arc<T>のポインタ)
|
||||
uint64_t metadata; // 拡張用(async flag等)
|
||||
} NyashValue;
|
||||
|
||||
// 統一関数シグネチャ
|
||||
typedef NyashValue (*NyashFunc)(
|
||||
uint32_t argc,
|
||||
NyashValue* args,
|
||||
void* context
|
||||
);
|
||||
```
|
||||
|
||||
【目的】
|
||||
- Rust、Python、JavaScript、C++等、すべての言語とNyashを繋ぐ
|
||||
- C ABIの安定性 + Nyash型システムの表現力
|
||||
- Everything is Box哲学の外部拡張
|
||||
|
||||
【技術的な質問】
|
||||
1. このような統一ABIの前例はありますか?(COM、GObject等との比較)
|
||||
2. 3つのu64で十分な表現力がありますか?
|
||||
3. パフォーマンスへの影響をどう評価しますか?
|
||||
4. GCやメモリ管理の課題は?
|
||||
5. 非同期処理の統一的な扱い方は?
|
||||
|
||||
正直「間に挟むだけ」ですが、世界を変える可能性について深く考察してください。
|
||||
|
||||
## Gemini先生の回答
|
||||
|
||||
Nyash ABI構想、拝見しました。これは非常に野心的で、プログラミング言語の相互運用性における根源的な課題に挑戦する、素晴らしい着想だと思います。「間に挟むだけ」とご謙遜されていますが、その「中間層」こそが、ソフトウェア工学における最も困難で価値のある部分です。
|
||||
|
||||
ご提示いただいた設計とご質問に基づき、深く考察させていただきます。
|
||||
|
||||
---
|
||||
|
||||
### Nyash ABIの技術的考察
|
||||
|
||||
#### 1. このような統一ABIの前例はありますか?
|
||||
|
||||
はい、数多くの前例が存在します。それらとの比較から、Nyash ABIの独自性と課題が見えてきます。
|
||||
|
||||
* **COM (Component Object Model) / WinRT:** Microsoftが提唱したバイナリ互換性のあるコンポーネント技術。参照カウントによるメモリ管理、インターフェースクエリ(`QueryInterface`)による動的な型チェックなど、Nyash ABIの思想と非常に近いです。しかし、COMはレジストリへの登録やIDL(インターフェース定義言語)が必須で、Windows中心の複雑なエコシステムでした。Nyash ABIは、これをよりシンプルでクロスプラットフォームな形で実現しようとしていると解釈できます。
|
||||
|
||||
* **GObject:** C言語でオブジェクト指向プログラミングを実現するためのライブラリで、GTK+の基盤です。こちらも参照カウント、プロパティ、シグナル(イベント)といった高度な機能を持ち、動的な型システムを備えています。Nyash ABIは、GObjectの核心的なアイデア(型情報を持つ汎用的な値コンテナ)を、よりミニマルな形で抽出したものと言えるでしょう。
|
||||
|
||||
* **WebAssembly Component Model:** これが現在最も思想的に近い最先端の取り組みです。Wasmは当初、単純な数値型しかやり取りできませんでしたが、Component Modelは、文字列、レコード、バリアントといった高レベルな型を言語間でどう受け渡すかを定義する仕様です。その内部では、すべての高レベルな型が最終的に単純な数値型(`i32`, `i64`など)に「下げられ(lowering)」てWasmコアABIを通過し、受け取り側で再度高レベルな型に「上げられ(lifting)」ます。Nyash ABIの`NyashValue`は、この「高レベルな型を表現するコンテナ」そのものであり、Component Modelが目指す世界を、ネイティブコードの世界で直接実現しようとする試みと見なせます。
|
||||
|
||||
* **結論:** アイデア自体は新しいものではありません。しかし、これは弱みではなく、むしろ**「この方向性が正しいことの証明」**です。COMやGObjectの複雑さを乗り越え、Wasm Component Modelのような現代的なシンプルさをネイティブABIとして提供できるなら、大きな価値があります。
|
||||
|
||||
#### 2. 3つのu64で十分な表現力がありますか?
|
||||
|
||||
はい、**十分すぎるほどの表現力**を持っています。これは非常に優れた設計です。
|
||||
|
||||
* `type_id (uint64_t)`: 64bitもあれば、型名のハッシュ値や、階層的な型IDなど、事実上無限の型を表現できます。衝突の心配はまずありません。
|
||||
* `box_handle (uint64_t)`: 64bitアーキテクチャのポインタを格納するのに最適です。`Arc<T>`のポインタをそのまま格納することで、言語間で所有権(参照カウント)を共有する核心的な役割を担います。
|
||||
* `metadata (uint64_t)`: このフィールドが鍵です。64個のビットフラグとして使えます。
|
||||
* 非同期フラグ (`IS_ASYNC`)
|
||||
* ミュータブルフラグ (`IS_MUTABLE`)
|
||||
* 所有権ヒント(呼び出し側が所有権を放棄するかどうか等)
|
||||
* **インライン値の格納:** `box_handle`が`NULL`の場合、この`metadata`フィールドに小さな整数や浮動小数点数を直接格納する(ポインタタグ付けのような)最適化も可能です。これにより、単純な数値の受け渡しでヒープ確保が不要になります。
|
||||
|
||||
この`3 * uint64_t`の設計は、シンプルさ、拡張性、そして最適化の余地を兼ね備えた、非常に堅牢な基盤です。
|
||||
|
||||
#### 3. パフォーマンスへの影響をどう評価しますか?
|
||||
|
||||
これは最大のトレードオフです。
|
||||
|
||||
* **オーバーヘッド:**
|
||||
1. **間接参照:** すべての値にアクセスするために、`NyashValue` -> `box_handle` -> `Arc<T>` -> `T`というポインタの連鎖をたどる必要があり、キャッシュ効率が悪化する可能性があります。
|
||||
2. **ヒープ確保:** すべてをBox化(`Arc`化)するため、単純な整数を渡すだけでもヒープ確保と参照カウントのオーバーヘッドが発生します。(前述のインライン値最適化で緩和可能)
|
||||
3. **動的ディスパッチ:** `type_id`に基づいた実行時の型チェックとディスパッチは、静的な関数呼び出しよりも遅くなります。
|
||||
|
||||
* **評価方法:**
|
||||
* **粒度(Granularity)が重要です。**
|
||||
* **粗い粒度(Chunky):** 大きなデータ(画像データ、長いテキスト)を一度渡して、言語の内部で長時間処理する場合は、ABIのオーバーヘッドは無視できるほど小さくなります。これはNyash ABIが得意とする領域です。
|
||||
* **細かい粒度(Chatty):** ループの中で、小さな値を何度も頻繁にやり取りする場合(例: `for i in 0..1_000_000 { foreign_add(1, 2) }`)、オーバーヘッドが致命的になります。
|
||||
* **ベンチマーク:** C言語のネイティブ関数呼び出しをベースライン(1.0)として、以下のようなシナリオで性能を測定すべきです。
|
||||
* 整数、浮動小数点数の受け渡し
|
||||
* 短い文字列、長い文字列の受け渡し
|
||||
* 大きなバイト配列の受け渡し
|
||||
* コールバック関数(Nyash -> C -> Nyash)の呼び出し
|
||||
|
||||
パフォーマンスが最重要視される場面では、このABIをバイパスする「高速パス」を用意することも検討すべきでしょう。
|
||||
|
||||
#### 4. GCやメモリ管理の課題は?
|
||||
|
||||
`Arc<T>`(アトミック参照カウント)をベースにしているのは素晴らしい選択です。これにより、RustやC++のような手動メモリ管理言語との連携は非常に堅牢になります。
|
||||
|
||||
**最大の課題は、GC(ガベージコレクション)を持つ言語(Python, JavaScript, Javaなど)との連携です。**
|
||||
|
||||
* **課題:** GCを持つ言語のオブジェクトをNyash側で`Arc`でラップし、同時にNyashのオブジェクトをGC言語側で参照すると、**循環参照**が容易に発生し、メモリリークの原因となります。
|
||||
* **解決策:**
|
||||
1. **プロキシオブジェクト:** 各言語のバインディング層で、「プロキシオブジェクト」を生成します。例えば、Python側でNyashオブジェクトを扱う場合、その`__del__`メソッドで`Arc`の参照カウントをデクリメントするPythonクラスを作ります。
|
||||
2. **弱参照(Weak References):** 循環を断ち切るために、片方の参照を弱参照にする必要があります。`Arc`は`Weak`へのダウングレードをサポートしているため、これを活用できます。
|
||||
3. **明示的な破棄:** `dispose()`や`close()`のようなメソッドを公開し、ユーザーが手動でリソースを解放できるようにすることも、確実な方法です。
|
||||
|
||||
このGCとの連携は、バインディングライブラリの設計で最も注意を要する部分です。
|
||||
|
||||
#### 5. 非同期処理の統一的な扱い方は?
|
||||
|
||||
`metadata`フィールドがここでも活躍します。
|
||||
|
||||
* **統一Future/Promiseモデル:**
|
||||
1. 非同期関数は、`IS_ASYNC`フラグを立てた`NyashValue`を即座に返します。
|
||||
2. この`box_handle`は、`Box<dyn NyashFuture>`のような、非同期処理の状態を持つオブジェクトを指します。
|
||||
3. `NyashFuture`トレイト(インターフェース)には、`poll(callback: NyashValue)`のようなメソッドを定義します。
|
||||
4. 各言語のバインディング層が、この`NyashFuture`をその言語の非同期プリミティブ(Rustの`Future`、JSの`Promise`、Pythonの`awaitable`)に変換します。
|
||||
5. `poll`メソッドに渡す`callback`もまた`NyashValue`(関数オブジェクト)であるため、言語をまたいで非同期処理の結果を返すことができます。
|
||||
|
||||
これにより、ある言語のイベントループが、別の言語の非同期処理を駆動することが可能になります。これは非常に強力です。
|
||||
|
||||
---
|
||||
|
||||
### 世界を変える可能性についての考察
|
||||
|
||||
「間に挟むだけ」のレイヤーが世界を変えた例は、歴史上数多くあります。コンテナリゼーション(Docker)、仮想化(VMware)、そしてウェブ(HTTP/HTML)も、すべては抽象化レイヤーです。Nyash ABIもその可能性を秘めています。
|
||||
|
||||
* **真のポリグロット・エコシステムの実現:** 現在、言語間の連携は多大な努力を要する「特殊な作業」です。Nyash ABIが普及すれば、それが「当たり前の作業」に変わります。高性能な数値計算はRustで、AIモデルはPythonで、UIはJavaScriptで書き、それらをあたかも単一言語内のモジュールのようにシームレスに組み合わせる。これが当たり前になれば、開発者は「どの言語で作るか」ではなく**「どのタスクにどの言語が最適か」**だけを考えればよくなります。
|
||||
|
||||
* **ソフトウェア資産の再利用と延命:** C++で書かれた巨大なレガシーライブラリ、科学技術計算で使われるFortranのコード、そういったものを一度`NyashValue`でラップしてしまえば、未来のどんな言語からも安全に呼び出せる「不滅のコンポーネント」と化します。これはソフトウェア資産の価値を最大化します。
|
||||
|
||||
* **複雑性の削減:** `N`個の言語と`M`個のライブラリを繋ぐのに、現状では`N*M`通りのバインディングが必要です。Nyash ABIが中心にあれば、`N+M`個のバインディングで済みます。これはエコシステム全体の複雑性を劇的に削減します。
|
||||
|
||||
* **新しいアーキテクチャの創出:** プラグインシステム、ゲームのMOD(改造)、動的なサーバー機能拡張などが、言語に依存しない統一的な方法で実現できます。Nyash ABIは、単なるFFI(Foreign Function Interface)を超え、**ユニバーサルなプラグイン・アーキテクチャの基盤**となり得ます。
|
||||
|
||||
**結論として、Nyash ABI構想は、単なる技術的挑戦ではなく、ソフトウェア開発のあり方そのものを変革する可能性を秘めた壮大なビジョンです。** パフォーマンスのトレードオフを理解し、GC言語との連携という困難な課題を乗り越え、高品質な多言語バインディングを提供できたとき、この「間に挟むだけ」のレイヤーが、ソフトウェアの世界を繋ぐ、不可欠なインフラになるでしょう。
|
||||
|
||||
ぜひ、この挑戦を続けてください。応援しています。
|
||||
@ -0,0 +1,102 @@
|
||||
# Nyash ABI革命 - AI大会議統合まとめ (2025-09-01)
|
||||
|
||||
## 🎯 結論:「間に挟むだけ」が世界を変える
|
||||
|
||||
Gemini先生(哲学的視点)とCodex先生(実装視点)の両方が、Nyash ABIの革命的可能性を認めた。
|
||||
|
||||
## 📊 両先生の共通認識
|
||||
|
||||
### 1. 既存技術との比較
|
||||
- **COM/GObject**: 複雑すぎる先行例
|
||||
- **WASM Component Model**: 最も思想的に近い
|
||||
- **Nyash ABI**: 上記の良いとこ取り+シンプルさ
|
||||
|
||||
### 2. 3×u64の表現力は十分
|
||||
```c
|
||||
typedef struct NyashValue {
|
||||
uint64_t type_id; // 無限の型を表現可能
|
||||
uint64_t box_handle; // Arc<T>ポインタ格納に最適
|
||||
uint64_t metadata; // 64bitフラグ+インライン値
|
||||
} NyashValue;
|
||||
```
|
||||
|
||||
### 3. 主要な技術的課題
|
||||
- **パフォーマンス**: 粒度による(粗い粒度なら影響小)
|
||||
- **GC連携**: 循環参照が最大の課題
|
||||
- **非同期処理**: metadataフラグで統一可能
|
||||
|
||||
## 🔧 実装戦略の統合
|
||||
|
||||
### Phase 1: 最小実装(MIR変更なし)
|
||||
```rust
|
||||
// 既存のExternCallをそのまま使用
|
||||
MirInstruction::ExternCall {
|
||||
iface_name,
|
||||
method_name,
|
||||
args,
|
||||
effects
|
||||
}
|
||||
// ランタイムでNyashFunc統一呼び出しに変換
|
||||
```
|
||||
|
||||
### Phase 2: インライン最適化
|
||||
```
|
||||
metadata上位4bit = タグ
|
||||
- 0: Boxed(通常のBox)
|
||||
- 1: I63(63bit整数を直接格納)
|
||||
- 2: Bool(真偽値)
|
||||
- 3: Null
|
||||
- 4: Void
|
||||
- 5: Reserved(Future/Async)
|
||||
```
|
||||
|
||||
### Phase 3: 段階的移行
|
||||
```toml
|
||||
# nyash.toml
|
||||
[plugin.math]
|
||||
abi = "nyash" # 新ABI
|
||||
# abi = "c" # 旧ABI(デフォルト)
|
||||
```
|
||||
|
||||
## 🌟 革命的インパクト
|
||||
|
||||
### Gemini先生の視点
|
||||
> 「単なる技術的挑戦ではなく、ソフトウェア開発のあり方そのものを変革する可能性を秘めた壮大なビジョン」
|
||||
|
||||
- **真のポリグロット・エコシステム**: 言語の壁が消える
|
||||
- **ソフトウェア資産の不滅化**: レガシーコードが永遠に生きる
|
||||
- **複雑性の劇的削減**: N×M → N+M のバインディング
|
||||
|
||||
### Codex先生の視点
|
||||
> 「まず壊さず、少しずつ置き換える」
|
||||
|
||||
- **即座の効果**: 整数/Bool/Null/Voidの即値化
|
||||
- **後方互換**: 既存プラグインは自動トランポリン
|
||||
- **段階的移行**: nyash.tomlで個別切り替え
|
||||
|
||||
## 🚀 実装優先順位
|
||||
|
||||
1. **nyash_abi.h/abi.rs**: 基本型定義とエンコード/デコード
|
||||
2. **トランポリン層**: 既存C ABI→Nyash ABI変換
|
||||
3. **#[nyash_abi]マクロ**: 自動バインディング生成
|
||||
4. **型レジストリ**: 64bitハッシュによる型ID管理
|
||||
5. **GC協調API**: trace/finalize/weak参照
|
||||
|
||||
## 💡 「Everything is Box」から「Everything is NyashValue」へ
|
||||
|
||||
Nyashの哲学が、言語の境界を超えて世界を統一する。
|
||||
|
||||
- **内部**: NyashValue enum(Rust表現)
|
||||
- **境界**: NyashValue struct(C ABI表現)
|
||||
- **統一**: すべての言語がNyashValueで会話
|
||||
|
||||
## 📝 次のアクション
|
||||
|
||||
1. Phase 12ドキュメントとの比較・統合
|
||||
2. nyash_abi.h の初版作成
|
||||
3. 最小トランポリン実装の検証
|
||||
4. 既存プラグイン1つでの動作確認
|
||||
|
||||
---
|
||||
|
||||
*「間に挟むだけ」が、プログラミング言語の未来を変える。*
|
||||
@ -0,0 +1,100 @@
|
||||
# Phase 12 × Nyash ABI 統合戦略
|
||||
|
||||
## 🎯 核心的発見
|
||||
|
||||
Phase 12(Nyashスクリプトプラグイン)とNyash ABI(多言語ブリッジ)は、**同じ統一インターフェースの内側と外側**だった!
|
||||
|
||||
## 🏗️ 統合アーキテクチャ
|
||||
|
||||
```
|
||||
外部言語(Python/JS/C++/Rust等)
|
||||
↓
|
||||
┌─────────────────────────────────┐
|
||||
│ Nyash ABI (C境界) │ ← 3×u64構造体
|
||||
│ NyashFunc統一呼び出し規約 │
|
||||
├─────────────────────────────────┤
|
||||
│ 統一レジストリ・ディスパッチャ │
|
||||
├─────────────────────────────────┤
|
||||
│ BoxInterface (Rust内部) │ ← trait実装
|
||||
│ invoke/get_methods/init/drop │
|
||||
├─────────────┬─────────────────┤
|
||||
│ Nyashスクリプト │ ネイティブ │
|
||||
│ プラグイン │ プラグイン │
|
||||
└────────────┴─────────────────┘
|
||||
```
|
||||
|
||||
## 🔧 実装フェーズ
|
||||
|
||||
### Phase 1: 基盤統合(1-2週間)
|
||||
- BoxInterfaceにNyashFunc変換レイヤー追加
|
||||
- NyashValue(enum)とNyashValue(struct)の相互変換
|
||||
- method_idをmetadataフィールドに統合
|
||||
|
||||
### Phase 2: export box拡張(2-3週間)
|
||||
```nyash
|
||||
export box MyPlugin {
|
||||
// 以下を自動生成:
|
||||
// 1. BoxInterface実装
|
||||
// 2. NyashFunc extern "C"関数
|
||||
// 3. 型レジストリ登録
|
||||
}
|
||||
```
|
||||
|
||||
### Phase 3: 多言語バインディング(3-4週間)
|
||||
- Python: `@nyash_plugin`デコレータ
|
||||
- JavaScript: `NyashPlugin`クラス
|
||||
- Rust: `#[nyash_abi]`マクロ
|
||||
- C++: `NYASH_PLUGIN`マクロ
|
||||
|
||||
### Phase 4: 最適化(継続的)
|
||||
- インライン値(整数/Bool)の高速化
|
||||
- method_id による高速ディスパッチ
|
||||
- JIT/AOTでの境界最適化
|
||||
|
||||
## 💡 革命的な統合効果
|
||||
|
||||
### 1. プラグイン開発の完全民主化
|
||||
- **Nyashで書く**: ビルド不要、即座に実行
|
||||
- **他言語で書く**: Nyash ABIで統一的に接続
|
||||
- **相互運用**: NyashプラグインをPythonから、PythonプラグインをNyashから
|
||||
|
||||
### 2. エコシステムの爆発的拡大
|
||||
```
|
||||
従来: Rust/C++開発者のみ → 狭いエコシステム
|
||||
統合後: 全言語の開発者 → 巨大エコシステム
|
||||
```
|
||||
|
||||
### 3. 実装の簡潔性
|
||||
- MIR変更最小(ExternCallのまま)
|
||||
- 既存プラグイン後方互換(トランポリン自動生成)
|
||||
- 段階的移行(nyash.tomlで制御)
|
||||
|
||||
## 📊 技術的シナジー
|
||||
|
||||
| Phase 12の強み | Nyash ABIの強み | 統合による相乗効果 |
|
||||
|---------------|----------------|------------------|
|
||||
| スクリプトで即開発 | 多言語対応 | どの言語でも即開発 |
|
||||
| BoxInterface統一 | C ABI安定性 | 内外統一インターフェース |
|
||||
| ホットリロード | メモリ安全 | 安全な動的更新 |
|
||||
| 既存Box活用 | インライン最適化 | 高速かつ柔軟 |
|
||||
|
||||
## 🚀 次期アクション
|
||||
|
||||
1. **仕様統合**: BoxInterfaceとNyashFuncの正確なマッピング定義
|
||||
2. **プロトタイプ**: 1つの既存プラグインで両方式を実装
|
||||
3. **ベンチマーク**: 性能影響の測定(特にインライン値)
|
||||
4. **ドキュメント**: 統合APIリファレンス作成
|
||||
|
||||
## 🌟 ビジョン
|
||||
|
||||
**「Everything is Box」が「Everything can be a Plugin」へ進化**
|
||||
|
||||
- Nyashで書いたコードが、そのままプラグイン
|
||||
- どの言語で書いたコードも、Nyashプラグイン
|
||||
- プラグインがプラグインを呼び、言語の壁が消える
|
||||
|
||||
これは単なる技術統合ではなく、**プログラミングの未来そのもの**。
|
||||
|
||||
---
|
||||
|
||||
*Phase 12とNyash ABIの統合により、史上最も開かれたプラグインエコシステムが誕生する。*
|
||||
255
docs/archive/roadmap/phases/phase-12/migration-guide.md
Normal file
255
docs/archive/roadmap/phases/phase-12/migration-guide.md
Normal file
@ -0,0 +1,255 @@
|
||||
# 統一TypeBox ABIへの移行ガイド
|
||||
|
||||
## 📋 概要
|
||||
|
||||
このガイドでは、既存のC ABIプラグインやTypeBoxプラグインを、新しい統一TypeBox ABIに移行する方法を説明します。
|
||||
|
||||
**良いニュース**:既存のプラグインは**そのまま動作し続けます**!段階的に移行できます。
|
||||
|
||||
## 🎯 移行のメリット
|
||||
|
||||
1. **パフォーマンス向上**:最大33倍の高速化(JIT最適化時)
|
||||
2. **プラグイン間連携**:他のBoxを自由に作成・使用可能
|
||||
3. **将来性**:async/await、並列実行、GPU対応への道
|
||||
4. **保守性向上**:統一された1つの形式
|
||||
|
||||
## 🔄 移行パターン
|
||||
|
||||
### パターン1: 既存のC ABIプラグインから移行
|
||||
|
||||
#### Before(旧C ABI)
|
||||
```c
|
||||
// 旧形式:3つの関数をエクスポート
|
||||
void* string_create(const char* initial) {
|
||||
return strdup(initial);
|
||||
}
|
||||
|
||||
void* string_method(void* self, const char* method,
|
||||
void** args, int argc) {
|
||||
if (strcmp(method, "length") == 0) {
|
||||
int* result = malloc(sizeof(int));
|
||||
*result = strlen((char*)self);
|
||||
return result;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void string_destroy(void* self) {
|
||||
free(self);
|
||||
}
|
||||
```
|
||||
|
||||
#### After(統一TypeBox)
|
||||
```c
|
||||
#include "nyash_typebox.h"
|
||||
|
||||
// メソッドIDを定義(高速化のため)
|
||||
#define METHOD_LENGTH 1
|
||||
|
||||
// resolve関数を追加
|
||||
uint32_t string_resolve(const char* name) {
|
||||
if (strcmp(name, "length") == 0) return METHOD_LENGTH;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 高速版メソッドを追加
|
||||
NyResult string_invoke_id(void* self, uint32_t id,
|
||||
NyValue* args, int argc) {
|
||||
switch (id) {
|
||||
case METHOD_LENGTH:
|
||||
return ny_result_ok(ny_value_int(strlen((char*)self)));
|
||||
default:
|
||||
return ny_result_error("Unknown method");
|
||||
}
|
||||
}
|
||||
|
||||
// TypeBox構造体として統合
|
||||
const NyashTypeBox nyash_typebox_StringBox = {
|
||||
.abi_tag = 0x54594258, // 'TYBX'
|
||||
.version = 1,
|
||||
.struct_size = sizeof(NyashTypeBox),
|
||||
.name = "StringBox",
|
||||
|
||||
// 既存の関数をそのまま使用
|
||||
.create = (void*)string_create,
|
||||
.destroy = string_destroy,
|
||||
.method = string_method, // 互換性のため残す
|
||||
|
||||
// 新規追加
|
||||
.resolve = string_resolve,
|
||||
.invoke_id = string_invoke_id,
|
||||
|
||||
.capabilities = NYASH_CAP_THREAD_SAFE,
|
||||
.reserved = {0}
|
||||
};
|
||||
```
|
||||
|
||||
### パターン2: 最小限の移行(互換モード)
|
||||
|
||||
既存のコードをほぼ変更せずに、TypeBox形式でラップ:
|
||||
|
||||
```c
|
||||
// 既存の関数はそのまま
|
||||
extern void* my_create(const char*);
|
||||
extern void* my_method(void*, const char*, void**, int);
|
||||
extern void my_destroy(void*);
|
||||
|
||||
// ラッパーを追加するだけ
|
||||
const NyashTypeBox nyash_typebox_MyBox = {
|
||||
.abi_tag = 0x54594258,
|
||||
.version = 1,
|
||||
.struct_size = sizeof(NyashTypeBox),
|
||||
.name = "MyBox",
|
||||
|
||||
.create = (void*)my_create,
|
||||
.destroy = my_destroy,
|
||||
.method = my_method,
|
||||
|
||||
// 高速版は後で追加可能
|
||||
.resolve = NULL,
|
||||
.invoke_id = NULL,
|
||||
|
||||
.capabilities = 0,
|
||||
.reserved = {0}
|
||||
};
|
||||
```
|
||||
|
||||
## 🛠️ 移行ツール
|
||||
|
||||
### 自動変換ツール
|
||||
|
||||
```bash
|
||||
# 既存のC ABIプラグインを分析して、TypeBoxラッパーを生成
|
||||
nyash-plugin migrate --input=old_plugin.c --output=new_plugin.c
|
||||
|
||||
# 生成されるコード例:
|
||||
# - TypeBox構造体定義
|
||||
# - resolve関数のスケルトン
|
||||
# - invoke_id関数のスケルトン
|
||||
```
|
||||
|
||||
### 検証ツール
|
||||
|
||||
```bash
|
||||
# 移行後のプラグインが正しく動作するかチェック
|
||||
nyash-plugin validate new_plugin.so
|
||||
|
||||
# 出力例:
|
||||
# ✅ ABI tag: OK (TYBX)
|
||||
# ✅ Version: OK (1)
|
||||
# ✅ Basic functions: OK
|
||||
# ⚠️ Performance functions: Not implemented (optional)
|
||||
# ✅ Thread safety: Declared
|
||||
```
|
||||
|
||||
## 📊 段階的移行戦略
|
||||
|
||||
### Step 1: 互換ラッパー(1日)
|
||||
- 最小限の変更でTypeBox形式に
|
||||
- 既存の機能はそのまま維持
|
||||
- テストがすべてパス
|
||||
|
||||
### Step 2: メソッドID化(1週間)
|
||||
- resolve関数を実装
|
||||
- 頻出メソッドにIDを割り当て
|
||||
- 10-20%の性能向上
|
||||
|
||||
### Step 3: 高速実装(2週間)
|
||||
- invoke_id関数を実装
|
||||
- NyValue形式に対応
|
||||
- 3-5倍の性能向上
|
||||
|
||||
### Step 4: 最適化(1ヶ月)
|
||||
- JITフレンドリーな実装に
|
||||
- インラインキャッシング対応
|
||||
- 最大33倍の性能向上
|
||||
|
||||
## 🚨 注意事項
|
||||
|
||||
### メモリ管理
|
||||
- NyValueは**ホスト管理**のメモリを使用
|
||||
- 戻り値の所有権ルールに注意:
|
||||
- `NYASH_OWN_TRANSFER`: 呼び出し元が解放責任
|
||||
- `NYASH_OWN_BORROW`: プラグインが管理、触らない
|
||||
- `NYASH_OWN_CLONE`: コピーして返す
|
||||
|
||||
### スレッド安全性
|
||||
- `NYASH_CAP_THREAD_SAFE`フラグを正しく設定
|
||||
- グローバル状態を避ける
|
||||
- 必要ならmutexで保護
|
||||
|
||||
### エラーハンドリング
|
||||
```c
|
||||
// 旧:NULLを返す
|
||||
return NULL;
|
||||
|
||||
// 新:明示的なエラー
|
||||
return ny_result_error("Invalid argument");
|
||||
```
|
||||
|
||||
## 💡 ベストプラクティス
|
||||
|
||||
### 1. メソッドIDは列挙型で管理
|
||||
```c
|
||||
enum {
|
||||
METHOD_NONE = 0,
|
||||
METHOD_LENGTH = 1,
|
||||
METHOD_TO_UPPER = 2,
|
||||
METHOD_CONCAT = 3,
|
||||
// ...
|
||||
};
|
||||
```
|
||||
|
||||
### 2. 型情報を提供
|
||||
```c
|
||||
const char* my_get_type_info(void) {
|
||||
return "{"
|
||||
"\"methods\": ["
|
||||
" {\"name\": \"length\", \"returns\": \"int\"},"
|
||||
" {\"name\": \"toUpper\", \"returns\": \"string\"}"
|
||||
"]"
|
||||
"}";
|
||||
}
|
||||
```
|
||||
|
||||
### 3. プラグイン間連携を活用
|
||||
```c
|
||||
// 他のBoxを使う例
|
||||
NyashTypeBox* array_type = ny_host_get_typebox("ArrayBox");
|
||||
void* array = array_type->create(NULL);
|
||||
```
|
||||
|
||||
## 📅 移行スケジュール
|
||||
|
||||
| フェーズ | 期間 | 内容 |
|
||||
|---------|------|------|
|
||||
| 現在 | - | 既存プラグインはそのまま動作 |
|
||||
| Phase 1 | 3ヶ月 | 新規プラグインは統一形式推奨 |
|
||||
| Phase 2 | 6ヶ月 | 移行ツール・ガイド充実 |
|
||||
| Phase 3 | 9ヶ月 | パフォーマンス最適化 |
|
||||
| Phase 4 | 12ヶ月 | 旧形式を非推奨に |
|
||||
|
||||
## 🆘 サポート
|
||||
|
||||
### ドキュメント
|
||||
- [統一TypeBox ABI仕様](./unified-typebox-abi.md)
|
||||
- [API詳細リファレンス](./specs/typebox-api-reference.md)
|
||||
- [サンプルコード集](./examples/)
|
||||
|
||||
### コミュニティ
|
||||
- Discord: #plugin-dev チャンネル
|
||||
- GitHub: Issues/Discussionsで質問歓迎
|
||||
|
||||
### 移行支援
|
||||
- 移行の相談・レビュー受付中
|
||||
- 大規模プラグインの移行支援あり
|
||||
|
||||
## 🎯 まとめ
|
||||
|
||||
統一TypeBox ABIへの移行は:
|
||||
- ✅ **段階的**:急ぐ必要なし
|
||||
- ✅ **互換性重視**:既存コードを保護
|
||||
- ✅ **ツール充実**:自動化でラクラク
|
||||
- ✅ **大きなメリット**:性能・機能・将来性
|
||||
|
||||
**今すぐ始められる小さな一歩から!**
|
||||
285
docs/archive/roadmap/phases/phase-12/nyash-script-plugins.md
Normal file
285
docs/archive/roadmap/phases/phase-12/nyash-script-plugins.md
Normal file
@ -0,0 +1,285 @@
|
||||
# Nyashスクリプトプラグイン
|
||||
|
||||
## 📦 概要
|
||||
|
||||
Nyashスクリプトプラグインは、**最もNyashらしいプラグインシステム**です。特別な仕組みは不要で、ユーザー定義Boxがそのままプラグインとして機能します。
|
||||
|
||||
> 💡 **「Everything is Box」哲学の究極形**
|
||||
> プラグインも、ただのBoxです!
|
||||
|
||||
## 🎯 特徴
|
||||
|
||||
### 究極のシンプルさ
|
||||
- **特別なAPIは不要** - 普通のNyashコードを書くだけ
|
||||
- **学習コストゼロ** - Nyashを知っていれば書ける
|
||||
- **即座に使える** - コンパイル不要、そのまま実行
|
||||
|
||||
### 完全な統合
|
||||
- Nyashの全機能が使える
|
||||
- 他のプラグイン(C ABI/Nyash ABI)も自由に組み合わせ可能
|
||||
- デバッグも通常のNyashコードと同じ
|
||||
|
||||
### 高い生産性
|
||||
- ホットリロード対応(開発中に即反映)
|
||||
- テストが簡単(通常のNyashテストフレームワーク使用可)
|
||||
- ドキュメント自動生成対応
|
||||
|
||||
## 📝 実装例
|
||||
|
||||
### 1. シンプルなユーティリティBox
|
||||
|
||||
```nyash
|
||||
# math_utils.hako - 数学ユーティリティプラグイン
|
||||
|
||||
box MathUtils {
|
||||
init { }
|
||||
|
||||
# 階乗を計算
|
||||
factorial(n) {
|
||||
if n <= 1 {
|
||||
return 1
|
||||
}
|
||||
return n * me.factorial(n - 1)
|
||||
}
|
||||
|
||||
# フィボナッチ数列
|
||||
fibonacci(n) {
|
||||
if n <= 1 {
|
||||
return n
|
||||
}
|
||||
return me.fibonacci(n - 1) + me.fibonacci(n - 2)
|
||||
}
|
||||
|
||||
# 最大公約数
|
||||
gcd(a, b) {
|
||||
if b == 0 {
|
||||
return a
|
||||
}
|
||||
return me.gcd(b, a % b)
|
||||
}
|
||||
}
|
||||
|
||||
# エクスポート(将来のexport構文)
|
||||
# export MathUtils
|
||||
```
|
||||
|
||||
### 2. 他のプラグインと組み合わせる例
|
||||
|
||||
```nyash
|
||||
# data_processor.hako - データ処理プラグイン
|
||||
|
||||
box DataProcessor {
|
||||
init { file, math, cache }
|
||||
|
||||
birth(outputPath) {
|
||||
me.file = new FileBox() # C ABIプラグイン
|
||||
me.math = new MathBox() # C ABIプラグイン
|
||||
me.cache = new MapBox() # C ABIプラグイン
|
||||
}
|
||||
|
||||
# CSVデータを処理
|
||||
processCSV(inputPath, outputPath) {
|
||||
# ファイル読み込み
|
||||
local data = me.file.read(inputPath)
|
||||
local lines = data.split("\n")
|
||||
|
||||
# 各行を処理
|
||||
local results = new ArrayBox()
|
||||
for line in lines {
|
||||
local values = line.split(",")
|
||||
local sum = 0
|
||||
|
||||
for value in values {
|
||||
local num = value.toFloat()
|
||||
# 三角関数で変換(C ABIのMathBox使用)
|
||||
local transformed = me.math.sin(num)
|
||||
sum = sum + transformed
|
||||
}
|
||||
|
||||
results.push(sum)
|
||||
}
|
||||
|
||||
# 結果を保存
|
||||
me.file.write(outputPath, results.join("\n"))
|
||||
return results
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 高度なプラグイン - P2Pノード拡張
|
||||
|
||||
```nyash
|
||||
# mesh_node.hako - P2Pメッシュネットワークノード
|
||||
|
||||
box MeshNode from P2PBox {
|
||||
init { routing, peers, messageHandlers }
|
||||
|
||||
pack(nodeId, transport) {
|
||||
# 親クラス(P2PBox)の初期化
|
||||
from P2PBox.pack(nodeId, transport)
|
||||
|
||||
# 追加の初期化
|
||||
me.routing = new RoutingTable()
|
||||
me.peers = new MapBox()
|
||||
me.messageHandlers = new MapBox()
|
||||
|
||||
# デフォルトハンドラー登録
|
||||
me.registerHandler("ping", me.handlePing)
|
||||
me.registerHandler("route", me.handleRoute)
|
||||
}
|
||||
|
||||
# メッセージハンドラー登録
|
||||
registerHandler(messageType, handler) {
|
||||
me.messageHandlers.set(messageType, handler)
|
||||
}
|
||||
|
||||
# オーバーライド: メッセージ送信時にルーティング
|
||||
override send(target, message) {
|
||||
# 最適なルートを探す
|
||||
local nextHop = me.routing.findBestRoute(target)
|
||||
|
||||
if nextHop == null {
|
||||
# 直接送信を試みる
|
||||
return from P2PBox.send(target, message)
|
||||
}
|
||||
|
||||
# ルーティング経由で送信
|
||||
local routedMessage = {
|
||||
type: "route",
|
||||
finalTarget: target,
|
||||
payload: message
|
||||
}
|
||||
|
||||
return from P2PBox.send(nextHop, routedMessage)
|
||||
}
|
||||
|
||||
# Pingハンドラー
|
||||
handlePing(sender, data) {
|
||||
me.send(sender, {
|
||||
type: "pong",
|
||||
timestamp: new TimeBox().now()
|
||||
})
|
||||
}
|
||||
|
||||
# ルーティングハンドラー
|
||||
handleRoute(sender, data) {
|
||||
local finalTarget = data.finalTarget
|
||||
|
||||
if finalTarget == me.nodeId {
|
||||
# 自分宛て
|
||||
me.processMessage(sender, data.payload)
|
||||
} else {
|
||||
# 転送
|
||||
me.send(finalTarget, data.payload)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🚀 プラグインの配布と使用
|
||||
|
||||
### 1. ローカルファイルとして
|
||||
|
||||
```nyash
|
||||
# main.hako
|
||||
include "plugins/math_utils.hako"
|
||||
|
||||
local utils = new MathUtils()
|
||||
print(utils.factorial(5)) # 120
|
||||
```
|
||||
|
||||
### 2. パッケージとして(将来)
|
||||
|
||||
```bash
|
||||
# パッケージのインストール
|
||||
nyash install awesome-math-utils
|
||||
|
||||
# パッケージの公開
|
||||
nyash publish my-cool-plugin
|
||||
```
|
||||
|
||||
```nyash
|
||||
# パッケージの使用
|
||||
import { MathUtils } from "awesome-math-utils"
|
||||
|
||||
local utils = new MathUtils()
|
||||
```
|
||||
|
||||
### 3. 動的ロード
|
||||
|
||||
```nyash
|
||||
# 実行時にプラグインをロード
|
||||
local pluginCode = new FileBox().read("plugin.hako")
|
||||
eval(pluginCode) # プラグインが利用可能に
|
||||
|
||||
local processor = new DataProcessor()
|
||||
```
|
||||
|
||||
## 💡 ベストプラクティス
|
||||
|
||||
### 1. 単一責任の原則
|
||||
```nyash
|
||||
# ✅ 良い例:特定の機能に集中
|
||||
box JSONParser {
|
||||
parse(text) { ... }
|
||||
stringify(obj) { ... }
|
||||
}
|
||||
|
||||
# ❌ 悪い例:何でも詰め込む
|
||||
box UtilityBox {
|
||||
parseJSON() { ... }
|
||||
sendEmail() { ... }
|
||||
calculateTax() { ... }
|
||||
playSound() { ... }
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 依存性の明示
|
||||
```nyash
|
||||
# ✅ 良い例:必要な依存を明示
|
||||
box DataAnalyzer {
|
||||
init { fileReader, mathLib, logger }
|
||||
|
||||
birth() {
|
||||
me.fileReader = new FileBox()
|
||||
me.mathLib = new MathBox()
|
||||
me.logger = new LoggerBox()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. エラーハンドリング
|
||||
```nyash
|
||||
# ✅ 良い例:適切なエラー処理
|
||||
box SafeCalculator {
|
||||
divide(a, b) {
|
||||
if b == 0 {
|
||||
throw new Error("Division by zero")
|
||||
}
|
||||
return a / b
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📊 他のプラグインシステムとの比較
|
||||
|
||||
| 特徴 | Nyashスクリプト | C ABI | Nyash ABI |
|
||||
|------|----------------|-------|-----------|
|
||||
| 実装言語 | Nyash | C/C++ | 任意 |
|
||||
| 学習コスト | ゼロ | 中 | 高 |
|
||||
| パフォーマンス | 中速 | 最速 | 高速 |
|
||||
| 開発効率 | 最高 | 中 | 中 |
|
||||
| デバッグ | 簡単 | 難しい | 中程度 |
|
||||
| 配布 | .hakoファイル | .so/.dll | 任意 |
|
||||
|
||||
## 📚 まとめ
|
||||
|
||||
Nyashスクリプトプラグインは「**Everything is Box**」哲学の究極の実現です。
|
||||
|
||||
- **特別なAPIは不要** - 普通のNyashコードがプラグイン
|
||||
- **完全な統合** - Nyashの全機能が使える
|
||||
- **高い生産性** - 書いてすぐ使える
|
||||
|
||||
**迷ったらNyashスクリプトプラグインから始めましょう!**
|
||||
|
||||
必要に応じて、パフォーマンスが必要な部分だけC ABIに、他言語連携が必要な部分だけNyash ABIに移行すれば良いのです。
|
||||
307
docs/archive/roadmap/phases/phase-12/specs/export-import-spec.md
Normal file
307
docs/archive/roadmap/phases/phase-12/specs/export-import-spec.md
Normal file
@ -0,0 +1,307 @@
|
||||
# Nyash Export/Import構文仕様 v1.0
|
||||
|
||||
## 🎯 概要
|
||||
|
||||
Nyashのコード共有エコシステムを実現するための`export`/`import`構文仕様。「Everything is Box」哲学に基づき、Boxを中心とした明快な構文を提供する。
|
||||
|
||||
## 📝 基本構文
|
||||
|
||||
### Export構文
|
||||
|
||||
```nyash
|
||||
# 単一Boxのエクスポート
|
||||
export box MathUtils {
|
||||
init { precision }
|
||||
|
||||
factorial(n) {
|
||||
if n <= 1 { return 1 }
|
||||
return n * me.factorial(n - 1)
|
||||
}
|
||||
|
||||
fibonacci(n) {
|
||||
if n <= 1 { return n }
|
||||
return me.fibonacci(n - 1) + me.fibonacci(n - 2)
|
||||
}
|
||||
}
|
||||
|
||||
# Static Boxのエクスポート
|
||||
export static box Constants {
|
||||
init { }
|
||||
|
||||
PI = 3.14159265359
|
||||
E = 2.71828182846
|
||||
GOLDEN_RATIO = 1.61803398875
|
||||
}
|
||||
|
||||
# 複数Boxの名前付きエクスポート
|
||||
export {
|
||||
MathUtils,
|
||||
Constants,
|
||||
StringHelpers as StrUtils # エイリアス付き
|
||||
}
|
||||
|
||||
# デフォルトエクスポート
|
||||
export default box Calculator {
|
||||
init { display }
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
### Import構文
|
||||
|
||||
```nyash
|
||||
# 名前付きインポート
|
||||
import { MathUtils } from "math_utils.ny"
|
||||
import { MathUtils, Constants } from "math_lib.ny"
|
||||
|
||||
# エイリアス付きインポート
|
||||
import { MathUtils as Math } from "math_utils.ny"
|
||||
|
||||
# デフォルトインポート
|
||||
import Calculator from "calculator.ny"
|
||||
|
||||
# 全体インポート(名前空間)
|
||||
import * as MathLib from "math_lib.ny"
|
||||
|
||||
# 複合インポート
|
||||
import Calculator, { MathUtils, Constants } from "advanced_calc.ny"
|
||||
```
|
||||
|
||||
## 🔧 モジュール解決
|
||||
|
||||
### ファイルパス解決
|
||||
|
||||
```nyash
|
||||
# 相対パス
|
||||
import { Utils } from "./utils.ny"
|
||||
import { Common } from "../common/helpers.ny"
|
||||
|
||||
# パッケージ名(nyash_modules/から)
|
||||
import { Logger } from "awesome-logger"
|
||||
|
||||
# 絶対パス(非推奨、移植性のため)
|
||||
import { Config } from "/home/user/project/config.ny"
|
||||
```
|
||||
|
||||
### 解決順序
|
||||
|
||||
1. 相対パス(`./`または`../`で始まる)
|
||||
2. `nyash_modules/`ディレクトリ
|
||||
3. グローバルパッケージディレクトリ(設定可能)
|
||||
4. 絶対パス
|
||||
|
||||
## 📦 パッケージ構造
|
||||
|
||||
### 基本的なパッケージ構成
|
||||
|
||||
```
|
||||
my-math-package/
|
||||
├── nyash.toml # パッケージメタデータ
|
||||
├── src/
|
||||
│ ├── index.ny # メインエントリーポイント
|
||||
│ ├── utils.ny
|
||||
│ └── advanced.ny
|
||||
├── tests/
|
||||
│ └── test_math.ny
|
||||
└── README.md
|
||||
```
|
||||
|
||||
### nyash.toml
|
||||
|
||||
```toml
|
||||
[package]
|
||||
name = "awesome-math"
|
||||
version = "1.0.0"
|
||||
description = "素晴らしい数学ユーティリティ"
|
||||
author = "Nyash Developer"
|
||||
license = "MIT"
|
||||
|
||||
[dependencies]
|
||||
# 他のNyashパッケージへの依存
|
||||
basic-utils = "^2.0.0"
|
||||
|
||||
[export]
|
||||
# パッケージのメインエクスポート
|
||||
main = "src/index.ny"
|
||||
```
|
||||
|
||||
### index.ny(エントリーポイント)
|
||||
|
||||
```nyash
|
||||
# 内部モジュールをインポート
|
||||
import { InternalUtils } from "./utils.ny"
|
||||
import { AdvancedMath } from "./advanced.ny"
|
||||
|
||||
# 外部にエクスポート
|
||||
export {
|
||||
InternalUtils as Utils,
|
||||
AdvancedMath
|
||||
}
|
||||
|
||||
# デフォルトエクスポート
|
||||
export default box MathPackage {
|
||||
init {
|
||||
me.utils = new Utils()
|
||||
me.advanced = new AdvancedMath()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🚀 高度な機能
|
||||
|
||||
### 条件付きエクスポート
|
||||
|
||||
```nyash
|
||||
# プラットフォーム別エクスポート
|
||||
if PLATFORM == "web" {
|
||||
export { WebLogger as Logger } from "./web_logger.ny"
|
||||
} else {
|
||||
export { ConsoleLogger as Logger } from "./console_logger.ny"
|
||||
}
|
||||
```
|
||||
|
||||
### 再エクスポート
|
||||
|
||||
```nyash
|
||||
# 他のモジュールから再エクスポート
|
||||
export { MathUtils } from "./math_utils.ny"
|
||||
export * from "./string_helpers.ny"
|
||||
```
|
||||
|
||||
### 動的インポート(将来拡張)
|
||||
|
||||
```nyash
|
||||
# 実行時に動的にインポート
|
||||
local dynamicModule = await import("./heavy_module.ny")
|
||||
local HeavyBox = dynamicModule.HeavyBox
|
||||
```
|
||||
|
||||
## 🔒 スコープとアクセス制御
|
||||
|
||||
### プライベートメンバー
|
||||
|
||||
```nyash
|
||||
export box SecureBox {
|
||||
init {
|
||||
_privateData # アンダースコアプレフィックスは慣習的にプライベート
|
||||
publicData
|
||||
}
|
||||
|
||||
# プライベートメソッド(エクスポートされない)
|
||||
_internalProcess() {
|
||||
// 内部処理
|
||||
}
|
||||
|
||||
# パブリックメソッド
|
||||
process() {
|
||||
return me._internalProcess()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🎯 実装優先順位
|
||||
|
||||
### Phase 1: 基本機能(必須)
|
||||
- [ ] `export box`構文
|
||||
- [ ] `import { Box } from "file"`構文
|
||||
- [ ] 相対パス解決
|
||||
- [ ] 基本的な循環参照チェック
|
||||
|
||||
### Phase 2: 拡張機能(推奨)
|
||||
- [ ] `export default`
|
||||
- [ ] `import * as namespace`
|
||||
- [ ] エイリアス(`as`)
|
||||
- [ ] nyash_modules/ディレクトリサポート
|
||||
|
||||
### Phase 3: 高度な機能(オプション)
|
||||
- [ ] 条件付きエクスポート
|
||||
- [ ] 再エクスポート
|
||||
- [ ] 動的インポート
|
||||
- [ ] パッケージマネージャー統合
|
||||
|
||||
## ⚠️ 制約事項
|
||||
|
||||
1. **循環参照の禁止**
|
||||
```nyash
|
||||
# ❌ エラー: 循環参照
|
||||
# a.ny: import { B } from "./b.ny"
|
||||
# b.ny: import { A } from "./a.ny"
|
||||
```
|
||||
|
||||
2. **トップレベルでのみ許可**
|
||||
```nyash
|
||||
# ✅ OK
|
||||
import { Utils } from "./utils.ny"
|
||||
|
||||
# ❌ エラー: 関数内でのインポート
|
||||
box MyBox {
|
||||
method() {
|
||||
import { Helper } from "./helper.ny" # エラー!
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
3. **export前の参照禁止**
|
||||
```nyash
|
||||
# ❌ エラー: 定義前のエクスポート
|
||||
export { UndefinedBox } # エラー!
|
||||
|
||||
box UndefinedBox { }
|
||||
```
|
||||
|
||||
## 🔄 他言語との比較
|
||||
|
||||
| 機能 | Nyash | JavaScript | Python | Rust |
|
||||
|------|-------|------------|--------|------|
|
||||
| 名前付きexport | ✅ | ✅ | ✅ | ✅ |
|
||||
| デフォルトexport | ✅ | ✅ | ❌ | ❌ |
|
||||
| 名前空間import | ✅ | ✅ | ✅ | ✅ |
|
||||
| 動的import | 🔄 | ✅ | ✅ | ❌ |
|
||||
| 再export | ✅ | ✅ | ✅ | ✅ |
|
||||
|
||||
## 📚 使用例
|
||||
|
||||
### 数学ライブラリ
|
||||
|
||||
```nyash
|
||||
# math_lib.ny
|
||||
export box Vector2D {
|
||||
init { x, y }
|
||||
|
||||
add(other) {
|
||||
return new Vector2D(me.x + other.x, me.y + other.y)
|
||||
}
|
||||
|
||||
magnitude() {
|
||||
return Math.sqrt(me.x * me.x + me.y * me.y)
|
||||
}
|
||||
}
|
||||
|
||||
export static box MathConstants {
|
||||
init { }
|
||||
TAU = 6.28318530718
|
||||
}
|
||||
```
|
||||
|
||||
### 使用側
|
||||
|
||||
```nyash
|
||||
# game.ny
|
||||
import { Vector2D, MathConstants } from "./math_lib.ny"
|
||||
|
||||
box Player {
|
||||
init {
|
||||
me.position = new Vector2D(0, 0)
|
||||
me.velocity = new Vector2D(1, 1)
|
||||
}
|
||||
|
||||
update() {
|
||||
me.position = me.position.add(me.velocity)
|
||||
local angle = MathConstants.TAU / 4 # 90度
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
*Everything is Box - そしてBoxは共有される*
|
||||
@ -0,0 +1,328 @@
|
||||
# Nyashパッケージマネージャー設計書 v1.0
|
||||
|
||||
## 🎯 概要
|
||||
|
||||
Nyashのコード共有エコシステムを支える、シンプルで直感的なパッケージマネージャー「nypm (Nyash Package Manager)」の設計。
|
||||
|
||||
## 📊 設計原則
|
||||
|
||||
1. **シンプルさ優先** - npmの良い部分を参考に、複雑さを避ける
|
||||
2. **Everything is Box** - パッケージもBoxの集合として扱う
|
||||
3. **明示性** - 依存関係は常に明確に
|
||||
4. **高速性** - 並列ダウンロード、効率的なキャッシュ
|
||||
|
||||
## 🔧 基本コマンド
|
||||
|
||||
### パッケージのインストール
|
||||
|
||||
```bash
|
||||
# 依存関係をインストール
|
||||
nyash install
|
||||
|
||||
# 特定パッケージをインストール
|
||||
nyash install awesome-math
|
||||
nyash install awesome-math@1.2.0
|
||||
|
||||
# 開発依存として追加
|
||||
nyash install --dev test-framework
|
||||
|
||||
# グローバルインストール
|
||||
nyash install -g nyash-formatter
|
||||
```
|
||||
|
||||
### パッケージの公開
|
||||
|
||||
```bash
|
||||
# パッケージを公開
|
||||
nyash publish
|
||||
|
||||
# ドライラン(実際には公開しない)
|
||||
nyash publish --dry-run
|
||||
|
||||
# アクセス制御付き公開
|
||||
nyash publish --access public
|
||||
```
|
||||
|
||||
### その他のコマンド
|
||||
|
||||
```bash
|
||||
# パッケージ初期化
|
||||
nyash init
|
||||
|
||||
# 依存関係の更新
|
||||
nyash update
|
||||
nyash update awesome-math
|
||||
|
||||
# パッケージの削除
|
||||
nyash uninstall awesome-math
|
||||
|
||||
# 依存関係ツリーの表示
|
||||
nyash list
|
||||
nyash list --depth=0
|
||||
|
||||
# パッケージ検索
|
||||
nyash search math
|
||||
|
||||
# パッケージ情報表示
|
||||
nyash info awesome-math
|
||||
```
|
||||
|
||||
## 📦 パッケージ構造
|
||||
|
||||
### ディレクトリ構成
|
||||
|
||||
```
|
||||
my-awesome-package/
|
||||
├── nyash.toml # パッケージマニフェスト
|
||||
├── src/
|
||||
│ ├── index.ny # メインエントリーポイント
|
||||
│ └── lib/
|
||||
│ └── utils.ny
|
||||
├── tests/
|
||||
│ └── test_main.ny
|
||||
├── docs/
|
||||
│ └── README.md
|
||||
├── examples/
|
||||
│ └── basic_usage.ny
|
||||
└── .hakoignore # 公開時の除外ファイル
|
||||
```
|
||||
|
||||
### nyash.toml仕様
|
||||
|
||||
```toml
|
||||
[package]
|
||||
name = "awesome-math"
|
||||
version = "1.0.0"
|
||||
description = "高度な数学計算ライブラリ"
|
||||
author = "Nyash Developer <dev@example.com>"
|
||||
license = "MIT"
|
||||
repository = "https://github.com/user/awesome-math"
|
||||
keywords = ["math", "calculation", "algebra"]
|
||||
|
||||
# メインエントリーポイント
|
||||
main = "src/index.ny"
|
||||
|
||||
# 最小Nyashバージョン
|
||||
nyash = ">=1.0.0"
|
||||
|
||||
[dependencies]
|
||||
# 実行時依存
|
||||
basic-utils = "^2.0.0"
|
||||
string-helpers = "~1.5.0"
|
||||
|
||||
[dev-dependencies]
|
||||
# 開発時のみ必要
|
||||
test-framework = "^3.0.0"
|
||||
mock-library = "^1.2.0"
|
||||
|
||||
[scripts]
|
||||
# カスタムスクリプト
|
||||
test = "nyash test tests/"
|
||||
build = "nyash compile src/"
|
||||
lint = "nyash-lint src/"
|
||||
```
|
||||
|
||||
### バージョン指定
|
||||
|
||||
```toml
|
||||
# 正確なバージョン
|
||||
"1.2.3"
|
||||
|
||||
# 互換性のあるバージョン(推奨)
|
||||
"^1.2.3" # >=1.2.3 <2.0.0
|
||||
|
||||
# 近似バージョン
|
||||
"~1.2.3" # >=1.2.3 <1.3.0
|
||||
|
||||
# 範囲指定
|
||||
">=1.0.0 <2.0.0"
|
||||
|
||||
# ワイルドカード
|
||||
"1.2.*" # >=1.2.0 <1.3.0
|
||||
```
|
||||
|
||||
## 🗂️ ローカルレジストリ
|
||||
|
||||
### nyash_modules構造
|
||||
|
||||
```
|
||||
project/
|
||||
├── nyash.toml
|
||||
├── src/
|
||||
│ └── main.ny
|
||||
└── nyash_modules/ # 依存パッケージ格納場所
|
||||
├── awesome-math/
|
||||
│ ├── nyash.toml
|
||||
│ └── src/
|
||||
├── string-helpers/
|
||||
│ ├── nyash.toml
|
||||
│ └── src/
|
||||
└── .cache/ # ダウンロードキャッシュ
|
||||
```
|
||||
|
||||
### パッケージ解決アルゴリズム
|
||||
|
||||
1. 現在のディレクトリの`nyash_modules/`をチェック
|
||||
2. 親ディレクトリを再帰的に探索
|
||||
3. グローバルインストールディレクトリをチェック
|
||||
4. 見つからない場合はエラー
|
||||
|
||||
## 🌐 中央レジストリ
|
||||
|
||||
### レジストリAPI
|
||||
|
||||
```
|
||||
GET /packages/{name} # パッケージ情報取得
|
||||
GET /packages/{name}/versions # バージョン一覧
|
||||
GET /packages/{name}/{version} # 特定バージョン情報
|
||||
POST /packages # パッケージ公開
|
||||
GET /search?q={query} # パッケージ検索
|
||||
```
|
||||
|
||||
### パッケージメタデータ
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "awesome-math",
|
||||
"version": "1.0.0",
|
||||
"description": "高度な数学計算ライブラリ",
|
||||
"author": {
|
||||
"name": "Nyash Developer",
|
||||
"email": "dev@example.com"
|
||||
},
|
||||
"repository": "https://github.com/user/awesome-math",
|
||||
"downloads": {
|
||||
"last_day": 150,
|
||||
"last_week": 1200,
|
||||
"last_month": 5000
|
||||
},
|
||||
"versions": ["1.0.0", "0.9.0", "0.8.0"],
|
||||
"dependencies": {
|
||||
"basic-utils": "^2.0.0"
|
||||
},
|
||||
"tarball": "https://registry.hako.dev/awesome-math-1.0.0.tgz"
|
||||
}
|
||||
```
|
||||
|
||||
## 🔒 セキュリティ
|
||||
|
||||
### パッケージ署名
|
||||
|
||||
```toml
|
||||
# nyash.toml
|
||||
[package.signature]
|
||||
algorithm = "ed25519"
|
||||
public_key = "..."
|
||||
```
|
||||
|
||||
### 整合性チェック
|
||||
|
||||
```
|
||||
nyash_modules/
|
||||
└── awesome-math/
|
||||
├── nyash.toml
|
||||
└── .hako-integrity # SHA256ハッシュ
|
||||
```
|
||||
|
||||
### 権限システム
|
||||
|
||||
- **read**: パッケージの参照(デフォルト:全員)
|
||||
- **write**: パッケージの更新(デフォルト:作者のみ)
|
||||
- **admin**: 権限管理(デフォルト:作者のみ)
|
||||
|
||||
## 🚀 高度な機能
|
||||
|
||||
### ワークスペース
|
||||
|
||||
```toml
|
||||
# ルートnyash.toml
|
||||
[workspace]
|
||||
members = [
|
||||
"packages/core",
|
||||
"packages/utils",
|
||||
"packages/cli"
|
||||
]
|
||||
```
|
||||
|
||||
### プライベートレジストリ
|
||||
|
||||
```toml
|
||||
# .hakorc
|
||||
[registries]
|
||||
default = "https://registry.hako.dev"
|
||||
company = "https://npm.company.com"
|
||||
|
||||
[scopes]
|
||||
"@company" = "company"
|
||||
```
|
||||
|
||||
### オフラインモード
|
||||
|
||||
```bash
|
||||
# キャッシュからインストール
|
||||
nyash install --offline
|
||||
|
||||
# キャッシュの事前ダウンロード
|
||||
nyash cache add awesome-math@1.0.0
|
||||
```
|
||||
|
||||
## 📈 パフォーマンス最適化
|
||||
|
||||
### 並列ダウンロード
|
||||
|
||||
- 最大10パッケージ同時ダウンロード
|
||||
- HTTP/2による効率的な接続再利用
|
||||
|
||||
### インテリジェントキャッシュ
|
||||
|
||||
```
|
||||
~/.hako/cache/
|
||||
├── packages/
|
||||
│ └── awesome-math-1.0.0.tgz
|
||||
├── metadata/
|
||||
│ └── awesome-math.json
|
||||
└── index.db # SQLiteインデックス
|
||||
```
|
||||
|
||||
### 差分更新
|
||||
|
||||
- パッケージ更新時は差分のみダウンロード
|
||||
- バイナリdiffアルゴリズム使用
|
||||
|
||||
## 🛣️ 実装ロードマップ
|
||||
|
||||
### Phase 1: MVP(4週間)
|
||||
- [ ] 基本的なinstall/publishコマンド
|
||||
- [ ] nyash.tomlパーサー
|
||||
- [ ] シンプルな依存解決
|
||||
- [ ] ローカルファイルシステムレジストリ
|
||||
|
||||
### Phase 2: 中央レジストリ(6週間)
|
||||
- [ ] HTTPSレジストリAPI
|
||||
- [ ] ユーザー認証システム
|
||||
- [ ] パッケージ検索
|
||||
- [ ] Webインターフェース
|
||||
|
||||
### Phase 3: 高度な機能(8週間)
|
||||
- [ ] ワークスペースサポート
|
||||
- [ ] プライベートレジストリ
|
||||
- [ ] セキュリティ機能(署名・監査)
|
||||
- [ ] 差分更新
|
||||
|
||||
## 🎯 成功指標
|
||||
|
||||
1. **使いやすさ**: 3コマンド以内で基本操作完了
|
||||
2. **高速性**: npm比で2倍以上の速度
|
||||
3. **信頼性**: 99.9%のアップタイム
|
||||
4. **エコシステム**: 1年で1000パッケージ
|
||||
|
||||
## 📚 参考実装
|
||||
|
||||
- **npm**: UIとワークフローを参考
|
||||
- **Cargo**: 依存解決アルゴリズム
|
||||
- **pnpm**: 効率的なディスク使用
|
||||
- **Deno**: セキュリティモデル
|
||||
|
||||
---
|
||||
|
||||
*Everything is Box - パッケージマネージャーもBoxを運ぶ*
|
||||
@ -0,0 +1,282 @@
|
||||
# 統一TypeBox API リファレンス
|
||||
|
||||
## 📋 目次
|
||||
|
||||
1. [基本構造体](#基本構造体)
|
||||
2. [関数ポインタ仕様](#関数ポインタ仕様)
|
||||
3. [NyValue型システム](#nyvalue型システム)
|
||||
4. [機能フラグ](#機能フラグ)
|
||||
5. [エラーハンドリング](#エラーハンドリング)
|
||||
6. [プラグイン間連携](#プラグイン間連携)
|
||||
|
||||
## 基本構造体
|
||||
|
||||
### NyashTypeBox
|
||||
|
||||
```c
|
||||
typedef struct {
|
||||
uint32_t abi_tag; // 必須: 0x54594258 ('TYBX')
|
||||
uint16_t version; // APIバージョン(現在: 1)
|
||||
uint16_t struct_size; // sizeof(NyashTypeBox)
|
||||
const char* name; // Box型名(NULL終端)
|
||||
|
||||
// 基本操作
|
||||
void* (*create)(void* args);
|
||||
void (*destroy)(void* self);
|
||||
|
||||
// 高速ディスパッチ
|
||||
uint32_t (*resolve)(const char* name);
|
||||
NyResult (*invoke_id)(void* self, uint32_t method_id,
|
||||
NyValue* args, int argc);
|
||||
|
||||
// 互換性
|
||||
void* (*method)(void* self, const char* name,
|
||||
void** args, int argc);
|
||||
|
||||
// メタ情報
|
||||
const char* (*get_type_info)(void);
|
||||
uint64_t capabilities;
|
||||
|
||||
// 予約済み
|
||||
void* reserved[4];
|
||||
} NyashTypeBox;
|
||||
```
|
||||
|
||||
## 関数ポインタ仕様
|
||||
|
||||
### create
|
||||
```c
|
||||
void* (*create)(void* args);
|
||||
```
|
||||
- **目的**: 新しいBoxインスタンスを生成
|
||||
- **引数**: `args` - 初期化パラメータ(型依存)
|
||||
- **戻り値**: 生成されたインスタンスのポインタ
|
||||
- **所有権**: 呼び出し元が所有(destroy必須)
|
||||
|
||||
### destroy
|
||||
```c
|
||||
void (*destroy)(void* self);
|
||||
```
|
||||
- **目的**: Boxインスタンスを破棄
|
||||
- **引数**: `self` - 破棄するインスタンス
|
||||
- **注意**: NULLチェックは呼び出し元の責任
|
||||
|
||||
### resolve
|
||||
```c
|
||||
uint32_t (*resolve)(const char* name);
|
||||
```
|
||||
- **目的**: メソッド名を数値IDに変換
|
||||
- **引数**: `name` - メソッド名
|
||||
- **戻り値**: メソッドID(0 = 未知のメソッド)
|
||||
- **用途**: JIT最適化、キャッシング
|
||||
|
||||
### invoke_id
|
||||
```c
|
||||
NyResult (*invoke_id)(void* self, uint32_t method_id,
|
||||
NyValue* args, int argc);
|
||||
```
|
||||
- **目的**: 高速メソッド呼び出し
|
||||
- **引数**:
|
||||
- `self` - 対象インスタンス
|
||||
- `method_id` - resolveで取得したID
|
||||
- `args` - 引数配列
|
||||
- `argc` - 引数数
|
||||
- **戻り値**: NyResult(成功/エラー)
|
||||
|
||||
### method(互換用)
|
||||
```c
|
||||
void* (*method)(void* self, const char* name,
|
||||
void** args, int argc);
|
||||
```
|
||||
- **目的**: 従来互換のメソッド呼び出し
|
||||
- **注意**: 新規実装では非推奨
|
||||
|
||||
### get_type_info
|
||||
```c
|
||||
const char* (*get_type_info)(void);
|
||||
```
|
||||
- **目的**: 型情報をJSON形式で返す
|
||||
- **戻り値**: JSON文字列(静的メモリ)
|
||||
- **形式例**:
|
||||
```json
|
||||
{
|
||||
"methods": [
|
||||
{"name": "length", "id": 1, "returns": "int"},
|
||||
{"name": "concat", "id": 2, "returns": "string"}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## NyValue型システム
|
||||
|
||||
### 基本構造
|
||||
```c
|
||||
typedef struct __attribute__((aligned(16))) {
|
||||
uint64_t type_tag; // 型識別子
|
||||
union {
|
||||
int64_t i64; // 整数
|
||||
double f64; // 浮動小数点
|
||||
void* ptr; // ポインタ
|
||||
uint64_t bits; // ビットパターン
|
||||
} payload;
|
||||
} NyValue;
|
||||
```
|
||||
|
||||
### 型タグ定義
|
||||
```c
|
||||
#define NYVAL_NULL 0x00
|
||||
#define NYVAL_BOOL 0x01
|
||||
#define NYVAL_INT 0x02
|
||||
#define NYVAL_FLOAT 0x03
|
||||
#define NYVAL_STRING 0x04
|
||||
#define NYVAL_BOX 0x05
|
||||
#define NYVAL_ARRAY 0x06
|
||||
#define NYVAL_MAP 0x07
|
||||
```
|
||||
|
||||
### ヘルパー関数
|
||||
```c
|
||||
// 値生成
|
||||
NyValue ny_value_null(void);
|
||||
NyValue ny_value_bool(bool val);
|
||||
NyValue ny_value_int(int64_t val);
|
||||
NyValue ny_value_float(double val);
|
||||
NyValue ny_value_string(const char* str);
|
||||
NyValue ny_value_box(void* box, NyashTypeBox* type);
|
||||
|
||||
// 値取得
|
||||
bool ny_is_null(NyValue val);
|
||||
bool ny_to_bool(NyValue val);
|
||||
int64_t ny_to_int(NyValue val);
|
||||
double ny_to_float(NyValue val);
|
||||
const char* ny_to_string(NyValue val);
|
||||
void* ny_to_box(NyValue val);
|
||||
```
|
||||
|
||||
## 機能フラグ
|
||||
|
||||
### 基本フラグ
|
||||
```c
|
||||
#define NYASH_CAP_THREAD_SAFE (1 << 0) // スレッドセーフ
|
||||
#define NYASH_CAP_ASYNC_SAFE (1 << 1) // async/await対応
|
||||
#define NYASH_CAP_REENTRANT (1 << 2) // 再入可能
|
||||
#define NYASH_CAP_PARALLELIZABLE (1 << 3) // 並列実行可能
|
||||
#define NYASH_CAP_PURE (1 << 4) // 副作用なし
|
||||
#define NYASH_CAP_DETERMINISTIC (1 << 5) // 決定的動作
|
||||
```
|
||||
|
||||
### 拡張フラグ
|
||||
```c
|
||||
#define NYASH_CAP_GPU_ACCEL (1 << 8) // GPU実行可能
|
||||
#define NYASH_CAP_SIMD_OPTIMIZED (1 << 9) // SIMD最適化済み
|
||||
#define NYASH_CAP_LAZY_EVAL (1 << 10) // 遅延評価対応
|
||||
```
|
||||
|
||||
## エラーハンドリング
|
||||
|
||||
### NyResult構造体
|
||||
```c
|
||||
typedef struct {
|
||||
int status; // 0 = 成功、非0 = エラー
|
||||
NyValue value; // 戻り値(成功時)
|
||||
const char* error_msg; // エラーメッセージ(エラー時)
|
||||
} NyResult;
|
||||
```
|
||||
|
||||
### ステータスコード
|
||||
```c
|
||||
#define NY_OK 0
|
||||
#define NY_ERROR_GENERIC -1
|
||||
#define NY_ERROR_NULL_PTR -2
|
||||
#define NY_ERROR_TYPE -3
|
||||
#define NY_ERROR_BOUNDS -4
|
||||
#define NY_ERROR_NOT_FOUND -5
|
||||
#define NY_ERROR_MEMORY -6
|
||||
```
|
||||
|
||||
### ヘルパー関数
|
||||
```c
|
||||
NyResult ny_result_ok(NyValue val);
|
||||
NyResult ny_result_error(const char* msg);
|
||||
bool ny_result_is_ok(NyResult res);
|
||||
bool ny_result_is_error(NyResult res);
|
||||
```
|
||||
|
||||
## プラグイン間連携
|
||||
|
||||
### TypeBox取得
|
||||
```c
|
||||
NyashTypeBox* ny_host_get_typebox(const char* name);
|
||||
```
|
||||
- **目的**: 他のプラグインのTypeBoxを取得
|
||||
- **引数**: `name` - Box型名
|
||||
- **戻り値**: TypeBoxポインタ(NULL = 未登録)
|
||||
|
||||
### 使用例
|
||||
```c
|
||||
// MapBoxがArrayBoxを生成する例
|
||||
NyResult map_keys(void* self, uint32_t method_id,
|
||||
NyValue* args, int argc) {
|
||||
MapBoxImpl* map = (MapBoxImpl*)self;
|
||||
|
||||
// ArrayBoxを取得
|
||||
NyashTypeBox* array_type = ny_host_get_typebox("ArrayBox");
|
||||
if (!array_type) {
|
||||
return ny_result_error("ArrayBox not found");
|
||||
}
|
||||
|
||||
// 新しいArrayBoxを生成
|
||||
void* array = array_type->create(NULL);
|
||||
|
||||
// キーを追加
|
||||
for (int i = 0; i < map->key_count; i++) {
|
||||
NyValue key = ny_value_string(map->keys[i]);
|
||||
array_type->invoke_id(array, 1, &key, 1); // push
|
||||
}
|
||||
|
||||
return ny_result_ok(ny_value_box(array, array_type));
|
||||
}
|
||||
```
|
||||
|
||||
## 所有権ルール
|
||||
|
||||
### 基本原則
|
||||
1. **create**の戻り値 → 呼び出し元が**destroy**責任
|
||||
2. **invoke_id**の引数 → プラグインは**借用**(変更/解放禁止)
|
||||
3. **invoke_id**の戻り値 → 呼び出し元が所有
|
||||
|
||||
### 文字列の扱い
|
||||
- 引数の文字列:コピー必須(借用のため)
|
||||
- 戻り値の文字列:新規確保(呼び出し元が解放)
|
||||
|
||||
### メモリ管理ベストプラクティス
|
||||
```c
|
||||
// 良い例:文字列をコピー
|
||||
void* string_concat(void* self, NyValue* args, int argc) {
|
||||
char* str1 = (char*)self;
|
||||
char* str2 = ny_to_string(args[0]);
|
||||
|
||||
// 新しいメモリを確保
|
||||
size_t len = strlen(str1) + strlen(str2) + 1;
|
||||
char* result = malloc(len);
|
||||
snprintf(result, len, "%s%s", str1, str2);
|
||||
|
||||
return ny_value_string(result);
|
||||
}
|
||||
```
|
||||
|
||||
## バージョニング
|
||||
|
||||
### APIバージョン
|
||||
- **現在**: 1
|
||||
- **互換性**: 上位互換を維持
|
||||
- **チェック**: `version`フィールドで確認
|
||||
|
||||
### 構造体サイズ
|
||||
- **用途**: 前方互換性の確保
|
||||
- **チェック**: `struct_size >= sizeof(NyashTypeBox)`
|
||||
|
||||
### 将来の拡張
|
||||
- `reserved`配列を使用
|
||||
- 新フィールドは構造体末尾に追加
|
||||
- 既存フィールドの意味は変更禁止
|
||||
296
docs/archive/roadmap/phases/phase-12/unified-typebox-abi.md
Normal file
296
docs/archive/roadmap/phases/phase-12/unified-typebox-abi.md
Normal file
@ -0,0 +1,296 @@
|
||||
# 統一TypeBox ABI - Nyashプラグインシステムの完成形
|
||||
|
||||
## 🌟 概要
|
||||
|
||||
**「Everything is Box」哲学の究極形:すべてのプラグインがTypeBoxになる!**
|
||||
|
||||
統一TypeBox ABIは、従来の2つのプラグイン形式(C ABIとTypeBox)を統合し、シンプルさと拡張性を両立させた、Nyashプラグインシステムの完成形です。
|
||||
|
||||
## 🎯 なぜ統合するのか?
|
||||
|
||||
### 現状の課題
|
||||
- **2つの形式が混在**:C ABI(シンプル)とTypeBox(拡張可能)
|
||||
- **プラグイン間連携が複雑**:C ABIプラグインは他のBoxを作れない
|
||||
- **概念の重複**:開発者が2つのシステムを学ぶ必要がある
|
||||
|
||||
### 統合のメリット
|
||||
1. **「Everything is Box」の完成**:型情報も実装もすべてBoxとして統一
|
||||
2. **プラグイン間連携が標準装備**:どのプラグインも他のBoxを作れる
|
||||
3. **JIT/AOT最適化と相性抜群**:メソッドID化で高速ディスパッチ
|
||||
4. **将来の拡張性**:async/await、並列実行、GPU対応などを容易に追加可能
|
||||
|
||||
## 📐 統一TypeBox構造体
|
||||
|
||||
```c
|
||||
typedef struct {
|
||||
// === 識別情報 ===
|
||||
uint32_t abi_tag; // 'TYBX' (0x54594258) - 必須
|
||||
uint16_t version; // APIバージョン(現在: 1)
|
||||
uint16_t struct_size; // 構造体サイズ(前方互換性)
|
||||
const char* name; // Box型名:"StringBox"
|
||||
|
||||
// === 基本操作(旧C ABI互換)===
|
||||
void* (*create)(void* args); // インスタンス生成
|
||||
void (*destroy)(void* self); // インスタンス破棄
|
||||
|
||||
// === 高速メソッドディスパッチ ===
|
||||
uint32_t (*resolve)(const char* name); // メソッド名→ID変換(初回のみ)
|
||||
NyResult (*invoke_id)(void* self, // ID指定の高速呼び出し
|
||||
uint32_t method_id,
|
||||
NyValue* args,
|
||||
int argc);
|
||||
|
||||
// === 従来互換(フォールバック)===
|
||||
void* (*method)(void* self, // 文字列指定の呼び出し
|
||||
const char* name,
|
||||
void** args,
|
||||
int argc);
|
||||
|
||||
// === メタ情報 ===
|
||||
const char* (*get_type_info)(void); // JSON形式の型情報
|
||||
uint64_t capabilities; // 機能フラグ(下記参照)
|
||||
|
||||
// === 将来拡張用 ===
|
||||
void* reserved[4]; // 将来の拡張用(NULL初期化)
|
||||
} NyashTypeBox;
|
||||
```
|
||||
|
||||
### 機能フラグ(capabilities)
|
||||
|
||||
```c
|
||||
#define NYASH_CAP_THREAD_SAFE (1 << 0) // スレッドセーフ
|
||||
#define NYASH_CAP_ASYNC_SAFE (1 << 1) // async/await対応
|
||||
#define NYASH_CAP_REENTRANT (1 << 2) // 再入可能
|
||||
#define NYASH_CAP_PARALLELIZABLE (1 << 3) // 並列実行可能
|
||||
#define NYASH_CAP_PURE (1 << 4) // 副作用なし
|
||||
#define NYASH_CAP_GPU_ACCEL (1 << 5) // GPU実行可能
|
||||
```
|
||||
|
||||
## 🚀 実装例
|
||||
|
||||
### 最小限のプラグイン
|
||||
|
||||
```c
|
||||
#include "nyash_typebox.h"
|
||||
|
||||
// === StringBoxの実装 ===
|
||||
|
||||
// メソッドIDの定義(事前計算)
|
||||
#define METHOD_LENGTH 1
|
||||
#define METHOD_TOUPPER 2
|
||||
#define METHOD_CONCAT 3
|
||||
|
||||
// インスタンス構造体
|
||||
typedef struct {
|
||||
char* value;
|
||||
} StringBoxImpl;
|
||||
|
||||
// create関数
|
||||
void* string_create(void* args) {
|
||||
StringBoxImpl* self = malloc(sizeof(StringBoxImpl));
|
||||
self->value = strdup((const char*)args);
|
||||
return self;
|
||||
}
|
||||
|
||||
// destroy関数
|
||||
void string_destroy(void* self) {
|
||||
StringBoxImpl* impl = (StringBoxImpl*)self;
|
||||
free(impl->value);
|
||||
free(impl);
|
||||
}
|
||||
|
||||
// メソッド名→ID変換
|
||||
uint32_t string_resolve(const char* name) {
|
||||
if (strcmp(name, "length") == 0) return METHOD_LENGTH;
|
||||
if (strcmp(name, "toUpper") == 0) return METHOD_TOUPPER;
|
||||
if (strcmp(name, "concat") == 0) return METHOD_CONCAT;
|
||||
return 0; // 未知のメソッド
|
||||
}
|
||||
|
||||
// 高速メソッド呼び出し(JIT最適化対応)
|
||||
NyResult string_invoke_id(void* self, uint32_t method_id,
|
||||
NyValue* args, int argc) {
|
||||
StringBoxImpl* impl = (StringBoxImpl*)self;
|
||||
|
||||
switch (method_id) {
|
||||
case METHOD_LENGTH: {
|
||||
int len = strlen(impl->value);
|
||||
return ny_result_ok(ny_value_int(len));
|
||||
}
|
||||
case METHOD_TOUPPER: {
|
||||
char* upper = strdup(impl->value);
|
||||
for (int i = 0; upper[i]; i++) {
|
||||
upper[i] = toupper(upper[i]);
|
||||
}
|
||||
return ny_result_ok(ny_value_string(upper));
|
||||
}
|
||||
case METHOD_CONCAT: {
|
||||
if (argc < 1) return ny_result_error("引数不足");
|
||||
// ... concat実装
|
||||
}
|
||||
default:
|
||||
return ny_result_error("未知のメソッド");
|
||||
}
|
||||
}
|
||||
|
||||
// 従来互換メソッド(フォールバック)
|
||||
void* string_method(void* self, const char* name,
|
||||
void** args, int argc) {
|
||||
// resolve + invoke_idを内部で呼ぶ
|
||||
uint32_t id = string_resolve(name);
|
||||
if (id == 0) return NULL;
|
||||
|
||||
// void** → NyValue*変換
|
||||
NyValue* ny_args = convert_args(args, argc);
|
||||
NyResult result = string_invoke_id(self, id, ny_args, argc);
|
||||
|
||||
// NyResult → void*変換
|
||||
return unwrap_result(result);
|
||||
}
|
||||
|
||||
// TypeBox定義(エクスポート)
|
||||
const NyashTypeBox nyash_typebox_StringBox = {
|
||||
.abi_tag = 0x54594258, // 'TYBX'
|
||||
.version = 1,
|
||||
.struct_size = sizeof(NyashTypeBox),
|
||||
.name = "StringBox",
|
||||
|
||||
.create = string_create,
|
||||
.destroy = string_destroy,
|
||||
.resolve = string_resolve,
|
||||
.invoke_id = string_invoke_id,
|
||||
.method = string_method, // 互換性のため
|
||||
|
||||
.get_type_info = string_get_type_info,
|
||||
.capabilities = NYASH_CAP_THREAD_SAFE | NYASH_CAP_PURE,
|
||||
|
||||
.reserved = {NULL, NULL, NULL, NULL}
|
||||
};
|
||||
```
|
||||
|
||||
### プラグイン間連携の例
|
||||
|
||||
```c
|
||||
// MapBoxがArrayBoxを返す例
|
||||
NyResult map_keys(void* self, uint32_t method_id,
|
||||
NyValue* args, int argc) {
|
||||
MapBoxImpl* map = (MapBoxImpl*)self;
|
||||
|
||||
// ArrayBoxのTypeBoxを取得(ホスト経由)
|
||||
NyashTypeBox* array_type = ny_host_get_typebox("ArrayBox");
|
||||
if (!array_type) {
|
||||
return ny_result_error("ArrayBox not found");
|
||||
}
|
||||
|
||||
// ArrayBoxインスタンスを生成
|
||||
void* array = array_type->create(NULL);
|
||||
|
||||
// キーを追加(ArrayBoxのメソッドを呼ぶ)
|
||||
for (int i = 0; i < map->key_count; i++) {
|
||||
NyValue key = ny_value_string(map->keys[i]);
|
||||
array_type->invoke_id(array, METHOD_PUSH, &key, 1);
|
||||
}
|
||||
|
||||
return ny_result_ok(ny_value_box(array, array_type));
|
||||
}
|
||||
```
|
||||
|
||||
## 💎 NyValue - 統一値表現
|
||||
|
||||
```c
|
||||
// 16バイト固定サイズ(JIT/SIMD最適化対応)
|
||||
typedef struct __attribute__((aligned(16))) {
|
||||
uint64_t type_tag; // 型識別子
|
||||
union {
|
||||
int64_t i64; // 整数
|
||||
double f64; // 浮動小数点
|
||||
void* ptr; // ポインタ(Box/String等)
|
||||
uint64_t bits; // ビットパターン
|
||||
} payload;
|
||||
} NyValue;
|
||||
|
||||
// ヘルパー関数
|
||||
NyValue ny_value_int(int64_t val);
|
||||
NyValue ny_value_string(const char* str);
|
||||
NyValue ny_value_box(void* box, NyashTypeBox* type);
|
||||
```
|
||||
|
||||
## 🔄 移行戦略
|
||||
|
||||
### Phase 1: 互換レイヤー(現在)
|
||||
- 既存のC ABIプラグインはそのまま動作
|
||||
- TypeBoxラッパーで自動変換
|
||||
|
||||
### Phase 2: 段階的移行(3ヶ月)
|
||||
- 新規プラグインは統一TypeBoxで作成
|
||||
- 移行ガイドとツールを提供
|
||||
|
||||
### Phase 3: 最適化(6ヶ月)
|
||||
- JITがinvoke_idを直接呼び出し
|
||||
- インラインキャッシング導入
|
||||
|
||||
### Phase 4: 完全移行(1年)
|
||||
- 旧C ABIを非推奨に
|
||||
- すべてのプラグインが統一形式に
|
||||
|
||||
## 🛠️ 開発者向けツール
|
||||
|
||||
### ヘルパーマクロ
|
||||
|
||||
```c
|
||||
// 簡単にTypeBoxを定義
|
||||
DEFINE_NYASH_TYPEBOX(MyBox, my_create, my_destroy,
|
||||
my_resolve, my_invoke_id);
|
||||
```
|
||||
|
||||
### コード生成ツール
|
||||
|
||||
```bash
|
||||
# TypeBoxプラグインのひな形を生成
|
||||
nyash-plugin new MyAwesomeBox
|
||||
|
||||
# 既存のC ABIプラグインを変換
|
||||
nyash-plugin migrate old_plugin.c
|
||||
```
|
||||
|
||||
### デバッグツール
|
||||
|
||||
```bash
|
||||
# プラグインのABI準拠をチェック
|
||||
nyash-plugin validate my_plugin.so
|
||||
|
||||
# メソッド呼び出しをトレース
|
||||
nyash-plugin trace --method="concat" my_plugin.so
|
||||
```
|
||||
|
||||
## ⚡ パフォーマンス最適化
|
||||
|
||||
### JIT最適化
|
||||
1. **メソッドID事前解決**:文字列比較を排除
|
||||
2. **インラインキャッシング**:頻出呼び出しを直接ジャンプ
|
||||
3. **NyValue最適化**:16バイトアライメントでSIMD対応
|
||||
|
||||
### ベンチマーク結果
|
||||
```
|
||||
旧C ABI (文字列dispatch) : 100ns/call
|
||||
統一TypeBox (ID dispatch) : 15ns/call (6.7x高速)
|
||||
統一TypeBox + JIT IC : 3ns/call (33x高速)
|
||||
```
|
||||
|
||||
## 🌟 まとめ
|
||||
|
||||
統一TypeBox ABIは:
|
||||
- ✅ **シンプル**:1つの形式ですべてを表現
|
||||
- ✅ **高速**:JIT最適化で従来比33倍高速
|
||||
- ✅ **拡張可能**:async/GPU/並列実行に対応
|
||||
- ✅ **互換性**:既存資産を保護しながら移行
|
||||
|
||||
**「Everything is Box」哲学の究極の実現です!**
|
||||
|
||||
## 📚 関連ドキュメント
|
||||
|
||||
- [移行ガイド](./migration-guide.md)
|
||||
- [API詳細リファレンス](./specs/typebox-api-reference.md)
|
||||
- [設計の詳細](./design/UNIFIED-ABI-DESIGN.md)
|
||||
- [なぜ統合するのか - AI議論の記録](./design/WHY-AIS-FAILED.md)
|
||||
- [AI先生たちの深い技術的検討](./ai-consultation-unified-typebox.md) 🆕
|
||||
218
docs/archive/roadmap/phases/phase-12/unified-typebox-user-box.md
Normal file
218
docs/archive/roadmap/phases/phase-12/unified-typebox-user-box.md
Normal file
@ -0,0 +1,218 @@
|
||||
# 統一TypeBox ABI - ユーザー定義Box統合
|
||||
|
||||
## 🎯 概要
|
||||
|
||||
統一TypeBox ABIの最終形:**ユーザー定義BoxもC ABIプラグインとして扱える!**
|
||||
|
||||
## 🚀 革命的な統合アーキテクチャ
|
||||
|
||||
### 提案されたAPI
|
||||
|
||||
```c
|
||||
// ユーザーBoxもプラグインとして動的登録
|
||||
NyashTypeBox* register_user_box(const char* name,
|
||||
NyashBoxMethods* methods) {
|
||||
// ユーザーBoxに一時的なtype_idを割り当て
|
||||
// メソッドテーブルを登録
|
||||
// → プラグインと同じように扱える
|
||||
}
|
||||
```
|
||||
|
||||
### 利点
|
||||
|
||||
1. **完全な統一性**: すべてのBox(ビルトイン、プラグイン、ユーザー定義)が同じABIで扱える
|
||||
2. **透過的な相互運用**: ユーザーBox ↔ プラグインBox間の自由な受け渡し
|
||||
3. **動的拡張性**: 実行時に新しい型を追加可能
|
||||
4. **既存コードとの互換性**: 現在のプラグインシステムと完全互換
|
||||
|
||||
## 📐 技術設計
|
||||
|
||||
### 統一TypeBox構造体(拡張版)
|
||||
|
||||
```c
|
||||
typedef struct NyashTypeBox {
|
||||
// === ヘッダー情報 ===
|
||||
uint32_t abi_tag; // 'TYBX'
|
||||
uint16_t version; // 2 (ユーザーBox対応)
|
||||
uint16_t flags; // HOST_MANAGED | THREAD_SAFE等
|
||||
|
||||
// === 型情報 ===
|
||||
uint32_t type_id; // 動的割り当て(高ビットで区別)
|
||||
const char* name; // "UserDefinedBox"
|
||||
|
||||
// === 基本操作 ===
|
||||
void* (*create)(void* args);
|
||||
void (*destroy)(void* self);
|
||||
void (*retain)(void* self); // 参照カウント増加
|
||||
void (*release)(void* self); // 参照カウント減少
|
||||
|
||||
// === メソッドディスパッチ ===
|
||||
uint32_t (*resolve)(const char* name);
|
||||
NyResult (*invoke_id)(void* self, uint32_t method_id,
|
||||
NyValue* args, int argc);
|
||||
|
||||
// === メタ情報(オプション)===
|
||||
size_t instance_size; // インスタンスサイズ
|
||||
void* metadata; // 追加メタデータ
|
||||
} NyashTypeBox;
|
||||
```
|
||||
|
||||
### Type ID管理
|
||||
|
||||
```c
|
||||
// 高ビットでホスト/プラグイン区別
|
||||
#define HOST_TYPE_FLAG 0x80000000
|
||||
#define PLUGIN_TYPE_FLAG 0x40000000
|
||||
#define BUILTIN_TYPE_FLAG 0x00000000
|
||||
|
||||
// 例
|
||||
uint32_t user_box_id = HOST_TYPE_FLAG | 0x00001234;
|
||||
uint32_t plugin_box_id = PLUGIN_TYPE_FLAG | 0x00005678;
|
||||
uint32_t builtin_box_id = BUILTIN_TYPE_FLAG | 0x00000001;
|
||||
```
|
||||
|
||||
## 🔧 実装詳細
|
||||
|
||||
### メモリ管理
|
||||
|
||||
```c
|
||||
typedef struct {
|
||||
atomic_uint ref_count; // アトミック参照カウント
|
||||
uint32_t finalizer_id; // クリーンアップ用ID
|
||||
void (*destroy)(void*); // デストラクタ
|
||||
} NyashBoxHeader;
|
||||
|
||||
// すべてのBoxインスタンスの先頭に配置
|
||||
typedef struct {
|
||||
NyashBoxHeader header;
|
||||
// ... Box固有のデータ
|
||||
} UserBoxInstance;
|
||||
```
|
||||
|
||||
### ユーザーBox登録の流れ
|
||||
|
||||
```nyash
|
||||
// Nyashでユーザー定義Box
|
||||
box Person {
|
||||
init { name, age }
|
||||
|
||||
greet() {
|
||||
return "Hello, I'm " + me.name
|
||||
}
|
||||
}
|
||||
|
||||
// 内部で自動的に以下が実行される:
|
||||
// 1. Personボックスのメソッドテーブル生成
|
||||
// 2. register_user_box("Person", methods)でC ABIに登録
|
||||
// 3. type_id割り当て(例: 0x80001234)
|
||||
// 4. プラグインから呼び出し可能に!
|
||||
```
|
||||
|
||||
### プラグインからの利用
|
||||
|
||||
```c
|
||||
// プラグイン側でユーザーBoxを受け取る
|
||||
NyResult process_person(void* self, uint32_t method_id,
|
||||
NyValue* args, int argc) {
|
||||
// args[0]がPersonBoxのhandle
|
||||
if (args[0].type_tag == TAG_HANDLE) {
|
||||
uint32_t type_id = extract_type_id(args[0]);
|
||||
uint32_t instance_id = extract_instance_id(args[0]);
|
||||
|
||||
// ホストに問い合わせてメソッド呼び出し
|
||||
NyValue result = ny_host_invoke(type_id, instance_id,
|
||||
"greet", NULL, 0);
|
||||
|
||||
// 結果を処理
|
||||
return ny_result_ok(result);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🛡️ セキュリティと安全性
|
||||
|
||||
### 多層防御アプローチ
|
||||
|
||||
1. **信頼レベル別処理**
|
||||
```c
|
||||
if (is_trusted_source(box_source)) {
|
||||
// 直接登録(高速パス)
|
||||
register_user_box_direct(name, methods);
|
||||
} else {
|
||||
// Wasmサンドボックス内で実行
|
||||
register_user_box_sandboxed(name, methods);
|
||||
}
|
||||
```
|
||||
|
||||
2. **メソッドポインタ検証**
|
||||
```c
|
||||
bool validate_method_pointer(void* ptr) {
|
||||
// 実行可能メモリ領域をチェック
|
||||
return is_executable_memory(ptr);
|
||||
}
|
||||
```
|
||||
|
||||
3. **権限ベースアクセス制御**
|
||||
```c
|
||||
#define CAP_FILE_ACCESS (1 << 0)
|
||||
#define CAP_NET_ACCESS (1 << 1)
|
||||
#define CAP_SPAWN_THREAD (1 << 2)
|
||||
|
||||
// 登録時に権限を指定
|
||||
register_user_box_with_caps(name, methods,
|
||||
CAP_FILE_ACCESS);
|
||||
```
|
||||
|
||||
## 📊 パフォーマンス考慮
|
||||
|
||||
### ベンチマーク予測
|
||||
```
|
||||
ネイティブメソッド呼び出し : 1ns
|
||||
プラグイン内メソッド呼び出し : 15ns
|
||||
ユーザーBox(同一プロセス) : 20ns
|
||||
ユーザーBox(Wasmサンドボックス): 100ns
|
||||
```
|
||||
|
||||
### 最適化戦略
|
||||
|
||||
1. **インラインキャッシング**: 頻繁に呼ばれるユーザーBoxメソッドをキャッシュ
|
||||
2. **JIT最適化**: 型が確定したらde-virtualization
|
||||
3. **バッチ処理**: 複数メソッド呼び出しをまとめて実行
|
||||
|
||||
## 🔄 段階的実装計画
|
||||
|
||||
### Phase 1: 基本実装(1ヶ月)
|
||||
- `register_user_box` APIの実装
|
||||
- 基本的な参照カウント管理
|
||||
- シンプルなメソッドディスパッチ
|
||||
|
||||
### Phase 2: GC統合(2ヶ月)
|
||||
- GCとの協調動作
|
||||
- 循環参照の検出と解決
|
||||
- WeakRef対応
|
||||
|
||||
### Phase 3: セキュリティ強化(3ヶ月)
|
||||
- Wasmサンドボックス統合
|
||||
- 権限管理システム
|
||||
- 監査ログ機能
|
||||
|
||||
### Phase 4: 最適化(6ヶ月)
|
||||
- JIT統合
|
||||
- インラインキャッシング
|
||||
- プロファイルベース最適化
|
||||
|
||||
## 🌟 Everything is Boxの完成
|
||||
|
||||
この実装により:
|
||||
- ✅ **すべてのBoxが平等に**: ビルトイン、プラグイン、ユーザー定義の区別なし
|
||||
- ✅ **完全な相互運用性**: どのBoxも自由に受け渡し可能
|
||||
- ✅ **動的な拡張性**: 実行時に新しい型を追加可能
|
||||
- ✅ **最高のパフォーマンス**: JIT最適化で高速実行
|
||||
|
||||
**「Everything is Box」哲学が、言語の境界を越えて完全に実現されます!**
|
||||
|
||||
## 📚 参考資料
|
||||
|
||||
- [AI先生たちの技術的検討](./ai-consultation-unified-typebox.md)
|
||||
- [統一TypeBox ABI仕様](./unified-typebox-abi.md)
|
||||
- [移行ガイド](./migration-guide.md)
|
||||
Reference in New Issue
Block a user