chore(legacy): remove unused legacy plugin loader and C-ABI nyash-file plugin; unify plugin headers to TypeBox v2
This commit is contained in:
316
docs/phases/00_MASTER_ROADMAP.md
Normal file
316
docs/phases/00_MASTER_ROADMAP.md
Normal file
@ -0,0 +1,316 @@
|
||||
# 🚀 Nyash開発マスタープラン
|
||||
|
||||
Status: Active Development
|
||||
Last Updated: 2025-09-02
|
||||
Purpose: Claude×Copilot×ChatGPT×Gemini×Codex協調開発の総合ロードマップ
|
||||
|
||||
## 📍 現在位置
|
||||
|
||||
- 現在フェーズ: Phase 12 TypeBox統合ABI・セルフホスティング準備
|
||||
- 最新成果: 🔥 **Nyash ABIをC実装TypeBoxで提供** - Rust依存排除への道!
|
||||
- 次フェーズ: Phase 12.0.5 Nyash ABI C実装開始
|
||||
- 備考: GeminiとCodexの深い考察により、セルフホスティングへの明確な道筋が見えました。
|
||||
|
||||
## 🗺️ フェーズ概要
|
||||
|
||||
| Phase | 状態 | 概要 | 詳細リンク |
|
||||
|-------|------|------|------------|
|
||||
| 8.4 | ✅完了 | AST→MIR Lowering完全実装 | [phase_8_4_ast_mir_lowering.md](phase-8/phase_8_4_ast_mir_lowering.md) |
|
||||
| 8.5 | ✅完了 | MIRダイエット(35→26→15命令) | [phase_8_5_mir_35_to_26_reduction.md](phase-8/phase_8_5_mir_35_to_26_reduction.md) |
|
||||
| 8.6 | 🔄進行中 | VM性能改善(0.9倍→2倍以上) | [phase_8_6_vm_performance_improvement.md](phase-8/phase_8_6_vm_performance_improvement.md) |
|
||||
| 9 | 📅予定 | JIT実装 | [phase-9/](phase-9/) |
|
||||
| 9.75g-0 | ✅完了 | BID-FFI Plugin System | [Phase-9.75g-0-BID-FFI-Developer-Guide.md](phase-9/Phase-9.75g-0-BID-FFI-Developer-Guide.md) |
|
||||
| 9.8 | 📅予定 | BIDレジストリ + 自動コード生成 | [phase_9_8_bid_registry_and_codegen.md](phase-9/phase_9_8_bid_registry_and_codegen.md) |
|
||||
| 10 | 📅予定 | Cranelift JIT(主経路) | [phase_10_cranelift_jit_backend.md](phase-10/phase_10_cranelift_jit_backend.md) |
|
||||
| 11 | ✅完了 | LLVM統合・AOT実装(依存重い) | [phase-11/](phase-11/) |
|
||||
| 11.8 | 📅予定 | MIR整理(Core-15→Core-13) | [phase-11.8_mir_cleanup/](phase-11.8_mir_cleanup/) |
|
||||
| 12 | 🔄進行中 | TypeBox統合ABI・セルフホスティング準備 | [phase-12/](phase-12/) |
|
||||
| 12.5 | 📅予定 | MIR15最適化戦略 | [phase-12.5/](phase-12.5/) |
|
||||
| 12.7 | 📅予定 | AI-Nyash Compact Notation Protocol (ANCP) | [phase-12.7/](phase-12.7/) |
|
||||
| 13 | 📅予定 | Nyashブラウザー革命 | [phase-13/](phase-13/) |
|
||||
| 14 | 📅予定 | パッケージング・CI改善 | [phase-14/](phase-14/) |
|
||||
| 15 | 🌟実現可能 | セルフホスティング(C実装ABI経由) | [phase-15/](phase-15/) |
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Nyash実行モード併用戦略
|
||||
|
||||
### 🌟 インタープリター+コンパイラ併用の価値
|
||||
|
||||
#### 実行モード使い分け
|
||||
```
|
||||
開発時: インタープリター(デバッグ・即時実行・非同期フル対応)
|
||||
本番時: インタープリター(Pythonのように実用的)
|
||||
OR
|
||||
WASM/AOT(性能要求時)
|
||||
配布時: AOT native(最高性能)
|
||||
Web時: WASM(ブラウザ対応)
|
||||
```
|
||||
|
||||
#### インタープリターの強み
|
||||
- **即時実行**: コンパイル不要で高速開発
|
||||
- **デバッグ容易**: 実行時情報の完全把握
|
||||
- **非同期完全対応**: Rust async/awaitで真の並行処理
|
||||
- **動的性**: 実行時評価・REPL対応
|
||||
- **十分な性能**: 多くのユースケースで実用的(Pythonが証明)
|
||||
|
||||
---
|
||||
|
||||
## 📊 Phase別詳細
|
||||
|
||||
### 🚨 Phase 8.6: VM性能改善 - 最優先課題(進行中)
|
||||
|
||||
**Summary**:
|
||||
- **緊急問題**: VMがインタープリターより0.9倍遅い(性能回帰!)
|
||||
- **目標**: 2倍以上高速化でVM実行を実用レベルに引き上げ
|
||||
- **担当**: Copilot主導(GitHub Issue #112)
|
||||
|
||||
**技術的課題**:
|
||||
```bash
|
||||
# 現状のベンチマーク結果
|
||||
Interpreter: 110.10ms (ベースライン)
|
||||
VM: 119.80ms (0.9倍 - 遅い...)
|
||||
Target: 55.00ms (2倍高速化目標)
|
||||
```
|
||||
|
||||
**推定原因と対策**:
|
||||
- **デバッグ出力過多**: `println!`による性能劣化
|
||||
- **HashMap操作重い**: ValueId → VM値の変換コスト
|
||||
- **命令ディスパッチ非効率**: switch文ベースディスパッチ
|
||||
|
||||
---
|
||||
|
||||
### 🎊 Phase 9.75g-0: BID-FFI Plugin System - 完全完了! ✅
|
||||
|
||||
**革命的成果**: NyashがプラグインでBox型を動的拡張可能に!
|
||||
|
||||
```nyash
|
||||
// これが現実になった!
|
||||
local file = new FileBox() // プラグイン提供
|
||||
local db = new PostgreSQLBox() // 将来: プラグイン提供
|
||||
local gpu = new CudaBox() // 将来: プラグイン提供
|
||||
```
|
||||
|
||||
**References**:
|
||||
- [Phase-9.75g-0-BID-FFI-Developer-Guide.md](phase-9/Phase-9.75g-0-BID-FFI-Developer-Guide.md)
|
||||
- tools/plugin-tester/ (プラグイン診断ツール)
|
||||
|
||||
---
|
||||
|
||||
### 📦 Phase 9.8: BIDレジストリ + 自動コード生成ツール
|
||||
|
||||
**Summary**:
|
||||
- Phase 9.75g-0完了により準備完了
|
||||
- BID→各ターゲットのスタブ生成自動化
|
||||
|
||||
**革命的価値**:
|
||||
```bash
|
||||
# 🎯 1つのプラグインが4バックエンド全対応!
|
||||
nyash bid gen --target wasm bid.yaml # WASM用import生成
|
||||
nyash bid gen --target vm bid.yaml # VM用関数テーブル生成
|
||||
nyash bid gen --target llvm bid.yaml # AOT用declare生成(LLVM実装時)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 🏆 Phase 10: Cranelift JIT(主経路)
|
||||
|
||||
**Summary**:
|
||||
- MIR→VMを維持しつつ、ホットパスをCraneliftでJIT化
|
||||
- 目標: VM比2倍以上の高速化
|
||||
- LLVM AOTは設計資産は維持しつつ、Phase 11以降に検討
|
||||
- **🌟 NEW: GC切り替え可能ランタイム(世界初の柔軟なメモリ管理)**
|
||||
|
||||
**Start Gate(着手前の必須完了)**:
|
||||
- ✅ MIRダイエット(15命令)整合完了
|
||||
- ✅ VM統計: `--vm-stats` でホット関数抽出可能
|
||||
- 🔄 Proof of Concept: MIR→CLIFの最小Lower
|
||||
- ❓ BoxCall/Array/MapのJIT最適化
|
||||
|
||||
**実装ステップ**:
|
||||
1. **Phase 10.1**: Proof of Concept(2週間)
|
||||
2. **Phase 10.2**: 基本実装(4週間)
|
||||
3. **Phase 10.3**: 非同期の扱い(最小)
|
||||
4. **Phase 10.4**: GC切り替え可能ランタイム(2-3ヶ月)
|
||||
5. **Phase 10.5**: セルフホスティング(並行実装)
|
||||
|
||||
---
|
||||
|
||||
### 🔧 Phase 11: LLVM統合・AOT実装(完了 - 依存重い)
|
||||
|
||||
**Summary**:
|
||||
- ✅ LLVM IRへの変換実装完了
|
||||
- ✅ AOT(Ahead-of-Time)コンパイル動作確認
|
||||
- ✅ ネイティブ実行ファイル生成成功
|
||||
|
||||
**得られた知見**:
|
||||
- **依存関係が重い**: LLVM自体のビルド時間・サイズが巨大
|
||||
- **動作は確認**: 技術的には成功、実用性に課題
|
||||
- **Cranelift回帰**: 軽量な代替として再評価
|
||||
|
||||
---
|
||||
|
||||
### 📐 Phase 11.8: MIR整理(Core-15→Core-13)
|
||||
|
||||
**Summary**:
|
||||
- ArrayGet/ArraySet → BoxCall統合
|
||||
- PluginInvoke → BoxCall統合
|
||||
- 最終的にCore-13を目指す
|
||||
|
||||
**詳細**: [phase-11.8_mir_cleanup/](phase-11.8_mir_cleanup/)
|
||||
|
||||
---
|
||||
|
||||
### 🎯 Phase 12: TypeBox統合ABI・セルフホスティング準備(進行中)
|
||||
|
||||
**Summary**:
|
||||
- TypeBox革命:型情報もBoxとして扱う統一設計
|
||||
- C ABI + Nyash ABI完全統合
|
||||
- 🔥 **Nyash ABIのC実装**でRust依存排除!
|
||||
|
||||
**革命的成果**:
|
||||
1. TypeBox:プラグイン間Box生成を可能に
|
||||
2. 統合ABI:C/Nyash ABIをシームレス統合
|
||||
3. **セルフホスティング**:C実装ABIで実現可能!
|
||||
|
||||
**AI専門家の評価**:
|
||||
- Gemini:「技術的妥当性が高く、哲学とも合致した極めて優れた設計」
|
||||
- Codex:「16バイトアライメント、セレクターキャッシング等の具体案」
|
||||
|
||||
---
|
||||
|
||||
### ⚡ Phase 12.5: MIR15最適化戦略 - コンパイラ丸投げ作戦
|
||||
|
||||
**Summary**:
|
||||
- 「CPU(コンパイラ)に丸投げできるところは丸投げ」
|
||||
- MIR15の美しさ(15命令)を保ちながら実用的性能達成
|
||||
- 自前最適化は最小限、成熟したコンパイラ技術を活用
|
||||
|
||||
**最適化境界線**:
|
||||
- **MIR側**: カノニカル化・軽量最適化のみ
|
||||
- **コンパイラ側**: ループ最適化・SIMD・レジスタ割当等
|
||||
|
||||
**ヒントシステム**:
|
||||
- 命令は増やさずメタデータでヒント付与
|
||||
- pure/readonly/noalias/likely等の属性
|
||||
- Cコンパイラ/Cranelift/LLVMへ機械的マップ
|
||||
|
||||
**詳細**: [phase-12.5/](phase-12.5/)
|
||||
|
||||
---
|
||||
|
||||
## 🧠 AI大会議から得られた技術的知見
|
||||
|
||||
### Gemini先生の助言
|
||||
- ✅ エスケープ解析・ボックス化解除が性能の鍵
|
||||
- ✅ wasmtime compileは短期的に実用的
|
||||
- ✅ WASM実行は確実に高速(13.5倍実証済み)
|
||||
- 🔄 Cranelift → LLVM段階的アプローチ
|
||||
|
||||
### codex先生の助言
|
||||
- ✅ MIR前倒し実装推奨(全バックエンドが恩恵)
|
||||
- ✅ wasmtime互換性管理が重要
|
||||
- ✅ CPU差異対応 (baseline/v3二段ビルド)
|
||||
- ✅ 起動時間・割当削減・配布体験がKPI
|
||||
|
||||
### Claude統合分析
|
||||
- ✅ 実用価値最大化: WASM+AOTで十分な競争力
|
||||
- ✅ 開発効率: Cranelift JITの恩恵限定的
|
||||
- ✅ Everything is Box最適化が差別化の核心
|
||||
- ✅ 時間効率: 2-3ヶ月節約でLLVM集中投資
|
||||
|
||||
---
|
||||
|
||||
## 💡 協調開発への具体的お願い
|
||||
|
||||
### 🔧 Phase 8.6 VM性能改善(最優先)
|
||||
- ❓ 命令ディスパッチのボトルネック特定方法は?
|
||||
- ❓ HashMap操作の最適化戦略は?
|
||||
- ❓ デバッグ出力削除による性能改善測定は?
|
||||
- ❓ Direct threading実装の現実的アプローチは?
|
||||
|
||||
### 🚀 長期戦略相談
|
||||
- ❓ インタープリターとコンパイラの互換性保証は?
|
||||
- ❓ MIR→LLVM IR変換の基本的な実装戦略は?
|
||||
- ❓ Box型のLLVM表現として最適なアプローチは?
|
||||
- ❓ エスケープ解析によるスタック化判定は?
|
||||
|
||||
---
|
||||
|
||||
## 🌟 Phase 15: セルフホスティング(実現可能!)
|
||||
|
||||
**革命的発見**: Nyash ABIをC実装TypeBoxで提供することで、Rust依存を排除!
|
||||
|
||||
### 実現への道筋(明確化)
|
||||
1. **Phase 12.0.5**: Nyash ABI C Shim実装(Rust FFI経由)
|
||||
2. **Phase 13**: C実装の完全化(基本型・参照カウント)
|
||||
3. **Phase 14**: NyashでABI再実装(AOTでC ABI公開)
|
||||
4. **Phase 15**: Nyashコンパイラ自身をNyashで実装!
|
||||
|
||||
### 技術的革新
|
||||
- **TypeBox哲学**: ABIすらBoxとして扱う究極の統一
|
||||
- **C ABI基盤**: 最も安定した普遍的インターフェース
|
||||
- **段階的移行**: 既存Rust実装との共存期間を確保
|
||||
|
||||
---
|
||||
|
||||
## 📊 進捗管理・コミュニケーション
|
||||
|
||||
### 🤝 協調開発ルール
|
||||
- ✅ 大きな変更前にはdocs/CURRENT_TASK.mdで情報共有
|
||||
- ✅ ベンチマーク機能は最優先で維持
|
||||
- ✅ 競合発生時は機能優先度で解決
|
||||
- ✅ AI専門家(Gemini/Codex)の深い考察を活用
|
||||
|
||||
### 品質保証
|
||||
- ✅ cargo check でビルドエラーなし
|
||||
- ✅ 既存ベンチマークが regression なし
|
||||
- ✅ 新機能のドキュメント整備
|
||||
- ✅ テストケース追加・CI通過
|
||||
|
||||
---
|
||||
|
||||
## 🎯 期待される成果
|
||||
|
||||
### 達成済み
|
||||
- 🏆 RefNew/RefGet/RefSet WASM完全動作
|
||||
- 🏆 MIR命令削減完了(35→26→15命令、Phase 8.5)
|
||||
- 🏆 Phase 9.75g-0 BID-FFI Plugin System完全完了
|
||||
- 🏆 警告削減100%達成(Phase 9.75j)
|
||||
|
||||
### 進行中・予定
|
||||
- 🔄 VM性能改善進行中(Phase 8.6)- GitHub Issue #112
|
||||
- 📅 Cranelift JIT(Phase 10): VM比2×以上の高速化
|
||||
- 📅 非同期ネイティブ実装: async/await完全対応
|
||||
- 📅 インタープリター併用: 開発・本番両対応
|
||||
|
||||
---
|
||||
|
||||
## 📞 連絡・相談方法
|
||||
|
||||
技術的相談や進捗報告は、以下の方法でお気軽にどうぞ:
|
||||
|
||||
1. 📝 GitHub Issues・Pull Request
|
||||
2. 📋 docs/CURRENT_TASK.md コメント
|
||||
3. 🤖 AI大会議 (重要な技術決定)
|
||||
4. 💬 コミットメッセージでの進捗共有
|
||||
|
||||
どんな小さなことでも相談大歓迎です!
|
||||
一緒にNyashを最高の言語にしていきましょう🚀
|
||||
|
||||
---
|
||||
|
||||
**最終更新**: 2025-08-26 (copilot_issues.txt統合・Markdown化)
|
||||
**作成者**: Claude (ファイル統合・構造整理)
|
||||
|
||||
### 🎯 重要な変更点
|
||||
- ✅ **Phase 9.75g-0 BID-FFI Plugin System完全完了**
|
||||
- 🔄 **Phase 8.6 VM性能改善を最優先** (進行中)
|
||||
- 📦 **Phase 9.8 BIDレジストリ** (Phase 8.6完了後の次期重点)
|
||||
- 🔍 **Phase 10 Cranelift JIT** (主経路として確定)
|
||||
- 🌟 **統一ロードマップ化** (phasesフォルダに集約)
|
||||
## 🌈 Phase 22構想 - Nyash LLVM Compiler (将来)
|
||||
- LLVMコンパイラ自体をNyashで実装
|
||||
- C++薄ラッパー(20-30関数) + Nyash実装(100-200行)
|
||||
- ビルド時間: 5-7分 → 即時反映
|
||||
- 詳細: [Phase 22 README](phase-22/README.md)
|
||||
104
docs/phases/phase-10.1/README.md
Normal file
104
docs/phases/phase-10.1/README.md
Normal file
@ -0,0 +1,104 @@
|
||||
# Phase 10.1: JIT→EXE via Plugin Box Unification
|
||||
|
||||
## 🎯 革新的発見:すべてはプラグインになる
|
||||
|
||||
### 核心的洞察
|
||||
既存のプラグインシステム(BID-FFI)がすでに完全なC ABIを持っている。
|
||||
これを活用することで、JIT→EXE変換が現実的に可能。
|
||||
|
||||
## 📊 フェーズ概要
|
||||
|
||||
### 目標
|
||||
- ビルトインBoxをプラグイン化してC ABI統一
|
||||
- JITから統一されたプラグインAPIを呼び出し
|
||||
- スタティックリンクによるスタンドアロンEXE生成
|
||||
|
||||
### 背景
|
||||
```
|
||||
現在の構造:
|
||||
- JIT → HostCall → Rustビルトイン(複雑)
|
||||
- JIT → PluginInvoke → プラグインBox(C FFI)
|
||||
|
||||
統一後:
|
||||
- JIT → PluginInvoke → すべてのBox(統一!)
|
||||
- EXE → PluginInvoke → スタティックリンクされたBox
|
||||
```
|
||||
|
||||
## 🚀 実装計画
|
||||
|
||||
### Week 1: ArrayBoxプラグイン化PoC(詳細は phase_plan.md 参照)
|
||||
- ArrayBoxをプラグインとして再実装
|
||||
- JITからのプラグイン呼び出しテスト
|
||||
- パフォーマンス測定(HostCall vs Plugin)
|
||||
|
||||
### Week 2: 主要Box移行(詳細は phase_plan.md 参照)
|
||||
- StringBox、IntegerBox、BoolBoxのプラグイン化
|
||||
- JIT lowering層の統一(plugin_invoke経由)
|
||||
- 既存HostCallとの共存メカニズム
|
||||
|
||||
### Week 3: 静的リンク基盤(詳細は phase_plan.md 参照)
|
||||
- プラグインの`.a`ライブラリビルド
|
||||
- 最小ランタイム(nyash-runtime)設計
|
||||
- リンカースクリプト作成
|
||||
|
||||
### Week 4: EXE生成実証(詳細は phase_plan.md 参照)
|
||||
- Hello Worldレベルのスタンドアロン実行
|
||||
- Linux/macOSでの動作確認
|
||||
- デバッグ情報とunwind対応
|
||||
|
||||
## 📁 ディレクトリ構造(予定)
|
||||
|
||||
```
|
||||
plugins/
|
||||
├── nyash-core-boxes/ # ビルトインBox群
|
||||
│ ├── nyash-array-plugin/
|
||||
│ ├── nyash-string-plugin/
|
||||
│ └── nyash-integer-plugin/
|
||||
├── nyash-runtime-minimal/ # 最小ランタイム
|
||||
└── existing/ # 既存プラグイン
|
||||
├── nyash-file-plugin/
|
||||
└── nyash-net-plugin/
|
||||
```
|
||||
|
||||
## 🔗 関連資料(整備済み)
|
||||
|
||||
- フェーズ計画の詳細: [phase_plan.md](./phase_plan.md)
|
||||
- C ABI v0 仕様(JIT/AOT/Plugin共通): ../../../../docs/reference/abi/nyrt_c_abi_v0.md
|
||||
- 命名: `nyrt_*`(コア)/ `nyplug_{name}_*`(プラグイン)
|
||||
- 呼出規約: x86_64 SysV / aarch64 AAPCS64 / Win64
|
||||
- `*_abi_version()` で fail-fast(v0=1)
|
||||
|
||||
## ストリームエラー対策(長文/大出力を避ける)
|
||||
- 先頭に短い要約(サマリ)を置く(本READMEの冒頭にあり)
|
||||
- 詳細設計や長いコードは分割して参照(phase_plan.md / nyrt_c_abi_v0.md)
|
||||
- コマンドやコードは三連バッククォートで閉じ忘れ防止
|
||||
|
||||
- [革新的アプローチ詳細](../../../ideas/new-features/2025-08-28-jit-exe-via-plugin-unification.md)
|
||||
- [プラグインAPI仕様](../../../../reference/plugin-system/)
|
||||
- [Phase 10.5: Python統合計画](../phase-10.5/) (旧10.1)
|
||||
- [Phase 10.10: 前段階の成果](../phase-10/phase_10_10/)
|
||||
|
||||
## ⚡ 成功指標
|
||||
|
||||
1. **技術的検証**
|
||||
- ArrayBoxがプラグインとして動作
|
||||
- JITからの呼び出し成功
|
||||
- 性能劣化10%以内
|
||||
|
||||
2. **統合達成**
|
||||
- 5つ以上のビルトインBoxがプラグイン化
|
||||
- JIT lowering層の完全統一
|
||||
|
||||
3. **EXE生成**
|
||||
- スタンドアロン実行ファイル生成
|
||||
- 基本的なNyashプログラムの動作
|
||||
|
||||
## 🎉 期待される成果
|
||||
|
||||
- **Everything is Plugin** - 新たな設計哲学の確立
|
||||
- 自己ホスティングへの現実的な道筋
|
||||
- プラグインエコシステムの拡大可能性
|
||||
|
||||
---
|
||||
|
||||
*"Everything is Box → Everything is Plugin → Everything is Possible"*
|
||||
157
docs/phases/phase-10.1/c_abi_unified_design.md
Normal file
157
docs/phases/phase-10.1/c_abi_unified_design.md
Normal file
@ -0,0 +1,157 @@
|
||||
# C ABI統一設計 - JIT/AOT共通基盤
|
||||
|
||||
*ChatGPT5さんからのアドバイスに基づく設計文書*
|
||||
|
||||
## 🎯 核心的洞察
|
||||
|
||||
**プラグインBoxのC ABI = そのままJIT/AOTの呼び出し土台**
|
||||
|
||||
JITで今呼んでいるC ABIをAOTでは静的リンクに差し替えるだけでexe化まで一直線!
|
||||
|
||||
## 📊 全体アーキテクチャ
|
||||
|
||||
```
|
||||
Nyash → MIR → VM/JIT/Cranelift ──┐
|
||||
├─ 呼ぶ先は全部 C ABI: nyrt_* / nyplug_*
|
||||
NyRT (libnyrt.a/.so) ←──────────┘
|
||||
PluginBox 実装 (libnyplug_*.a/.so)
|
||||
```
|
||||
|
||||
- **JIT**: `extern "C"` シンボル(`nyrt_*`/`nyplug_*`)をその場で呼ぶ
|
||||
- **AOT**: 同じシンボルを`.o`に未解決のまま出力→`libnyrt.a`とプラグイン`.a`をリンク
|
||||
- **動的配布**: `.so/.dll`に差し替え(同じC ABIでOK)
|
||||
|
||||
## 🔧 C ABIルール(小さく強い)
|
||||
|
||||
### 1. 命名/可視性
|
||||
- コア: `nyrt_*`(Box/weak/bus/gc/sync/alloc...)
|
||||
- プラグイン: `nyplug_{name}_*`(ArrayBox, StringBox など)
|
||||
- `extern "C"` + 明示の可視性(ELF: `__attribute__((visibility("default")))`)
|
||||
|
||||
### 2. ABIの型
|
||||
- 引数/戻り: `int32_t/int64_t/uint64_t/double/void*` のみに限定
|
||||
- `bool`は`uint8_t`統一、構造体は不透明ポインタ(ハンドル)
|
||||
- `varargs`と例外のABI横断は**禁止**(戻り値でエラーコード/out-paramで返す)
|
||||
|
||||
### 3. レイアウト/アライン
|
||||
```c
|
||||
// Boxハンドル例
|
||||
struct NyBox {
|
||||
void* data;
|
||||
uint64_t typeid;
|
||||
uint32_t flags;
|
||||
uint32_t gen;
|
||||
};
|
||||
```
|
||||
※JIT側は中身に触らない。操作はAPI経由のみ。
|
||||
|
||||
### 4. 呼び出し規約
|
||||
- x86_64 SysV / aarch64 AAPCS64 / Win64 をターゲットごとに固定
|
||||
- Craneliftの`call_conv`を上記に合わせる(JIT/AOT共通)
|
||||
|
||||
### 5. バージョン管理(fail-fast)
|
||||
- `nyrt_abi_version()` / `nyplug_{name}_abi_version()`(v0=1)。不一致は起動時に即fail(ローダ側で検査)。
|
||||
|
||||
## 📝 最小ヘッダ雛形
|
||||
|
||||
### nyrt.h(コアランタイム)
|
||||
```c
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct NyBox {
|
||||
void* data;
|
||||
uint64_t typeid;
|
||||
uint32_t flags;
|
||||
uint32_t gen;
|
||||
} NyBox;
|
||||
|
||||
int32_t nyrt_abi_version(void);
|
||||
|
||||
// Box/weak
|
||||
NyBox nyrt_box_new(uint64_t typeid, uint64_t size);
|
||||
void nyrt_box_free(NyBox b);
|
||||
int32_t nyrt_adopt(NyBox parent, NyBox child);
|
||||
int32_t nyrt_release(NyBox parent, NyBox child, NyBox* out_weak);
|
||||
NyBox nyrt_weak_load(NyBox weak); // gen一致ならBox, 失効なら{0}
|
||||
|
||||
// GC/epoch
|
||||
void nyrt_epoch_collect(void);
|
||||
|
||||
// Sync(最低限)
|
||||
void* nyrt_mutex_lock(NyBox sync);
|
||||
void nyrt_mutex_unlock(void* guard);
|
||||
|
||||
// Bus
|
||||
int32_t nyrt_bus_send(NyBox port, NyBox msg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
### nyplug_array.h(プラグイン例:ArrayBox)
|
||||
```c
|
||||
#pragma once
|
||||
#include "nyrt.h"
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int32_t nyplug_array_abi_version(void);
|
||||
NyBox nyplug_array_new(void);
|
||||
int32_t nyplug_array_get(NyBox arr, uint64_t i, NyBox* out);
|
||||
int32_t nyplug_array_set(NyBox arr, uint64_t i, NyBox v);
|
||||
uint64_t nyplug_array_len(NyBox arr);
|
||||
int32_t nyplug_array_push(NyBox arr, NyBox v);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
## 🚀 ビルド・配布フロー(AOT静的リンク)
|
||||
|
||||
1. **JITと同じLowering**でCLIF生成
|
||||
2. **ObjectWriter**で`mod.o`出力(未解決:`nyrt_*`/`nyplug_*`)
|
||||
3. **リンク**
|
||||
- Linux/macOS: `cc mod.o -static -L. -lnyrt -lnyplug_array -o app`
|
||||
- Windows: `link mod.obj nyrt.lib nyplug_array.lib /OUT:app.exe`
|
||||
4. 実行:`./app`でJIT無しに動作
|
||||
|
||||
補足: 現行実装ではプラグインは `nyash_plugin_invoke`(BID-FFI v1, TLV)を用いる。v0ではこれを固定し、将来的に `nyplug_*` 直関数を併置する場合も `*_abi_version()` で互換を担保する。
|
||||
|
||||
## ⚡ 実装順序(重要!)
|
||||
|
||||
1. **必要なビルトインBoxをプラグインBoxに変換**
|
||||
2. **VM動作確認**
|
||||
3. **JIT動作確認**
|
||||
4. **AOT実装**
|
||||
|
||||
## ⚠️ 地雷と回避策
|
||||
|
||||
- **名前修飾/装飾**: C++で実装するなら`extern "C"`を絶対忘れない
|
||||
- **サイズ違い**: `bool`/`size_t`のプラットフォーム差 → 明示幅型で統一
|
||||
- **例外越境**: C ABI越しに`throw`/`panic`禁止。エラーコード+out-paramで返す
|
||||
- **並行**: JITから`nyrt_mutex_*`を呼ぶ箇所はSafepointとも整合するように(長保持しない)
|
||||
|
||||
## 📋 即実行ToDo(30分で前進)
|
||||
|
||||
- [ ] `nyrt.h`最小セット確定(上の雛形でOK)
|
||||
- [ ] Craneliftの`call_conv`をターゲットに合わせて固定
|
||||
- [ ] JIT経路で`nyrt_abi_version()==NYRT_ABI`を起動時チェック
|
||||
- [ ] AOT試作:`add.o`を吐いて`libnyrt.a`とリンク→`add()`を呼ぶ最小exe
|
||||
|
||||
## 💡 まとめ
|
||||
|
||||
> プラグインBoxのC ABI=JIT/AOTの土台だから、
|
||||
> **いまのJITが動いている=静的リンクexeの最短ルートはもう目の前。**
|
||||
> まずは`nyrt.h`を固定して、JITとAOTの両方で同じシンボルを呼ぶ状態にしよう。
|
||||
> それで**"今日のJIT"が"明日のexe"**に化けるにゃ。
|
||||
|
||||
---
|
||||
|
||||
*最終更新: 2025-08-28*
|
||||
180
docs/phases/phase-10.1/implementation_steps.md
Normal file
180
docs/phases/phase-10.1/implementation_steps.md
Normal file
@ -0,0 +1,180 @@
|
||||
# Phase 10.1 実装ステップガイド
|
||||
|
||||
## 🎯 実装の鉄則:必ずこの順序で!
|
||||
|
||||
ChatGPT5さんの指摘通り、緻密な計画と順序が成功の鍵にゃ。
|
||||
|
||||
## 📊 実装ステップ
|
||||
|
||||
### Step 1: ArrayBoxのプラグイン化(最小実装)
|
||||
|
||||
#### 1.1 プロジェクト作成
|
||||
```bash
|
||||
cd plugins/
|
||||
cargo new nyash-array-plugin --lib
|
||||
cd nyash-array-plugin
|
||||
```
|
||||
|
||||
#### 1.2 最小限のC FFI実装
|
||||
```rust
|
||||
// src/lib.rs
|
||||
#[repr(C)]
|
||||
pub struct NyBox {
|
||||
data: *mut u8,
|
||||
typeid: u64,
|
||||
flags: u32,
|
||||
gen: u32,
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn nyplug_array_abi_version() -> i32 { 1 }
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn nyplug_array_new() -> NyBox {
|
||||
// 簡略実装:Vec<i64>のみサポート
|
||||
let vec = Box::new(Vec::<i64>::new());
|
||||
NyBox {
|
||||
data: Box::into_raw(vec) as *mut u8,
|
||||
typeid: 3, // ArrayBox
|
||||
flags: 0,
|
||||
gen: 1,
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn nyplug_array_len(arr: NyBox) -> u64 {
|
||||
unsafe {
|
||||
let vec = &*(arr.data as *const Vec<i64>);
|
||||
vec.len() as u64
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 1.3 ビルド設定
|
||||
```toml
|
||||
# Cargo.toml
|
||||
[lib]
|
||||
crate-type = ["cdylib", "staticlib"] # 動的・静的両対応
|
||||
```
|
||||
|
||||
### Step 2: VM動作確認
|
||||
|
||||
#### 2.1 プラグインローダーとの統合
|
||||
```rust
|
||||
// src/runtime/plugin_loader_v2.rsに追加
|
||||
fn load_builtin_plugins(&mut self) {
|
||||
// 既存のFileBox等に加えて
|
||||
self.register_plugin("nyash-array-plugin", 3); // ArrayBox type_id = 3
|
||||
}
|
||||
```
|
||||
|
||||
#### 2.2 テストプログラム
|
||||
```nyash
|
||||
// test_array_plugin.nyash
|
||||
local arr
|
||||
arr = new ArrayBox() // プラグイン版を呼ぶ
|
||||
print(arr.length()) // 0が出力されれば成功
|
||||
```
|
||||
|
||||
#### 2.3 VM実行
|
||||
```bash
|
||||
./target/release/nyash --backend vm test_array_plugin.nyash
|
||||
```
|
||||
|
||||
### Step 3: JIT動作確認
|
||||
|
||||
#### 3.1 LowerCoreの修正
|
||||
```rust
|
||||
// src/jit/lower/core.rs
|
||||
match box_type {
|
||||
"ArrayBox" => {
|
||||
// HostCallからPluginInvokeに切り替え
|
||||
b.emit_plugin_invoke(3, method_id, args);
|
||||
}
|
||||
// 他のBoxは従来通り
|
||||
}
|
||||
```
|
||||
|
||||
#### 3.2 JIT実行テスト
|
||||
```bash
|
||||
NYASH_JIT_EXEC=1 NYASH_JIT_THRESHOLD=1 ./target/release/nyash --backend vm test_array_plugin.nyash
|
||||
```
|
||||
|
||||
### Step 4: 段階的移行
|
||||
|
||||
#### 4.1 移行優先順位
|
||||
1. **ArrayBox** - 最も使用頻度が高い
|
||||
2. **StringBox** - 基本的なデータ型
|
||||
3. **IntegerBox/BoolBox** - プリミティブ型
|
||||
4. **MapBox** - コレクション型
|
||||
5. **その他** - 順次移行
|
||||
|
||||
#### 4.2 互換性維持
|
||||
```rust
|
||||
// フラグで切り替え可能に
|
||||
if env::var("NYASH_USE_PLUGIN_BUILTINS").is_ok() {
|
||||
// プラグイン版を使用
|
||||
} else {
|
||||
// 従来のビルトイン版
|
||||
}
|
||||
```
|
||||
|
||||
### Step 5: パフォーマンス測定
|
||||
|
||||
#### 5.1 ベンチマーク作成
|
||||
```nyash
|
||||
// bench_array_ops.nyash
|
||||
local arr = new ArrayBox()
|
||||
local start = Timer.now()
|
||||
loop(i in 0..1000000) {
|
||||
arr.push(i)
|
||||
}
|
||||
local elapsed = Timer.now() - start
|
||||
print("Time: " + elapsed)
|
||||
```
|
||||
|
||||
#### 5.2 比較測定
|
||||
```bash
|
||||
# 従来版
|
||||
./target/release/nyash --benchmark bench_array_ops.nyash
|
||||
|
||||
# プラグイン版
|
||||
NYASH_USE_PLUGIN_BUILTINS=1 ./target/release/nyash --benchmark bench_array_ops.nyash
|
||||
```
|
||||
|
||||
## 🎯 成功基準
|
||||
|
||||
### Phase 1(1週間)
|
||||
- [ ] ArrayBoxプラグインが動作
|
||||
- [ ] VM経由で基本操作(new, length, push, get)が可能
|
||||
- [ ] パフォーマンス劣化が10%以内
|
||||
|
||||
### Phase 2(2週間)
|
||||
- [ ] JIT経由でも動作
|
||||
- [ ] 5つ以上のビルトインBoxがプラグイン化
|
||||
- [ ] 既存テストがすべてパス
|
||||
|
||||
### Phase 3(1ヶ月)
|
||||
- [ ] すべての主要ビルトインBoxがプラグイン化
|
||||
- [ ] 静的リンクでの最小exe生成
|
||||
- [ ] Linux/macOSで動作確認
|
||||
|
||||
## ⚠️ 注意事項
|
||||
|
||||
1. **TLVエンコーディング**: 既存のプラグインシステムに合わせる
|
||||
2. **エラー処理**: panicではなくエラーコードを返す
|
||||
3. **メモリ管理**: Box化されたデータのライフサイクルに注意
|
||||
|
||||
## 💡 デバッグ時のヒント
|
||||
|
||||
```bash
|
||||
# プラグインロード確認
|
||||
NYASH_DEBUG_PLUGIN=1 ./target/release/nyash test.nyash
|
||||
|
||||
# JIT呼び出し確認
|
||||
NYASH_JIT_EVENTS=1 ./target/release/nyash --backend vm test.nyash
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
*"手順を守れば大丈夫" - 一歩ずつ確実に進めるにゃ!*
|
||||
87
docs/phases/phase-10.1/phase_plan.md
Normal file
87
docs/phases/phase-10.1/phase_plan.md
Normal file
@ -0,0 +1,87 @@
|
||||
# Phase 10.1 – Plugin Unification Path (MIR→JIT/AOT via C ABI)
|
||||
|
||||
This plan refines how we leverage the existing plugin system (BID-FFI) to unify JIT and AOT (EXE) paths using a single C ABI surface.
|
||||
|
||||
## Goals
|
||||
- Unify calls from JIT and AOT to the same C ABI (`nyrt_*` / `nyplug_*`).
|
||||
- Convert builtin Boxes to Plugin Boxes in small steps (read-only first).
|
||||
- Produce a minimal standalone EXE via static linking after unification.
|
||||
|
||||
## Feasibility Summary
|
||||
- JIT: emit calls to `extern "C"` symbols (no change in semantics, only target).
|
||||
- AOT: emit `.o` with unresolved `nyrt_*` / `nyplug_*` and link with `libnyrt.a` + plugin `.a`.
|
||||
- Compatibility: guard with `NYASH_USE_PLUGIN_BUILTINS` and keep HostCall fallback.
|
||||
|
||||
## Phase Breakdown
|
||||
|
||||
### 10.1: Plugin PoC + C ABI base (1 week)
|
||||
- Deliverables:
|
||||
- Minimal headers: `nyrt.h` (runtime), `nyplug_array.h` (ArrayBox plugin).
|
||||
- ArrayBox as a plugin (`cdylib` + `staticlib`), ABI version functions.
|
||||
- VM loader integration and `NYASH_USE_PLUGIN_BUILTINS` switch.
|
||||
- Smoke: `new/len/push/get` working via plugin.
|
||||
- DoD:
|
||||
- Array plugin works on VM path; perf regression ≤10% on micro bench.
|
||||
|
||||
### 10.2: JIT Lowering unification (Array first) (1–1.5 weeks)
|
||||
- Deliverables:
|
||||
- IRBuilder: `emit_plugin_invoke(type_id, method_id, args, sig)`.
|
||||
- LowerCore BoxCall for Array routes to `plugin_invoke` (events/stats intact).
|
||||
- Feature-flagged enablement: `NYASH_USE_PLUGIN_BUILTINS=1`.
|
||||
- DoD:
|
||||
- JIT execution of Array read/write (policy-constrained) via plugin path.
|
||||
- Behavior parity with HostCall; no regressions on CI smoke.
|
||||
|
||||
### 10.2b: JIT Coverage Unblockers (0.5–1 week)
|
||||
- Goal:
|
||||
- Remove practical blockers so plugin_invoke can be exercised in typical Nyash functions and `.o` can be produced.
|
||||
- Deliverables:
|
||||
- Lowering for `NewBox` of pluginized builtins → translate `new <Box>()` to plugin `birth()` via `emit_plugin_invoke(type_id, 0, argc=1 recvr-param)` with appropriate handle threading.
|
||||
- Treat `Print/Debug` as no-op/hostcall for v0 to avoid function-wide skip.
|
||||
- Keep conservative skip policy by default; document `NYASH_AOT_ALLOW_UNSUPPORTED=1` for validation-only `.o` emission.
|
||||
- DoD:
|
||||
- Minimal demo function with `String.length()` compiled by JIT (Cranelift) and `.o` emitted. Plugin events visible under JIT.
|
||||
|
||||
### 10.3: Broaden plugin coverage + Compatibility (2 weeks)
|
||||
- Targets: String/Integer/Bool/Map (read-only first).
|
||||
- Deliverables:
|
||||
- Pluginized Boxes and `plugin_invoke` lowering for BoxCall.
|
||||
- HostCall route retained; whitelist-driven co-existence.
|
||||
- Added smoke and microbenches comparing HostCall vs Plugin.
|
||||
- DoD:
|
||||
- ≥5 builtin Boxes pluginized; `NYASH_USE_PLUGIN_BUILTINS=1` green on smoke.
|
||||
|
||||
### 10.4: AOT/EXE minimal pipeline (2–3 weeks)
|
||||
- Deliverables:
|
||||
- ObjectWriter path to emit `.o` with unresolved `nyrt_*`/`nyplug_*`.
|
||||
- `libnyrt.a` minimal runtime + selected plugin `.a`.
|
||||
- Link scripts and `nyc build-aot` proof-of-concept.
|
||||
- Hello World-level standalone EXE on Linux/macOS.
|
||||
- DoD:
|
||||
- `nyc build-aot <file.nyash> -o app` runs without JIT/VM.
|
||||
- Basic debug info and minimal unwind.
|
||||
|
||||
### 10.5: Python Integration (moved; separate phase)
|
||||
- Python work is deferred to 10.5 and builds on the plugin/AOT foundation.
|
||||
|
||||
## Flags & Compatibility
|
||||
- `NYASH_USE_PLUGIN_BUILTINS=1` – enables plugin path for builtin Boxes.
|
||||
- `NYASH_JIT_HOSTCALL=1` – preserves HostCall path for comparison.
|
||||
- Call conv alignment: x86_64 SysV, aarch64 AAPCS64, Win64.
|
||||
- ABI version checks: `nyrt_abi_version()`, `nyplug_*_abi_version()` hard-fail on mismatch.
|
||||
|
||||
## Risks & Mitigations
|
||||
- ABI drift: minimal headers + version checks.
|
||||
- Linking complexity: start with the smallest set (Array/Print/GC-minimal), expand gradually.
|
||||
- Performance: keep RO-first; benchmark and fall back to HostCall if needed.
|
||||
- Windows linkage: prioritize Linux/macOS, then handle Win specifics in a follow-up task.
|
||||
- JIT coverage: adopt staged lowering (NewBox→birth, Print/Debug no-op) to clear blockers; retain strict skip policy otherwise.
|
||||
|
||||
## References
|
||||
- `c_abi_unified_design.md`
|
||||
- `implementation_steps.md`
|
||||
- `../phase-10.5/` (Python integration)
|
||||
|
||||
---
|
||||
|
||||
Everything is Plugin → unified paths for JIT and AOT.
|
||||
54
docs/phases/phase-10.11-builtins-to-plugins.md
Normal file
54
docs/phases/phase-10.11-builtins-to-plugins.md
Normal file
@ -0,0 +1,54 @@
|
||||
# Phase 10.11: Builtins → Plugins Migration
|
||||
|
||||
## Goals
|
||||
- Remove builtin Box implementations from execution paths (Interpreter/VM/JIT) to avoid divergence and double sources of truth.
|
||||
- Provide all functionality via plugins (BID-FFI v1) and/or user-defined boxes.
|
||||
- Keep backward compatibility guarded behind env flags until migration completes.
|
||||
|
||||
## Rationale
|
||||
- Conflicts like ConsoleBox builtin vs plugin cause unexpected behavior.
|
||||
- Native build (AOT/EXE) path benefits from uniform plugin boundary.
|
||||
- One registry, one implementation per Box: simpler, safer.
|
||||
|
||||
## Plan (Incremental)
|
||||
1) Disable Switch (Now)
|
||||
- Add `NYASH_DISABLE_BUILTINS=1` to skip registering builtin box factory.
|
||||
- Keep off by default; use in CI lanes and targeted tests.
|
||||
|
||||
2) Constructor Delegation (Now → Next)
|
||||
- Ensure all constructors go through the unified registry, not direct builtin instantiation.
|
||||
- Done: ConsoleBox; Next: remaining non-basic constructors.
|
||||
|
||||
3) Override Policy (Ongoing)
|
||||
- Use `NYASH_USE_PLUGIN_BUILTINS=1` + `NYASH_PLUGIN_OVERRIDE_TYPES` to prefer plugins for selected types.
|
||||
- Grow the allowlist as plugins become available.
|
||||
|
||||
4) Plugin Coverage (Milestones)
|
||||
- ConsoleBox (stdout) — done
|
||||
- Array/Map/String/Integer — in place
|
||||
- File/Net/Python — in place
|
||||
- Math/Time/etc. — add `nyash_box.toml` and minimal plugins
|
||||
|
||||
5) Remove Builtins (Final)
|
||||
- Remove builtin factory or move into separate optional crate for legacy runs.
|
||||
- Update docs, examples, and CI to plugin-only.
|
||||
|
||||
## Acceptance Criteria
|
||||
- `NYASH_DISABLE_BUILTINS=1` + plugin set → examples run green (VM path).
|
||||
- No direct builtins in interpreter constructors (registry only).
|
||||
- JIT/AOT compile from MIR uses only plugin invoke shims for Box methods.
|
||||
|
||||
## How to Test
|
||||
```bash
|
||||
# Strict plugin preference + disable builtins
|
||||
export NYASH_USE_PLUGIN_BUILTINS=1
|
||||
export NYASH_PLUGIN_OVERRIDE_TYPES="ArrayBox,MapBox,ConsoleBox,StringBox,IntegerBox"
|
||||
export NYASH_DISABLE_BUILTINS=1
|
||||
|
||||
cargo build --release --features cranelift-jit
|
||||
./target/release/nyash --backend vm examples/console_demo.nyash
|
||||
```
|
||||
|
||||
## Notes
|
||||
- Temporary breakages expected when some builtin-only boxes remain. Use the override allowlist tactically.
|
||||
- Keep `[libraries]` and `[plugins]` configured to ensure provider discovery.
|
||||
29
docs/phases/phase-10.5/10.1a_planning/README.md
Normal file
29
docs/phases/phase-10.5/10.1a_planning/README.md
Normal file
@ -0,0 +1,29 @@
|
||||
[Archived] 旧10.1系ドキュメントです。最新は ../INDEX.md を参照してください。
|
||||
|
||||
# Phase 10.1a - 計画と設計
|
||||
|
||||
## 🎯 このフェーズの目的
|
||||
PythonParserBoxの全体計画を理解し、実装の方向性を把握する。
|
||||
|
||||
## 📁 含まれるファイル
|
||||
- **`pythonparser_integrated_plan_summary.txt`** - 統合実装計画(最重要)
|
||||
- **`expert_feedback_gemini_codex.txt`** - Gemini先生とCodex先生の技術評価
|
||||
- **`archive/`** - 初期検討資料
|
||||
|
||||
## ✅ 完了条件
|
||||
- [ ] 統合計画を読んで理解
|
||||
- [ ] エキスパートフィードバックを確認
|
||||
- [ ] 5つの核心戦略を把握
|
||||
- 関数単位フォールバック
|
||||
- Python 3.11固定
|
||||
- 意味論の正確な実装優先
|
||||
- GIL管理の最小化
|
||||
- テレメトリー重視
|
||||
|
||||
## 📝 重要ポイント
|
||||
- **Differential Testing戦略** - 世界中のPythonコードがテストケースに
|
||||
- **段階的実装** - 完璧を求めず動くものから
|
||||
- **成功の測定基準** - カバレッジ率70%以上、性能向上2-10倍
|
||||
|
||||
## ⏭️ 次のフェーズ
|
||||
→ Phase 10.1b (環境設定)
|
||||
@ -0,0 +1,138 @@
|
||||
# ChatGPT5の革命的アイデア - 多言語統合とBox化
|
||||
|
||||
## 元の発想
|
||||
|
||||
ChatGPT5さんの発想は「すべての言語をBoxで包んで統一的に扱う」という革命的なアプローチです。
|
||||
これにより、Python、Rust、JavaScript、Java等の既存エコシステムをNyashから自然に利用できるようになります。
|
||||
|
||||
## 核心概念
|
||||
|
||||
### 1. ForeignBox - 外部リソースのBox化
|
||||
```nyash
|
||||
// 外部言語のオブジェクトをBoxとして扱う
|
||||
box ForeignBox<T> {
|
||||
private { handle } // 外部リソースへのハンドル
|
||||
|
||||
fini() {
|
||||
ny_host_finalizer(me.handle) // 適切にリソース解放
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. ProxyBox - スレッドセーフな委譲
|
||||
```nyash
|
||||
// GILやイベントループを持つ言語用
|
||||
box ProxyBox<T> {
|
||||
private { bus, worker_id } // Bus経由で別スレッドに委譲
|
||||
|
||||
call(method, args) {
|
||||
return me.bus.send_and_wait(me.worker_id, method, args)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 言語別統合戦略(ChatGPT5原案)
|
||||
|
||||
### Python統合
|
||||
- **課題**: GIL(Global Interpreter Lock)
|
||||
- **解決**: ProxyBoxでBus経由ワーカー委譲
|
||||
- **実装**: CPython C-APIで`PyObject*`をForeignBoxに入れる
|
||||
|
||||
### JavaScript/Node.js統合
|
||||
- **課題**: イベントループを壊さない
|
||||
- **解決**: ProxyBox(postMessage/uv_queue_work)
|
||||
- **短い同期関数**: ForeignBoxでも可
|
||||
|
||||
### Rust/C統合
|
||||
- **最短パス**: C-ABI直接
|
||||
- **Rust側**: `#[no_mangle] extern "C"`
|
||||
- **所有権**: Nyash↔Rustのどちらかに寄せる(二重所有禁止)
|
||||
|
||||
### JVM/.NET統合
|
||||
- **方式**: JNI/P-Invoke
|
||||
- **要件**: Pinning必要
|
||||
- **GC連携**: SafeHandle/PhantomReferenceでFinalizer橋渡し
|
||||
|
||||
### WASM統合
|
||||
- **方式**: `ny_host_*`をimport
|
||||
- **データ**: リニアメモリへBytes/Strで搬送
|
||||
|
||||
## 統一インターフェース設計
|
||||
|
||||
### NyIDL(Nyash Interface Definition Language)
|
||||
```idl
|
||||
module ny {
|
||||
box Image;
|
||||
fn load(path: str) -> Image effects = io
|
||||
fn resize(img: Image, w: i32, h: i32) -> Image effects = mut
|
||||
fn width(img: look Image) -> i32 effects = pure
|
||||
}
|
||||
```
|
||||
|
||||
### 自動生成される要素
|
||||
1. Nyash側extern宣言
|
||||
2. C-ABIシム層
|
||||
3. 各言語用スタブ(Rust/Node/Python/JVM)
|
||||
4. ForeignBox/ProxyBoxラッパー
|
||||
|
||||
## 所有権と寿命管理
|
||||
|
||||
### One Strong Owner原則
|
||||
- ForeignBoxは所有者1本(NyashまたはA外部)
|
||||
- 弱参照は`weak/look`で管理
|
||||
- 失効時はnull/false
|
||||
|
||||
### Finalizerの橋渡し
|
||||
1. Nyash `fini` → `ny_host_finalizer`呼び出し
|
||||
2. 外部GC/finalize → `ny_host_finalizer`経由でNyashのweakを失効
|
||||
|
||||
## 効果システムとの統合
|
||||
|
||||
```nyash
|
||||
// 効果注釈でFFI境界の振る舞いを明示
|
||||
extern fn py_numpy_matmul(a: ForeignBox<ndarray>, b: ForeignBox<ndarray>)
|
||||
-> ForeignBox<ndarray> effects mut
|
||||
|
||||
extern fn rust_image_load(path: str)
|
||||
-> ForeignBox<Image> effects io
|
||||
|
||||
extern fn js_fetch(url: str)
|
||||
-> ProxyBox<Promise> effects io
|
||||
```
|
||||
|
||||
## MIRレベルでの統合
|
||||
|
||||
### BoxCall命令の拡張
|
||||
```
|
||||
// 通常のBoxCall
|
||||
BoxCall(%result, %box, "method", [%arg1, %arg2])
|
||||
|
||||
// ForeignBoxのメソッド呼び出し
|
||||
BoxCall(%result, %foreign_box, "py_method", [%arg1])
|
||||
// → 内部でFFI境界を越えて呼び出し
|
||||
|
||||
// ProxyBoxの非同期呼び出し
|
||||
Send(%msg_id, %proxy_box, "method", [%args])
|
||||
Recv(%result, %msg_id)
|
||||
```
|
||||
|
||||
## 革命的な利点
|
||||
|
||||
1. **即座の多言語資産活用**: 既存ライブラリを「箱に詰めて」即Nyashで使える
|
||||
2. **統一的な寿命管理**: 強1+weak/look+finiで外部リソースも確定的に回収
|
||||
3. **配布の柔軟性**: WASM/VM/ネイティブのどれでも同じIDLから出荷
|
||||
4. **MIR最適化の恩恵**: 外部言語呼び出しもMIRレベルで最適化可能
|
||||
5. **段階的移行**: 既存プロジェクトを徐々にNyashに移行
|
||||
|
||||
## 実装優先順位
|
||||
|
||||
1. **Phase 1**: C/Rust統合(最も単純)
|
||||
2. **Phase 2**: Python統合(PythonParserBox)
|
||||
3. **Phase 3**: JavaScript/Node.js統合
|
||||
4. **Phase 4**: JVM/.NET統合
|
||||
5. **Phase 5**: 統一IDLと自動生成ツール
|
||||
|
||||
## まとめ
|
||||
|
||||
「すべてをBoxに閉じ込める」という設計を正式化することで、あらゆる言語→NyashとNyash→あらゆる実行系が綺麗に繋がる。
|
||||
これはまさに「Everything is Box」哲学の究極の実現形態といえる。
|
||||
@ -0,0 +1,207 @@
|
||||
# PythonParserBox設計提案 - CPythonパーサーを使ったPython→Nyash変換
|
||||
|
||||
## 概要
|
||||
CPythonの公式パーサーを活用して、PythonコードをNyashで直接実行可能にする革命的なアプローチ。
|
||||
PythonコードをNyashのAST/MIRに変換し、Nyashの最適化・JITコンパイルの恩恵を受けられるようにする。
|
||||
|
||||
## アーキテクチャ
|
||||
|
||||
### 1. PythonParserBox(ビルトインBox)
|
||||
```nyash
|
||||
// 使用例
|
||||
local py_parser = new PythonParserBox()
|
||||
|
||||
// Pythonコードを直接パース
|
||||
local ast = py_parser.parse("""
|
||||
def calculate(x, y):
|
||||
return x * 2 + y
|
||||
|
||||
result = calculate(10, 5)
|
||||
""")
|
||||
|
||||
// NyashのASTに変換
|
||||
local nyash_ast = py_parser.to_nyash_ast(ast)
|
||||
|
||||
// 直接実行も可能
|
||||
local result = py_parser.run(python_code)
|
||||
```
|
||||
|
||||
### 2. 実装構造
|
||||
```rust
|
||||
pub struct PythonParserBox {
|
||||
base: BoxBase,
|
||||
parser: CPythonParser, // CPythonの公式パーサー使用
|
||||
}
|
||||
|
||||
impl PythonParserBox {
|
||||
// Python → Python AST
|
||||
pub fn parse(&self, code: &str) -> Box<dyn NyashBox> {
|
||||
let py_ast = self.parser.parse_string(code);
|
||||
Box::new(PythonAstBox { ast: py_ast })
|
||||
}
|
||||
|
||||
// Python AST → Nyash AST
|
||||
pub fn to_nyash_ast(&self, py_ast: &PythonAstBox) -> Box<dyn NyashBox> {
|
||||
let converter = AstConverter::new();
|
||||
converter.convert_python_to_nyash(py_ast)
|
||||
}
|
||||
|
||||
// Python AST → MIR(直接変換)
|
||||
pub fn to_mir(&self, py_ast: &PythonAstBox) -> MirModule {
|
||||
let mut builder = MirBuilder::new();
|
||||
for func in py_ast.functions() {
|
||||
self.convert_function_to_mir(&mut builder, func);
|
||||
}
|
||||
builder.build()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## AST変換マッピング
|
||||
|
||||
### Python → Nyash対応表
|
||||
| Python AST | Nyash AST | 説明 |
|
||||
|------------|-----------|------|
|
||||
| FunctionDef | FunctionDecl | 関数定義 |
|
||||
| BinOp | BinaryOp | 二項演算 |
|
||||
| Call | MethodCall | 関数呼び出し |
|
||||
| Assign | Assignment | 代入 |
|
||||
| If | IfStatement | 条件分岐 |
|
||||
| While/For | LoopStatement | ループ |
|
||||
| Return | ReturnStatement | return文 |
|
||||
| Import | NewBox/LoadPlugin | import → Box化 |
|
||||
|
||||
### 型変換戦略
|
||||
```rust
|
||||
// Python動的型 → Nyash Box
|
||||
match py_value {
|
||||
PyInt(n) => IntegerBox::new(n),
|
||||
PyFloat(f) => FloatBox::new(f),
|
||||
PyStr(s) => StringBox::new(s),
|
||||
PyList(items) => ArrayBox::from_iter(items),
|
||||
PyDict(map) => MapBox::from_iter(map),
|
||||
PyObject(obj) => PythonObjectBox::new(obj), // 変換不能な場合
|
||||
}
|
||||
```
|
||||
|
||||
## MIR生成例
|
||||
|
||||
### Pythonコード
|
||||
```python
|
||||
def calculate(x, y):
|
||||
return x * 2 + y
|
||||
```
|
||||
|
||||
### 生成されるMIR
|
||||
```
|
||||
function calculate(%x, %y) {
|
||||
Load(%1, %x)
|
||||
Const(%2, 2)
|
||||
BinOp(%3, Mul, %1, %2)
|
||||
Load(%4, %y)
|
||||
BinOp(%5, Add, %3, %4)
|
||||
Return(%5)
|
||||
}
|
||||
```
|
||||
|
||||
## 利点
|
||||
|
||||
1. **完全な互換性**: CPython公式パーサーで100%正確なパース
|
||||
2. **統一最適化**: PythonコードもNyashのMIR最適化パイプラインを通る
|
||||
3. **JIT/AOTコンパイル**: PythonコードをネイティブコードにJIT/AOTコンパイル可能
|
||||
4. **段階的移行**: 既存Pythonコードを徐々にNyashに移行
|
||||
5. **デバッグ統一**: Nyashのデバッグツールでpythonコードもデバッグ可能
|
||||
|
||||
## 実装フェーズ
|
||||
|
||||
### Phase 1: 基本パーサー統合
|
||||
- CPythonパーサーのFFIバインディング
|
||||
- parse()メソッドでPython ASTを取得
|
||||
- AST可視化(dump_ast)
|
||||
|
||||
### Phase 2: AST変換
|
||||
- Python AST → Nyash AST変換器
|
||||
- 基本的な文法要素のサポート
|
||||
- 型変換システム
|
||||
|
||||
### Phase 3: MIR直接生成
|
||||
- Python AST → MIR変換
|
||||
- Python特有の最適化(動的型推論等)
|
||||
- ベンチマーク
|
||||
|
||||
### Phase 4: エコシステム統合
|
||||
- NumPy等の主要ライブラリサポート
|
||||
- Python例外 → Nyashエラー変換
|
||||
- async/await対応
|
||||
- GIL管理の自動化
|
||||
|
||||
## 技術的課題と解決策
|
||||
|
||||
### 1. GIL(Global Interpreter Lock)
|
||||
- 解決策: PythonコードはGILスコープ内で実行
|
||||
- 将来: MIR変換後はGILフリーで実行可能
|
||||
|
||||
### 2. Python動的型とNyash Box型のマッピング
|
||||
- 解決策: 実行時型情報を保持するPythonObjectBox
|
||||
- 最適化: よく使う型(int, str等)は専用Boxに変換
|
||||
|
||||
### 3. Pythonモジュールシステム
|
||||
- 解決策: importをNyashのプラグインロードにマッピング
|
||||
- pip packages → Nyashプラグインとして扱う
|
||||
|
||||
## 実用例
|
||||
|
||||
### 機械学習コードの実行
|
||||
```nyash
|
||||
local ml_code = """
|
||||
import numpy as np
|
||||
from sklearn.linear_model import LinearRegression
|
||||
|
||||
# データ準備
|
||||
X = np.array([[1, 1], [1, 2], [2, 2], [2, 3]])
|
||||
y = np.dot(X, np.array([1, 2])) + 3
|
||||
|
||||
# モデル訓練
|
||||
model = LinearRegression()
|
||||
model.fit(X, y)
|
||||
|
||||
# 予測
|
||||
predictions = model.predict(np.array([[3, 5]]))
|
||||
print(f'Prediction: {predictions[0]}')
|
||||
"""
|
||||
|
||||
local py_parser = new PythonParserBox()
|
||||
local result = py_parser.run(ml_code)
|
||||
```
|
||||
|
||||
### Webアプリケーション
|
||||
```nyash
|
||||
local flask_app = """
|
||||
from flask import Flask, jsonify
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
@app.route('/api/hello/<name>')
|
||||
def hello(name):
|
||||
return jsonify({'message': f'Hello, {name}!'})
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run(port=5000)
|
||||
"""
|
||||
|
||||
local py_parser = new PythonParserBox()
|
||||
py_parser.run(flask_app) // FlaskアプリがNyash内で起動
|
||||
```
|
||||
|
||||
## 期待される効果
|
||||
|
||||
1. **パフォーマンス向上**: PythonコードがJITコンパイルされ高速化
|
||||
2. **メモリ効率**: NyashのGC/メモリ管理を活用
|
||||
3. **相互運用性**: Python↔Nyash↔Rust↔JS等の自由な組み合わせ
|
||||
4. **開発効率**: 既存Pythonライブラリをそのまま使える
|
||||
5. **将来性**: PythonコードをネイティブAOTコンパイル可能
|
||||
|
||||
## まとめ
|
||||
|
||||
PythonParserBoxは、Pythonの豊富なエコシステムとNyashの高性能実行エンジンを組み合わせる画期的なアプローチ。
|
||||
CPythonパーサーの信頼性とNyashのMIR/JIT最適化により、Pythonコードをより高速に、より効率的に実行できる。
|
||||
@ -0,0 +1,98 @@
|
||||
# 2025-08-27 議論まとめ - PythonParserBoxと言語間統合
|
||||
|
||||
## 本日の議論の流れ
|
||||
|
||||
### 1. ベンチマーク実行と問題発見
|
||||
- インタープリター性能問題(10万回ループで2分以上)
|
||||
- VM変数管理エラー
|
||||
- Box APIの成熟度不足(TimeBox.elapsed()が呼べない)
|
||||
- 問題点をPhase 10ドキュメントに追記
|
||||
|
||||
### 2. Cranelift AOT Backendの追加(Phase 10.9)
|
||||
- JIT実装の基盤を再利用して事前コンパイル可能
|
||||
- 非同期完全サポート(WASMの制限なし)
|
||||
- 実装期間2-3週間で可能(上乗せだけ)
|
||||
|
||||
### 3. PythonParserBox構想の深堀り
|
||||
- ChatGPT5さんの「CPythonをBoxで包みMIRに落とし込む」アイデアを具体化
|
||||
- CPythonの公式パーサーを使ってPythonコード→Nyash AST/MIR変換
|
||||
- ビルトインBoxとして分離実装
|
||||
|
||||
### 4. エキスパートへの相談結果
|
||||
|
||||
#### Gemini先生の分析
|
||||
- pyo3活用で技術的課題は解決可能
|
||||
- 最初は特定ドメインのサブセットから開始すべき
|
||||
- GIL管理のBox隠蔽は現実的
|
||||
- 設計思想は他言語(Ruby/JS)にも応用可能
|
||||
|
||||
#### Codex先生の実装提案
|
||||
- CPython内部APIではなく、安定した`ast`モジュール経由
|
||||
- Python側で`ast.parse()` → JSON → Rust側で処理
|
||||
- 最小実装セット定義(基本構造+演算+制御フロー)
|
||||
- 純Pythonループで2-10倍の高速化が現実的
|
||||
|
||||
### 5. Phase 10.1フォルダの作成と整理
|
||||
以下のドキュメントをPhase 10.1に整理:
|
||||
- python_parser_box_design.txt(基本設計)
|
||||
- python_parser_box_implementation_plan.txt(実装計画)
|
||||
- chatgpt5_original_idea.txt(元のアイデア)
|
||||
- summary_2025_08_27.txt(本まとめ)
|
||||
|
||||
## 技術的な要点
|
||||
|
||||
### 実装アプローチ
|
||||
```rust
|
||||
// pyo3でCPythonを埋め込み
|
||||
pyo3 = { version = "0.22", features = ["auto-initialize"] }
|
||||
|
||||
// Python側でAST→JSON変換
|
||||
def parse_to_json(code):
|
||||
tree = ast.parse(code)
|
||||
return json.dumps(ast_to_dict(tree))
|
||||
|
||||
// Rust側で受け取り
|
||||
let json_ast = py_helper.parse_to_json(python_code);
|
||||
let nyash_ast = convert_json_to_nyash_ast(json_ast);
|
||||
```
|
||||
|
||||
### 最小実装セット(Phase 1-2)
|
||||
- 構造: Module, FunctionDef, Return, Assign
|
||||
- 演算: BinOp, Compare, Call, Name, Constant
|
||||
- 制御: If, While, Br, CondBr
|
||||
- 実行: 最初はCPython exec委譲、段階的にMIR実行へ
|
||||
|
||||
### データ共有戦略
|
||||
- NumPy配列: pyo3-numpyでゼロコピー共有
|
||||
- NdArrayBox: Nyash側でNumPy配列を効率的に扱う
|
||||
- バッファプロトコル: PEP 3118で汎用オブジェクト共有
|
||||
|
||||
### 期待される効果
|
||||
- 純Pythonループ: 2-10倍高速化
|
||||
- NumPy処理: 1.0-1.2倍(既に最適化済み)
|
||||
- 将来的: トレースベース最適化で10-30倍も可能
|
||||
|
||||
## 次のステップ
|
||||
|
||||
1. **Phase 1実装開始**(1-2週間)
|
||||
- pyo3統合とPythonParserBox基本実装
|
||||
- parse_to_jsonヘルパー作成
|
||||
- 最小AST変換動作確認
|
||||
|
||||
2. **小規模ベンチマーク**
|
||||
- 簡単なPython関数で動作確認
|
||||
- 性能測定と改善点洗い出し
|
||||
|
||||
3. **段階的拡張**
|
||||
- MIR変換実装
|
||||
- NumPy統合
|
||||
- より複雑なPython機能対応
|
||||
|
||||
## まとめ
|
||||
|
||||
PythonParserBoxは、Nyashの「Everything is Box」哲学を言語間統合に拡張する革命的なアプローチ。
|
||||
CPythonパーサーの信頼性とNyashのMIR/JIT最適化を組み合わせることで、Pythonエコシステムを
|
||||
Nyashから自然に利用でき、かつ高速化も実現できる。
|
||||
|
||||
ChatGPT5さんの最初のアイデア(ForeignBox/ProxyBox)を基に、具体的な実装計画まで落とし込めた。
|
||||
技術的にも実現可能で、段階的なアプローチにより着実に実装できる見込み。
|
||||
@ -0,0 +1,197 @@
|
||||
# PythonParserBox実装計画 - エキスパートフィードバック
|
||||
日付: 2025-08-27
|
||||
|
||||
## Gemini先生のフィードバック
|
||||
|
||||
### 総評
|
||||
これは非常に野心的で、言語の成熟度を飛躍的に高める可能性を秘めた素晴らしい計画です。Nyashの「Everything is a Box」哲学とPythonエコシステムを融合させるという着眼点に大変興奮しました。
|
||||
|
||||
### 1. 実装計画は技術的に健全か?落とし穴は?
|
||||
|
||||
**技術的健全性:**
|
||||
はい、計画は全体として技術的に非常に健全です。
|
||||
|
||||
* **CPythonパーサーの利用:** `pyo3`経由で`ast.parse()`を利用するのは、Python構文との互換性を100%保証するための最も確実で賢明なアプローチです。
|
||||
* **JSON中間表現(IR):** Python AST (Pythonメモリ空間) と Nyash AST (Rustメモリ空間) の間にJSONを挟むのは、言語間の境界を明確に分離する良い設計です。
|
||||
* **段階的実装とフォールバック:** 未実装機能を`exec()`にフォールバックする戦略は、実用性を保ちながら段階的に実装を進めるための極めて現実的なアプローチです。
|
||||
|
||||
**潜在的な落とし穴:**
|
||||
* **パフォーマンス:** `Python AST → JSON → Nyash AST → Nyash実行`というパイプラインは、特に初期段階では非常に低速になります。
|
||||
* **ASTの複雑性の爆発:** PythonのASTは非常に巨大で、言語バージョンの更新も速いです。
|
||||
* **標準ライブラリの壁:** Pythonの真の力は広範な標準/サードパーティライブラリにあります。`import`文をどう扱うかは最重要課題です。
|
||||
|
||||
### 2. Python AST → Nyash AST変換で注意すべき意味論の違いは?
|
||||
|
||||
* **型システム:** Pythonは動的型付け、Nyashは静的型付けまたはより厳格な型システムを持つと推測
|
||||
* **オブジェクトモデルと可変性:** Pythonのオブジェクトは基本的に可変(mutable)
|
||||
* **スコープとクロージャ:** Pythonの`global`や`nonlocal`の挙動は独特
|
||||
* **特殊メソッド (`__dunder__`):** Pythonの挙動は特殊メソッドで定義される
|
||||
* **組み込み関数:** `len()`, `print()`, `range()`などをどう扱うか
|
||||
|
||||
### 3. Nyashパーサーのバグ検証戦略として効果的か?
|
||||
|
||||
**非常に効果的です。** これは「Differential Testing(差分テスト)」と呼ばれる強力な手法です。
|
||||
* **巨大なテストスイート:** 事実上、世の中にある無数のPythonコードがNyashのテストケースになります。
|
||||
* **微妙なバグの発見:** 手書きの単体テストでは見逃しがちなセマンティクスのバグを発見するのに絶大な効果を発揮します。
|
||||
|
||||
### 4. pyo3統合でのGIL管理のベストプラクティスは?
|
||||
|
||||
* **基本原則:** Pythonオブジェクトに触れるコードは、必ずGILを獲得した状態で実行
|
||||
* **GILの必要期間を最小化する**
|
||||
* **`py.allow_threads`の活用:** 時間がかかり、かつPythonオブジェクトに触れない処理で使用
|
||||
|
||||
### 5. 段階的実装(Phase 1-4)の優先順位は適切か?
|
||||
|
||||
はい、提案されている優先順位は非常に適切です。
|
||||
1. Phase 1: 基本構文 + 変数束縛 + 基本的な式 + プリミティブ型
|
||||
2. Phase 2: list, dict, tuple
|
||||
3. Phase 3: 関数とスコープ
|
||||
4. Phase 4: モジュールとクラス
|
||||
|
||||
**最優先で並行すべきこと:** `exec()`へのフォールバック機構
|
||||
|
||||
### 6. 言語成熟度向上への貢献度をどう評価する?
|
||||
|
||||
**定量的指標:**
|
||||
* ライブラリ互換性カバレッジ
|
||||
* パフォーマンステスト
|
||||
* 発見バグ数
|
||||
|
||||
**定性的指標:**
|
||||
* 表現力の向上
|
||||
* 開発者体験
|
||||
* エコシステムのマイルストーン
|
||||
|
||||
### 結論
|
||||
|
||||
この`PythonParserBox`計画は、単なる機能追加ではなく、**Nyash言語のテスト、デバッグ、そしてエコシステム獲得を同時に加速させる、極めて戦略的な一手**です。
|
||||
|
||||
---
|
||||
|
||||
## Codex先生のフィードバック
|
||||
|
||||
### Overall Verdict
|
||||
- Sound approach: Using CPython's parser via pyo3, lowering via a JSON IR, and gradually replacing exec() with Nyash MIR/JIT is feasible and strategically strong.
|
||||
- Biggest risks: Semantic mismatches at statement/expression boundaries, version skew of Python AST, and boundary-costs between CPython and Nyash during phased rollout.
|
||||
|
||||
### Architectural Pitfalls
|
||||
- **Python version skew:** `ast` schema changes across minors. Pin and encode `py_version` + `ast_format` in the JSON.
|
||||
- **AST stability vs syntax fidelity:** `ast` loses comments and some token distinctions
|
||||
- **Boundary granularity:** Whole-file fallback wastes partial coverage; per-node fallback is unsafe. **The practical unit is per-function.**
|
||||
- **Import system and environment:** Python imports pull arbitrary code
|
||||
- **Error mapping:** Propagate Python exceptions with full traceback
|
||||
- **Performance overhead:** Python AST→JSON→Nyash→MIR is heavy
|
||||
- **Object model mismatch:** Identity (`is`), mutability, truthiness, numeric tower
|
||||
- **Concurrency:** GIL limits parallel parse/exec
|
||||
|
||||
### AST→Nyash Semantics: High-Risk Differences
|
||||
- **Names and scope:**
|
||||
- LEGB resolution; `global`/`nonlocal` behavior; closures and cell variables
|
||||
- Comprehension scopes (separate scope in Python 3)
|
||||
- **Control flow:**
|
||||
- `for` iterates via iterator protocol; `for/else`, `while/else` semantics
|
||||
- Short-circuit truthiness uses Python rules; `__bool__` then `__len__`
|
||||
- **Functions:**
|
||||
- Defaults evaluated at definition time; `*args/**kwargs`
|
||||
- Decorators transform functions at definition time
|
||||
- **Operators and numbers:**
|
||||
- `/` true division; `//` floor division; big integers by default
|
||||
- Operator dispatch via dunder methods; `is` vs `==`
|
||||
|
||||
For Phase 1, the must-haves are: LEGB + locals/freevars, default args timing, iterator-based `for`, `for/else` + `while/else`, Python truthiness and short-circuiting.
|
||||
|
||||
### Fallback Strategy
|
||||
- **Fallback unit: Per-function.** If a function body contains unsupported nodes, compile a "PyThunk" that calls into CPython.
|
||||
- **Boundary types:** Define canonical bridges: `PyAnyBox` in Nyash wrapping `Py<PyAny>`
|
||||
- **Imports and globals:** Execute module top-level in Python; then selectively replace functions
|
||||
|
||||
### pyo3/GIL Best Practices
|
||||
- **Initialization:** Call `pyo3::prepare_freethreaded_python()` once
|
||||
- **GIL usage:**
|
||||
- Use `Python::with_gil(|py| { ... })` for all Python calls
|
||||
- Minimize time under GIL; copy data out promptly
|
||||
- For heavy Rust work, drop GIL: `py.allow_threads(|| { ... })`
|
||||
- **Data transfer:** Prefer building JSON on the Python side
|
||||
- **Versioning:** Pin Python minor version; embed version string in the IR
|
||||
|
||||
### Phasing and Priorities (Refined)
|
||||
- **Phase 1 (Parser + Minimal Semantics):**
|
||||
- Python→JSON exporter with location info
|
||||
- Nyash IR for expressions and basic statements
|
||||
- Semantics fidelity for: iterator protocol, truthiness, scoping
|
||||
- **Fallback per-function for anything else**
|
||||
- **Phase 2-4:** Coverage expansion → Objects/Runtime → MIR/JIT
|
||||
|
||||
### Parser Bug Validation Strategy
|
||||
- **Differential execution:** Curate pairs of semantically equivalent snippets
|
||||
- **Oracle testing:** Run CPython as oracle and compare
|
||||
- **Fuzzing:** Grammar-based fuzzers
|
||||
- **Coverage and gating:** Track node-kind coverage
|
||||
|
||||
### IR/JSON Design Tips
|
||||
- Include: `node_type`, children, `lineno/col_offset`, `py_version`, `ast_format`, `support_level`
|
||||
- Canonicalize: normalize forms, operator names
|
||||
- Determinism: maintain stable field ordering
|
||||
|
||||
### Concrete Recommendations
|
||||
- **Pin to one Python minor (e.g., 3.11 or 3.12)**
|
||||
- **Choose per-function fallback as the core boundary**
|
||||
- **Implement Python truthiness, iterator protocol, and scoping correctly before optimizing**
|
||||
- **Keep the GIL minimal: build the JSON in Python; parse in Rust**
|
||||
- **Telemetry from day one: log unsupported node kinds and fallback counts**
|
||||
- **Start with JSON; plan migration to a compact binary once stable**
|
||||
|
||||
---
|
||||
|
||||
## 統合された重要ポイント
|
||||
|
||||
### 🎯 両エキスパートが一致した最重要事項
|
||||
|
||||
1. **関数単位のフォールバック戦略**
|
||||
- ファイル全体でなく関数レベルでコンパイル/フォールバックを切り替え
|
||||
- 未対応機能を含む関数はCPython exec、対応済み関数はNyash MIR/JIT
|
||||
|
||||
2. **Python バージョン固定**
|
||||
- Python 3.11または3.12に固定
|
||||
- AST安定性の確保とバージョン間の差異回避
|
||||
|
||||
3. **意味論の正確な実装が最優先**
|
||||
- 最適化より先にPython互換性を確保
|
||||
- 特に: イテレータプロトコル、真偽値判定、スコーピング規則
|
||||
|
||||
4. **GIL管理の最小化**
|
||||
- Python側でJSON生成、Rust側で解析
|
||||
- 重い処理はGIL外で実行
|
||||
|
||||
5. **テレメトリーの重要性**
|
||||
- 未対応ノードの記録
|
||||
- フォールバック率の計測
|
||||
- 実行時の統計情報収集
|
||||
|
||||
### 🚨 特に注意すべき意味論の違い
|
||||
|
||||
1. **制御フロー**
|
||||
- for/else, while/else の独特な挙動
|
||||
- forループのイテレータプロトコル
|
||||
|
||||
2. **スコープ規則**
|
||||
- LEGB(Local, Enclosing, Global, Builtins)
|
||||
- global/nonlocal宣言
|
||||
- 内包表記の独立スコープ(Python 3)
|
||||
|
||||
3. **数値演算**
|
||||
- / (true division) vs // (floor division)
|
||||
- デフォルトで大整数
|
||||
- NaN の扱い
|
||||
|
||||
4. **関数定義**
|
||||
- デフォルト引数は定義時に評価
|
||||
- *args/**kwargs の扱い
|
||||
- デコレータの実行順序
|
||||
|
||||
### 📊 成功の測定指標
|
||||
|
||||
1. **カバレッジ**: コンパイル済み vs フォールバック関数の比率
|
||||
2. **性能向上**: 数値計算ベンチマークでの改善率
|
||||
3. **バグ発見数**: Differential Testingで発見されたバグ数
|
||||
4. **エコシステム**: 動作する有名Pythonライブラリの数
|
||||
@ -0,0 +1,148 @@
|
||||
# PythonParserBox統合実装計画 - エキスパート評価後の最終版
|
||||
作成日: 2025-08-27
|
||||
|
||||
## 🎯 革命的な3つの価値
|
||||
|
||||
### 1. Pythonエコシステムの即座活用
|
||||
- 既存のPythonライブラリをNyashから直接利用可能
|
||||
- 段階的な移行パスの提供
|
||||
|
||||
### 2. Nyashパーサーのバグ自動検証(Differential Testing)
|
||||
- **世界中のPythonコードがNyashのテストケースに!**
|
||||
- CPythonをオラクルとして使用、出力・戻り値・例外を自動比較
|
||||
- 微妙なセマンティクスバグを大量に発見可能
|
||||
|
||||
### 3. 言語成熟度の飛躍的向上
|
||||
- 実用的なPythonコードでNyashをストレステスト
|
||||
- 発見されたバグ数が成熟度向上の定量的指標
|
||||
|
||||
## 🏆 エキスパート評価サマリー
|
||||
|
||||
### Gemini先生の評価
|
||||
**「非常に野心的で、言語の成熟度を飛躍的に高める可能性を秘めた素晴らしい計画」**
|
||||
|
||||
- 技術的に健全なアプローチ
|
||||
- pyo3経由のCPythonパーサー利用は最も確実
|
||||
- Differential Testingは極めて強力な手法
|
||||
|
||||
### Codex先生の評価
|
||||
**「Sound approach with strategic strength」**
|
||||
|
||||
- 関数単位フォールバックが実用的かつ効果的
|
||||
- Python 3.11固定でAST安定性確保
|
||||
- テレメトリー重視で継続的改善可能
|
||||
|
||||
## 🔑 統合された5つの核心戦略
|
||||
|
||||
### 1. 関数単位フォールバック(両エキスパート一致)
|
||||
```python
|
||||
def supported_function(): # → Nyash MIR/JIT
|
||||
return x + y
|
||||
|
||||
def unsupported_function(): # → CPython exec
|
||||
yield from generator # Phase 1では未対応
|
||||
```
|
||||
|
||||
### 2. Python 3.11固定
|
||||
- AST安定性確保(3.8 Constant統一、3.10 match/case、3.12位置情報)
|
||||
- `py_version`と`ast_format`をJSON IRに埋め込む
|
||||
|
||||
### 3. 意味論の正確な実装優先
|
||||
Phase 1必須要素(Codex先生強調):
|
||||
- LEGB + locals/freevars(スコーピング)
|
||||
- デフォルト引数の評価タイミング(定義時)
|
||||
- イテレータベースのfor文
|
||||
- for/else + while/else(Python独特)
|
||||
- Python真偽値判定(`__bool__` → `__len__`)
|
||||
- 短絡評価(and/or)
|
||||
|
||||
### 4. GIL管理の最小化
|
||||
```rust
|
||||
// GILは最小限に!
|
||||
let json_ast = Python::with_gil(|py| {
|
||||
py_helper.parse_to_json(py, code) // Python側でJSON生成
|
||||
})?;
|
||||
|
||||
// GIL外でRust処理
|
||||
let nyash_ast = py.allow_threads(|| {
|
||||
convert_json_to_nyash(json_ast)
|
||||
});
|
||||
```
|
||||
|
||||
### 5. テレメトリー基盤
|
||||
```bash
|
||||
[PythonParser] Module: example.py (Python 3.11)
|
||||
Functions: 10 total
|
||||
Compiled: 7 (70%)
|
||||
Fallback: 3 (30%)
|
||||
- async_function: unsupported node 'AsyncFunctionDef' at line 23
|
||||
```
|
||||
|
||||
## 📋 実装フェーズ(詳細版)
|
||||
|
||||
### Phase 0: 準備(1週間)
|
||||
- [ ] Python 3.11.9環境固定
|
||||
- [ ] テレメトリー基盤構築
|
||||
- [ ] Differential Testingフレームワーク
|
||||
- [ ] JSON IR仕様策定
|
||||
|
||||
### Phase 1: Core Subset(2週間)
|
||||
- [ ] pyo3統合(prepare_freethreaded_python)
|
||||
- [ ] 関数単位コンパイル判定器
|
||||
- [ ] 基本構文(def/if/for/while/return)
|
||||
- [ ] 意味論必須要素の実装
|
||||
- [ ] CPythonとの出力比較テスト
|
||||
|
||||
### Phase 2: Data Model(3週間)
|
||||
- [ ] 特殊メソッドマッピング
|
||||
- [ ] list/dict/tuple実装
|
||||
- [ ] 演算子オーバーロード
|
||||
|
||||
### Phase 3: Advanced Features(1ヶ月)
|
||||
- [ ] 例外処理(try/except)
|
||||
- [ ] with文、ジェネレータ
|
||||
- [ ] 内包表記、デコレータ
|
||||
|
||||
## 📊 成功の測定基準
|
||||
|
||||
### 定量的指標
|
||||
| 指標 | 目標 | 測定方法 |
|
||||
|------|------|----------|
|
||||
| カバレッジ率 | 70%以上 | コンパイル済み vs フォールバック関数 |
|
||||
| 性能向上 | 2-10倍 | 純Pythonループのベンチマーク |
|
||||
| バグ発見数 | 10+件/Phase | Differential Testing |
|
||||
| エコシステム | 1以上 | 動作する有名ライブラリ数 |
|
||||
|
||||
### マイルストーン
|
||||
- Phase 1: "Hello from Python in Nyash"が動作
|
||||
- Phase 2: scikit-learnの基本アルゴリズムが動作
|
||||
- Phase 3: FlaskのHello Worldが動作
|
||||
- Phase 4: PyPIトップ100の30%が基本動作
|
||||
|
||||
## 🚨 注意すべき意味論の違い(トップ5)
|
||||
|
||||
1. **制御フロー**: for/else, while/else
|
||||
2. **スコープ規則**: LEGB、global/nonlocal
|
||||
3. **数値演算**: / (true division) vs //
|
||||
4. **関数定義**: デフォルト引数は定義時評価
|
||||
5. **真偽値判定**: Pythonの__bool__/__len__ルール
|
||||
|
||||
## 🎉 期待されるインパクト
|
||||
|
||||
### 技術的成果
|
||||
- Pythonエコシステムの活用
|
||||
- Nyashパーサーの品質向上
|
||||
- 性能最適化の実証
|
||||
|
||||
### 戦略的価値
|
||||
- 言語成熟度の飛躍的向上
|
||||
- 開発者コミュニティの拡大
|
||||
- 実用アプリケーション開発の加速
|
||||
|
||||
## 📝 結論
|
||||
|
||||
PythonParserBoxは、単なる機能追加ではなく、**Nyash言語のテスト、デバッグ、エコシステム獲得を同時に加速させる極めて戦略的なプロジェクト**。
|
||||
|
||||
両エキスパートの技術的評価と具体的な実装指針により、実現可能性が確認され、明確な実装パスが定まった。
|
||||
|
||||
**「Everything is Box」哲学を、言語の壁を超えて実現する革命的な一歩。**
|
||||
57
docs/phases/phase-10.5/10.1b_setup/README.md
Normal file
57
docs/phases/phase-10.5/10.1b_setup/README.md
Normal file
@ -0,0 +1,57 @@
|
||||
[Archived] 旧10.1系ドキュメントです。最新は ../INDEX.md を参照してください。
|
||||
|
||||
# Phase 10.1b - 環境設定とセットアップ
|
||||
|
||||
## 🎯 このフェーズの目的
|
||||
PythonParserBox実装に必要な開発環境を整える。
|
||||
|
||||
## 📋 セットアップ手順
|
||||
|
||||
### 1. Python 3.11環境の固定
|
||||
```bash
|
||||
# pyenvを使用する場合
|
||||
pyenv install 3.11.9
|
||||
pyenv local 3.11.9
|
||||
|
||||
# または直接指定
|
||||
python3.11 --version # 3.11.9であることを確認
|
||||
```
|
||||
|
||||
### 2. Cargo.tomlへの依存関係追加
|
||||
```toml
|
||||
[dependencies]
|
||||
pyo3 = { version = "0.22", features = ["auto-initialize"] }
|
||||
pyo3-numpy = "0.22" # NumPy連携用(Phase 3で使用)
|
||||
serde_json = "1.0" # JSON中間表現用
|
||||
```
|
||||
|
||||
### 3. 環境変数の設定
|
||||
```bash
|
||||
# テレメトリー用
|
||||
export NYASH_PYTHONPARSER_TELEMETRY=1 # 基本統計
|
||||
export NYASH_PYTHONPARSER_TELEMETRY=2 # 詳細ログ
|
||||
export NYASH_PYTHONPARSER_STRICT=1 # フォールバック時にパニック(CI用)
|
||||
```
|
||||
|
||||
### 4. ディレクトリ構造の準備
|
||||
```
|
||||
src/boxes/python_parser_box/
|
||||
├── mod.rs # メインモジュール
|
||||
├── py_helper.rs # Python側ヘルパー
|
||||
├── converter.rs # AST変換器
|
||||
└── telemetry.rs # テレメトリー実装
|
||||
```
|
||||
|
||||
## ✅ 完了条件
|
||||
- [ ] Python 3.11.9がインストールされている
|
||||
- [ ] Cargo.tomlに依存関係が追加されている
|
||||
- [ ] 開発ディレクトリ構造が準備されている
|
||||
- [ ] 環境変数の設定方法を理解している
|
||||
|
||||
## 🚨 注意事項
|
||||
- **Python 3.11固定必須** - AST安定性のため
|
||||
- **pyo3::prepare_freethreaded_python()** を一度だけ呼ぶ
|
||||
- GIL管理に注意(Phase 10.1cで詳細)
|
||||
|
||||
## ⏭️ 次のフェーズ
|
||||
→ Phase 10.1c (パーサー統合実装)
|
||||
65
docs/phases/phase-10.5/10.1c_parser_integration/README.md
Normal file
65
docs/phases/phase-10.5/10.1c_parser_integration/README.md
Normal file
@ -0,0 +1,65 @@
|
||||
[Archived] 旧10.1系ドキュメントです。最新は ../INDEX.md を参照してください。
|
||||
|
||||
Note: 本来は「PythonをNyashで動かすフェーズ(パーサー統合)」の位置づけでしたが、現在は順番を変更し、先に 10.5b(MIR→VM→ネイティブビルド基盤)を進めています。
|
||||
|
||||
# Phase 10.1c - パーサー統合実装
|
||||
|
||||
## 🎯 このフェーズの目的
|
||||
pyo3を使ってCPythonパーサーをNyashに統合し、Python AST → JSON → Nyash ASTの変換パイプラインを構築する。
|
||||
|
||||
## 📁 実装ドキュメント
|
||||
- **`python_parser_box_implementation_plan.txt`** - 技術的実装計画
|
||||
- **`builtin_box_implementation_flow.txt`** - ビルトインBox実装フロー
|
||||
|
||||
## 🔧 実装タスク
|
||||
|
||||
### 1. PythonParserBoxの基本構造
|
||||
```rust
|
||||
pub struct PythonParserBox {
|
||||
base: BoxBase,
|
||||
py_helper: Arc<Mutex<PyHelper>>,
|
||||
}
|
||||
```
|
||||
|
||||
### 2. GIL管理の実装
|
||||
```rust
|
||||
// ✅ 良い例:GILを最小限に
|
||||
let json_ast = Python::with_gil(|py| {
|
||||
py_helper.parse_to_json(py, code)
|
||||
})?;
|
||||
|
||||
// GIL外でRust処理
|
||||
let nyash_ast = py.allow_threads(|| {
|
||||
convert_json_to_nyash(json_ast)
|
||||
});
|
||||
```
|
||||
|
||||
### 3. Python側ヘルパー実装
|
||||
- `ast.parse()` → JSON変換
|
||||
- 位置情報の保持(lineno, col_offset)
|
||||
- Python 3.11固定チェック
|
||||
|
||||
### 4. 関数単位フォールバック判定
|
||||
```rust
|
||||
pub fn can_compile(&self, func_def: &PythonAst) -> CompileResult {
|
||||
// サポートされているノードかチェック
|
||||
// CompileResult::Compile or CompileResult::Fallback
|
||||
}
|
||||
```
|
||||
|
||||
## ✅ 完了条件
|
||||
- [ ] PythonParserBoxがビルトインBoxとして登録されている
|
||||
- [ ] `parse_to_json()` メソッドが動作する
|
||||
- [ ] GIL管理が適切に実装されている
|
||||
- [ ] テレメトリー基盤が組み込まれている
|
||||
- [ ] 簡単なPythonコードでJSON ASTが取得できる
|
||||
|
||||
## 🧪 動作確認
|
||||
```nyash
|
||||
local py = new PythonParserBox()
|
||||
local json_ast = py.parse_to_json("def hello(): return 'Hello'")
|
||||
print(json_ast) // JSON ASTが表示される
|
||||
```
|
||||
|
||||
## ⏭️ 次のフェーズ
|
||||
→ Phase 10.1d (Core実装)
|
||||
@ -0,0 +1,553 @@
|
||||
# PythonParserBox ビルトインBox実装フロー(エキスパート統合版)
|
||||
~CPythonパーサー統合とPhase 1実装の具体的な流れ~
|
||||
更新日: 2025-08-27
|
||||
|
||||
## 🎯 全体の実装フロー
|
||||
|
||||
### Step 0: Python 3.11固定(エキスパート推奨)
|
||||
```
|
||||
- Python 3.11.9を使用(AST安定性確保)
|
||||
- pyenvまたはpython3.11コマンドで固定
|
||||
- py_versionとast_formatをJSON IRに必ず含める
|
||||
```
|
||||
|
||||
### Step 1: ビルトインBoxとしての基盤作成
|
||||
```
|
||||
1. src/boxes/python_parser_box/mod.rs を作成
|
||||
2. BoxBase + BoxCore統一アーキテクチャに準拠
|
||||
3. PythonParserBoxの基本構造を定義
|
||||
4. src/boxes/mod.rs に登録
|
||||
5. テレメトリー基盤を初期から組み込む
|
||||
```
|
||||
|
||||
### Step 2: pyo3統合とCPythonパーサー接続
|
||||
```
|
||||
1. Cargo.tomlに pyo3依存関係追加
|
||||
2. pyo3::prepare_freethreaded_python()で一度だけ初期化
|
||||
3. ast.parse()へのFFIブリッジ実装
|
||||
4. JSON中間表現への変換(Python側でJSON生成)
|
||||
5. GILは最小限に、py.allow_threads()でRust処理
|
||||
```
|
||||
|
||||
### Step 3: Phase 1機能の実装(必須意味論要素)
|
||||
```
|
||||
必須要素(Codex先生強調):
|
||||
- LEGBスコーピング + locals/freevars
|
||||
- デフォルト引数の定義時評価
|
||||
- イテレータプロトコル(for文)
|
||||
- for/else + while/else
|
||||
- Python真偽値判定
|
||||
- 短絡評価(and/or)
|
||||
|
||||
実装手順:
|
||||
1. 関数単位フォールバック戦略の実装
|
||||
2. 基本的なAST変換(def, if, for, while, return)
|
||||
3. 式の変換(算術/比較/論理演算子、関数呼び出し)
|
||||
4. Nyash ASTへの意味論を保ったマッピング
|
||||
5. Differential Testingフレームワーク
|
||||
```
|
||||
|
||||
## 📝 具体的な実装コード
|
||||
|
||||
### 1. ビルトインBox定義(src/boxes/python_parser_box/mod.rs)
|
||||
```rust
|
||||
use crate::core::{BoxBase, BoxCore, NyashBox};
|
||||
use crate::ast;
|
||||
use pyo3::prelude::*;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
pub struct PythonParserBox {
|
||||
base: BoxBase,
|
||||
py_helper: Arc<Mutex<PyHelper>>, // Python実行環境
|
||||
}
|
||||
|
||||
impl BoxCore for PythonParserBox {
|
||||
fn box_id(&self) -> u64 {
|
||||
self.base.box_id()
|
||||
}
|
||||
|
||||
fn parent_type_id(&self) -> Option<std::any::TypeId> {
|
||||
self.base.parent_type_id()
|
||||
}
|
||||
|
||||
fn fmt_box(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(f, "PythonParserBox#{}", self.box_id())
|
||||
}
|
||||
}
|
||||
|
||||
impl NyashBox for PythonParserBox {
|
||||
fn type_name(&self) -> &'static str {
|
||||
"PythonParserBox"
|
||||
}
|
||||
|
||||
fn clone_box(&self) -> Box<dyn NyashBox> {
|
||||
Box::new(PythonParserBox {
|
||||
base: BoxBase::new(),
|
||||
py_helper: self.py_helper.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. メソッド実装(Phase 1対応)
|
||||
```rust
|
||||
// テレメトリー用構造体
|
||||
#[derive(Default)]
|
||||
pub struct CompilationTelemetry {
|
||||
compiled_functions: Vec<String>,
|
||||
fallback_functions: Vec<(String, String, usize)>, // (name, reason, lineno)
|
||||
unsupported_nodes: HashMap<String, usize>, // node_type -> count
|
||||
}
|
||||
|
||||
impl PythonParserBox {
|
||||
// コンストラクタ
|
||||
pub fn new() -> Result<Self, String> {
|
||||
// 一度だけ初期化
|
||||
static INIT: std::sync::Once = std::sync::Once::new();
|
||||
INIT.call_once(|| {
|
||||
pyo3::prepare_freethreaded_python();
|
||||
});
|
||||
|
||||
// Python環境の初期化
|
||||
Python::with_gil(|py| {
|
||||
// Python 3.11確認
|
||||
let version = py.version_info();
|
||||
if version.major != 3 || version.minor != 11 {
|
||||
return Err(format!("Python 3.11 required, got {}.{}",
|
||||
version.major, version.minor));
|
||||
}
|
||||
|
||||
let helper = PyHelper::new(py)?;
|
||||
Ok(PythonParserBox {
|
||||
base: BoxBase::new(),
|
||||
py_helper: Arc::new(Mutex::new(helper)),
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// Python code → JSON AST
|
||||
pub fn parse_to_json(&self, code: &str) -> Result<String, String> {
|
||||
let helper = self.py_helper.lock().unwrap();
|
||||
Python::with_gil(|py| {
|
||||
helper.parse_to_json(py, code)
|
||||
})
|
||||
}
|
||||
|
||||
// JSON AST → Nyash AST(Phase 1機能のみ)
|
||||
pub fn json_to_nyash_ast(&self, json: &str) -> Result<ast::Program, String> {
|
||||
let py_ast: Phase1PythonAst = serde_json::from_str(json)
|
||||
.map_err(|e| format!("JSON parse error: {}", e))?;
|
||||
|
||||
let converter = Phase1Converter::new();
|
||||
converter.convert(py_ast)
|
||||
}
|
||||
|
||||
// 直接実行(関数単位フォールバック)
|
||||
pub fn run(&self, code: &str) -> Result<Box<dyn NyashBox>, String> {
|
||||
// まずJSON ASTを取得
|
||||
let json_ast = self.parse_to_json(code)?;
|
||||
let py_ast: serde_json::Value = serde_json::from_str(&json_ast)?;
|
||||
|
||||
// モジュール内の各関数をチェック
|
||||
let compiler = FunctionCompiler::new();
|
||||
let module_result = compiler.compile_module(&py_ast)?;
|
||||
|
||||
// テレメトリー出力(環境変数で制御)
|
||||
if std::env::var("NYASH_PYTHONPARSER_TELEMETRY").is_ok() {
|
||||
compiler.print_telemetry();
|
||||
}
|
||||
|
||||
// 実行(コンパイル済み関数はMIR、他はCPython)
|
||||
module_result.execute()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Python側ヘルパー実装
|
||||
```rust
|
||||
// Pythonコードを文字列として埋め込み
|
||||
const PYTHON_HELPER_CODE: &str = r#"
|
||||
import ast
|
||||
import json
|
||||
import sys
|
||||
|
||||
# Python 3.11固定チェック
|
||||
assert sys.version_info[:2] == (3, 11), f"Python 3.11 required, got {sys.version}"
|
||||
|
||||
def ast_to_dict(node):
|
||||
"""Phase 1: 基本的なAST要素のみ変換(エキスパート推奨JSON IR)"""
|
||||
|
||||
result = {
|
||||
"node_type": node.__class__.__name__,
|
||||
"py_version": "3.11",
|
||||
"ast_format": "v1"
|
||||
}
|
||||
|
||||
# 位置情報(エラー診断用)
|
||||
if hasattr(node, 'lineno'):
|
||||
result['lineno'] = node.lineno
|
||||
result['col_offset'] = node.col_offset
|
||||
if hasattr(node, 'end_lineno'):
|
||||
result['end_lineno'] = node.end_lineno
|
||||
result['end_col_offset'] = node.end_col_offset
|
||||
if isinstance(node, ast.Module):
|
||||
return {
|
||||
"type": "Module",
|
||||
"body": [ast_to_dict(stmt) for stmt in node.body]
|
||||
}
|
||||
elif isinstance(node, ast.FunctionDef):
|
||||
# 意味論上重要:デフォルト引数情報を保存
|
||||
args_info = {
|
||||
"args": [arg.arg for arg in node.args.args],
|
||||
"defaults": [ast_to_dict(default) for default in node.args.defaults],
|
||||
"kwonlyargs": [arg.arg for arg in node.args.kwonlyargs],
|
||||
"kw_defaults": [ast_to_dict(d) if d else None for d in node.args.kw_defaults]
|
||||
}
|
||||
result.update({
|
||||
"name": node.name,
|
||||
"args": args_info,
|
||||
"body": [ast_to_dict(stmt) for stmt in node.body],
|
||||
"decorator_list": [], # Phase 1では未対応
|
||||
"support_level": "full" # コンパイル可能
|
||||
})
|
||||
return result
|
||||
elif isinstance(node, ast.Return):
|
||||
return {
|
||||
"type": "Return",
|
||||
"value": ast_to_dict(node.value) if node.value else None
|
||||
}
|
||||
elif isinstance(node, ast.BinOp):
|
||||
return {
|
||||
"type": "BinOp",
|
||||
"op": node.op.__class__.__name__,
|
||||
"left": ast_to_dict(node.left),
|
||||
"right": ast_to_dict(node.right)
|
||||
}
|
||||
elif isinstance(node, ast.Call):
|
||||
return {
|
||||
"type": "Call",
|
||||
"func": ast_to_dict(node.func),
|
||||
"args": [ast_to_dict(arg) for arg in node.args]
|
||||
}
|
||||
elif isinstance(node, ast.Name):
|
||||
return {
|
||||
"type": "Name",
|
||||
"id": node.id
|
||||
}
|
||||
elif isinstance(node, ast.Constant):
|
||||
return {
|
||||
"type": "Constant",
|
||||
"value": node.value
|
||||
}
|
||||
elif isinstance(node, ast.If):
|
||||
return {
|
||||
"type": "If",
|
||||
"test": ast_to_dict(node.test),
|
||||
"body": [ast_to_dict(stmt) for stmt in node.body],
|
||||
"orelse": [ast_to_dict(stmt) for stmt in node.orelse]
|
||||
}
|
||||
elif isinstance(node, ast.For):
|
||||
# 意味論上重要:for/else構文
|
||||
result.update({
|
||||
"target": ast_to_dict(node.target),
|
||||
"iter": ast_to_dict(node.iter),
|
||||
"body": [ast_to_dict(stmt) for stmt in node.body],
|
||||
"orelse": [ast_to_dict(stmt) for stmt in node.orelse], # else節
|
||||
"support_level": "full"
|
||||
})
|
||||
return result
|
||||
|
||||
elif isinstance(node, ast.While):
|
||||
# 意味論上重要:while/else構文
|
||||
result.update({
|
||||
"test": ast_to_dict(node.test),
|
||||
"body": [ast_to_dict(stmt) for stmt in node.body],
|
||||
"orelse": [ast_to_dict(stmt) for stmt in node.orelse], # else節
|
||||
"support_level": "full"
|
||||
})
|
||||
return result
|
||||
|
||||
elif isinstance(node, ast.BoolOp):
|
||||
# 意味論上重要:短絡評価
|
||||
result.update({
|
||||
"op": node.op.__class__.__name__, # And, Or
|
||||
"values": [ast_to_dict(v) for v in node.values],
|
||||
"support_level": "full"
|
||||
})
|
||||
return result
|
||||
else:
|
||||
# Phase 1では未対応(テレメトリー用)
|
||||
return {
|
||||
"node_type": "Unsupported",
|
||||
"original_type": type(node).__name__,
|
||||
"support_level": "fallback",
|
||||
"lineno": getattr(node, 'lineno', -1)
|
||||
}
|
||||
|
||||
def parse_to_json(code):
|
||||
try:
|
||||
tree = ast.parse(code)
|
||||
return json.dumps(ast_to_dict(tree))
|
||||
except Exception as e:
|
||||
return json.dumps({"type": "Error", "message": str(e)})
|
||||
"#;
|
||||
|
||||
struct PyHelper {
|
||||
// Python側のヘルパー関数への参照を保持
|
||||
parse_func: PyObject,
|
||||
}
|
||||
|
||||
impl PyHelper {
|
||||
fn new(py: Python) -> PyResult<Self> {
|
||||
// ヘルパーコードをPythonで実行
|
||||
let helpers = PyModule::from_code(py, PYTHON_HELPER_CODE, "helper.py", "helper")?;
|
||||
let parse_func = helpers.getattr("parse_to_json")?.to_object(py);
|
||||
|
||||
Ok(PyHelper { parse_func })
|
||||
}
|
||||
|
||||
fn parse_to_json(&self, py: Python, code: &str) -> Result<String, String> {
|
||||
match self.parse_func.call1(py, (code,)) {
|
||||
Ok(result) => result.extract::<String>(py)
|
||||
.map_err(|e| format!("Extract error: {}", e)),
|
||||
Err(e) => Err(format!("Parse error: {}", e))
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Phase 1 AST変換器
|
||||
```rust
|
||||
struct Phase1Converter;
|
||||
|
||||
impl Phase1Converter {
|
||||
fn new() -> Self {
|
||||
Phase1Converter
|
||||
}
|
||||
|
||||
fn convert(&self, py_ast: Phase1PythonAst) -> Result<ast::Program, String> {
|
||||
match py_ast {
|
||||
Phase1PythonAst::Module { body } => {
|
||||
let mut items = vec![];
|
||||
for stmt in body {
|
||||
match self.convert_statement(stmt)? {
|
||||
Some(item) => items.push(item),
|
||||
None => {} // 未対応要素はスキップ
|
||||
}
|
||||
}
|
||||
Ok(ast::Program { items })
|
||||
}
|
||||
_ => Err("Expected Module at top level".into())
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_statement(&self, stmt: Phase1PythonAst) -> Result<Option<ast::ProgramItem>, String> {
|
||||
match stmt {
|
||||
Phase1PythonAst::FunctionDef { name, args, body } => {
|
||||
// Python def → Nyash function
|
||||
let params = args.into_iter()
|
||||
.map(|arg| ast::Parameter { name: arg, ty: None })
|
||||
.collect();
|
||||
|
||||
let nyash_body = self.convert_body(body)?;
|
||||
|
||||
Ok(Some(ast::ProgramItem::Function(ast::FunctionDef {
|
||||
name,
|
||||
params,
|
||||
body: nyash_body,
|
||||
return_type: None,
|
||||
})))
|
||||
}
|
||||
Phase1PythonAst::Return { value } => {
|
||||
let expr = value
|
||||
.map(|v| self.convert_expression(v))
|
||||
.transpose()?;
|
||||
|
||||
Ok(Some(ast::ProgramItem::Statement(ast::Statement::Return(expr))))
|
||||
}
|
||||
// 他の文も同様に変換
|
||||
_ => Ok(None) // Phase 1では未対応
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_expression(&self, expr: Phase1PythonAst) -> Result<ast::Expression, String> {
|
||||
match expr {
|
||||
Phase1PythonAst::BinOp { op, left, right } => {
|
||||
let left = Box::new(self.convert_expression(*left)?);
|
||||
let right = Box::new(self.convert_expression(*right)?);
|
||||
|
||||
let op = match op.as_str() {
|
||||
"Add" => ast::BinaryOp::Add,
|
||||
"Sub" => ast::BinaryOp::Sub,
|
||||
"Mul" => ast::BinaryOp::Mul,
|
||||
"Div" => ast::BinaryOp::Div,
|
||||
_ => return Err(format!("Unsupported operator: {}", op))
|
||||
};
|
||||
|
||||
Ok(ast::Expression::BinaryOp { op, left, right })
|
||||
}
|
||||
Phase1PythonAst::Constant { value } => {
|
||||
// Python定数 → Nyashリテラル
|
||||
match value {
|
||||
serde_json::Value::Number(n) => {
|
||||
if let Some(i) = n.as_i64() {
|
||||
Ok(ast::Expression::Integer(i))
|
||||
} else if let Some(f) = n.as_f64() {
|
||||
Ok(ast::Expression::Float(f))
|
||||
} else {
|
||||
Err("Unsupported number type".into())
|
||||
}
|
||||
}
|
||||
serde_json::Value::String(s) => {
|
||||
Ok(ast::Expression::String(s))
|
||||
}
|
||||
serde_json::Value::Bool(b) => {
|
||||
Ok(ast::Expression::Bool(b))
|
||||
}
|
||||
_ => Err("Unsupported constant type".into())
|
||||
}
|
||||
}
|
||||
// 他の式も同様
|
||||
_ => Err("Unsupported expression in Phase 1".into())
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 5. インタープリター統合(src/interpreter/builtins.rs)
|
||||
```rust
|
||||
// ビルトインBox登録に追加
|
||||
pub fn register_builtin_boxes(env: &mut Environment) {
|
||||
// 既存のBox登録...
|
||||
|
||||
// PythonParserBox追加
|
||||
env.register_builtin_box("PythonParserBox", || {
|
||||
match PythonParserBox::new() {
|
||||
Ok(parser) => Arc::new(parser) as Arc<dyn NyashBox>,
|
||||
Err(e) => panic!("Failed to initialize PythonParserBox: {}", e)
|
||||
}
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
### 6. 使用例とテストケース
|
||||
```nyash
|
||||
// test_python_parser_phase1.nyash
|
||||
local py = new PythonParserBox()
|
||||
|
||||
// Phase 1: 基本的な関数定義と演算
|
||||
local code = """
|
||||
def add(x, y):
|
||||
return x + y
|
||||
|
||||
def multiply(x, y):
|
||||
return x * y
|
||||
|
||||
def calculate(a, b):
|
||||
sum_val = add(a, b)
|
||||
prod_val = multiply(a, b)
|
||||
return sum_val + prod_val
|
||||
"""
|
||||
|
||||
// パースしてJSON ASTを確認
|
||||
local json_ast = py.parse_to_json(code)
|
||||
print("JSON AST: " + json_ast)
|
||||
|
||||
// Nyash ASTに変換
|
||||
local nyash_ast = py.json_to_nyash_ast(json_ast)
|
||||
print("Conversion successful!")
|
||||
|
||||
// 実行(最初はCPython経由)
|
||||
local result = py.run(code + "\nprint(calculate(10, 5))")
|
||||
```
|
||||
|
||||
## 📊 段階的な実装計画
|
||||
|
||||
### Week 1: 基盤構築
|
||||
- [ ] PythonParserBoxの基本構造
|
||||
- [ ] pyo3統合とPython環境初期化
|
||||
- [ ] parse_to_json基本実装
|
||||
- [ ] エラーハンドリング
|
||||
|
||||
### Week 2: Phase 1変換器
|
||||
- [ ] Phase1PythonAstの定義
|
||||
- [ ] Phase1Converterの実装
|
||||
- [ ] 基本的な文と式の変換
|
||||
- [ ] テストケース作成
|
||||
|
||||
### Week 3: 統合とテスト
|
||||
- [ ] インタープリター統合
|
||||
- [ ] CPython exec経由の実行
|
||||
- [ ] ベンチマーク準備
|
||||
- [ ] ドキュメント整備
|
||||
|
||||
## 🚀 期待される成果
|
||||
|
||||
### Phase 1完了時点で実現できること:
|
||||
1. **基本的なPythonコードの実行**
|
||||
- 関数定義、算術演算、条件分岐、ループ
|
||||
|
||||
2. **Nyash ASTへの変換**
|
||||
- 将来のMIR/JIT最適化への道筋
|
||||
|
||||
3. **統合開発環境**
|
||||
- PythonコードとNyashコードの混在実行
|
||||
|
||||
4. **性能測定基盤**
|
||||
- CPython実行 vs Nyash実行の比較
|
||||
|
||||
## 📡 テレメトリー出力例
|
||||
|
||||
```bash
|
||||
# 環境変数で制御
|
||||
export NYASH_PYTHONPARSER_TELEMETRY=1 # 基本統計
|
||||
export NYASH_PYTHONPARSER_TELEMETRY=2 # 詳細ログ
|
||||
export NYASH_PYTHONPARSER_STRICT=1 # フォールバック時にパニック
|
||||
|
||||
# 実行例
|
||||
./target/release/nyash test_python_parser.nyash
|
||||
|
||||
# 出力
|
||||
[PythonParser] Module: test.py (Python 3.11)
|
||||
Functions: 10 total
|
||||
Compiled: 7 (70%) → Nyash MIR/JIT
|
||||
Fallback: 3 (30%) → CPython exec
|
||||
- async_function: unsupported node 'AsyncFunctionDef' at line 23
|
||||
- generator_func: unsupported node 'Yield' at line 45
|
||||
- decorator_func: unsupported node 'decorator_list' at line 67
|
||||
|
||||
Unsupported Nodes Summary:
|
||||
AsyncFunctionDef: 1
|
||||
Yield: 2
|
||||
ClassDef: 1
|
||||
```
|
||||
|
||||
## 📊 Differential Testingフレームワーク
|
||||
|
||||
```rust
|
||||
// CPythonとNyashの出力比較
|
||||
pub fn differential_test(code: &str) -> TestResult {
|
||||
// CPythonで実行(オラクル)
|
||||
let python_result = Python::with_gil(|py| {
|
||||
capture_python_execution(py, code)
|
||||
})?;
|
||||
|
||||
// Nyashで実行
|
||||
let nyash_result = execute_with_pythonparser(code)?;
|
||||
|
||||
// 結果比較
|
||||
compare_results(python_result, nyash_result)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
作成日: 2025-08-27
|
||||
Phase 1実装の具体的な手順とエキスパートフィードバック統合
|
||||
@ -0,0 +1,361 @@
|
||||
# PythonParserBox実装計画(統合版)
|
||||
更新日: 2025-08-27
|
||||
|
||||
## 🎯 エキスパートからの統合フィードバック
|
||||
|
||||
### 最重要ポイント(両エキスパートが一致)
|
||||
1. **関数単位のフォールバック戦略**
|
||||
- ファイル全体でなく関数レベルでコンパイル/フォールバックを切り替え
|
||||
- 未対応機能を含む関数はCPython exec、対応済み関数はNyash MIR/JIT
|
||||
|
||||
2. **Python 3.11固定**
|
||||
- AST安定性の確保(3.8 Constant統一、3.10 match/case、3.12位置情報)
|
||||
- `py_version`と`ast_format`をJSON IRに埋め込む
|
||||
|
||||
3. **意味論の正確な実装が最優先**
|
||||
- 最適化より先にPython互換性を確保
|
||||
- 特に: イテレータプロトコル、真偽値判定、スコーピング規則(LEGB)
|
||||
|
||||
4. **GIL管理の最小化**
|
||||
- Python側でJSON生成(`ast.NodeVisitor` + `json.dumps`)
|
||||
- Rust側で解析(GIL外で実行)
|
||||
- `py.allow_threads(|| { ... })`で重い処理をGIL外実行
|
||||
|
||||
5. **テレメトリー重視**
|
||||
- 未対応ノードの記録(`support_level`フィールド)
|
||||
- フォールバック率の計測
|
||||
- ソース位置情報の保持(`lineno/col_offset/end_*`)
|
||||
|
||||
### Differential Testing戦略
|
||||
- **世界中のPythonコードがNyashのテストケース**
|
||||
- CPythonを「オラクル」として使用
|
||||
- 出力、戻り値、例外を比較
|
||||
- Grammar-based fuzzing(Hypothesis活用)
|
||||
|
||||
## 技術的実装方針
|
||||
|
||||
### 1. CPythonパーサー統合(pyo3使用)
|
||||
```rust
|
||||
// Cargo.toml
|
||||
[dependencies]
|
||||
pyo3 = { version = "0.22", features = ["auto-initialize"] }
|
||||
pyo3-numpy = "0.22" // NumPy連携用
|
||||
|
||||
// 初期化(一度だけ)
|
||||
pyo3::prepare_freethreaded_python();
|
||||
|
||||
// Python側ヘルパー(embedded)
|
||||
const PYTHON_HELPER: &str = r#"
|
||||
import ast
|
||||
import json
|
||||
import sys
|
||||
|
||||
def parse_to_json(code, filename="<string>", mode="exec"):
|
||||
tree = ast.parse(code, filename, mode)
|
||||
return json.dumps(ast_to_dict(tree))
|
||||
|
||||
def ast_to_dict(node):
|
||||
result = {}
|
||||
|
||||
# 必須フィールド
|
||||
result['node_type'] = node.__class__.__name__
|
||||
result['py_version'] = f"{sys.version_info.major}.{sys.version_info.minor}"
|
||||
|
||||
# 位置情報(エラー診断用)
|
||||
if hasattr(node, 'lineno'):
|
||||
result['lineno'] = node.lineno
|
||||
result['col_offset'] = node.col_offset
|
||||
if hasattr(node, 'end_lineno'): # Python 3.8+
|
||||
result['end_lineno'] = node.end_lineno
|
||||
result['end_col_offset'] = node.end_col_offset
|
||||
|
||||
# サポートレベル(Nyash側で設定)
|
||||
result['support_level'] = 'unknown'
|
||||
|
||||
# ASTフィールド
|
||||
if isinstance(node, ast.AST):
|
||||
for field in node._fields:
|
||||
value = getattr(node, field)
|
||||
result[field] = ast_to_dict(value)
|
||||
elif isinstance(node, list):
|
||||
return [ast_to_dict(x) for x in node]
|
||||
else:
|
||||
return node
|
||||
|
||||
return result
|
||||
"#;
|
||||
```
|
||||
|
||||
### 2. 最小実装セット(Phase 1: Must-Have)
|
||||
```
|
||||
Phase 1 意味論の必須要素(Codex先生強調):
|
||||
- LEGB + locals/freevars(スコーピング)
|
||||
- デフォルト引数の評価タイミング(定義時)
|
||||
- イテレータベースのfor文
|
||||
- for/else + while/else(Python独特)
|
||||
- Python真偽値判定(__bool__ → __len__)
|
||||
- 短絡評価(and/or)
|
||||
|
||||
Phase 1 AST構造:
|
||||
├─ Module (py_version, ast_format)
|
||||
├─ FunctionDef (name, args, body, decorator_list=[])
|
||||
│ └─ arguments (args, defaults, kwonlyargs=[], kw_defaults=[])
|
||||
├─ Return (value)
|
||||
├─ Assign (targets, value)
|
||||
├─ AugAssign (target, op, value) # +=, -=等
|
||||
└─ Expr (value)
|
||||
|
||||
Phase 1 式:
|
||||
├─ BinOp (left, op, right)
|
||||
│ └─ ops: Add, Sub, Mult, Div, FloorDiv, Mod, Pow
|
||||
├─ Compare (left, ops, comparators)
|
||||
│ └─ ops: Eq, NotEq, Lt, LtE, Gt, GtE, Is, IsNot
|
||||
├─ BoolOp (op, values) # and/or
|
||||
├─ UnaryOp (op, operand) # not, -, +
|
||||
├─ Call (func, args, keywords=[])
|
||||
├─ Name (id, ctx=Load/Store/Del)
|
||||
├─ Constant (value) # Python 3.8+統一
|
||||
└─ IfExp (test, body, orelse) # 三項演算子
|
||||
|
||||
Phase 1 制御フロー:
|
||||
├─ If (test, body, orelse)
|
||||
├─ While (test, body, orelse) # else節対応必須
|
||||
├─ For (target, iter, body, orelse) # else節対応必須
|
||||
├─ Break
|
||||
└─ Continue
|
||||
```
|
||||
|
||||
### 3. 関数単位フォールバック戦略
|
||||
```rust
|
||||
// 関数単位のコンパイル判定
|
||||
pub struct FunctionCompiler {
|
||||
supported_nodes: HashSet<&'static str>,
|
||||
telemetry: CompilationTelemetry,
|
||||
}
|
||||
|
||||
impl FunctionCompiler {
|
||||
pub fn can_compile(&self, func_def: &PythonAst) -> CompileResult {
|
||||
let mut visitor = SupportChecker::new(&self.supported_nodes);
|
||||
visitor.visit(func_def);
|
||||
|
||||
if visitor.has_unsupported() {
|
||||
// CPython execへフォールバック
|
||||
CompileResult::Fallback {
|
||||
reason: visitor.unsupported_nodes(),
|
||||
location: func_def.location(),
|
||||
}
|
||||
} else {
|
||||
// Nyash MIR/JITへコンパイル
|
||||
CompileResult::Compile
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compile_module(&mut self, module: &PythonAst) -> ModuleUnit {
|
||||
let mut units = vec![];
|
||||
|
||||
// モジュールトップレベルはPythonで実行(globals設定)
|
||||
units.push(ExecutionUnit::PythonExec(module.top_level));
|
||||
|
||||
// 各関数を判定
|
||||
for func in module.functions() {
|
||||
match self.can_compile(func) {
|
||||
CompileResult::Compile => {
|
||||
let mir = self.compile_to_mir(func);
|
||||
units.push(ExecutionUnit::NyashFunction(mir));
|
||||
self.telemetry.record_compiled(func.name);
|
||||
}
|
||||
CompileResult::Fallback { reason, location } => {
|
||||
units.push(ExecutionUnit::PythonThunk(func));
|
||||
self.telemetry.record_fallback(func.name, reason, location);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ModuleUnit { units }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4. データ共有戦略
|
||||
```rust
|
||||
// NdArrayBox定義
|
||||
pub struct NdArrayBox {
|
||||
base: BoxBase,
|
||||
py_array: Py<PyArray<f64, Dim<[usize; 2]>>>, // Python側の参照保持
|
||||
// 操作時のみGIL取得してArrayViewを取る
|
||||
}
|
||||
|
||||
impl NdArrayBox {
|
||||
pub fn to_view(&self) -> PyResult<ArrayView2<f64>> {
|
||||
Python::with_gil(|py| {
|
||||
let array = self.py_array.as_ref(py);
|
||||
Ok(array.readonly())
|
||||
})
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4. 実装ロードマップ
|
||||
|
||||
#### Phase 1: パーサー統合(1-2週間)
|
||||
- [ ] pyo3セットアップとPythonParserBox骨格
|
||||
- [ ] Python側parse_to_jsonヘルパー実装
|
||||
- [ ] JSON→Nyash AST最小変換
|
||||
- [ ] run()メソッド(CPython exec委譲)
|
||||
- [ ] 例外変換(PyErr → NyashError)
|
||||
|
||||
#### Phase 2: MIR変換(2-4週間)
|
||||
- [ ] AST→MIR変換器(最小セット)
|
||||
- [ ] 数値演算プリミティブ実装
|
||||
- [ ] スコープ解決(関数ローカル/グローバル)
|
||||
- [ ] 基本的な制御フロー(If/While)
|
||||
|
||||
#### Phase 3: NumPy統合(並行可能)
|
||||
- [ ] pyo3-numpy統合
|
||||
- [ ] NdArrayBox実装
|
||||
- [ ] ゼロコピーベンチマーク
|
||||
- [ ] バッファプロトコル対応
|
||||
|
||||
#### Phase 4: 最適化と拡張
|
||||
- [ ] 型特化とガード最適化
|
||||
- [ ] 例外処理(try/except)
|
||||
- [ ] クラス/メソッド対応
|
||||
- [ ] import統合
|
||||
|
||||
## 性能目標(現実的な見積もり)
|
||||
|
||||
| コードタイプ | 期待される高速化 | 備考 |
|
||||
|------------|----------------|------|
|
||||
| 純Pythonループ | 2-10倍 | 型安定なホットパス |
|
||||
| 関数呼び出し多 | 1.5-3倍 | インライン化効果 |
|
||||
| NumPy処理中心 | 1.0-1.2倍 | 既に最適化済み |
|
||||
| 動的特性多用 | 1.2-3倍 | ガード頻発で限定的 |
|
||||
|
||||
## 実装上の注意点(エキスパート推奨)
|
||||
|
||||
### 意味論の重要な違い(Phase 1で対応必須)
|
||||
|
||||
1. **制御フロー**
|
||||
- `for`文: イテレータプロトコル必須(`__iter__`/`__next__`)
|
||||
- `for/else`, `while/else`: breakしなかった場合のelse実行
|
||||
- 短絡評価: `and`は左がFalseなら右を評価しない
|
||||
|
||||
2. **スコープ規則(LEGB)**
|
||||
```python
|
||||
# Local → Enclosing → Global → Builtins
|
||||
global_var = 1
|
||||
|
||||
def outer():
|
||||
enclosing_var = 2
|
||||
|
||||
def inner():
|
||||
local_var = 3
|
||||
nonlocal enclosing_var # 明示的な宣言
|
||||
global global_var # 明示的な宣言
|
||||
```
|
||||
|
||||
3. **数値演算の違い**
|
||||
- `/`: Python 3では常にfloat(true division)
|
||||
- `//`: floor division(整数除算)
|
||||
- 大整数: デフォルトで無限精度
|
||||
- `is` vs `==`: オブジェクト同一性 vs 値の等価性
|
||||
|
||||
4. **関数定義の罠**
|
||||
```python
|
||||
def f(x, y=[]): # デフォルト引数は定義時に1度だけ評価!
|
||||
y.append(x) # 全呼び出しで同じリストを共有
|
||||
return y
|
||||
```
|
||||
|
||||
### GIL管理のベストプラクティス
|
||||
|
||||
```rust
|
||||
// ❌ 悪い例: GILを長時間保持
|
||||
let result = Python::with_gil(|py| {
|
||||
let ast = parse_python(py, code)?;
|
||||
let json = convert_to_json(py, ast)?; // ここまでGIL必要
|
||||
let nyash_ast = parse_json(&json)?; // GIL不要なのに保持
|
||||
compile_to_mir(nyash_ast)? // GIL不要なのに保持
|
||||
});
|
||||
|
||||
// ✅ 良い例: GILを最小限に
|
||||
let json = Python::with_gil(|py| {
|
||||
let ast = parse_python(py, code)?;
|
||||
convert_to_json(py, ast) // JSON生成まで
|
||||
})?;
|
||||
|
||||
// GIL外で重い処理
|
||||
let nyash_ast = parse_json(&json)?;
|
||||
let mir = compile_to_mir(nyash_ast)?;
|
||||
|
||||
// 必要時のみ再取得
|
||||
Python::with_gil(|py| {
|
||||
py.allow_threads(|| {
|
||||
// 時間のかかるRust処理
|
||||
optimize_mir(mir)
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
### テレメトリーとデバッグ
|
||||
|
||||
```rust
|
||||
// 環境変数で制御
|
||||
NYASH_PYTHONPARSER_TELEMETRY=1 # 基本統計
|
||||
NYASH_PYTHONPARSER_TELEMETRY=2 # 詳細ログ
|
||||
NYASH_PYTHONPARSER_STRICT=1 # フォールバック時にパニック(CI用)
|
||||
|
||||
// 出力例
|
||||
[PythonParser] Module: example.py
|
||||
Functions: 10 total
|
||||
Compiled: 7 (70%)
|
||||
Fallback: 3 (30%)
|
||||
- async_function: unsupported node 'AsyncFunctionDef' at line 23
|
||||
- generator_func: unsupported node 'Yield' at line 45
|
||||
- class_method: unsupported node 'ClassDef' at line 67
|
||||
```
|
||||
|
||||
## 次のステップ
|
||||
|
||||
### 即座に開始すべきこと
|
||||
|
||||
1. **Python 3.11環境固定**
|
||||
```bash
|
||||
pyenv install 3.11.9
|
||||
pyenv local 3.11.9
|
||||
```
|
||||
|
||||
2. **最小動作確認**
|
||||
```python
|
||||
# test_minimal.py
|
||||
def add(x, y):
|
||||
return x + y
|
||||
|
||||
result = add(10, 5)
|
||||
print(f"Result: {result}") # → Nyashで15が出力されれば成功!
|
||||
```
|
||||
|
||||
3. **テレメトリー基盤構築**
|
||||
- 未対応ノードの記録システム
|
||||
- フォールバック率の可視化
|
||||
- ソース位置情報の保持
|
||||
|
||||
4. **Differential Testingの準備**
|
||||
- CPythonとの出力比較フレームワーク
|
||||
- 標準出力、戻り値、例外のキャプチャ
|
||||
- テストコーパスの選定
|
||||
|
||||
### 成功の測定基準
|
||||
|
||||
| フェーズ | 目標 | 測定指標 |
|
||||
|---------|------|----------|
|
||||
| Phase 1 | 基本動作 | 簡単な数値計算の70%がコンパイル可能 |
|
||||
| Phase 2 | 実用性 | scikit-learnの基本アルゴリズムが動作 |
|
||||
| Phase 3 | 性能 | 純Pythonループで5倍以上の高速化 |
|
||||
| Phase 4 | 成熟度 | PyPIトップ100の30%が基本動作 |
|
||||
|
||||
## まとめ
|
||||
|
||||
このPythonParserBox実装は、単なる機能追加ではなく、Nyash言語の成熟度を飛躍的に高める戦略的プロジェクト。
|
||||
エキスパートの指摘を踏まえ、関数単位のフォールバック、Python 3.11固定、意味論の正確な実装、
|
||||
GIL最小化、テレメトリー重視で着実に実装を進める。
|
||||
76
docs/phases/phase-10.5/10.1d_core_implementation/README.md
Normal file
76
docs/phases/phase-10.5/10.1d_core_implementation/README.md
Normal file
@ -0,0 +1,76 @@
|
||||
[Archived] 旧10.1系ドキュメントです。最新は ../INDEX.md を参照してください。
|
||||
|
||||
Note: 本来は「PythonをNyashで動かすフェーズ(Core実装)」の位置づけでしたが、現在は順番を変更し、先に 10.5b(MIR→VM→ネイティブビルド基盤)を進めています。
|
||||
|
||||
# Phase 10.1d - Core実装(Phase 1機能)
|
||||
|
||||
## 🎯 このフェーズの目的
|
||||
Python AST → Nyash AST変換のPhase 1機能(基本構文)を実装する。
|
||||
|
||||
## 📁 実装ドキュメント
|
||||
- **`python_implementation_roadmap.txt`** - Phase別実装ロードマップ
|
||||
|
||||
## 🔧 Phase 1必須要素(Codex先生強調)
|
||||
|
||||
### 意味論の必須実装
|
||||
1. **LEGB + locals/freevars** - スコーピング規則
|
||||
2. **デフォルト引数の評価タイミング** - 定義時に一度だけ
|
||||
3. **イテレータベースのfor文** - `__iter__`/`__next__`プロトコル
|
||||
4. **for/else + while/else** - Python独特のelse節
|
||||
5. **Python真偽値判定** - `__bool__` → `__len__`
|
||||
6. **短絡評価** - and/orの正確な挙動
|
||||
|
||||
### サポートする文(Statement)
|
||||
- [x] def - 関数定義
|
||||
- [x] if/elif/else - 条件分岐
|
||||
- [x] for - ループ(else節対応必須)
|
||||
- [x] while - ループ(else節対応必須)
|
||||
- [x] break/continue - ループ制御
|
||||
- [x] return - 戻り値
|
||||
|
||||
### サポートする式(Expression)
|
||||
- [x] 算術演算子(+,-,*,/,//,%)
|
||||
- [x] 比較演算子(==,!=,<,>,<=,>=,is,is not)
|
||||
- [x] 論理演算子(and,or,not)- 短絡評価
|
||||
- [x] 関数呼び出し
|
||||
- [x] 変数参照/代入
|
||||
- [x] リテラル(数値/文字列/bool)
|
||||
|
||||
## 🧪 テストケース
|
||||
```python
|
||||
# Phase 1で動作すべきコード
|
||||
def fibonacci(n):
|
||||
if n <= 1:
|
||||
return n
|
||||
return fibonacci(n-1) + fibonacci(n-2)
|
||||
|
||||
# for/else のテスト
|
||||
for i in range(10):
|
||||
if i == 5:
|
||||
break
|
||||
else:
|
||||
print("No break") # 実行されない
|
||||
|
||||
# デフォルト引数の罠
|
||||
def append_to_list(item, lst=[]): # 定義時に評価!
|
||||
lst.append(item)
|
||||
return lst
|
||||
```
|
||||
|
||||
## ✅ 完了条件
|
||||
- [ ] 基本的な関数定義が変換できる
|
||||
- [ ] 制御フローが正しく変換される
|
||||
- [ ] 演算子が正しくマッピングされる
|
||||
- [ ] Python意味論が保たれている
|
||||
- [ ] 70%以上の関数がコンパイル可能
|
||||
|
||||
## 📊 テレメトリー確認
|
||||
```bash
|
||||
[PythonParser] Module: test.py (Python 3.11)
|
||||
Functions: 10 total
|
||||
Compiled: 7 (70%) ← 目標達成!
|
||||
Fallback: 3 (30%)
|
||||
```
|
||||
|
||||
## ⏭️ 次のフェーズ
|
||||
→ Phase 10.1e (トランスパイラー)
|
||||
@ -0,0 +1,264 @@
|
||||
# PythonParserBox 実装ロードマップ(エキスパート統合版)
|
||||
Based on ChatGPT5's Python Language Feature Surface Map + Expert Feedback
|
||||
更新日: 2025-08-27
|
||||
|
||||
## 🎯 実装優先順位の考え方(エキスパート統合)
|
||||
|
||||
### 🏯 核心戦略:関数単位フォールバック
|
||||
**両エキスパートが強調:** ファイル全体ではなく、**関数単位**でコンパイル/フォールバックを判断
|
||||
```python
|
||||
def supported_function(): # → Nyash MIR/JIT
|
||||
return x + y
|
||||
|
||||
def unsupported_function(): # → CPython exec
|
||||
yield from generator # Phase 1では未対応
|
||||
```
|
||||
|
||||
### 🔧 Python 3.11固定
|
||||
- AST安定性確保(3.8 Constant統一、3.10 match/case、3.12位置情報)
|
||||
- `py_version`と`ast_format`をJSON IRに埋め込む
|
||||
|
||||
### 🌟 Differential Testing戦略
|
||||
- **世界中のPythonコードがNyashのテストケースに**
|
||||
- CPythonをオラクルとして使用、出力・戻り値・例外を比較
|
||||
- 微妙なセマンティクスバグを自動発見
|
||||
|
||||
### 📊 テレメトリー重視
|
||||
- 未対応ノードの記録(`support_level`フィールド)
|
||||
- フォールバック率の計測
|
||||
- ソース位置情報保持(`lineno/col_offset/end_*`)
|
||||
|
||||
## 📋 Phase 1: Core Subset(1-2週間)
|
||||
**目標**: 基本的なPythonコードをNyashで実行可能にする
|
||||
|
||||
### ❌ Phase 1での必須意味論要素(Codex先生強調)
|
||||
- **LEGB + locals/freevars**: スコーピング規則
|
||||
- **デフォルト引数の評価タイミング**: 定義時に一度だけ
|
||||
- **イテレータベースのfor文**: `__iter__`/`__next__`プロトコル
|
||||
- **for/else + while/else**: Python独特のelse節
|
||||
- **Python真偽値判定**: `__bool__` → `__len__`
|
||||
- **短絡評価**: and/orの正確な挙動
|
||||
|
||||
### 文(Statement)
|
||||
- [x] def - 関数定義 → Nyash関数/Box
|
||||
- デフォルト引数の定義時評価
|
||||
- argumentsオブジェクトの完全解析
|
||||
- [x] if/elif/else - 条件分岐 → CondBr
|
||||
- [x] for - ループ → Loop + Iterator
|
||||
- **else節対応必須**
|
||||
- [x] while - ループ → Loop
|
||||
- **else節対応必須**
|
||||
- [x] break/continue - ループ制御
|
||||
- [x] return - 戻り値 → Return
|
||||
- [ ] pass - 空文
|
||||
- [ ] import(Phase 3へ延期)
|
||||
|
||||
### 式(Expression)
|
||||
- [x] 関数呼び出し - Call → BoxCall
|
||||
- [x] 算術演算子 - +,-,*,/,//,% → BinOp
|
||||
- `/`: true division(常にfloat)
|
||||
- `//`: floor division
|
||||
- [x] 比較演算子 - ==,!=,<,>,<=,>=,is,is not → Compare
|
||||
- [x] 論理演算子 - and,or,not → BoolOp/UnaryOp
|
||||
- 短絡評価の正確な実装
|
||||
- [x] 変数参照/代入 - Name → Load/Store
|
||||
- [x] リテラル - 数値/文字列/bool → Constant
|
||||
- [x] 三項演算子 - IfExp
|
||||
|
||||
### データ型(最小限)
|
||||
- [x] int → IntegerBox(大整数対応)
|
||||
- [x] float → FloatBox(NaNの扱い注意)
|
||||
- [x] str → StringBox
|
||||
- [x] bool → BoolBox
|
||||
- [x] list(基本) → ArrayBox
|
||||
|
||||
## 📋 Phase 2: Data Model(2-3週間)
|
||||
**目標**: Pythonの特殊メソッドをNyashのBoxメソッドにマッピング
|
||||
|
||||
### 特殊メソッド
|
||||
- [ ] __init__ → constructor/birth
|
||||
- [ ] __len__ → length()
|
||||
- [ ] __getitem__ → get()
|
||||
- [ ] __setitem__ → set()
|
||||
- [ ] __iter__ → iterator()
|
||||
- [ ] __str__ → toString()
|
||||
|
||||
### コレクション拡張
|
||||
- [ ] dict → MapBox
|
||||
- [ ] tuple → ImmutableArrayBox(新規)
|
||||
- [ ] set → SetBox(新規)
|
||||
|
||||
### 演算子オーバーロード
|
||||
- [ ] __add__, __sub__ 等 → operator+, operator-
|
||||
- [ ] __eq__, __lt__ 等 → equals(), compareTo()
|
||||
|
||||
## 📋 Phase 3: Advanced Features(1ヶ月)
|
||||
**目標**: Pythonの生産性の高い機能を実装
|
||||
|
||||
### 制御フロー拡張
|
||||
- [ ] try/except → エラーハンドリング
|
||||
- [ ] with文 → リソース管理
|
||||
- [ ] break/continue → ループ制御
|
||||
|
||||
### 高度な機能
|
||||
- [ ] ジェネレータ(yield) → GeneratorBox
|
||||
- [ ] デコレータ → 関数ラッパー
|
||||
- [ ] 内包表記 → 最適化されたループ
|
||||
- [ ] ラムダ式 → 匿名関数
|
||||
|
||||
### クラスシステム
|
||||
- [ ] class文 → box定義
|
||||
- [ ] 継承 → from構文
|
||||
- [ ] super() → from Parent.method()
|
||||
|
||||
## 📋 Phase 4: Modern Python(将来)
|
||||
**目標**: 最新のPython機能をサポート
|
||||
|
||||
### 非同期
|
||||
- [ ] async/await → 非同期Box(将来のNyash非同期と統合)
|
||||
- [ ] async for/with → 非同期イテレータ
|
||||
|
||||
### パターンマッチ(3.10+)
|
||||
- [ ] match/case → Nyashのパターンマッチ(将来実装時)
|
||||
|
||||
### 型ヒント
|
||||
- [ ] 型アノテーション → MIRの型情報として活用
|
||||
- [ ] typing モジュール → 静的型チェック情報
|
||||
|
||||
## 🚀 実装戦略
|
||||
|
||||
### Step 1: AST変換の基礎(Phase 1開始)
|
||||
```python
|
||||
# Python側でAST→JSON
|
||||
import ast
|
||||
import json
|
||||
|
||||
def parse_to_json(code):
|
||||
tree = ast.parse(code)
|
||||
return json.dumps(ast_to_dict(tree))
|
||||
|
||||
# 最小限のノードから実装
|
||||
def ast_to_dict(node):
|
||||
if isinstance(node, ast.FunctionDef):
|
||||
return {
|
||||
"type": "FunctionDef",
|
||||
"name": node.name,
|
||||
"args": [arg.arg for arg in node.args.args],
|
||||
"body": [ast_to_dict(stmt) for stmt in node.body]
|
||||
}
|
||||
# ... 他のノードタイプを順次追加
|
||||
```
|
||||
|
||||
### Step 2: Nyash AST生成(Rust側)
|
||||
```rust
|
||||
// JSON → Nyash AST
|
||||
fn convert_python_ast(json: &str) -> Result<ast::Program> {
|
||||
let py_ast: PythonAst = serde_json::from_str(json)?;
|
||||
match py_ast {
|
||||
PythonAst::FunctionDef { name, args, body } => {
|
||||
// Python def → Nyash function
|
||||
ast::BoxDef {
|
||||
name,
|
||||
methods: vec![ast::Method {
|
||||
name: name.clone(),
|
||||
params: args,
|
||||
body: convert_statements(body),
|
||||
}],
|
||||
..
|
||||
}
|
||||
}
|
||||
// ... 他のケース
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Step 3: 段階的な実行
|
||||
1. 最初はCPython exec()でそのまま実行
|
||||
2. 変換可能な部分からMIR生成
|
||||
3. MIR化された部分はVM/JITで高速実行
|
||||
4. 未対応部分は自動的にCPythonフォールバック
|
||||
|
||||
## 📊 期待される成果
|
||||
|
||||
### Phase 1完了時点
|
||||
- 簡単な数値計算スクリプトが2-5倍高速化
|
||||
- 基本的なループが最適化される
|
||||
- Nyashの既存Box(FileBox等)がPythonから使える
|
||||
|
||||
### Phase 2完了時点
|
||||
- Pythonのリスト/辞書操作が高速化
|
||||
- NyashとPythonのデータ構造が相互運用可能
|
||||
- 特殊メソッドによる自然な統合
|
||||
|
||||
### Phase 3完了時点
|
||||
- Pythonの生産的な機能がNyashで高速実行
|
||||
- 既存Pythonコードの大部分が動作
|
||||
- デコレータやジェネレータも最適化
|
||||
|
||||
## 🎯 最初の一歩(今すぐ開始)
|
||||
|
||||
1. pyo3でPythonParserBoxの骨組み作成
|
||||
2. 最小限のparse_to_json実装(def + return)
|
||||
3. 単純な関数のAST変換テスト
|
||||
4. "Hello from Python in Nyash"を表示
|
||||
|
||||
```python
|
||||
# 最初のテストケース
|
||||
def hello():
|
||||
return "Hello from Python in Nyash"
|
||||
|
||||
# これがNyashで動けば成功!
|
||||
```
|
||||
|
||||
## 📊 成功の測定基準(エキスパート推奨)
|
||||
|
||||
### 定量的指標
|
||||
| 指標 | 目標 | 測定方法 |
|
||||
|------|-------|----------|
|
||||
| カバレッジ率 | 70%以上 | コンパイル済み vs フォールバック関数の比率 |
|
||||
| 性能向上 | 2-10倍 | 純Pythonループのベンチマーク |
|
||||
| バグ発見数 | 10+件/Phase | Differential Testingで発見されたNyashバグ |
|
||||
| エコシステム | 1以上 | 動作する有名Pythonライブラリ |
|
||||
|
||||
### マイルストーン
|
||||
- Phase 1: "Hello from Python in Nyash"が動作
|
||||
- Phase 2: scikit-learnの基本アルゴリズムが動作
|
||||
- Phase 3: FlaskのHello Worldが動作
|
||||
- Phase 4: PyPIトップ100の30%が基本動作
|
||||
|
||||
## 🔧 GIL管理の黄金律
|
||||
|
||||
```rust
|
||||
// GILは最小限に!
|
||||
let json_ast = Python::with_gil(|py| {
|
||||
// Python側でJSON生成(高速)
|
||||
py_helper.parse_to_json(py, code)
|
||||
})?;
|
||||
|
||||
// GIL外でRust処理(並列可能)
|
||||
let nyash_ast = py.allow_threads(|| {
|
||||
convert_json_to_nyash(json_ast)
|
||||
});
|
||||
```
|
||||
|
||||
## 🔍 JSON IR設計(Codex先生推奨)
|
||||
|
||||
```json
|
||||
{
|
||||
"node_type": "FunctionDef",
|
||||
"py_version": "3.11",
|
||||
"ast_format": "v2",
|
||||
"support_level": "full", // "partial", "fallback"
|
||||
"lineno": 1,
|
||||
"col_offset": 0,
|
||||
"end_lineno": 3,
|
||||
"end_col_offset": 15,
|
||||
"name": "hello",
|
||||
"args": {...},
|
||||
"body": [...]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
作成日: 2025-08-27
|
||||
ChatGPT5のサーフェスマップ + Gemini/Codex先生のエキスパートフィードバックを統合
|
||||
72
docs/phases/phase-10.5/10.1e_transpiler/README.md
Normal file
72
docs/phases/phase-10.5/10.1e_transpiler/README.md
Normal file
@ -0,0 +1,72 @@
|
||||
[Archived] 旧10.1系ドキュメントです。最新は ../INDEX.md を参照してください。
|
||||
|
||||
# Phase 10.1e - Python → Nyashトランスパイラー
|
||||
|
||||
## 🎯 このフェーズの目的
|
||||
Python ASTをNyashソースコードとして出力する機能を実装する。
|
||||
|
||||
## 📁 実装ドキュメント
|
||||
- **`python_to_nyash_transpiler.txt`** - トランスパイラー設計
|
||||
|
||||
## 🔧 実装機能
|
||||
|
||||
### 1. AST → Nyashソース生成
|
||||
```rust
|
||||
impl PythonParserBox {
|
||||
pub fn to_nyash_source(&self, python_code: &str) -> Result<String, String> {
|
||||
// Python → JSON AST → Nyash AST → Nyashソース
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 変換例
|
||||
```python
|
||||
# Python入力
|
||||
def add(x, y):
|
||||
return x + y
|
||||
|
||||
result = add(10, 5)
|
||||
```
|
||||
|
||||
```nyash
|
||||
# Nyash出力
|
||||
function add(x, y) {
|
||||
return x + y
|
||||
}
|
||||
|
||||
local result
|
||||
result = add(10, 5)
|
||||
```
|
||||
|
||||
### 3. 出力フォーマッター
|
||||
- インデント管理
|
||||
- 括弧の追加(Nyashは明示的)
|
||||
- コメント保持(可能な範囲で)
|
||||
|
||||
## 🛠️ コマンドラインツール
|
||||
```bash
|
||||
# 基本変換
|
||||
nyash-transpile input.py -o output.nyash
|
||||
|
||||
# 変換統計付き
|
||||
nyash-transpile --stats complex.py
|
||||
# Output: Converted 15/17 functions (88%)
|
||||
|
||||
# 部分変換(サポート関数のみ)
|
||||
nyash-transpile --partial script.py
|
||||
```
|
||||
|
||||
## ✅ 完了条件
|
||||
- [ ] `to_nyash_source()` メソッドが動作する
|
||||
- [ ] 基本的なPythonコードが正しいNyashに変換される
|
||||
- [ ] インデントが正しく管理される
|
||||
- [ ] 変換統計が表示される
|
||||
- [ ] ファイル出力ができる
|
||||
|
||||
## 🌟 期待される利用シーン
|
||||
1. **学習ツール** - PythonユーザーがNyash構文を学ぶ
|
||||
2. **段階的移行** - 既存Pythonコードの移行
|
||||
3. **性能最適化** - ホットパスをNyashネイティブに
|
||||
|
||||
## ⏭️ 次のフェーズ
|
||||
→ Phase 10.1f (テストとベンチマーク)
|
||||
@ -0,0 +1,225 @@
|
||||
# Python → Nyashトランスパイラー機能
|
||||
~PythonParserBoxの応用による自動変換~
|
||||
|
||||
## 🎯 概要
|
||||
|
||||
PythonParserBoxでPython AST → Nyash ASTの変換ができるなら、それを**Nyashソースコードとして出力**できる!
|
||||
|
||||
## 🚀 実現可能な機能
|
||||
|
||||
### 1. Python → Nyashファイル変換
|
||||
```python
|
||||
# input.py
|
||||
def calculate(x, y):
|
||||
result = x * 2 + y
|
||||
return result
|
||||
|
||||
for i in range(10):
|
||||
print(calculate(i, 5))
|
||||
```
|
||||
|
||||
↓ 変換
|
||||
|
||||
```nyash
|
||||
# output.nyash
|
||||
function calculate(x, y) {
|
||||
local result
|
||||
result = x * 2 + y
|
||||
return result
|
||||
}
|
||||
|
||||
local i
|
||||
for i in range(0, 10) {
|
||||
print(calculate(i, 5))
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 実装方法
|
||||
|
||||
```rust
|
||||
impl PythonParserBox {
|
||||
// Python → Nyashファイル出力
|
||||
pub fn transpile_to_file(&self, python_code: &str, output_path: &str) -> Result<(), String> {
|
||||
// 1. Python → JSON AST
|
||||
let json_ast = self.parse_to_json(python_code)?;
|
||||
|
||||
// 2. JSON AST → Nyash AST
|
||||
let nyash_ast = self.json_to_nyash_ast(&json_ast)?;
|
||||
|
||||
// 3. Nyash AST → Nyashソースコード
|
||||
let nyash_code = self.ast_to_nyash_source(&nyash_ast)?;
|
||||
|
||||
// 4. ファイルに出力
|
||||
std::fs::write(output_path, nyash_code)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// AST → Nyashソースコード生成
|
||||
fn ast_to_nyash_source(&self, ast: &NyashAst) -> Result<String, String> {
|
||||
let mut output = String::new();
|
||||
let formatter = NyashFormatter::new();
|
||||
|
||||
for item in &ast.items {
|
||||
formatter.format_item(item, &mut output)?;
|
||||
}
|
||||
|
||||
Ok(output)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📋 使用例
|
||||
|
||||
### コマンドライン版
|
||||
```bash
|
||||
# PythonファイルをNyashに変換
|
||||
nyash-transpile input.py -o output.nyash
|
||||
|
||||
# 標準出力に出力
|
||||
nyash-transpile script.py
|
||||
|
||||
# 部分変換(サポートされる構文のみ)
|
||||
nyash-transpile --partial complex_script.py
|
||||
```
|
||||
|
||||
### Nyashスクリプト内での使用
|
||||
```nyash
|
||||
local transpiler = new PythonParserBox()
|
||||
|
||||
// Pythonコードを読み込み
|
||||
local python_code = FileBox.read("algorithm.py")
|
||||
|
||||
// Nyashに変換
|
||||
local nyash_code = transpiler.to_nyash_source(python_code)
|
||||
|
||||
// ファイルに保存
|
||||
FileBox.write("algorithm.nyash", nyash_code)
|
||||
|
||||
// または直接実行
|
||||
eval(nyash_code)
|
||||
```
|
||||
|
||||
## 🎨 変換マッピング例
|
||||
|
||||
### 基本構文
|
||||
| Python | Nyash |
|
||||
|--------|-------|
|
||||
| `def func():` | `function func() {` |
|
||||
| `if x > 0:` | `if (x > 0) {` |
|
||||
| `for i in range(10):` | `for i in range(0, 10) {` |
|
||||
| `while x < 10:` | `while (x < 10) {` |
|
||||
| `x = 5` | `local x; x = 5` または `x = 5`(スコープによる)|
|
||||
|
||||
### データ型
|
||||
| Python | Nyash |
|
||||
|--------|-------|
|
||||
| `x = 42` | `x = 42` |
|
||||
| `s = "hello"` | `s = "hello"` |
|
||||
| `lst = [1, 2, 3]` | `lst = new ArrayBox([1, 2, 3])` |
|
||||
| `d = {"a": 1}` | `d = new MapBox(); d.set("a", 1)` |
|
||||
|
||||
### 特殊なケース
|
||||
```python
|
||||
# Pythonのfor/else
|
||||
for i in items:
|
||||
if condition:
|
||||
break
|
||||
else:
|
||||
print("No break")
|
||||
```
|
||||
|
||||
```nyash
|
||||
# Nyashでの実装(フラグを使用)
|
||||
local broke = false
|
||||
for i in items {
|
||||
if (condition) {
|
||||
broke = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if (not broke) {
|
||||
print("No break")
|
||||
}
|
||||
```
|
||||
|
||||
## 🌟 利点
|
||||
|
||||
### 1. 段階的移行支援
|
||||
- 既存のPythonプロジェクトを段階的にNyashに移行
|
||||
- 変換されたコードを手動で最適化可能
|
||||
|
||||
### 2. 学習ツールとして
|
||||
- PythonユーザーがNyash構文を学ぶ
|
||||
- 両言語の違いを理解
|
||||
|
||||
### 3. コード生成
|
||||
- Pythonで書いたアルゴリズムをNyashネイティブコードに
|
||||
- より高速な実行のための前処理
|
||||
|
||||
### 4. 逆方向変換の可能性
|
||||
- Nyash → Pythonも将来的に可能
|
||||
- 真のバイリンガル環境
|
||||
|
||||
## ⚠️ 制限事項と課題
|
||||
|
||||
### 1. 完全な互換性は不可能
|
||||
- Pythonの動的機能すべては変換できない
|
||||
- 一部の構文は手動調整が必要
|
||||
|
||||
### 2. 意味論の違い
|
||||
```python
|
||||
# Pythonのデフォルト引数(定義時評価)
|
||||
def f(x, lst=[]):
|
||||
lst.append(x)
|
||||
return lst
|
||||
```
|
||||
|
||||
```nyash
|
||||
// Nyashでは毎回新しいリスト(異なる挙動)
|
||||
function f(x, lst) {
|
||||
if (lst == null) {
|
||||
lst = new ArrayBox()
|
||||
}
|
||||
lst.push(x)
|
||||
return lst
|
||||
}
|
||||
```
|
||||
|
||||
### 3. サポートレベルの明示
|
||||
```nyash
|
||||
// 生成されたファイルのヘッダー
|
||||
// Generated from Python by Nyash Transpiler v1.0
|
||||
// Original file: script.py
|
||||
// Conversion rate: 85% (15/17 functions transpiled)
|
||||
// Manual review recommended for: async_func, generator_func
|
||||
```
|
||||
|
||||
## 📊 実装フェーズ
|
||||
|
||||
### Phase 1.5: 基本トランスパイラ(Phase 1と並行)
|
||||
- [ ] NyashFormatter実装(AST → ソースコード)
|
||||
- [ ] 基本構文の出力(def, if, for, while)
|
||||
- [ ] インデント管理
|
||||
- [ ] コメント保持(可能な範囲で)
|
||||
|
||||
### Phase 2.5: 高度な変換
|
||||
- [ ] クラス → Box変換
|
||||
- [ ] 特殊メソッド → Nyashメソッド
|
||||
- [ ] import文の処理
|
||||
|
||||
### Phase 3.5: ツール化
|
||||
- [ ] コマンドラインツール
|
||||
- [ ] VSCode拡張機能
|
||||
- [ ] オンライン変換ツール
|
||||
|
||||
## 🎉 期待される効果
|
||||
|
||||
1. **Pythonエコシステムの資産をNyashネイティブ化**
|
||||
2. **パフォーマンスクリティカルな部分をNyash/MIR/JITで高速化**
|
||||
3. **両言語間のシームレスな相互運用**
|
||||
4. **Nyashの採用障壁を大幅に下げる**
|
||||
|
||||
---
|
||||
|
||||
これは**PythonParserBoxの価値をさらに高める**素晴らしい応用です!
|
||||
94
docs/phases/phase-10.5/10.1f_testing/README.md
Normal file
94
docs/phases/phase-10.5/10.1f_testing/README.md
Normal file
@ -0,0 +1,94 @@
|
||||
[Archived] 旧10.1系ドキュメントです。最新は ../INDEX.md を参照してください。
|
||||
|
||||
# Phase 10.1f - テストとベンチマーク
|
||||
|
||||
## 🎯 このフェーズの目的
|
||||
Differential Testingでバグを発見し、性能向上を検証する。
|
||||
|
||||
## 🧪 Differential Testing戦略
|
||||
|
||||
### 1. テストフレームワーク
|
||||
```rust
|
||||
pub fn differential_test(code: &str) -> TestResult {
|
||||
// CPythonで実行(オラクル)
|
||||
let python_result = capture_python_execution(code)?;
|
||||
|
||||
// Nyashで実行
|
||||
let nyash_result = execute_with_pythonparser(code)?;
|
||||
|
||||
// 結果比較
|
||||
compare_results(python_result, nyash_result)
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 比較項目
|
||||
- **標準出力** - print文の結果
|
||||
- **戻り値** - 関数の返す値
|
||||
- **例外** - エラーメッセージ(正規化後)
|
||||
- **副作用** - グローバル変数の変更等
|
||||
|
||||
### 3. テストコーパス
|
||||
```
|
||||
test_corpus/
|
||||
├── basic/ # 基本構文テスト
|
||||
├── stdlib/ # 標準ライブラリから抜粋
|
||||
├── pypi_top100/ # 人気ライブラリから抜粋
|
||||
└── edge_cases/ # エッジケース集
|
||||
```
|
||||
|
||||
## 📊 ベンチマーク
|
||||
|
||||
### 1. 性能測定対象
|
||||
```python
|
||||
# 数値計算ベンチマーク
|
||||
def mandelbrot(max_iter=100):
|
||||
# フラクタル計算
|
||||
pass
|
||||
|
||||
# ループベンチマーク
|
||||
def sum_of_primes(n):
|
||||
# 素数の和
|
||||
pass
|
||||
|
||||
# 再帰ベンチマーク
|
||||
def ackermann(m, n):
|
||||
# アッカーマン関数
|
||||
pass
|
||||
```
|
||||
|
||||
### 2. 測定項目
|
||||
- **実行時間** - CPython vs Nyash
|
||||
- **メモリ使用量** - 最大/平均
|
||||
- **コンパイル時間** - AST変換時間
|
||||
- **フォールバック率** - 関数別統計
|
||||
|
||||
## 🐛 バグ発見と報告
|
||||
|
||||
### 発見されたバグの例
|
||||
```
|
||||
[BUG-001] for/else semantics mismatch
|
||||
Python: else executed when no break
|
||||
Nyash: else never executed
|
||||
Fixed in: commit abc123
|
||||
|
||||
[BUG-002] Division operator difference
|
||||
Python: 5/2 = 2.5 (float)
|
||||
Nyash: 5/2 = 2 (integer)
|
||||
Fixed in: commit def456
|
||||
```
|
||||
|
||||
## ✅ 完了条件
|
||||
- [ ] Differential Testingフレームワークが動作する
|
||||
- [ ] 基本的なテストコーパスが準備されている
|
||||
- [ ] 10個以上のバグを発見・修正
|
||||
- [ ] ベンチマークで2倍以上の高速化を確認
|
||||
- [ ] CI/CDパイプラインに統合されている
|
||||
|
||||
## 📈 成功の測定
|
||||
- **カバレッジ率**: 70%以上の関数がコンパイル
|
||||
- **性能向上**: 純Pythonループで2-10倍
|
||||
- **バグ発見数**: Phase毎に10件以上
|
||||
- **テスト成功率**: 95%以上
|
||||
|
||||
## ⏭️ 次のフェーズ
|
||||
→ Phase 10.1g (ドキュメント作成)
|
||||
102
docs/phases/phase-10.5/10.1g_documentation/README.md
Normal file
102
docs/phases/phase-10.5/10.1g_documentation/README.md
Normal file
@ -0,0 +1,102 @@
|
||||
[Archived] 旧10.1系ドキュメントです。最新は ../INDEX.md を参照してください。
|
||||
|
||||
# Phase 10.1g - ドキュメントとリリース準備
|
||||
|
||||
## 🎯 このフェーズの目的
|
||||
PythonParserBoxの使い方を文書化し、コミュニティに公開する準備をする。
|
||||
|
||||
## 📚 作成するドキュメント
|
||||
|
||||
### 1. ユーザーガイド
|
||||
- **Getting Started** - 最初の一歩
|
||||
- **Python互換性ガイド** - サポートされる構文
|
||||
- **トランスパイラー使用法** - Python→Nyash変換
|
||||
- **トラブルシューティング** - よくある問題と解決法
|
||||
|
||||
### 2. API リファレンス
|
||||
```nyash
|
||||
// PythonParserBox API
|
||||
box PythonParserBox {
|
||||
// Python code → JSON AST
|
||||
parse_to_json(code: String) -> String
|
||||
|
||||
// JSON AST → Nyash AST
|
||||
json_to_nyash_ast(json: String) -> AstBox
|
||||
|
||||
// Python code → Nyash source
|
||||
to_nyash_source(code: String) -> String
|
||||
|
||||
// 直接実行(関数単位フォールバック)
|
||||
run(code: String) -> Box
|
||||
|
||||
// 変換統計
|
||||
get_conversion_stats() -> MapBox
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 移行ガイド
|
||||
- **段階的移行戦略** - Pythonプロジェクトの移行手順
|
||||
- **パフォーマンスチューニング** - ホットパスの最適化
|
||||
- **ベストプラクティス** - 推奨される使い方
|
||||
|
||||
### 4. 内部設計ドキュメント
|
||||
- **アーキテクチャ** - 全体設計
|
||||
- **関数単位フォールバック** - 実装詳細
|
||||
- **GIL管理** - pyo3との統合
|
||||
- **テレメトリー** - 統計収集の仕組み
|
||||
|
||||
## 🎬 デモとチュートリアル
|
||||
|
||||
### 1. 動画チュートリアル
|
||||
- 5分で分かるPythonParserBox
|
||||
- Python→Nyash移行実演
|
||||
- パフォーマンス比較デモ
|
||||
|
||||
### 2. サンプルプロジェクト
|
||||
```
|
||||
examples/
|
||||
├── hello_python/ # 最小限の例
|
||||
├── data_analysis/ # データ分析の移行例
|
||||
├── web_api/ # WebAPIの移行例
|
||||
└── benchmarks/ # ベンチマーク比較
|
||||
```
|
||||
|
||||
## 📣 リリース準備
|
||||
|
||||
### 1. リリースノート作成
|
||||
```markdown
|
||||
# PythonParserBox v1.0 リリース!
|
||||
|
||||
## 🎉 新機能
|
||||
- Python AST → Nyash AST変換
|
||||
- 関数単位フォールバック
|
||||
- Python→Nyashトランスパイラー
|
||||
- Differential Testing
|
||||
|
||||
## 📊 パフォーマンス
|
||||
- 純Pythonループ: 2-10倍高速化
|
||||
- 数値計算: 5倍以上の改善
|
||||
- メモリ効率: 30%削減
|
||||
|
||||
## 🐛 発見されたバグ
|
||||
- Nyashパーサー: 15件修正
|
||||
- セマンティクス: 8件修正
|
||||
```
|
||||
|
||||
### 2. ブログ記事
|
||||
- 「なぜPythonParserBoxを作ったのか」
|
||||
- 「Differential Testingの威力」
|
||||
- 「Everything is Boxの新たな展開」
|
||||
|
||||
## ✅ 完了条件
|
||||
- [ ] ユーザーガイドが完成している
|
||||
- [ ] APIリファレンスが完成している
|
||||
- [ ] サンプルプロジェクトが動作する
|
||||
- [ ] リリースノートが準備されている
|
||||
- [ ] CI/CDでの自動テストが通る
|
||||
|
||||
## 🎯 Phase 10.1の完了!
|
||||
これでPythonParserBoxの最初のリリースが完成!
|
||||
|
||||
## ⏭️ 次の展開
|
||||
→ Phase 10.2 (Phase 2機能の実装) または Phase 10.x (他言語対応)
|
||||
53
docs/phases/phase-10.5/10.5a-ABI-DESIGN.md
Normal file
53
docs/phases/phase-10.5/10.5a-ABI-DESIGN.md
Normal file
@ -0,0 +1,53 @@
|
||||
# Phase 10.5a – Python 統合 ABI 設計(Draft)
|
||||
|
||||
目的: Everything is Plugin/AOT の既存基盤上に Python を最小リスクで統合するための ABI と型・メソッド定義を固定する。
|
||||
|
||||
## スコープ(10.5a)
|
||||
- v2 プラグイン ABI 準拠(`nyash_plugin_abi/init/invoke`)の Python プラグイン雛形を作成
|
||||
- 2 Box を定義: `PyRuntimeBox(type_id=40)`, `PyObjectBox(type_id=41)`
|
||||
- メソッド ID の割り当てと TLV 方針を文書化(実装は 10.5b 以降)
|
||||
|
||||
## TLV マッピング(現行運用)
|
||||
- 1 = Bool (1 byte)
|
||||
- 2 = I32 (4 bytes, LE)
|
||||
- 3 = I64 (8 bytes, LE)
|
||||
- 4 = F32 (4 bytes, LE)
|
||||
- 5 = F64 (8 bytes, LE)
|
||||
- 6 = String (UTF-8, n bytes)
|
||||
- 7 = Bytes (opaque, n bytes)
|
||||
- 8 = Handle/BoxRef (`u32 type_id || u32 instance_id`)
|
||||
|
||||
備考: 既存ドキュメントには古い表記の混在があるため、VM_README 準拠で統一。
|
||||
|
||||
## Box とメソッド設計
|
||||
|
||||
### PyRuntimeBox (type_id=40)
|
||||
- birth(0): ランタイムの生成(後続で GIL 初期化などを担当)。戻り値: `instance_id`(非 TLV, u32 LE)
|
||||
- eval(1, code: String): Python コードを評価して `PyObjectBox` を返す。戻り値: `Handle(tag=8)`
|
||||
- import(2, name: String): `__import__(name)` または `importlib.import_module`。戻り値: `Handle(tag=8)`
|
||||
- fini(MAX): ランタイム破棄(GIL 終了・クリーンアップ)
|
||||
|
||||
### PyObjectBox (type_id=41)
|
||||
- birth(0): 予約(通常は runtime 側から生まれる)
|
||||
- getattr(1, name: String): 属性取得 → `Handle(tag=8)`
|
||||
- call(2, args: TLV...): 可変長引数。初期段は I64/String/Bool/Bytes/Handle のサブセットに限定。戻り値: `Handle(tag=8)`
|
||||
- str(3): Python 側で `PyObject_Str` → String へ。戻り値: `String(tag=6)`
|
||||
- fini(MAX): 参照カウント `Py_DECREF` に対応(後続)
|
||||
|
||||
## 参照管理・GIL(概要)
|
||||
- GIL: birth/invoke/fini の入口で確保し、出口で解放(再入を許容)。
|
||||
- 参照: `PyObjectBox` は生成時に `INCREF`、`fini` で `DECREF`。ランタイム終了時に孤立検知の簡易テストを導入。
|
||||
|
||||
## 設定ファイル(nyash.toml)
|
||||
- `libnyash_python_plugin.so` を 2 Box 含む形で登録(path/type_id/method_id を固定)
|
||||
- JIT/VM 側は既存の `plugin_invoke` 経由で呼び出し(AOT は 10.5d で `libnyrt.a` にシム追加)
|
||||
|
||||
## 次フェーズ(10.5b 以降)
|
||||
- 10.5b: `PyRuntimeBox`/`PyObjectBox` 実装(CPython 埋め込み、最小 RO 経路)
|
||||
- 10.5c: Python→Nyash 方向(CPython 拡張 `nyashrt`)
|
||||
- 10.5d: JIT/AOT 連携(`emit_plugin_invoke` 対応・静的リンクシム)
|
||||
- 10.5e: サンプル・テスト・ドキュメント
|
||||
|
||||
---
|
||||
|
||||
補足: 本ドキュメントは「設計の固定」を目的とし、実装は段階的に進める。タグ/ID は既存と衝突しない値を選定した(40/41)。
|
||||
37
docs/phases/phase-10.5/10.5b-native-build-consolidation.md
Normal file
37
docs/phases/phase-10.5/10.5b-native-build-consolidation.md
Normal file
@ -0,0 +1,37 @@
|
||||
# 10.5b – ネイティブビルド基盤の固め(AOT/EXE)
|
||||
|
||||
Python統合を本格化する前に、配布可能なネイティブ実行ファイル(EXE)の足回りを先に完成させる。JITは実行エンジンから外し、EXE生成専用のコンパイラとして運用する。
|
||||
|
||||
## 🎯 目的
|
||||
- VM=実行、JIT=EXE(AOT)の二系統を明確化(フォールバックなし/Fail-Fast)
|
||||
- CLIF→.o→`libnyrt`リンク→EXEのパイプラインを実効化
|
||||
- プラグイン解決をクロスプラットフォームに(.so/.dll/.dylib、自動lib剥がし、検索パス)
|
||||
- Windowsを含む実用的な配布体験を整備
|
||||
|
||||
## 🧩 範囲
|
||||
- JIT分離・Strict運用(Fail-Fast/No-fallback)
|
||||
- AOTパイプライン: `--compile-native` と `tools/build_aot.{sh,ps1}`
|
||||
- プラグインローダの拡張: 拡張子変換/`lib`剥がし、`plugin_paths`+`NYASH_PLUGIN_PATHS`
|
||||
- Windowsリンク: clang優先(`nyrt.lib`/`libnyrt.a`両対応)、bash+cc fallback
|
||||
- 観測/EXE出力の統一: `Result: <val>`、終了コード=<val>
|
||||
|
||||
## ✅ 成果(DoD)
|
||||
- `cargo build --release --features cranelift-jit` の後、
|
||||
- Linux: `./tools/build_aot.sh examples/aot_min_string_len.nyash -o app && ./app`
|
||||
- Windows: `powershell -ExecutionPolicy Bypass -File tools\build_aot.ps1 -Input examples\aot_min_string_len.nyash -Out app.exe && .\app.exe`
|
||||
- プラグインは `.so` 記述でも各OSで自動解決(.dll/.dylib へ変換、lib剥がし)
|
||||
- `tools/smoke_aot_vs_vm.sh` で VM/EXE の `Result:` 行比較が可能(差異は警告表示)
|
||||
|
||||
## 🔧 実装メモ
|
||||
- `src/runtime/plugin_loader_v2.rs` に `resolve_library_path()` を追加:
|
||||
- OS別拡張子、Windowsの`lib`剥がし、`plugin_paths`探索
|
||||
- `src/config/nyash_toml_v2.rs` に `NYASH_PLUGIN_PATHS` を追加(`;`/`:`区切り)
|
||||
- `AotConfigBox` に `set_plugin_paths()` 追加(env同期)
|
||||
- `crates/nyrt` の EXE出力統一(`Result:`/exit code)
|
||||
- Windows: `tools/build_aot.ps1`(clang→bash fallback)、Linux: `tools/build_aot.sh`
|
||||
|
||||
## 📌 次(10.5c 以降)
|
||||
- PyRuntimeBox/PyObjectBox(RO優先)
|
||||
- Python ABIルータを `libnyrt` に同梱(type_id→invokeディスパッチ)
|
||||
- 配布用パッケージ整備(nyash.toml/プラグイン配置ガイドの最終化)
|
||||
|
||||
@ -0,0 +1,46 @@
|
||||
# Phase 10.5c — Handle-First PluginInvoke 設計(最優先計画)
|
||||
|
||||
目的: Python専用の型伝搬を撤廃し、プラグイン呼び出しを「Everything is Handle」で統一。Lowererは箱名や戻り型に依存しない最小知識で `PluginInvoke` を実Emitし、型解決は実行時(TLV/Handle)に委譲する。
|
||||
|
||||
## 背景と問題
|
||||
- 現状のLowererに「import/getattr/call の戻りを PyObjectBox とみなす」暫定コードが混入。これは Python 特化のハードコーディングで、将来のプラグイン拡張(File/Net/DB 等)にブレーキとなる。
|
||||
- すでに ABI/VM は TLV tag=8(Handle)を標準化。戻り値を Handle として受け取り、タイプ情報(type_id)は実行時に判明する。
|
||||
|
||||
## 原則(Handle-First)
|
||||
- すべてのプラグインメソッドの戻りは Handle(TLV: tag=8)またはプリミティブ(i64/f64/bool/string/bytes)。
|
||||
- Lowerer は「戻り型が box かどうか」だけを気にすればよい。個々の箱名(PyObjectBox 等)を前提にしない。
|
||||
- 型の詳細は `type_id` によって実行時に解決される。JIT/AOT は型非依存の汎用コード生成を行う。
|
||||
|
||||
## 設計
|
||||
1) メタデータ駆動
|
||||
- `nyash_box.toml` の `methods.*.returns = { type = "box" | "i64" | "f64" | "string" | "void" | ... }` を単一の参照源に。
|
||||
- `PluginHost.resolve_method` に `returns.type` を含む情報を公開(Lowerer から参照)。
|
||||
|
||||
2) Lowerer の汎用化
|
||||
- `PluginInvoke` を常に `emit_plugin_invoke(type_id, method_id, argc, has_ret)` に落とす。
|
||||
- 「戻りが box のときに特定箱名を記録する」実装を撤去。必要なら「dst は Handle(box)」のヒントのみ保持。
|
||||
- 受け手箱名が未確定の場合に備え、by-name 経路(後述)を用意。
|
||||
|
||||
3) by-name シム(任意→推奨)
|
||||
- `nyrt`/builder に `nyash_plugin_invoke_by_name_{i64,f64}(box_type_name?, method_name, a0, a1, a2)` を追加。
|
||||
- 受け手の箱名が Lowerer 時点で特定できない場合、by-name シムを使用して実行時に `method_id` を解決。
|
||||
|
||||
4) 実行時の統一
|
||||
- 既存の `nyash_plugin_invoke3_{i64,f64}` と同様に、TLVで引数を構築。Handle/プリミティブ変換(StringBox/IntegerBoxの自動プリミティブ化)を継続。
|
||||
- 戻りTLVの tag を見て i64/f64 経由の値化(`NYASH_JIT_NATIVE_F64`)またはハンドル登録を行う。
|
||||
|
||||
## マイルストーン
|
||||
- M1: Lowerer から Python特化の型伝搬を除去(dst=Handle ヒントのみ)。
|
||||
- M2: `PluginHost.resolve_method` 拡張で `returns.type` を取得可能に。
|
||||
- M3: by-name シムの追加と Lowerer 配線(箱名未確定時)。
|
||||
- M4: AOT 最小ケース(import→getattr→call)を Handle-First で Green。
|
||||
- M5: ドキュメントと CURRENT_TASK を刷新。
|
||||
|
||||
## 受け入れ条件(DoD)
|
||||
- VM: `py.import("math"); (math.getattr("sqrt")).call(9)` が Green(autodecode=1 で 3)。
|
||||
- AOT(strict): 上記チェーン最小例で unsupported=0。Console 出力経路は PluginInvoke または extern 経由で表示。
|
||||
- Lowerer に Python 固有の型分岐が存在しない(grepで検出不可)。
|
||||
|
||||
## 運用メモ
|
||||
- 将来的な最適化(箱名が静的に分かる場面での特殊化)は、Handle-First を壊さない範囲で「分岐の1箇所」に限定して導入する。
|
||||
|
||||
21
docs/phases/phase-10.5/INDEX.md
Normal file
21
docs/phases/phase-10.5/INDEX.md
Normal file
@ -0,0 +1,21 @@
|
||||
# Phase 10.5 – Index (Active vs Archived)
|
||||
|
||||
このフォルダは Python ネイティブ統合とネイティブビルド基盤のための現行計画(10.5系)と、旧計画(10.1系:アーカイブ)を併置しています。迷った場合は「Active」を参照してください。
|
||||
|
||||
## Active(現行)
|
||||
- 10.5 README(全体像): ./README.md
|
||||
- 10.5a – Python ABI 設計: ./10.5a-ABI-DESIGN.md
|
||||
- 10.5b – ネイティブビルド基盤: ./10.5b-native-build-consolidation.md
|
||||
- 現在フォーカス: MIR→VM→ネイティブビルド(AOT/EXE)を先に堅牢化
|
||||
- 10.5c – Handle-First PluginInvoke / PyRuntimeBox / PyObjectBox(次段)
|
||||
- 10.5d – JIT/AOT 統合(予定)
|
||||
- 10.5e – サンプル / テスト / ドキュメント(予定)
|
||||
|
||||
## Archived(旧10.1系・参照用)
|
||||
- chatgpt5 統合計画(旧称 Phase 10.1): ./chatgpt5_integrated_plan.md
|
||||
- 10.1a_planning ~ 10.1g_documentation 各READMEと資料
|
||||
- 10.1c / 10.1d は「PythonをNyashで動かすフェーズ」の設計・実装メモです(順番変更により後段へ)。
|
||||
|
||||
整理方針:
|
||||
- Active ドキュメントに計画と用語を集約。旧10.1系は背景情報として参照のみ。
|
||||
- 実装の優先は「必要最小の箱(PyRuntimeBox / PyObjectBox)」→ 後から最適化。
|
||||
110
docs/phases/phase-10.5/README.md
Normal file
110
docs/phases/phase-10.5/README.md
Normal file
@ -0,0 +1,110 @@
|
||||
# Phase 10.5 – ネイティブ基盤固め + Python ネイティブ統合
|
||||
*(旧10.1の一部を後段フェーズに再編。まずネイティブ/AOT基盤を固め、その上でPythonを統合する方針に整理)*
|
||||
|
||||
このフォルダの全体像と最新の導線は INDEX を参照してください:
|
||||
- INDEX: ./INDEX.md(Active と Archived の区分とリンク集)
|
||||
|
||||
本フェーズでは方針を明確化する:実行はVMが唯一の基準系、JITは「EXE/AOT生成専用のコンパイラ」として分離運用する。
|
||||
|
||||
アーキテクチャの整理(決定)
|
||||
- 開発/デバッグ: MIR → VM(完全実行)
|
||||
- 本番/配布: MIR → JIT(CLIF)→ OBJ → EXE(完全コンパイル)
|
||||
|
||||
ポイント
|
||||
- フォールバック不要/禁止: JITが未対応ならコンパイルエラー。VMへは落とさない。
|
||||
- 役割分担の明確化: VM=仕様/挙動の唯一の基準、JIT=ネイティブ生成器。
|
||||
- プラグイン整合: VM/EXEとも同一のBID/FFIプラグインを利用(Everything is Plugin)。
|
||||
|
||||
## 📂 サブフェーズ構成(10.5s → 10.5e)
|
||||
|
||||
先行タスク(最優先)
|
||||
- 10.5s JIT Strict/分離の確定(Fail-Fast / ノーフォールバック) [DONE]
|
||||
- 目的: 「VM=実行・JIT=コンパイル」の二系統で混在を排除し、検証を単純化
|
||||
- 仕様:
|
||||
- JITは実行経路から外し、`--compile-native`(AOT)でのみ使用
|
||||
- Lowerer/Engine: unsupported>0 または fallback判定>0 でコンパイル中止(Fail-Fast)
|
||||
- 実行: VMのみ。フォールバックという概念自体を削除
|
||||
- DoD:
|
||||
- CLIに `--compile-native` を追加し、OBJ/EXE生成が一発で通る
|
||||
- VM実行は常にVMのみ(JITディスパッチ既定OFF)。
|
||||
|
||||
### 10.5a(Python)設計・ABI整合(1–2日)
|
||||
- ルート選択:
|
||||
- Embedding: NyashプロセスにCPythonを埋め込み、PyObject*をハンドル管理
|
||||
- Extending: Python拡張モジュール(nyashrt)を提供し、PythonからNyashを呼ぶ
|
||||
- ABI方針:
|
||||
- ハンドル: TLV tag=8(type_id+instance_id)。Pythonオブジェクトは `PyObjectBox` として格納
|
||||
- 変換: Nyash ⇄ Python で Bool/I64/String/Bytes/Handle を相互変換
|
||||
- GIL: birth/invoke/decRef中はGIL確保。AOTでも同等
|
||||
|
||||
### 10.5b ネイティブビルド基盤の固め(AOT/EXE)(2–4日)
|
||||
- 目的: Python統合の前に、AOT/EXE配布体験・クロスプラットフォーム実行の足回りを先に完成させる
|
||||
- 範囲:
|
||||
- VMとJITの分離(JIT=EXE専用)とStrict運用の徹底
|
||||
- AOTパイプラインの実働(CLIF→.o→libnyrtリンク→EXE)
|
||||
- プラグイン解決のクロスプラットフォーム化(.so/.dll/.dylib、自動lib剥がし、検索パス)
|
||||
- Windowsビルド/リンク(clang優先、MSYS2/WSL fallback)
|
||||
- EXE出力の統一(`Result: <val>`)とスモークテスト
|
||||
- DoD:
|
||||
- Linux/Windowsで `--compile-native` が通り、`plugins/` のDLL/so/dylibを自動解決
|
||||
- `tools/build_aot.{sh,ps1}` で配布しやすいEXEが生成される
|
||||
- `tools/smoke_aot_vs_vm.sh` でVM/EXEの出力照合が可能
|
||||
|
||||
### 10.5c PyRuntimeBox / PyObjectBox 実装(3–5日)
|
||||
- `PyRuntimeBox`(シングルトン): `eval(code) -> Handle` / `import(name) -> Handle`
|
||||
- `PyObjectBox`: `getattr(name) -> Handle` / `call(args...) -> Handle` / `str() -> String`
|
||||
- 参照管理: `Py_INCREF`/`Py_DECREF` をBoxライフサイクル(fini)に接続
|
||||
- プラグイン化: `nyash-python-plugin`(cdylib/staticlib)で `nyplug_python_invoke` を提供(将来の静的同梱に対応)
|
||||
|
||||
追加方針(10.5c Handle-First/TLV 統一)
|
||||
- Lowerer は Handle-First を徹底(a0 は常に `nyash.handle.of(receiver)`)。
|
||||
- 引数TLVは String/Integer をプリミティブ化、その他は Handle(tag=8) に統一。
|
||||
- 受け手箱名が未確定な経路には by-name シムを導入(後方安全の回避路)。
|
||||
- 参考: `docs/reference/abi/ffi_calling_convention_min.md`
|
||||
|
||||
### 10.5c 境界の双方向化(3–5日)
|
||||
- Nyash→Python: BoxCall→plugin_invokeでCPython C-APIに橋渡し
|
||||
- Python→Nyash: `nyashrt`(CPython拡張)で `nyash.call(func, args)` を提供
|
||||
- エラーハンドリング: 例外は文字列化(tag=6)でNyashに返却、またはResult化
|
||||
|
||||
### 10.5d JIT/AOT 統合(3–5日)
|
||||
- AOTパイプライン固定: Lower→CLIF→OBJ出力→`ny_main`+`libnyrt.a`リンク→EXE
|
||||
- CLI: `nyash --compile-native file.nyash -o app` を追加(失敗は非ゼロ終了)
|
||||
- libnyrt: `nyash.python.*` 等のシムを提供し、未解決シンボル解決
|
||||
- ディスパッチ: type_id→`nyplug_*_invoke` の静的/動的ルート(第一段は動的優先)
|
||||
|
||||
### 10.5e サンプル/テスト/ドキュメント(1週間)
|
||||
- サンプル: `py.eval("'hello' * 3").str()`、`numpy`の軽量ケース(import/shape参照などRO中心)
|
||||
- テスト: GILの再入・参照カウントリーク検知・例外伝搬・多プラットフォーム
|
||||
- ドキュメント: 使用例、制約(GIL/スレッド)、AOT時のリンク・ランタイム要件
|
||||
|
||||
追加済みサンプル(最小チェーン)
|
||||
- VM: `examples/py_min_chain_vm.nyash`(import→getattr→call→println)
|
||||
- AOT: `examples/aot_py_min_chain.nyash`(import→getattr→call→return)
|
||||
|
||||
## 🎯 DoD(定義)
|
||||
- NyashからPythonコードを評価し、PyObjectをHandleで往復できる
|
||||
- 代表的なプロパティ取得/呼び出し(RO)がJIT/VMで動作
|
||||
- AOTリンク後のEXEで `py.eval()` 代表例が起動できる(動的ロード前提)
|
||||
- 10.5s Strict: VM=仕様/JIT=高速実装の原則に基づき、フォールバック無しで fail-fast が機能
|
||||
|
||||
## ⌛ 目安
|
||||
| サブフェーズ | 目安 |
|
||||
|---|---|
|
||||
| 10.5a 設計 | 1–2日 |
|
||||
| 10.5b 実装 | 3–5日 |
|
||||
| 10.5c 双方向 | 3–5日 |
|
||||
| 10.5d JIT/AOT | 3–5日 |
|
||||
| 10.5e 仕上げ | 1週間 |
|
||||
|
||||
## ⚠️ リスクと対策
|
||||
- GILデッドロック: 入口/出口で厳格に確保/解放。ネスト呼び出しの方針を文書化
|
||||
- 参照カウント漏れ: BoxライフサイクルでDECREFを必ず実施、リークテストを追加
|
||||
- リンク/配布: Linux/macOS優先。WindowsのPythonリンクは後段で対応
|
||||
- 性能: RO先行でJITに寄せ、ミューテーションはポリシー制御
|
||||
|
||||
---
|
||||
|
||||
注: 旧10.1系の資料(10.1a〜g, chatgpt5_integrated_plan.md)は背景情報として残置(Archived)。現行の実装計画と用語は本READMEと 10.5a/b に集約します。
|
||||
|
||||
次は 10.5a(設計・ABI整合)から着手。Everything is Plugin / libnyrt シムの成功パターンをPythonにも適用し、最小リスクで“Pythonネイティブ”を実現する。
|
||||
244
docs/phases/phase-10.5/chatgpt5_integrated_plan.md
Normal file
244
docs/phases/phase-10.5/chatgpt5_integrated_plan.md
Normal file
@ -0,0 +1,244 @@
|
||||
# [Archived] 旧 Phase 10.1 - Python統合計画(ChatGPT5高速開発版)
|
||||
最終更新: 2025-08-27 / 状態: Archived(Phase 10.5 に統合)
|
||||
|
||||
現行の計画は Phase 10.5 のドキュメントに集約しています。最新は以下を参照してください:
|
||||
- Phase 10.5 Index: ./INDEX.md
|
||||
- 10.5a – Python ABI 設計: ./10.5a-ABI-DESIGN.md
|
||||
- 10.5b – ネイティブビルド基盤: ./10.5b-native-build-consolidation.md
|
||||
|
||||
## 🚀 概要:2週間での爆速実装(当時案)
|
||||
|
||||
ChatGPT5の最小Box設計により、元の1ヶ月計画を**2週間**に圧縮。Nyash既存アーキテクチャ(MirBuilder 100%実装済み、HandleRegistry 80%実装済み)を最大活用。
|
||||
|
||||
## 📦 ChatGPT5の6つの必須Box(最小実装)
|
||||
|
||||
### 1. **PythonParserBox** - CPython AST取得(3日)
|
||||
```rust
|
||||
// 既存: pyo3統合済み
|
||||
// 追加: JSON出力とバージョン固定
|
||||
pub struct PythonParserBox {
|
||||
base: BoxBase,
|
||||
py_helper: Arc<Mutex<PyHelper>>,
|
||||
version: String, // "3.11"固定
|
||||
}
|
||||
|
||||
// メソッド(最小限)
|
||||
- parse_to_json(src: String) -> String // ast.parse() → JSON
|
||||
- get_version() -> String // "3.11"
|
||||
```
|
||||
|
||||
### 2. **Py2NyASTBox** - AST変換(3日)
|
||||
```rust
|
||||
// 新規実装
|
||||
pub struct Py2NyASTBox {
|
||||
base: BoxBase,
|
||||
normalizer: AstNormalizer,
|
||||
}
|
||||
|
||||
// メソッド(制御フロー正規化)
|
||||
- convert(json: String) -> NyashAst
|
||||
- normalize_for_else(ast: &mut PyAst) // for/else → if分岐
|
||||
- normalize_comprehensions(ast: &mut PyAst)
|
||||
```
|
||||
|
||||
### 3. **MirBuilderBox** - MIR生成(0日 - 既存活用)
|
||||
```rust
|
||||
// 既存実装100%活用
|
||||
// 追加: Python由来フラグのみ
|
||||
pub struct MirBuilderBox {
|
||||
// 既存フィールド
|
||||
is_python_origin: bool, // 追加
|
||||
}
|
||||
```
|
||||
|
||||
### 4. **BoundaryBox** - 型変換(2日)
|
||||
```rust
|
||||
// Python版のHandleRegistry相当
|
||||
pub struct BoundaryBox {
|
||||
base: BoxBase,
|
||||
handle_registry: Arc<Mutex<HandleRegistry>>, // 既存80%活用
|
||||
}
|
||||
|
||||
// メソッド
|
||||
- py_to_jit(py_val: PyValBox) -> JitValue
|
||||
- jit_to_py(jit_val: JitValue) -> PyValBox
|
||||
- register_handle(obj: Arc<dyn NyashBox>) -> u64
|
||||
```
|
||||
|
||||
### 5. **PyRuntimeBox** - 実行制御(2日)
|
||||
```rust
|
||||
pub struct PyRuntimeBox {
|
||||
base: BoxBase,
|
||||
fallback_stats: FallbackStats,
|
||||
}
|
||||
|
||||
// メソッド(関数単位フォールバック)
|
||||
- execute_function(name: &str, args: Vec<JitValue>) -> JitValue
|
||||
- should_fallback(func_ast: &PyAst) -> bool // Phase1機能判定
|
||||
- fallback_to_cpython(code: &str) -> PyObject
|
||||
```
|
||||
|
||||
### 6. **ObservabilityBox** - 統計収集(1日)
|
||||
```rust
|
||||
// 既存のJIT統計システム(70%実装済み)を拡張
|
||||
pub struct ObservabilityBox {
|
||||
base: BoxBase,
|
||||
stats_collector: StatsCollector,
|
||||
}
|
||||
|
||||
// JSONLフォーマット出力
|
||||
- log_attempt(module: &str, func: &str, compiled: bool, reason: Option<&str>)
|
||||
- output_jsonl() -> String
|
||||
```
|
||||
|
||||
## 🗓️ 実装タイムライン(2週間)
|
||||
|
||||
### Week 1: 基盤実装(7日)
|
||||
- **Day 1-3**: PythonParserBox実装
|
||||
- pyo3統合(既存活用)
|
||||
- Python 3.11固定
|
||||
- JSON出力実装
|
||||
|
||||
- **Day 4-6**: Py2NyASTBox実装
|
||||
- 制御フロー正規化
|
||||
- for/else, while/else変換
|
||||
- Phase1機能のみサポート
|
||||
|
||||
- **Day 7**: ObservabilityBox実装
|
||||
- 既存JIT統計拡張
|
||||
- JSONLフォーマット
|
||||
|
||||
### Week 2: 統合と検証(7日)
|
||||
- **Day 8-9**: BoundaryBox実装
|
||||
- HandleRegistry活用
|
||||
- 型変換ルール確立
|
||||
|
||||
- **Day 10-11**: PyRuntimeBox実装
|
||||
- 関数単位フォールバック
|
||||
- CPython連携
|
||||
|
||||
- **Day 12-13**: 統合テスト
|
||||
- Differential Testing
|
||||
- ベンチマーク実行
|
||||
|
||||
- **Day 14**: ドキュメント・リリース
|
||||
- 使用例作成
|
||||
- パフォーマンス測定
|
||||
|
||||
## 📊 既存アーキテクチャとの整合性
|
||||
|
||||
### 活用率
|
||||
- **MirBuilderBox**: 100%(変更なし)
|
||||
- **HandleRegistry**: 80%(BoundaryBoxで再利用)
|
||||
- **JIT統計**: 70%(ObservabilityBoxで拡張)
|
||||
- **VM/JIT実行**: 100%(そのまま使用)
|
||||
|
||||
### 新規実装
|
||||
- **PythonParserBox**: 30%(pyo3部分は既存)
|
||||
- **Py2NyASTBox**: 100%新規
|
||||
- **PyRuntimeBox**: 100%新規
|
||||
|
||||
## 🎯 Phase 1でサポートする機能(Codex先生推奨)
|
||||
|
||||
### 必須実装
|
||||
1. **LEGB + locals/freevars** - スコーピング規則
|
||||
2. **デフォルト引数の評価タイミング** - 定義時評価
|
||||
3. **イテレータベースのfor文**
|
||||
4. **for/else + while/else**
|
||||
5. **Python真偽値判定**
|
||||
6. **短絡評価**
|
||||
|
||||
### サポートする文
|
||||
- def(関数定義)
|
||||
- if/elif/else
|
||||
- for(else節対応)
|
||||
- while(else節対応)
|
||||
- break/continue
|
||||
- return
|
||||
|
||||
### サポートする式
|
||||
- 算術演算子(+,-,*,/,//,%)
|
||||
- 比較演算子(==,!=,<,>,<=,>=)
|
||||
- 論理演算子(and,or,not)
|
||||
- 関数呼び出し
|
||||
- リテラル(数値/文字列/bool)
|
||||
|
||||
## 📈 成功指標(2週間後)
|
||||
|
||||
### 定量的
|
||||
- **関数コンパイル率**: 70%以上(Phase 1機能)
|
||||
- **実行速度**: 純Pythonループで2倍以上
|
||||
- **メモリ効率**: CPython比50%削減
|
||||
|
||||
### 定性的
|
||||
- **統計可視化**: JSONL形式で全実行を記録
|
||||
- **デバッグ容易性**: 関数単位でフォールバック理由明示
|
||||
- **将来拡張性**: Phase 2-4への明確な道筋
|
||||
|
||||
## 🔧 実装例(最終形)
|
||||
|
||||
```nyash
|
||||
// Nyashから使用
|
||||
local py = new PythonParserBox()
|
||||
local converter = new Py2NyASTBox()
|
||||
local builder = new MirBuilderBox()
|
||||
local runtime = new PyRuntimeBox()
|
||||
local stats = new ObservabilityBox()
|
||||
|
||||
// Pythonコードをコンパイル・実行
|
||||
local code = "def fib(n): return n if n <= 1 else fib(n-1) + fib(n-2)"
|
||||
local json_ast = py.parse_to_json(code)
|
||||
local ny_ast = converter.convert(json_ast)
|
||||
local mir = builder.build(ny_ast)
|
||||
|
||||
// 実行(自動的にJIT/VMで高速化)
|
||||
local result = runtime.execute_function("fib", [10])
|
||||
print(result) // 55
|
||||
|
||||
// 統計出力
|
||||
print(stats.output_jsonl())
|
||||
// {"mod":"test","func":"fib","attempt":1,"jitted":true,"native":true}
|
||||
```
|
||||
|
||||
## 🚨 重要な設計判断
|
||||
|
||||
### 1. 関数単位の境界
|
||||
- ファイル単位ではなく**関数単位**でコンパイル/フォールバック
|
||||
- 未対応機能を含む関数のみCPython実行
|
||||
|
||||
### 2. Python 3.11固定
|
||||
- AST安定性の確保
|
||||
- 将来のバージョンアップは別Phase
|
||||
|
||||
### 3. 箱境界の明確化
|
||||
- 各Boxは単一責任
|
||||
- 相互依存を最小化
|
||||
- テスト可能な粒度
|
||||
|
||||
### 4. 既存資産の最大活用
|
||||
- MirBuilder/VM/JITはそのまま使用
|
||||
- 新規実装は変換層のみ
|
||||
|
||||
## 🎉 期待される成果
|
||||
|
||||
### 即時的効果(2週間後)
|
||||
- Pythonコードの70%がNyashで高速実行
|
||||
- バグ検出力の飛躍的向上(Differential Testing)
|
||||
- 統計による最適化ポイントの可視化
|
||||
|
||||
### 長期的効果
|
||||
- Python→Nyash→Native の世界初パイプライン確立
|
||||
- Nyash言語の成熟度向上
|
||||
- エコシステムの爆発的拡大
|
||||
|
||||
## 📝 次のステップ
|
||||
|
||||
1. **Phase 10.7完了確認** - JIT統計JSONの安定化
|
||||
2. **PythonParserBox実装開始** - pyo3統合から着手
|
||||
3. **テストコーパス準備** - Python標準ライブラリから抜粋
|
||||
|
||||
---
|
||||
|
||||
**作成者**: Claude(Claude Code)
|
||||
**承認者**: ChatGPT5(予定)
|
||||
**開始予定**: Phase 10.7完了直後
|
||||
87
docs/phases/phase-10.6/PLAN.txt
Normal file
87
docs/phases/phase-10.6/PLAN.txt
Normal file
@ -0,0 +1,87 @@
|
||||
# Phase 10.6 計画(整理版 / txt)
|
||||
|
||||
目的: Thread-Safety(監査→仕込み)と協調スケジューラ(Safepoint連携)を最小構成で通し、次段の並列GC/並列実行に備える。
|
||||
|
||||
====================
|
||||
1) ゴール(DoD)
|
||||
====================
|
||||
- 10.6a: Thread-Safety Audit の完了(一次)
|
||||
- NyashBox/Runtime の共有戦略(Arc+RwLock/Mutex)を棚卸し、未整備箇所はTODO化
|
||||
- Plugin-First 前提(PluginBoxV2 はクロススレッド未サポ運用を明記)
|
||||
- 10.6b: 協調スケジューラの足場
|
||||
- SingleThreadScheduler(queue + delayed + poll)を Safepoint に接続済み
|
||||
- デモ/トレース(NYASH_SCHED_DEMO=1, NYASH_SCHED_TRACE=1, 予算NYASH_SCHED_POLL_BUDGET)で観測可
|
||||
- 10.6c: 並列GC 設計の下準備
|
||||
- Per-thread roots / Safepoint協調 / カードマーキングの設計メモを確定(段階導入方針)
|
||||
|
||||
====================
|
||||
2) スコープ
|
||||
====================
|
||||
- 実装は“最小で通す”に限定(最適化は後続)。
|
||||
- 既存のVM=仕様、JIT=AOT生成専用という原則は維持。
|
||||
- Python/Plugin 経路は Plugin-First/Handle-First/TLV 統一の上に載せる(10.5で固定済)。
|
||||
|
||||
====================
|
||||
3) サブフェーズとタスク
|
||||
====================
|
||||
3.1) 10.6a Thread-Safety Audit(1–2日)
|
||||
- ドキュメント: phase-10/phase_10_6a_thread_safety_audit.md(既存)に一次棚卸しを反映
|
||||
- Grepチェック: Arc/Mutex/RwLock/Send/Sync の確認と未整備箇所の列挙
|
||||
- 確認対象:
|
||||
- ArrayBox/MapBox/BufferBox の共有戦略(Arc<RwLock<...>>)
|
||||
- NyashRuntime メンバのSend+Sync前提(Arcで包む)
|
||||
- Scheduler/GC Hooks のSend+Sync前提
|
||||
- PluginBoxV2: クロススレッド未サポ運用を明記(将来設計のTODO)
|
||||
|
||||
3.2) 10.6b Scheduler Prep(1–2日)
|
||||
- 仕様固定: poll() を MIR Safepoint で呼ぶ(既実装の確認)
|
||||
- 観測: NYASH_SCHED_DEMO=1 / NYASH_SCHED_TRACE=1 / NYASH_SCHED_POLL_BUDGET で動作確認
|
||||
- 最小API: spawn/spawn_after/poll/yield_now(SingleThreadScheduler)
|
||||
- ドキュメント: phase-10/phase_10_6b_scheduler_prep.txt 更新(Trace/観測例追加済)
|
||||
|
||||
3.3) 10.6c Parallel GC Design(2–3日)
|
||||
- 設計メモ: phase-10/phase_10_6c_parallel_gc_design.txt(既存)を最終化
|
||||
- 方針:
|
||||
- Per-thread roots, Safepoint協調、カードマーキングの段階導入
|
||||
- デフォルトは単一スレッド継続(featureで並列ON)
|
||||
- API拡張は後方互換シムを用意(barrier引数拡張など)
|
||||
|
||||
====================
|
||||
4) 成果物(Artifacts)
|
||||
====================
|
||||
- Docs
|
||||
- 10.6a 監査メモ: phase-10/phase_10_6a_thread_safety_audit.md(一次棚卸し完了)
|
||||
- 10.6b スケジューラ: phase-10/phase_10_6b_scheduler_prep.txt(Trace/デモ手順)
|
||||
- 10.6c 並列GC設計: phase-10/phase_10_6c_parallel_gc_design.txt(確定版)
|
||||
- Code
|
||||
- src/runtime/scheduler.rs(SingleThreadScheduler / Send+Sync)
|
||||
- MIR Safepoint → VM Runtime.scheduler.poll()(済)
|
||||
|
||||
====================
|
||||
5) リスクと緩和
|
||||
====================
|
||||
- 共有の粒度: 競合を避けるため、Box内部は最小限のロックで運用(RwLock優先)。
|
||||
- 並列前倒しの誘惑: 10.6では並列化を“設計と足場”に限定、実実装は次フェーズ(feature)
|
||||
- Plugin/FFI: クロススレッド呼出しは明示的に非対応(ドキュメントで制約明記)。
|
||||
|
||||
====================
|
||||
6) タイムライン(目安)
|
||||
====================
|
||||
- 10.6a: 1–2日
|
||||
- 10.6b: 1–2日
|
||||
- 10.6c: 2–3日
|
||||
|
||||
====================
|
||||
7) 依存関係
|
||||
====================
|
||||
- 10.5 完了(AOT/nyrt/Handle-First/TLV統一/Strict運用)を前提
|
||||
- Docsの最新導線: docs/development/roadmap/phases/phase-10.5/INDEX.md
|
||||
|
||||
====================
|
||||
8) 参照リンク
|
||||
====================
|
||||
- phase-10/phase_10_6_thread_safe_revolution.md(設計準備)
|
||||
- phase-10/phase_10_6a_thread_safety_audit.md(監査)
|
||||
- phase-10/phase_10_6b_scheduler_prep.txt(スケジューラ)
|
||||
- phase-10/phase_10_6c_parallel_gc_design.txt(並列GC)
|
||||
|
||||
79
docs/phases/phase-10.6/PYTHON_NATIVE_PLAN.txt
Normal file
79
docs/phases/phase-10.6/PYTHON_NATIVE_PLAN.txt
Normal file
@ -0,0 +1,79 @@
|
||||
# Phase 10.6 → Pythonネイティブ接続プラン(整理版 / txt)
|
||||
|
||||
目的: 10.6で整えたThread-Safety/Schedulerの最小足場の上に、Pythonプラグイン(PyRuntimeBox/PyObjectBox)をネイティブEXE(AOT)まで安定接続する。
|
||||
|
||||
====================
|
||||
1) 到達イメージ(DoD)
|
||||
====================
|
||||
- Linux/Windows で以下が安定動作:
|
||||
- AOT: `examples/aot_py_min_chain.nyash` → `Result: 4`(math.sqrt(16))
|
||||
- VM: `examples/py_min_chain_vm.nyash` → 4.0 表示(NYASH_PY_AUTODECODE=1)
|
||||
- returns_result 系サンプル(importR/getattrR/callR)で Ok/Err が期待通りに表示
|
||||
- AOTビルドの配布体験が明確:
|
||||
- `tools/build_aot.{sh,ps1}` で .o → EXE、`nyash.toml`/plugins 解決、Windowsでは PATH/PYTHONHOME 調整
|
||||
- 配布ガイド(依存コピー/環境変数/動作確認手順)が `docs/guides/build/aot_quickstart.md` に追記済み
|
||||
|
||||
====================
|
||||
2) 方針(変えない原則)
|
||||
====================
|
||||
- Plugin-First / Handle-First / TLV 統一(String/Integerはプリミティブ、Bufferはbytes(tag=7)、他はHandle(tag=8))。
|
||||
- Strict: 実行はVM、JITはAOT生成専用(フォールバック禁止)。
|
||||
- by-name経路: 受け手箱名未確定時は `nyash_plugin_invoke_name_{getattr,call}_i64` で実行時解決。
|
||||
|
||||
====================
|
||||
3) 実装タスク(M1→M5)
|
||||
====================
|
||||
M1: AOT最小ルートの安定(完了確認/微修正)
|
||||
- nyrt シム:BufferBox→bytes(tag=7) 対応、3引数目以降をレガシーVM引数からTLV追補(暫定N引数)
|
||||
- Windows探索:EXE起動時に PATH へ exe/`plugins/` を追加、`PYTHONHOME` が未設定なら `exe\python` を採用(相対はexe基準に正規化)
|
||||
- ドキュメント:AOTクイックスタートにWindows注意点を追記(済)
|
||||
|
||||
M2: TLV/FFIカバレッジ拡大(最小)
|
||||
- kwargs/辞書のパス(callKwR)をbytes(tag=7) or string(tag=6, JSON)で暫定対応(将来 BID-1拡張)
|
||||
- N引数の一般化(invoke3→invokeN 設計、実装は段階導入。先行はレガシー補完で可)
|
||||
- returns_result の統一処理(VM既存→AOTでも同等に扱う)
|
||||
|
||||
M3: Lowerer/Policy の整流
|
||||
- Handle-First統一の確認:Python特化の型伝搬は撤去済み(戻りはHandle or プリミティブのみ参照)
|
||||
- birth引数の一般化(TLVメモに沿い、Integer/Stringはプリミティブ、他はHandle)
|
||||
- by-name の適用範囲と導線(`getattr`/`call` はby-name固定、importはmethod_id直参照)
|
||||
|
||||
M4: 配布導線とサンプル
|
||||
- スクリプト整備:`tools/build_python_aot.sh` の統合(`build_aot.sh` に一本化 or ラッパー)
|
||||
- サンプル最小化:returns_result(Ok/Err)、例外伝搬(Error文字列)、bytes引数、context共有(per-runtime globals)
|
||||
- ガイド整理:`docs/guides/build/aot_quickstart.md` に「Pythonネイティブ」節を追加(動作要件・環境変数)
|
||||
|
||||
M5: 観測/CI(軽量)
|
||||
- スモーク:VMチェーン / AOTチェーンの比較(Result行)を `tools/smoke_aot_vs_vm.sh` に追加(Python系は最小のみ)
|
||||
- ログ:`NYASH_JIT_EVENTS*`/`NYASH_JIT_NATIVE_F64`/`NYASH_PY_AUTODECODE` による差分観測
|
||||
|
||||
====================
|
||||
4) リスク/制約
|
||||
====================
|
||||
- CPython依存の配布:WindowsのDLL探索(PATH/PYTHONHOME)は最小整備。完全同梱(embedded)は後段で検討。
|
||||
- KW/辞書のTLV表現:暫定はbytes/stringでブリッジ。正式BIDタグは将来導入(後方互換のためJSON連携を許容)。
|
||||
- ネイティブN引数:v0はレガシーVM引数からのTLV補完でしのぎ、invokeNは次期導入。
|
||||
|
||||
====================
|
||||
5) タイムライン(目安)
|
||||
====================
|
||||
- M1(安定): 0.5日(確認/微修正)
|
||||
- M2(TLV拡充): 1–2日(kwargsは暫定・bytes/JSON)
|
||||
- M3(Lowerer整流): 0.5–1日
|
||||
- M4(配布/サンプル): 1日
|
||||
- M5(観測/CI): 0.5日
|
||||
|
||||
====================
|
||||
6) 成果物(Artifacts)
|
||||
====================
|
||||
- 例: `examples/aot_py_min_chain.nyash`, `examples/py_min_chain_vm.nyash`(既存)
|
||||
- ツール: `tools/build_aot.{sh,ps1}`(Python節)、`tools/smoke_aot_vs_vm.sh`(Python最小)
|
||||
- Docs: `docs/guides/build/aot_quickstart.md`(Python節)、`docs/reference/abi/ffi_calling_convention_min.md`(bytes/N引数注記)
|
||||
|
||||
====================
|
||||
7) 参照
|
||||
====================
|
||||
- 10.5c: Handle-First/PluginInvoke 設計(by-name シム)
|
||||
- 10.5d/e: AOT統合/最終仕上げ(nyrt/Windows探索/TLV拡張)
|
||||
- 10.6: Thread-Safety/Scheduler(並列化前の足場)
|
||||
|
||||
67
docs/phases/phase-10.7/PLAN.txt
Normal file
67
docs/phases/phase-10.7/PLAN.txt
Normal file
@ -0,0 +1,67 @@
|
||||
# Phase 10.7 – Python Native 再スタート計画(合意版 / txt)
|
||||
|
||||
目的: 現行の Plugin-First(PyRuntimeBox/PyObjectBox, Handle-First/TLV)を維持しつつ、トランスパイル路線(Python→Nyash)を“All or Nothing”原則で段階導入。10.6の足場(Thread-Safety/Scheduler)上で、AOT配布体験に直結する最短ラインを構築する。
|
||||
|
||||
====================
|
||||
A) 方針(判断)
|
||||
====================
|
||||
- 二本立てを明確化:
|
||||
1) 実行系(現行): PyRuntimeBox 経由(VM=仕様、JIT=AOT生成のみ)。配布/運用の実用ライン。
|
||||
2) トランスパイル系(10.7): Python→Nyash→MIR→AOT。コンパイル成功/失敗の二択(フォールバック自動無し)。
|
||||
- 役割分担:未対応Pythonはユーザーが明示的に PyRuntimeBox を使う。トランスパイルはコンパイル成功率を段階的に拡大。
|
||||
- Plugin-Firstは維持(Parser/CompilerもプラグインBox化)。CLI/VMから統一呼び出し。
|
||||
|
||||
====================
|
||||
B) 最小成功像(Phase 1 / DoD)
|
||||
====================
|
||||
- サンプルpy(Phase 1 範囲内)を `pythonc`(仮)で Nyashスクリプトへ生成 → `--compile-native` で EXE 生成 → 実行。
|
||||
- 機能カバレッジ(Phase 1): def/if/for/while/return/bool/算術/比較/関数呼び出し/LEGB/デフォルト引数/for-else。
|
||||
- Differential(限定): Phase 1 サンプル群で CPython と一致(出力/戻り/例外の有無)。
|
||||
|
||||
====================
|
||||
C) サブフェーズとタスク
|
||||
====================
|
||||
C1) Parser Plugin(1週)
|
||||
- `plugins/nyash-python-parser-plugin`: Python→AST(pyo3)。
|
||||
- AST→CorePy IR(JSON): 構文の正規化(with→try/finally などはPhase 2)。
|
||||
- Telemetry: ノード統計/未対応ノードを列挙。
|
||||
|
||||
C2) Compiler Core(2週)
|
||||
- IR→Nyash AST 生成(Box化/クロージャ/LEGB/デフォ引数の再現)。
|
||||
- peephole最小(定数畳み込み)。
|
||||
- 生成NyashのPretty-print + 簡易ソースマップ。
|
||||
|
||||
C3) 配線/CLI/実行(3日)
|
||||
- `nyash --pyc file.py -o out.ny`(Nyash出力)/ `--pyc-native file.py -o app`(EXE直行)を追加(内部で既存 `--compile-native` を利用)。
|
||||
- 生成Nyashは既存コンパイラ経由で MIR→AOT を通す(Strict)。
|
||||
|
||||
C4) テスト/観測(1週並行)
|
||||
- `phase-10.7/testing-plan.md` の Phase 1 部分を小粒に実装。
|
||||
- VM vs AOT の「Result:」比較ラインを流用(既存スモークベース)。
|
||||
|
||||
====================
|
||||
D) インターフェース / 成果物
|
||||
====================
|
||||
- ParserBox: `parse(code: String) -> AstBox/CorePyBox`(内部JSON保持 or to_json)
|
||||
- CompilerBox: `compile(ir: CorePyBox) -> Result<NyashSourceBox, ErrorBox>`
|
||||
- CLI: `--pyc/--pyc-native`(初期は隠しフラグでも可)
|
||||
- Docs: README/implementation/testing-plan を PLAN に沿って更新。
|
||||
|
||||
====================
|
||||
E) リスク/緩和
|
||||
====================
|
||||
- 範囲膨張: Phase 1 の構文/意味論を固定し、Beyondは即Err。PyRuntimeBoxは明示利用。
|
||||
- 例外/with/comp/async: Phase 2/3の対象。IR設計時に将来ノードを予約(後方互換)。
|
||||
- Windows配布: 10.5で整えた PATH/PYTHONHOME 補助はPyRuntime向け。トランスパイル後はCPython依存なし。
|
||||
|
||||
====================
|
||||
F) タイムライン(目安)
|
||||
====================
|
||||
- C1: 1週 / C2: 2週 / C3: 3日 / C4: 1週(並行)。
|
||||
|
||||
====================
|
||||
G) 現行との接続
|
||||
====================
|
||||
- 10.6の足場(Thread-Safety/Scheduler)は維持。トランスパイル系は単一スレッド/VM基準で十分。
|
||||
- 10.5のAOT導線/nyrtシムはそのまま活用(生成Nyashに対して適用)。
|
||||
|
||||
148
docs/phases/phase-10.7/README.md
Normal file
148
docs/phases/phase-10.7/README.md
Normal file
@ -0,0 +1,148 @@
|
||||
# Phase 10.7 - True Python Native via Plugin Boxes
|
||||
|
||||
## 🎯 概要
|
||||
|
||||
PythonコードをNyashで**本当にネイティブ実行**する。CPythonへの依存なしに、Pythonコードが完全にNyash MIR/JIT経由で機械語として実行される。
|
||||
|
||||
### 現状 vs 理想
|
||||
|
||||
**現状(Phase 10.6)**: PyRuntimeBox → libpython呼び出し
|
||||
**理想(Phase 10.7)**: Python → Nyashスクリプト → MIR → ネイティブ
|
||||
|
||||
## 🏗️ アーキテクチャ:トランスパイル方式
|
||||
|
||||
```
|
||||
Python AST → CorePy IR → Nyash AST → Nyashスクリプト
|
||||
```
|
||||
|
||||
### なぜトランスパイル?
|
||||
|
||||
1. **透明性**: 生成コードが見える・デバッグできる・手を加えられる
|
||||
2. **既存資産活用**: Nyashコンパイラの最適化を自動享受
|
||||
3. **教育的価値**: PythonとNyashの対応が学習価値を持つ
|
||||
4. **段階的改善**: 生成コードの品質を徐々に向上
|
||||
|
||||
### プラグインBox群
|
||||
|
||||
- **PythonParserBox**: Python → AST変換
|
||||
- **PythonCompilerBox**: AST → Nyashスクリプト生成
|
||||
- **py_runtime.ny**: Pythonセマンティクス保持ライブラリ
|
||||
|
||||
## ⚠️ All or Nothing設計(フォールバックなし)
|
||||
|
||||
**コンパイルできる or できない の2択のみ**
|
||||
|
||||
```nyash
|
||||
compiler = new PythonCompilerBox()
|
||||
result = compiler.compile(ast)
|
||||
|
||||
if result.isOk() {
|
||||
// 100%コンパイル成功 → ネイティブ実行
|
||||
print("Success! Native execution ready.")
|
||||
} else {
|
||||
// 未対応機能あり → 完全拒否
|
||||
print("Cannot compile: " + result.getError())
|
||||
print("Use PyRuntimeBox instead.")
|
||||
}
|
||||
```
|
||||
|
||||
理由:開発時と本番時で挙動が変わるのは最悪の設計
|
||||
|
||||
## 📋 実装フェーズ
|
||||
|
||||
### Phase 10.7a - Parser Plugin(1週間)
|
||||
- PythonParserBoxの実装
|
||||
- Python AST → ASTBox変換
|
||||
- テレメトリー基盤
|
||||
|
||||
### Phase 10.7b - Compiler Core(2週間)
|
||||
**Phase 1機能(必須)**
|
||||
- 関数定義、条件分岐、ループ
|
||||
- 演算子、関数呼び出し
|
||||
- Python固有:LEGB、デフォルト引数、for/else
|
||||
|
||||
### Phase 10.7c - Validation & Testing(1週間)
|
||||
- コンパイル可能性の事前検証
|
||||
- Differential testing(CPythonと比較)
|
||||
- 明確なエラーメッセージ
|
||||
|
||||
### Phase 10.7d - Coverage拡大(3-4週間)
|
||||
**Phase 2**: 例外処理、with文、comprehensions
|
||||
**Phase 3**: async/await、デコレータ、ジェネレータ
|
||||
|
||||
## 🧪 py_runtime設計
|
||||
|
||||
```nyash
|
||||
// Pythonセマンティクスを忠実に再現
|
||||
box PyRuntime {
|
||||
py_truthy(x) {
|
||||
// Python的真偽値判定
|
||||
if x == null or x == false { return false }
|
||||
if x.hasMethod("__bool__") { return x.__bool__() }
|
||||
if x.hasMethod("__len__") { return x.__len__() != 0 }
|
||||
return true
|
||||
}
|
||||
|
||||
py_getattr(obj, name) {
|
||||
// ディスクリプタプロトコル、MRO探索
|
||||
}
|
||||
|
||||
py_call(f, args, kwargs) {
|
||||
// デフォルト引数、*args/**kwargs処理
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📊 成功指標
|
||||
|
||||
### Phase 1完了時
|
||||
```
|
||||
Compilable files: 15/100 (15%)
|
||||
Performance (numeric): 10x faster than CPython
|
||||
Correctness: 100% (differential testing)
|
||||
```
|
||||
|
||||
### 最終目標(Phase 3)
|
||||
```
|
||||
Coverage: 95%+ of common patterns
|
||||
Performance: 5-20x faster
|
||||
Distribution: Single binary, no CPython
|
||||
```
|
||||
|
||||
## 🚀 クイックスタート
|
||||
|
||||
```bash
|
||||
# プラグイン作成
|
||||
cd plugins/
|
||||
cargo new nyash-python-parser-plugin --lib
|
||||
|
||||
# 最小実装
|
||||
[dependencies]
|
||||
pyo3 = { version = "0.22", features = ["auto-initialize"] }
|
||||
nyash-plugin-sdk = { path = "../../crates/plugin-sdk" }
|
||||
|
||||
# テスト実行
|
||||
cargo build --release
|
||||
../../target/release/nyash test_parser.nyash
|
||||
```
|
||||
|
||||
## 💡 創造的可能性
|
||||
|
||||
### ハイブリッドプログラミング
|
||||
```python
|
||||
@nyash.vectorize # PythonデコレータがNyashのSIMD生成!
|
||||
def matrix_multiply(a, b):
|
||||
return a @ b
|
||||
```
|
||||
|
||||
### 言語の共進化
|
||||
- Nyashが「Pythonで最も使われるイディオム」から学習
|
||||
- Pythonに「Nyash-aware」コーディングスタイル誕生
|
||||
|
||||
### 教育的インパクト
|
||||
左にPython、右にリアルタイムNyash変換のPlayground
|
||||
|
||||
## 📚 参考資料
|
||||
|
||||
- **archive/gemini-analysis-transpile-beauty.md** - 創造性分析
|
||||
- **archive/codex-analysis-technical-implementation.md** - 技術分析
|
||||
@ -0,0 +1,252 @@
|
||||
# Codex (GPT-5)の技術分析:Python→Nyashトランスパイルの実装詳細
|
||||
|
||||
2025-08-30 - OpenAI Codex v0.25.0による技術的深掘り
|
||||
|
||||
## Big Picture
|
||||
|
||||
- **Purpose**: Generate Nyash source from Python to leverage Nyash's optimizer, keep debugging simple, and "think in Nyash" early without locking into MIR details.
|
||||
- **Core idea**: Normalize Python to a small CorePy IR, then lower to idiomatic Nyash with a thin "Py runtime shim" in Nyash that preserves Python's dynamic semantics where required.
|
||||
|
||||
## AST Conversion
|
||||
|
||||
### Two-stage lowering
|
||||
```
|
||||
Python AST → CorePy IR → Nyash AST
|
||||
```
|
||||
|
||||
CorePy should be expression-friendly, desugared, and semantics-explicit (e.g., with→try/finally, for→iterator loop, boolean ops→if/else).
|
||||
|
||||
### Visitor + environment
|
||||
Implement a node visitor that carries scope info (locals/free/globals), evaluation order, and source spans. Use Python's `symtable` to seed symbol kinds; validate against your own pass.
|
||||
|
||||
### Semantic shims
|
||||
Lower Python ops to Nyash intrinsics that preserve semantics:
|
||||
- `py_truthy(x)`
|
||||
- `py_getattr(o,"a")`
|
||||
- `py_setattr(o,"a",v)`
|
||||
- `py_binop("add", a, b)`
|
||||
- `py_cmp("lt", a, b)`
|
||||
- `py_iter(x)`
|
||||
- `py_call(f, args, kwargs)`
|
||||
- `py_slice(x, i, j, k)`
|
||||
|
||||
### Boxes and cells
|
||||
Model Python variables and closures with Box/Cell objects. Rule of thumb: locals are unboxed unless captured or aliased; promote to Box when needed. Everything-is-Box in Nyash aligns well with Python's mutability/aliasing.
|
||||
|
||||
### Control flow
|
||||
Normalize to a small set: `if`, `block`, `loop`, `break`, `continue`, `try/catch/finally`, `throw`. Lower `and`/`or` with short-circuit temp; turn comprehensions into explicit loops with dedicated inner scope.
|
||||
|
||||
## Transpile Quality
|
||||
|
||||
### Readability vs optimize
|
||||
Offer modes. Default emits idiomatic Nyash constructs and meaningful identifiers, comments with source spans, and simple temporaries. "Optimize" mode switches to `py_*` intrinsics fusion and fewer temps.
|
||||
|
||||
### Idiomatic Nyash
|
||||
Prefer Nyash control constructs over procedural labels. Use native blocks for `if/else`, `match` if Nyash has it; only fall back to runtime calls where semantics demand.
|
||||
|
||||
### Stable pretty-printer
|
||||
Round-trip friendly formatter with consistent whitespace, trailing comma rules, and deterministic temp naming (`_t1`, `_t2…`). Keep def/class emitted in declaration-order.
|
||||
|
||||
### Debug info
|
||||
Attach `span(file, line, col)` to every IR node, carry through to Nyash AST, then emit a sidecar source map. Optionally embed lightweight `#line` directives or inline comments per statement in debug builds.
|
||||
|
||||
## Python Feature Mapping
|
||||
|
||||
### Default args
|
||||
Evaluate at def-time; store tuple/dict on the function object. At call-time, fill missing with stored defaults. Beware mutable defaults: do not clone; reuse exact object.
|
||||
|
||||
### LEGB scoping
|
||||
Build symbol table with flags for `global`/`nonlocal`. Emit closure "cells" (Boxes) for free vars; functions capture a vector of cells. Globals map to the module dict; builtins fallback when name miss in global.
|
||||
|
||||
### for/else, while/else
|
||||
Introduce `broken=false`. On `break`, set and exit; after loop, `if !broken { else_block }`.
|
||||
|
||||
### Comprehensions
|
||||
Create inner function/scope per comprehension (Python 3 semantics). Assignment targets exist only in that scope. Preserve evaluation order and late binding behavior.
|
||||
|
||||
### With statement
|
||||
Desugar to try/finally per Python spec: evaluate context expr, call `__enter__`, bind target, run body, always call `__exit__`, and suppress exception only if `__exit__` returns truthy.
|
||||
|
||||
### Decorators
|
||||
Evaluate bottom-up at def-time: `fn = decoN(...(deco1(fn)))` then assign back. Keep evaluation order of decorator expressions.
|
||||
|
||||
### Generators
|
||||
Lower to a state machine object implementing Nyash's iterator protocol, with saved instruction pointer, stack slots, and exception injection (`throw`, `close`). Support `yield from` by delegation trampoline.
|
||||
|
||||
### Pattern matching (PEP 634)
|
||||
If supported by Nyash, map directly; else lower to nested guards and extractor calls in a `py_match` helper library.
|
||||
|
||||
### Data model
|
||||
Attribute access honors descriptors; method binding creates bound objects; arithmetic and comparisons dispatch to `__op__`/`__rop__` and rich comparisons; truthiness via `__bool__`/`__len__`.
|
||||
|
||||
## Performance Opportunities
|
||||
|
||||
### At transpile-time
|
||||
- Constant fold literals, f-strings (format plan precomputation), simple arithmetic if types are literal.
|
||||
- Invariant hoisting for loop-invariant comprehensions and attribute chains when no side-effects (guarded).
|
||||
- Direct calls to Nyash intrinsics for selected builtins (`len`, `isinstance`, `range`) only if not shadowed (prove via symbol table).
|
||||
- Peephole: collapse nested `py_truthy(py_truthy(x))`, merge adjacent `if` with literal conditions, drop dead temporaries.
|
||||
|
||||
### Defer to Nyash compiler
|
||||
- Inlining across Nyash functions, register allocation, loop unrolling, vectorization, constant propagation at MIR level.
|
||||
- DCE/CSE once `py_*` helpers are inlined or annotated as pure/idempotent where legal.
|
||||
|
||||
### Types as hints
|
||||
- Consume Python annotations/`typing` to emit specialized fast paths: e.g., `int` → direct Nyash integer ops, else fallback to `py_binop`. Plumb types through IR as optional metadata for MIR to exploit.
|
||||
- Profile-guided guards: optional mode emits guards around hot calls to enable Nyash JIT/AOT to speculate and deopt to generic `py_*`.
|
||||
|
||||
## Error Handling & Debug
|
||||
|
||||
### Source maps
|
||||
Emit a compact mapping (e.g., VLQ JSON) from Nyash line/col → Python original; include segment mappings per expression for precise stepping.
|
||||
|
||||
### Exception rewriting
|
||||
Wrap Nyash runtime entrypoints to translate stack frames via the source map, hiding frames from helpers (`py_*`) unless verbose mode is on.
|
||||
|
||||
### Stage diagnostics
|
||||
- CorePy dump: toggle to print normalized IR with spans.
|
||||
- Nyash preview: post-format preview with original Python line hints.
|
||||
- Trace toggles: selective tracing of `py_call`, `py_getattr`, iteration; throttle to avoid noise.
|
||||
|
||||
### Friendly messages
|
||||
On unsupported nodes or ambiguous semantics, show minimal repro, Python snippet, and link to a doc page. Include symbol table excerpt when scoping fails.
|
||||
|
||||
## Architecture & DX
|
||||
|
||||
### Pass pipeline
|
||||
```
|
||||
Parse Python AST → Symbol table → Normalize to CorePy →
|
||||
Scope/closure analysis → Type/meta attach → Lower to Nyash AST →
|
||||
Optimize (peephole/simplify) → Pretty-print + source map
|
||||
```
|
||||
|
||||
### Runtime shim (`nyash/lib/py_runtime.ny`)
|
||||
Core APIs:
|
||||
- `py_call(f, pos, kw, star, dstar)`
|
||||
- `py_truthy(x)`
|
||||
- `py_getattr/py_setattr`
|
||||
- `py_binop(op, a, b)`
|
||||
- `py_cmp(op,a,b)`
|
||||
- `py_iter(x)`
|
||||
- `py_next(it)`
|
||||
- `py_slice(x,i,j,k)`
|
||||
- `py_with(mgr, body_fn)`
|
||||
- `py_raise`
|
||||
- `py_is`
|
||||
- `py_eq`
|
||||
|
||||
Data model support: descriptor get/set, method binding, MRO lookup, exception hierarchy, StopIteration protocol.
|
||||
|
||||
Perf annotations: mark pure or inline candidates; keep stable ABI.
|
||||
|
||||
### CLI/flags
|
||||
Modes:
|
||||
- `--readable`
|
||||
- `--optimized`
|
||||
- `--debug`
|
||||
- `--emit-sourcemap`
|
||||
- `--dump-corepy`
|
||||
- `--strict-builtins`
|
||||
|
||||
Caching: hash of Python AST + flags to cache Nyash output, source map, and diagnostics.
|
||||
|
||||
Watch/incremental: re-transpile changed modules, preserve source map continuity.
|
||||
|
||||
### Tests
|
||||
- Golden tests: Python snippet → Nyash output diff, with normalization.
|
||||
- Differential: run under CPython vs Nyash runtime for functional parity on a corpus (unit/property tests).
|
||||
- Conformance: edge cases (scoping, descriptors, generators, exceptions) and evaluation order tests.
|
||||
|
||||
## Pitfalls & Remedies
|
||||
|
||||
### Evaluation order
|
||||
Python's left-to-right arg eval, starred/unpacking, and kw conflict checks. Enforce by sequencing temps precisely before `py_call`.
|
||||
|
||||
### Shadowing builtins/globals
|
||||
Only specialize when proven not shadowed in any reachable scope. Provide `--strict-builtins` to disable specialization unless guaranteed.
|
||||
|
||||
### Identity vs equality
|
||||
`is` is reference identity; avoid folding or substituting.
|
||||
|
||||
### Integer semantics
|
||||
Python's bigints; ensure Nyash numeric layer matches or route to bigints in `py_*`.
|
||||
|
||||
## Future Extensibility
|
||||
|
||||
### Plugins
|
||||
Pass manager with hooks (`before_lower`, `after_lower`, `on_node_<Type>`). Allow project-local rewrites and macros, with access to symbol/type info.
|
||||
|
||||
### Custom rules
|
||||
DSL for pattern→rewrite with predicates (types, purity), e.g., rewrite `dataclass` patterns to Nyash records.
|
||||
|
||||
### Multi-language
|
||||
Keeping the Nyash script as a stable contract invites other frontends (e.g., a subset of JS/TypeScript or Lua) to target Nyash; keep `py_*` separate from language-agnostic intrinsics to avoid contamination.
|
||||
|
||||
### Gradual migration
|
||||
As Nyash grows Pythonic libraries, progressively replace `py_*` with native Nyash idioms; keep a compatibility layer for mixed projects.
|
||||
|
||||
## Concrete Translation Sketches
|
||||
|
||||
### Attribute
|
||||
```python
|
||||
a.b
|
||||
```
|
||||
→
|
||||
```nyash
|
||||
py_getattr(a, "b")
|
||||
```
|
||||
|
||||
### Call
|
||||
```python
|
||||
f(x, y=1, *as, **kw)
|
||||
```
|
||||
→
|
||||
```nyash
|
||||
py_call(f, [x], {"y":1}, as, kw)
|
||||
```
|
||||
|
||||
### If
|
||||
```python
|
||||
if a and b:
|
||||
```
|
||||
→
|
||||
```nyash
|
||||
let _t=py_truthy(a); if _t { if py_truthy(b) { ... } }
|
||||
```
|
||||
|
||||
### For/else
|
||||
```python
|
||||
for x in xs:
|
||||
if cond:
|
||||
break
|
||||
else:
|
||||
else_block
|
||||
```
|
||||
→
|
||||
```nyash
|
||||
let _it = py_iter(xs);
|
||||
let _broken=false;
|
||||
loop {
|
||||
let _n = py_next(_it) catch StopIteration { break };
|
||||
x = _n;
|
||||
...
|
||||
if cond { _broken=true; break }
|
||||
}
|
||||
if !_broken { else_block }
|
||||
```
|
||||
|
||||
### With
|
||||
Evaluate mgr, call `__enter__`, bind val; try body; on exception, call `__exit__(type,e,tb)` and suppress if returns true; finally call `__exit__(None,None,None)` when no exception.
|
||||
|
||||
### Decorators
|
||||
```nyash
|
||||
let f = <def>;
|
||||
f = decoN(...(deco1(f)));
|
||||
name = f
|
||||
```
|
||||
|
||||
## Why Nyash Script First
|
||||
|
||||
- **Debuggability**: Human-readable Nyash is easier to inspect, diff, and map errors to; source maps stay small and precise.
|
||||
- **Optimization leverage**: Nyash compiler/MIR can keep improving independently; your Python frontend benefits automatically.
|
||||
- **Ecosystem fit**: Generates idiomatic Nyash that other tools (formatters, linters, analyzers) can understand; fosters a consistent DX.
|
||||
@ -0,0 +1,72 @@
|
||||
# Gemini先生の分析:Python→Nyashトランスパイルの「面白さ」と「可能性」
|
||||
|
||||
2025-08-30 - Geminiによる深い洞察
|
||||
|
||||
## 1. 創造的な活用方法 - 「ハイブリッドプログラミング」の新しい形
|
||||
|
||||
このアプローチの最大の面白さは、**PythonとNyashの境界を曖昧にし、両者の長所を自在に組み合わせられる「ハイブリッドプログラミング」環境**が生まれる点にあります。
|
||||
|
||||
### パフォーマンスの「目利き」チューニング
|
||||
開発者はまず、書き慣れたPythonで迅速にプロトタイプを構築します。パフォーマンスが問題になる箇所だけ、トランスパイルされたNyashコードを覗き見ます。「なるほど、このリスト内包表記はこういうループになるのか。ここをNyashの並列処理機能に書き換えれば速くなりそうだ」といった具合に、**生成されたコードを"最適化のためのヒント"として活用**し、手動で高性能なNyashコードに置き換えることができます。これは、Pythonの手軽さとネイティブの速度を、開発者が主体的にコントロールできる、非常に楽しいプロセスです。
|
||||
|
||||
### Nyashを操るためのDSL(ドメイン固有言語)としてPythonを使う
|
||||
Pythonの強力なメタプログラミング能力(デコレータ、AST操作など)を使い、「Nyashコードジェネレータ」をPythonで記述できます。例えば、特定の計算パターンを最適化するNyashコードを生成するPythonデコレータを作るのはどうでしょう。
|
||||
|
||||
```python
|
||||
# このデコレータがNyashのSIMD命令を使うコードを生成する
|
||||
@nyash.vectorize
|
||||
def python_function(a, b):
|
||||
return a + b
|
||||
```
|
||||
|
||||
このように、Pythonの簡潔な記述から、裏では非常に複雑で高性能なNyashコードが生成される。これはまさに、**Pythonを「Nyashのための高級マクロ言語」として使う**創造的なハックです。
|
||||
|
||||
### 動的なコード生成と実行
|
||||
実行時にPythonコード文字列を生成し、それをNyashにトランスパイルして即座にネイティブ実行する、といった芸当も可能です。これにより、設定ファイルやユーザー入力に基づいて動的に高性能な処理ロジックを組み立てるような、柔軟なアプリケーションが実現できます。
|
||||
|
||||
## 2. 言語進化への影響 - 共進化するエコシステム
|
||||
|
||||
この方式は、一方的な変換ではなく、両言語が互いに影響を与え合う「共進化」の触媒となります。
|
||||
|
||||
### Nyashへのフィードバック
|
||||
Pythonの標準的なイディオム(例: `with`文、ジェネレータ、リスト内包表記)をNyashに変換する際、「どうもしっくりくる表現がNyashにない」「もっとエレガントに書ける構文が欲しい」という課題が必ず見つかります。これは、**Pythonという巨大なユースケースからNyashが学ぶ絶好の機会**です。このフィードバックループが、Nyashをより表現力豊かで実用的な言語へと進化させます。
|
||||
|
||||
### Pythonコミュニティへの影響
|
||||
「この書き方をすれば、Nyashで速くなる」という知見が広まると、Pythonプログラマーの中に**「Nyash-aware」なコーディングスタイル**が生まれる可能性があります。これは、Pythonのサブセットや方言のようなもので、パフォーマンスを意識した新しいPythonの書き方として定着するかもしれません。Pythonのコードが、静的解析や型ヒントだけでなく、「ネイティブ変換効率」という新しい評価軸を持つようになります。
|
||||
|
||||
## 3. 実装の優雅さ - 「AST to AST」という美しい設計
|
||||
|
||||
トランスパイラの内部実装そのものにも、開発者を楽しませるエレガントなパターンが存在します。
|
||||
|
||||
### AST(抽象構文木)レベルでの変換
|
||||
最もクリーンな実装は、Pythonの`ast`モジュールでソースコードをASTに変換し、そのASTの各ノードを再帰的に辿りながら、対応するNyashのASTノードを構築していく方法です。これは、文字列置換のような場当たり的な方法とは異なり、非常に構造的で堅牢です。Pythonの`for`ループのASTノードが、Nyashの`for`ループのASTノードに1対1で対応付けられる様は、パズルを解くような知的な面白さがあります。
|
||||
|
||||
### 変換パターンの分離と合成
|
||||
Pythonの各構文要素(関数定義、if文、クラスなど)に対応する変換ロジックを、それぞれ独立した小さな関数やクラスとして実装します。これにより、トランスパイラ全体の見通しが良くなり、テストも容易になります。新しい構文への対応も、新しい変換パターンを追加するだけで済みます。このモジュール性は、大規模なソフトウェアを設計する上での美しさそのものです。
|
||||
|
||||
## 4. 教育的インパクト - 生きた「コンパイラ入門」
|
||||
|
||||
このツールは、プログラミング学習者にとって最高の教材となり得ます。
|
||||
|
||||
### 概念の可視化
|
||||
「高級言語の裏側では、実際にはもっと低レベルな処理が行われている」というコンピュータサイエンスの基本概念を、これ以上なく明確に示せます。Pythonのたった1行が、Nyashの数行のコードに展開されるのを見ることで、抽象化のコストとメリットを直感的に理解できます。
|
||||
|
||||
### 言語間の「ロゼッタストーン」
|
||||
PythonとNyashという2つの言語の思考様式の違いを学ぶための、動的な「ロゼッタストーン」になります。「Pythonの辞書は、Nyashではハッシュマップとしてこう表現されるのか」「Pythonの動的型付けは、Nyashの型推論によってこう解決されるのか」といった発見は、学習者にとって大きな喜びとなるでしょう。
|
||||
|
||||
### インタラクティブな学習環境
|
||||
Web上で、左にPython、右にリアルタイムで変換されたNyashコードが表示されるような「Nyash Playground」を作れば、非常に人気の出る学習ツールになるはずです。
|
||||
|
||||
## 5. 長期的な展望 - 5年後、10年後の可能性
|
||||
|
||||
このアプローチは、短期的な実装の容易さだけでなく、長期的に大きな可能性を秘めています。
|
||||
|
||||
### 5年後: Pythonエコシステムのシームレスな高速化
|
||||
トランスパイラの完成度が高まり、主要なPythonライブラリ(NumPy, Pandasの一部など)をNyashに変換できるようになっているかもしれません。`pip install`するだけで、内部的にNyashへ変換・コンパイルされ、ユーザーは意識することなくPythonコードのままネイティブの速度を手に入れる、という未来が考えられます。Pythonの型ヒントが、単なる静的解析のためだけでなく、**Nyashへの最適化コンパイルのための重要なヒント**として活用されているでしょう。
|
||||
|
||||
### 10年後: 「ハイブリッド言語」としての地位確立
|
||||
PythonとNyashの関係は、TypeScriptとJavaScriptの関係に似たものになっているかもしれません。開発者は、プロジェクトの大部分をPythonで書き、パフォーマンスクリティカルな部分はNyashで書く、あるいはPythonで書いたものをトランスパイルして微調整する、という開発スタイルが当たり前になっている可能性があります。Nyashは「Pythonをネイティブ速度で動かすための最高のパートナー言語」としての地位を確立し、両言語は互いに補完し合う強力なエコシステムを形成しているでしょう。最終的には、**Pythonの書きやすさと、ネイティブコードの実行性能を両立させた、究極のスクリプト環境**が実現しているかもしれません。
|
||||
|
||||
## まとめ
|
||||
|
||||
B案(トランスパイル方式)は、単に技術的に堅実なだけでなく、開発者の知的好奇心を刺激し、言語コミュニティ全体を巻き込んで成長していく「面白さ」と「可能性」に満ちた選択です。生成されたNyashコードが「ブラックボックス」ではなく「ホワイトボックス」であることが、デバッグ、最適化、学習、そして未来の創造的なハックへと繋がる鍵となります。この選択は、Nyashプロジェクトの成功に大きく貢献する戦略的な一手だと確信します。
|
||||
295
docs/phases/phase-10.7/examples.md
Normal file
295
docs/phases/phase-10.7/examples.md
Normal file
@ -0,0 +1,295 @@
|
||||
# Python Native実装例
|
||||
|
||||
## 🎯 実装イメージ
|
||||
|
||||
### 使用例1: 基本的な関数のネイティブ化
|
||||
|
||||
```nyash
|
||||
// example1_basic.nyash
|
||||
// Pythonコードをネイティブコンパイル
|
||||
|
||||
// Step 1: Pythonコードを用意
|
||||
code = """
|
||||
def fibonacci(n):
|
||||
if n <= 1:
|
||||
return n
|
||||
return fibonacci(n-1) + fibonacci(n-2)
|
||||
|
||||
def factorial(n):
|
||||
if n == 0:
|
||||
return 1
|
||||
return n * factorial(n-1)
|
||||
"""
|
||||
|
||||
// Step 2: パース
|
||||
parser = new PythonParserBox()
|
||||
ast = parser.parse(code)
|
||||
print("Parsed functions: " + parser.getStats().get("functions"))
|
||||
|
||||
// Step 3: コンパイル
|
||||
compiler = new PythonCompilerBox()
|
||||
mir_module = compiler.compile(ast)
|
||||
|
||||
// Step 4: 実行
|
||||
if mir_module.isOk() {
|
||||
// ネイティブ実行!
|
||||
module = mir_module.get()
|
||||
|
||||
// 関数を取得して実行
|
||||
fib = module.getFunction("fibonacci")
|
||||
result = fib.call(10)
|
||||
print("fibonacci(10) = " + result) // 55
|
||||
|
||||
fact = module.getFunction("factorial")
|
||||
result = fact.call(5)
|
||||
print("factorial(5) = " + result) // 120
|
||||
} else {
|
||||
print("Compilation failed: " + mir_module.getError())
|
||||
}
|
||||
```
|
||||
|
||||
### 使用例2: コンパイル可否の明確な判定
|
||||
|
||||
```nyash
|
||||
// example2_clear_separation.nyash
|
||||
// コンパイルできるかどうか事前に判定
|
||||
|
||||
// Phase 1対応のコード
|
||||
code_phase1 = """
|
||||
def compute_sum(n):
|
||||
total = 0
|
||||
for i in range(n):
|
||||
total += i * i
|
||||
return total
|
||||
|
||||
def factorial(n):
|
||||
if n == 0:
|
||||
return 1
|
||||
return n * factorial(n-1)
|
||||
"""
|
||||
|
||||
// Phase 1未対応のコード
|
||||
code_unsupported = """
|
||||
def fibonacci_generator(n):
|
||||
a, b = 0, 1
|
||||
for _ in range(n):
|
||||
yield a
|
||||
a, b = b, a + b
|
||||
"""
|
||||
|
||||
// コンパイラーで判定
|
||||
parser = new PythonParserBox()
|
||||
compiler = new PythonCompilerBox()
|
||||
|
||||
// Phase 1対応コードのチェック
|
||||
ast1 = parser.parse(code_phase1)
|
||||
result1 = compiler.compile(ast1)
|
||||
if result1.isOk() {
|
||||
print("✅ Phase 1 code compiled successfully!")
|
||||
module = result1.get()
|
||||
print("compute_sum(100) = " + module.call("compute_sum", 100))
|
||||
} else {
|
||||
print("❌ Compilation failed: " + result1.getError())
|
||||
}
|
||||
|
||||
// 未対応コードのチェック
|
||||
ast2 = parser.parse(code_unsupported)
|
||||
result2 = compiler.compile(ast2)
|
||||
if result2.isOk() {
|
||||
print("✅ Compiled successfully!")
|
||||
} else {
|
||||
print("❌ Cannot compile: " + result2.getError())
|
||||
print(" Reason: yield expression not supported in Phase 1")
|
||||
print(" Please use PyRuntimeBox instead")
|
||||
}
|
||||
```
|
||||
|
||||
### 使用例3: プログレッシブ最適化
|
||||
|
||||
```nyash
|
||||
// example3_progressive.nyash
|
||||
// 実行しながら徐々に最適化
|
||||
|
||||
// 型推論付きコンパイラー
|
||||
compiler = new PythonCompilerBox()
|
||||
compiler.enableTypeInference(true)
|
||||
compiler.enableProfiling(true)
|
||||
|
||||
// 初回実行(型情報収集)
|
||||
code = """
|
||||
def matrix_multiply(A, B):
|
||||
# 最初は型が不明
|
||||
result = []
|
||||
for i in range(len(A)):
|
||||
row = []
|
||||
for j in range(len(B[0])):
|
||||
sum = 0
|
||||
for k in range(len(B)):
|
||||
sum += A[i][k] * B[k][j]
|
||||
row.append(sum)
|
||||
result.append(row)
|
||||
return result
|
||||
"""
|
||||
|
||||
// プロファイル付き実行
|
||||
for i in range(5) {
|
||||
mir = compiler.compile(parser.parse(code))
|
||||
|
||||
// 実行してプロファイル収集
|
||||
module = mir.get()
|
||||
A = [[1, 2], [3, 4]]
|
||||
B = [[5, 6], [7, 8]]
|
||||
result = module.call("matrix_multiply", A, B)
|
||||
|
||||
// 型情報が蓄積される
|
||||
print("Iteration " + i + ": ")
|
||||
print(" Type confidence: " + compiler.getTypeConfidence())
|
||||
print(" Optimization level: " + compiler.getOptimizationLevel())
|
||||
}
|
||||
|
||||
// 5回実行後、完全に最適化されたコードが生成される
|
||||
```
|
||||
|
||||
### 使用例4: 言語間相互運用
|
||||
|
||||
```nyash
|
||||
// example4_interop.nyash
|
||||
// PythonコードとNyashコードのシームレスな連携
|
||||
|
||||
// Pythonで数値計算関数を定義
|
||||
python_math = """
|
||||
import math
|
||||
|
||||
def distance(x1, y1, x2, y2):
|
||||
return math.sqrt((x2-x1)**2 + (y2-y1)**2)
|
||||
|
||||
def normalize(vector):
|
||||
magnitude = math.sqrt(sum(x**2 for x in vector))
|
||||
return [x/magnitude for x in vector]
|
||||
"""
|
||||
|
||||
// コンパイルしてNyashから使用
|
||||
module = compile_python(python_math)
|
||||
|
||||
// Nyash側のゲームロジック
|
||||
box GameObject {
|
||||
init { x, y, vx, vy }
|
||||
|
||||
update(dt) {
|
||||
// Python関数をネイティブ速度で呼び出し
|
||||
me.x = me.x + me.vx * dt
|
||||
me.y = me.y + me.vy * dt
|
||||
|
||||
// 正規化(Pythonの関数を使用)
|
||||
local normalized = module.normalize([me.vx, me.vy])
|
||||
me.vx = normalized[0]
|
||||
me.vy = normalized[1]
|
||||
}
|
||||
|
||||
distanceTo(other) {
|
||||
// Pythonの距離計算関数を使用
|
||||
return module.distance(me.x, me.y, other.x, other.y)
|
||||
}
|
||||
}
|
||||
|
||||
// 完全にネイティブコードとして実行される!
|
||||
```
|
||||
|
||||
### 使用例5: デバッグとプロファイリング
|
||||
|
||||
```nyash
|
||||
// example5_debug.nyash
|
||||
// 開発時のデバッグ支援
|
||||
|
||||
// デバッグモード有効
|
||||
parser = new PythonParserBox()
|
||||
parser.enableDebug(true)
|
||||
|
||||
compiler = new PythonCompilerBox()
|
||||
compiler.enableDebug(true)
|
||||
compiler.enableSourceMap(true) // 元のPythonコードへのマッピング
|
||||
|
||||
problematic_code = """
|
||||
def buggy_function(items):
|
||||
total = 0
|
||||
for item in items:
|
||||
# バグ: itemが文字列の場合エラー
|
||||
total += item * 2
|
||||
return total / len(items)
|
||||
"""
|
||||
|
||||
// コンパイル試行
|
||||
result = compiler.compile(parser.parse(problematic_code))
|
||||
|
||||
if result.isErr() {
|
||||
// 詳細なエラー情報
|
||||
diag = compiler.getDiagnostics()
|
||||
print("Compilation failed at line " + diag.line)
|
||||
print("Issue: " + diag.message)
|
||||
print("Suggestion: " + diag.suggestion)
|
||||
|
||||
// フォールバックで実行してランタイムエラーを確認
|
||||
runtime = new PythonRuntimeBox()
|
||||
try {
|
||||
runtime.exec(problematic_code)
|
||||
runtime.call("buggy_function", ["a", "b", "c"])
|
||||
} catch (e) {
|
||||
print("Runtime error: " + e.message)
|
||||
print("This would have been caught at compile time!")
|
||||
}
|
||||
}
|
||||
|
||||
// プロファイリング情報
|
||||
profiler = new PythonProfiler()
|
||||
profiler.attach(module)
|
||||
profiler.run()
|
||||
|
||||
print("Hot spots:")
|
||||
print(profiler.getHotSpots())
|
||||
print("Type instability:")
|
||||
print(profiler.getTypeInstability())
|
||||
```
|
||||
|
||||
## 🎯 実装の進化
|
||||
|
||||
### Phase 1(現在)
|
||||
```python
|
||||
# これらがネイティブ化可能
|
||||
def add(x, y): return x + y
|
||||
def factorial(n): ...
|
||||
def fibonacci(n): ...
|
||||
```
|
||||
|
||||
### Phase 2(予定)
|
||||
```python
|
||||
# 特殊メソッド対応
|
||||
class Vector:
|
||||
def __add__(self, other): ...
|
||||
def __len__(self): ...
|
||||
|
||||
# 内包表記
|
||||
squares = [x**2 for x in range(10)]
|
||||
```
|
||||
|
||||
### Phase 3(将来)
|
||||
```python
|
||||
# 完全な言語機能
|
||||
async def fetch_data(): ...
|
||||
@decorator
|
||||
def enhanced_function(): ...
|
||||
yield from generator
|
||||
```
|
||||
|
||||
## 🚀 パフォーマンス期待値
|
||||
|
||||
```
|
||||
Benchmark: Fibonacci(30)
|
||||
CPython: 1.234s
|
||||
PyPy: 0.123s
|
||||
Nyash Native: 0.012s (100x faster!)
|
||||
|
||||
Benchmark: Matrix Multiplication (100x100)
|
||||
CPython: 5.678s
|
||||
NumPy: 0.234s
|
||||
Nyash Native: 0.198s (NumPyに匹敵!)
|
||||
```
|
||||
249
docs/phases/phase-10.7/implementation.md
Normal file
249
docs/phases/phase-10.7/implementation.md
Normal file
@ -0,0 +1,249 @@
|
||||
# Phase 10.7 実装詳細
|
||||
|
||||
## 🛠️ 技術アーキテクチャ
|
||||
|
||||
### 2段階変換パイプライン
|
||||
|
||||
```
|
||||
Python AST → CorePy IR → Nyash AST → Nyashスクリプト
|
||||
```
|
||||
|
||||
**CorePy IR**の役割:
|
||||
- Pythonの複雑な構文を正規化
|
||||
- セマンティクスを明示的に(with→try/finally等)
|
||||
- 最適化しやすい中間表現
|
||||
|
||||
### 実装構造
|
||||
|
||||
```rust
|
||||
// plugins/nyash-python-parser-plugin/src/lib.rs
|
||||
#[plugin_box]
|
||||
pub struct PythonParserBox {
|
||||
base: BoxBase,
|
||||
}
|
||||
|
||||
#[plugin_methods]
|
||||
impl PythonParserBox {
|
||||
pub fn parse(&self, code: &str) -> Result<Box<dyn NyashBox>> {
|
||||
Python::with_gil(|py| {
|
||||
let ast_mod = py.import("ast")?;
|
||||
let tree = ast_mod.call_method1("parse", (code,))?;
|
||||
Ok(self.convert_ast(tree)?)
|
||||
})
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📐 Python固有機能の実装戦略
|
||||
|
||||
### 1. デフォルト引数の罠
|
||||
|
||||
```python
|
||||
# Python: 定義時に一度だけ評価
|
||||
def bad_default(lst=[]):
|
||||
lst.append(1)
|
||||
return lst
|
||||
```
|
||||
|
||||
```nyash
|
||||
// 生成されるNyash
|
||||
box GeneratedModule {
|
||||
init { _default_lst }
|
||||
|
||||
constructor() {
|
||||
me._default_lst = new ArrayBox() // 定義時に一度だけ
|
||||
}
|
||||
|
||||
bad_default(lst) {
|
||||
if lst == null {
|
||||
lst = me._default_lst // 同じインスタンスを再利用!
|
||||
}
|
||||
lst.append(1)
|
||||
return lst
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. LEGB スコーピング
|
||||
|
||||
```python
|
||||
# Local → Enclosing → Global → Builtin
|
||||
global_var = 1
|
||||
def outer():
|
||||
enclosing_var = 2
|
||||
def inner():
|
||||
local_var = 3
|
||||
```
|
||||
|
||||
実装:
|
||||
- シンボルテーブルでスコープ管理
|
||||
- クロージャはBox/Cellで実装
|
||||
- global/nonlocalフラグを追跡
|
||||
|
||||
### 3. for/else, while/else
|
||||
|
||||
```python
|
||||
for i in range(10):
|
||||
if i == 5:
|
||||
break
|
||||
else:
|
||||
print("No break")
|
||||
```
|
||||
|
||||
```nyash
|
||||
// 生成されるNyash
|
||||
local _broken = false
|
||||
local _iter = py_iter(range(10))
|
||||
loop(true) {
|
||||
local _next = py_next(_iter)
|
||||
if _next.isStopIteration() { break }
|
||||
local i = _next.value
|
||||
|
||||
if i == 5 {
|
||||
_broken = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if not _broken {
|
||||
print("No break")
|
||||
}
|
||||
```
|
||||
|
||||
## 🔧 パスパイプライン
|
||||
|
||||
```
|
||||
Parse Python AST
|
||||
↓
|
||||
Symbol table analysis
|
||||
↓
|
||||
Normalize to CorePy IR
|
||||
↓
|
||||
Scope/closure analysis
|
||||
↓
|
||||
Type metadata attachment
|
||||
↓
|
||||
Lower to Nyash AST
|
||||
↓
|
||||
Peephole optimization
|
||||
↓
|
||||
Pretty-print + source map
|
||||
```
|
||||
|
||||
## 📊 最適化戦略
|
||||
|
||||
### トランスパイル時の最適化
|
||||
- 定数畳み込み
|
||||
- ループ不変式の巻き上げ
|
||||
- ビルトイン関数の直接呼び出し(シャドウイングなし時)
|
||||
- 冗長な`py_truthy()`の除去
|
||||
|
||||
### Nyashコンパイラに委ねる最適化
|
||||
- インライン展開
|
||||
- レジスタ割り当て
|
||||
- ループアンローリング
|
||||
- ベクトル化
|
||||
|
||||
### 型情報の活用
|
||||
```python
|
||||
def add(x: int, y: int) -> int:
|
||||
return x + y
|
||||
```
|
||||
→ 型ヒントがあれば`py_binop`ではなく直接整数演算
|
||||
|
||||
## 🐛 エラー処理とデバッグ
|
||||
|
||||
### ソースマップ
|
||||
```json
|
||||
{
|
||||
"version": 3,
|
||||
"sources": ["example.py"],
|
||||
"mappings": "AAAA,IAAM,CAAC,GAAG...",
|
||||
"names": ["add", "x", "y"]
|
||||
}
|
||||
```
|
||||
|
||||
### デバッグモード
|
||||
```bash
|
||||
nyash-transpile --debug example.py
|
||||
# 出力:
|
||||
# - CorePy IRダンプ
|
||||
# - Nyashプレビュー(元のPython行ヒント付き)
|
||||
# - 変換トレース
|
||||
```
|
||||
|
||||
### エラーメッセージ
|
||||
```
|
||||
ERROR: Cannot compile function 'async_func' at line 10
|
||||
Reason: async/await not supported in Phase 1
|
||||
AST Node: AsyncFunctionDef
|
||||
Suggestion: Use PyRuntimeBox or wait for Phase 3
|
||||
```
|
||||
|
||||
## ⚡ パフォーマンス最適化
|
||||
|
||||
### ホットパス識別
|
||||
```nyash
|
||||
// プロファイル情報を活用
|
||||
if compiler.isHotPath(func) {
|
||||
// 積極的な最適化
|
||||
result = compiler.optimizeAggressive(func)
|
||||
} else {
|
||||
// 標準的な変換
|
||||
result = compiler.compile(func)
|
||||
}
|
||||
```
|
||||
|
||||
### JIT連携
|
||||
```nyash
|
||||
// 型特化コード生成
|
||||
@jit_specialize(int, int)
|
||||
def add(x, y):
|
||||
return x + y
|
||||
```
|
||||
|
||||
## 🔌 プラグインAPI
|
||||
|
||||
### 変換フック
|
||||
```rust
|
||||
trait TransformHook {
|
||||
fn before_lower(&mut self, node: &CorePyNode);
|
||||
fn after_lower(&mut self, node: &NyashNode);
|
||||
fn on_function(&mut self, func: &FunctionDef);
|
||||
}
|
||||
```
|
||||
|
||||
### カスタムルール
|
||||
```yaml
|
||||
# custom_rules.yaml
|
||||
rules:
|
||||
- pattern: "dataclass"
|
||||
action: "convert_to_nyash_box"
|
||||
- pattern: "numpy.array"
|
||||
action: "use_native_array"
|
||||
```
|
||||
|
||||
## 📋 実装チェックリスト
|
||||
|
||||
### Phase 1(必須)
|
||||
- [ ] 関数定義(def)
|
||||
- [ ] 条件分岐(if/elif/else)
|
||||
- [ ] ループ(for/while with else)
|
||||
- [ ] 基本演算子
|
||||
- [ ] 関数呼び出し
|
||||
- [ ] return/break/continue
|
||||
- [ ] LEGB スコーピング
|
||||
- [ ] デフォルト引数
|
||||
|
||||
### Phase 2(拡張)
|
||||
- [ ] 例外処理(try/except/finally)
|
||||
- [ ] with文
|
||||
- [ ] list/dict/set comprehensions
|
||||
- [ ] lambda式
|
||||
- [ ] *args, **kwargs
|
||||
|
||||
### Phase 3(高度)
|
||||
- [ ] async/await
|
||||
- [ ] yield/yield from
|
||||
- [ ] デコレータ
|
||||
- [ ] クラス定義(基本)
|
||||
- [ ] import文
|
||||
285
docs/phases/phase-10.7/testing-plan.md
Normal file
285
docs/phases/phase-10.7/testing-plan.md
Normal file
@ -0,0 +1,285 @@
|
||||
# Python Native Testing Plan
|
||||
|
||||
## 🎯 テスト戦略の全体像
|
||||
|
||||
「世界中のPythonコードがNyashのテストケース」という思想のもと、CPythonをオラクルとして使用する包括的なテスト戦略。
|
||||
|
||||
## 🧪 テストレベル
|
||||
|
||||
### 1. プラグインレベルテスト
|
||||
|
||||
#### PythonParserBox Tests
|
||||
```rust
|
||||
// plugins/nyash-python-parser-plugin/tests/parser_tests.rs
|
||||
#[test]
|
||||
fn test_parse_simple_function() {
|
||||
let parser = create_parser_box();
|
||||
let code = "def add(x, y): return x + y";
|
||||
let ast = parser.parse(create_string_box(code));
|
||||
|
||||
assert_eq!(ast.get_type().to_string(), "Module");
|
||||
let functions = ast.get_children();
|
||||
assert_eq!(functions.length(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_with_telemetry() {
|
||||
let parser = create_parser_box();
|
||||
parser.enable_telemetry(true);
|
||||
|
||||
let code = r#"
|
||||
def supported(): return 1
|
||||
async def unsupported(): await foo()
|
||||
"#;
|
||||
|
||||
parser.parse(create_string_box(code));
|
||||
let stats = parser.get_stats();
|
||||
|
||||
assert_eq!(stats.get("total_functions"), 2);
|
||||
assert_eq!(stats.get("supported_functions"), 1);
|
||||
}
|
||||
```
|
||||
|
||||
#### PythonCompilerBox Tests
|
||||
```rust
|
||||
#[test]
|
||||
fn test_compile_arithmetic() {
|
||||
let compiler = create_compiler_box();
|
||||
let ast = /* ... */;
|
||||
|
||||
let mir = compiler.compile(ast);
|
||||
assert!(mir.is_ok());
|
||||
|
||||
// MIR検証
|
||||
let module = mir.unwrap();
|
||||
assert!(module.has_function("add"));
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Differential Testing Framework
|
||||
|
||||
```nyash
|
||||
// tests/differential/framework.nyash
|
||||
box DifferentialTester {
|
||||
init { oracle, implementation, results }
|
||||
|
||||
constructor() {
|
||||
me.oracle = new PythonRuntimeBox() // CPython
|
||||
me.implementation = new NativeEngine()
|
||||
me.results = new ArrayBox()
|
||||
}
|
||||
|
||||
test(code) {
|
||||
local oracle_result, impl_result
|
||||
|
||||
// CPythonで実行
|
||||
oracle_result = me.oracle.eval(code)
|
||||
|
||||
// Native実装で実行
|
||||
impl_result = me.implementation.exec(code)
|
||||
|
||||
// 結果比較
|
||||
return me.compare(oracle_result, impl_result)
|
||||
}
|
||||
|
||||
compare(expected, actual) {
|
||||
// 出力、戻り値、例外を比較
|
||||
local match = new MapBox()
|
||||
match.set("output", expected.output == actual.output)
|
||||
match.set("return", expected.return == actual.return)
|
||||
match.set("exception", expected.exception == actual.exception)
|
||||
return match
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. テストケース生成
|
||||
|
||||
#### 基本テストスイート
|
||||
```python
|
||||
# tests/suites/phase1_tests.py
|
||||
|
||||
# 算術演算
|
||||
def test_arithmetic():
|
||||
assert add(2, 3) == 5
|
||||
assert multiply(4, 5) == 20
|
||||
assert divide(10, 2) == 5.0 # true division
|
||||
|
||||
# 制御フロー
|
||||
def test_control_flow():
|
||||
# if/else
|
||||
result = conditional_logic(True, 10, 20)
|
||||
assert result == 10
|
||||
|
||||
# for/else
|
||||
found = search_with_else([1, 2, 3], 5)
|
||||
assert found == "not found" # else節実行
|
||||
|
||||
# デフォルト引数の罠
|
||||
def test_default_args():
|
||||
list1 = append_to_default(1)
|
||||
list2 = append_to_default(2)
|
||||
assert list1 is list2 # 同じリスト!
|
||||
```
|
||||
|
||||
#### Fuzzing with Hypothesis
|
||||
```python
|
||||
# tests/fuzzing/property_tests.py
|
||||
from hypothesis import given, strategies as st
|
||||
|
||||
@given(st.integers(), st.integers())
|
||||
def test_arithmetic_properties(x, y):
|
||||
"""算術演算の性質をテスト"""
|
||||
# Commutativity
|
||||
assert add(x, y) == add(y, x)
|
||||
|
||||
# Identity
|
||||
assert add(x, 0) == x
|
||||
|
||||
# Differential testing
|
||||
native_result = native_add(x, y)
|
||||
cpython_result = x + y
|
||||
assert native_result == cpython_result
|
||||
```
|
||||
|
||||
### 4. ベンチマークスイート
|
||||
|
||||
```nyash
|
||||
// benchmarks/numeric_suite.nyash
|
||||
box NumericBenchmark {
|
||||
run() {
|
||||
local suite = new BenchmarkSuite()
|
||||
|
||||
// Fibonacci
|
||||
suite.add("fibonacci", {
|
||||
"cpython": { return me.runCPython("fib.py") },
|
||||
"native": { return me.runNative("fib.py") }
|
||||
})
|
||||
|
||||
// Matrix multiplication
|
||||
suite.add("matrix_mult", {
|
||||
"cpython": { return me.runCPython("matrix.py") },
|
||||
"native": { return me.runNative("matrix.py") }
|
||||
})
|
||||
|
||||
return suite.execute()
|
||||
}
|
||||
}
|
||||
|
||||
// 実行結果例
|
||||
// fibonacci:
|
||||
// CPython: 1.234s
|
||||
// Native: 0.123s (10.0x faster)
|
||||
// matrix_mult:
|
||||
// CPython: 5.678s
|
||||
// Native: 0.456s (12.4x faster)
|
||||
```
|
||||
|
||||
### 5. 回帰テスト
|
||||
|
||||
```yaml
|
||||
# .github/workflows/python-native-tests.yml
|
||||
name: Python Native Tests
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Differential Tests
|
||||
run: |
|
||||
cargo test --package nyash-python-parser-plugin
|
||||
cargo test --package nyash-python-compiler-plugin
|
||||
|
||||
- name: Coverage Report
|
||||
run: |
|
||||
./tools/measure_compilation_coverage.sh
|
||||
# Expected output:
|
||||
# Phase 1 compatible files: 15%
|
||||
# Phase 2 functions: 40% compilable
|
||||
# Phase 3 functions: 10% compilable
|
||||
```
|
||||
|
||||
## 📊 メトリクス収集
|
||||
|
||||
### コンパイル成功率
|
||||
```nyash
|
||||
// 自動計測ツール
|
||||
box CoverageAnalyzer {
|
||||
analyze(directory) {
|
||||
local parser = new PythonParserBox()
|
||||
local compiler = new PythonCompilerBox()
|
||||
local stats = new MapBox()
|
||||
|
||||
for file in directory.glob("*.py") {
|
||||
local ast = parser.parseFile(file)
|
||||
local result = compiler.compile(ast)
|
||||
|
||||
stats.increment("total")
|
||||
if result.isOk() {
|
||||
stats.increment("success")
|
||||
} else {
|
||||
stats.increment("not_compilable")
|
||||
stats.record("unsupported", result.getError())
|
||||
}
|
||||
}
|
||||
|
||||
return stats
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### パフォーマンス追跡
|
||||
```sql
|
||||
-- メトリクスDB
|
||||
CREATE TABLE benchmark_results (
|
||||
id SERIAL PRIMARY KEY,
|
||||
test_name VARCHAR(255),
|
||||
implementation VARCHAR(50), -- 'cpython' or 'native'
|
||||
execution_time FLOAT,
|
||||
memory_usage BIGINT,
|
||||
timestamp TIMESTAMP,
|
||||
git_hash VARCHAR(40)
|
||||
);
|
||||
```
|
||||
|
||||
## 🚨 失敗時の診断
|
||||
|
||||
### デバッグ情報収集
|
||||
```nyash
|
||||
// コンパイル失敗時の詳細情報
|
||||
compiler.enableDebug(true)
|
||||
result = compiler.compile(ast)
|
||||
|
||||
if result.isErr() {
|
||||
local diag = compiler.getDiagnostics()
|
||||
print("Failed at: " + diag.get("location"))
|
||||
print("Reason: " + diag.get("reason"))
|
||||
print("AST node: " + diag.get("node_type"))
|
||||
print("Suggestion: " + diag.get("suggestion"))
|
||||
}
|
||||
```
|
||||
|
||||
### トレース機能
|
||||
```
|
||||
NYASH_PYTHON_TRACE=1 ./target/release/nyash test.py
|
||||
[Parser] Parsing function 'compute' at line 5
|
||||
[Compiler] Compiling BinOp: Add at line 7
|
||||
[Compiler] Unsupported: YieldFrom at line 15
|
||||
[Error] Cannot compile function 'generator_func' - yield not supported
|
||||
```
|
||||
|
||||
## ✅ 受け入れ基準
|
||||
|
||||
### Phase 1完了
|
||||
- [ ] 基本テストスイート100%パス
|
||||
- [ ] Differential testing 100%一致
|
||||
- [ ] Phase 1対応コードの100%コンパイル成功
|
||||
- [ ] 10x性能向上(数値計算ベンチマーク)
|
||||
|
||||
### 各PR必須
|
||||
- [ ] 新機能の単体テスト
|
||||
- [ ] Differential testケース追加
|
||||
- [ ] ベンチマーク結果(該当する場合)
|
||||
- [ ] カバレッジ低下なし
|
||||
13
docs/phases/phase-10.7/workbench/DECISIONS.md
Normal file
13
docs/phases/phase-10.7/workbench/DECISIONS.md
Normal file
@ -0,0 +1,13 @@
|
||||
# DECISIONS (Phase 10.7)
|
||||
|
||||
## 2025-08-30 — 二本立て運用(決定)
|
||||
- 決定: 現行の実行系(PyRuntimeBox, Plugin-First)は維持し、トランスパイル系(Python→Nyash)は All-or-Nothing で併走。
|
||||
- 代替案: トランスパイルの部分フォールバック(実行時にPyRuntimeへ落とす)。
|
||||
- 理由: 実行時の不一致/隠れ分岐を避ける。デプロイ時の挙動を単純に保つ。
|
||||
- 影響: 生成Nyashの品質責任はトランスパイラ側。利用者は明示的に系を選択。
|
||||
|
||||
## 2025-08-30 — Parser/CompilerもプラグインBox(決定)
|
||||
- 決定: PythonParserBox/PythonCompilerBox としてプラグイン化し、CLIから呼び出す。
|
||||
- 代替案: コア組込み。
|
||||
- 理由: Plugin-First原則、配布容易性、差し替え性、隔離テスト。
|
||||
- 影響: plugins/ 以下に新規プラグインを追加。SDKの最小拡張が必要になる場合あり。
|
||||
39
docs/phases/phase-10.7/workbench/IR_SCHEMA_MIN.md
Normal file
39
docs/phases/phase-10.7/workbench/IR_SCHEMA_MIN.md
Normal file
@ -0,0 +1,39 @@
|
||||
# CorePy IR 最小スキーマ(C2草案)
|
||||
|
||||
目的: Phase 1 の End-to-End を最短で通すための暫定IR。将来は構造化・拡張(with/try/comp/async等)。
|
||||
|
||||
## JSON 形式(暫定)
|
||||
```json
|
||||
{
|
||||
"module": {
|
||||
"functions": [
|
||||
{
|
||||
"name": "main", // 省略可(既定: "main")
|
||||
"return_value": 0, // 省略可(bodyと排他)
|
||||
"body": [ // 省略可(return_valueと排他)
|
||||
{ "Return": { "value": 0 } }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
ショートカット(デバッグ/ブリッジ用)
|
||||
```json
|
||||
{ "nyash_source": "static box Generated { main() { return 0 } }" }
|
||||
```
|
||||
|
||||
## 変換規則(最小)
|
||||
- module.functions[0] だけを見る(複数関数は将来対応)
|
||||
- name があれば `static box Generated { <name>() { ... } }`
|
||||
- return_value が数値/文字列なら `return <value>` を生成
|
||||
- body があれば先頭の Return.value を探し、`return <value>` を生成
|
||||
- 上記が無ければ `return 0`
|
||||
|
||||
## 将来(予約)
|
||||
- statements: If/While/For/Assign/Expr などの節を追加
|
||||
- expressions: BinOp/Call/Name/Constant などを構造化
|
||||
- functions配列の複数対応、クロージャは別Box化の方針を検討
|
||||
|
||||
注意: All-or-Nothing 原則のもと、未対応ノードはCompiler側で明示的にエラーにする(現段階では未実装のため、return 0にフォールバックするが、C2終盤でStrict化する)。
|
||||
21
docs/phases/phase-10.7/workbench/README.md
Normal file
21
docs/phases/phase-10.7/workbench/README.md
Normal file
@ -0,0 +1,21 @@
|
||||
# Phase 10.7 Workbench
|
||||
|
||||
このフォルダは Python Native(トランスパイル路線, All-or-Nothing)専用の作業台です。仕様・決定・スパイク・タスクをここに集約し、雑多にならないようにします。
|
||||
|
||||
構成
|
||||
- TODO.md: 直近の作業キュー(小粒で管理)
|
||||
- DECISIONS.md: 決定事項(理由/代替案/影響)
|
||||
- SPIKES/: 検証スパイクの成果(小さなPoCやプロト)
|
||||
- notes-YYYYMMDD.md: 打合せ/検討メモ(必要に応じて)
|
||||
|
||||
関連
|
||||
- 計画: ../PLAN.txt
|
||||
- 実装: ../implementation.md
|
||||
- テスト: ../testing-plan.md
|
||||
- 背景: ../README.md
|
||||
|
||||
運用ルール(最小)
|
||||
- 一度に大きくしない(5〜30分単位の成果で刻む)
|
||||
- 決定は DECISIONS.md に残す(誰でも後から辿れる)
|
||||
- スパイクは SPIKES に隔離(本流に混ぜない)
|
||||
|
||||
13
docs/phases/phase-10.7/workbench/TODO.md
Normal file
13
docs/phases/phase-10.7/workbench/TODO.md
Normal file
@ -0,0 +1,13 @@
|
||||
# TODO (Phase 10.7 Workbench)
|
||||
|
||||
短期(C1〜C3に向けた小粒タスク)
|
||||
- [ ] C1: Parser plugin 雛形スケルトンを作る(pyo3, parse(code)->AstBox/to_json)
|
||||
- [ ] C1: Telemetry最小(node種別カウント, 未対応ノード列挙)
|
||||
- [ ] C2: CorePy IR最小スキーマ(JSON)を commit(with/async系は予約)
|
||||
- [ ] C2: IR→Nyash ASTの最小変換(def/if/for/while/return/算術/比較/呼出し)
|
||||
- [ ] C3: CLI隠しフラグ prototyping(--pyc/--pyc-native)
|
||||
- [ ] Docs: PLANとimplementationの差分同期(週次)
|
||||
|
||||
メモ
|
||||
- All-or-Nothing原則:未対応は即Err(自動フォールバックなし)
|
||||
- 生成Nyashは現行AOT導線で配布可能(Strict)
|
||||
61
docs/phases/phase-10/README.md
Normal file
61
docs/phases/phase-10/README.md
Normal file
@ -0,0 +1,61 @@
|
||||
# Phase 10: JIT実装とセルフホスティング
|
||||
|
||||
## 🎯 Phase 10の全体像
|
||||
|
||||
Phase 10は、Nyashの実行性能を大幅に向上させるJIT実装と、言語の成熟度を示すセルフホスティングを実現します。
|
||||
|
||||
## 📊 実装優先順位
|
||||
|
||||
### 1️⃣ **メイン実装: Cranelift JIT**
|
||||
→ [phase_10_cranelift_jit_backend.md](phase_10_cranelift_jit_backend.md)
|
||||
- VMとのハイブリッド実行(ホットパス検出→JIT化)
|
||||
- 実装期間: 2-3ヶ月
|
||||
- 目標: ホットパスで2倍以上の高速化
|
||||
|
||||
### 🌟 **革新的機能: GC切り替え可能ランタイム**
|
||||
→ [phase_10_4_gc_switchable_runtime.md](phase_10_4_gc_switchable_runtime.md)
|
||||
- 世界初:実行時にGCモード切り替え可能
|
||||
- 開発時はGCオンで快適、本番はGCオフで高速
|
||||
- 実装期間: 2-3ヶ月(Cranelift JIT後)
|
||||
- 技術的にCodex GPT-5が実現可能性を確認済み
|
||||
|
||||
### 2️⃣ **並行プロジェクト: セルフホスティング**
|
||||
→ [phase_10_5_core_std_nyash_impl.md](phase_10_5_core_std_nyash_impl.md)
|
||||
- String/Array/MapをNyash自身で実装
|
||||
- Rust依存の段階的削減
|
||||
- 実装期間: 1-2ヶ月
|
||||
|
||||
### 3️⃣ **実戦テスト: アプリケーション移植**
|
||||
→ [phase_10_app_migration.md](phase_10_app_migration.md)
|
||||
- Tinyproxy: ゼロコピー判定機能の検証
|
||||
- Chip-8エミュレータ: fini伝播とweak参照の実戦テスト
|
||||
- kiloエディタ: メモリ効率の「うっかり全体コピー」検出
|
||||
|
||||
### 🚫 **延期プロジェクト**
|
||||
→ [Phase 11: LLVM AOT Backend](../phase-11/) - 将来の研究開発として分離
|
||||
|
||||
## 🛤️ 実装ロードマップ
|
||||
|
||||
```
|
||||
Phase 9.79b (現在)
|
||||
↓
|
||||
Phase 10.0: Cranelift JIT基盤構築
|
||||
├→ Phase 10.1-10.3: JIT実装・最適化
|
||||
├→ Phase 10.4: GC切り替え可能ランタイム ← NEW!
|
||||
└→ Phase 10.5: セルフホスティング(並行)
|
||||
↓
|
||||
Phase 10.9: アプリケーション移植で実戦検証
|
||||
↓
|
||||
Phase 11: LLVM AOT研究(将来)
|
||||
```
|
||||
|
||||
## 📈 期待される成果
|
||||
|
||||
1. **実行性能**: インタープリタ比100倍、VM比2-3倍の高速化
|
||||
2. **言語成熟度**: 基本コンテナのセルフホスティング達成
|
||||
3. **実用性検証**: 実アプリケーションの移植による実戦テスト
|
||||
|
||||
## 🔗 関連ドキュメント
|
||||
- [00_MASTER_ROADMAP.md](../00_MASTER_ROADMAP.md) - 全体計画
|
||||
- [Phase 9.79b](../phase-9/) - 統一Box設計(前提)
|
||||
- [MIR仕様](../../../../reference/mir/) - 中間表現
|
||||
94
docs/phases/phase-10/phase_10_10/README.md
Normal file
94
docs/phases/phase-10/phase_10_10/README.md
Normal file
@ -0,0 +1,94 @@
|
||||
# Phase 10.10 – Python→Nyash→MIR→VM/Native ラインの実用化整備(Box-First 継続)
|
||||
|
||||
目的: Nyash→MIR→VM/Native の実行ラインを日常運用レベルに引き上げ、GC/デバッグ/HostCallの柱を整備する。
|
||||
|
||||
## ゴール(DoD)
|
||||
- エンドツーエンド実行ライン(Parser→AST→MIR→VM→JIT)がビルトインBoxで安定(RO/一部WO)
|
||||
- GC切替(Null/Counting)をCLI/Boxから操作可能、root領域APIが一箇所化
|
||||
- デバッグ/可視化の旗振り(DebugConfig/Box)でJIT/VM/イベント/DOTを一本化
|
||||
- HostCall: 読み取り系はparam受けでJIT直実行(allow)。書き込み系はポリシー/whitelistでopt-in可能
|
||||
- 最小ベンチと回帰(サンプル)でラインの劣化を検知
|
||||
|
||||
## 事前整備(現状)
|
||||
- HostCall基盤: Registry/Policy/Events/Boundary(10.9-β/δ完了)
|
||||
- JITイベント: `NYASH_JIT_EVENTS=1` 時に `threshold=1` 自動適用でLower確実実行
|
||||
- 戻り境界: CallBoundaryBox で JitValue→VMValue を一元化(ハンドル復元含む)
|
||||
|
||||
## ワークストリーム
|
||||
1) GC Switchable Runtime(phase_10_4_gc_switchable_runtime.md)
|
||||
- 目標: NullGc/CountingGc の切替、root領域/バリアAPIの一本化
|
||||
- タスク:
|
||||
- NyashRuntimeBuilder: GC選択をCLI/Box反映(NYASH_GC=none|counting など)
|
||||
- ScopeTracker/enter_root_region()/pin_roots() の公開インターフェース確認
|
||||
- CountingGcの統計出力(roots/reads/writes/safepoints)
|
||||
- 書き込み系HostCallにバリアサイトのフック(Map/Array set/push)
|
||||
- 受入: GC切替コマンドで統計差分が取れる/HostCall書き込みでバリアサイトが加算される
|
||||
|
||||
2) Unified Debug System(phase_10_8_unified_debug_system.md)
|
||||
- 目標: デバッグ/観測フラグを DebugConfig/Box に統合(CLI/env/Boxの単一路)
|
||||
- タスク:
|
||||
- DebugConfig(Rust側): dump/events/stats/dot/phi_min 等を集約
|
||||
- DebugConfigBox: Boxから get/set/apply/toJson/fromJson
|
||||
- Runner: CLI→DebugConfig→env/Box の一本化(env直読み排除)
|
||||
- イベント出力先: stdout/file 切替の設定(NYASH_JIT_EVENTS_PATH のBox反映)
|
||||
- 受入: Boxから apply 後、JIT/VM/DOTの挙動が即時反映/JSONLが指定先に出力
|
||||
|
||||
3) E2Eラインの実用化(builtin→pluginの足場)
|
||||
- 目標: ビルトインBoxで日常運用レベル、プラグインBoxはTLV HostCallの足場を準備
|
||||
- タスク:
|
||||
- Lowerカバレッジの整理(BoxCall/RO/WO・param/非paramの分岐ダンプ)
|
||||
- 署名管理: レジストリのオーバーロード運用方針(canonical idと派生idの整理)
|
||||
- 返り型推論: MIR Builderのreturn_type推定を確認(main/補助関数とも)
|
||||
- Plugin PoC: TLV/handle経由のread-onlyメソッド1つをHostCall経由で通す(allowログまで)
|
||||
- 受入: 代表サンプル(math/map/array/string)でallow/fallbackが意図通り、plugin PoCでallowイベントが出る
|
||||
|
||||
4) ドキュメントと例の整理
|
||||
- 目標: 例の最小集合化(param/非param/RO/WO/HH/Hの代表)、手順の簡潔化
|
||||
- タスク:
|
||||
- examples/: 重複の削減、README(実行コマンド付き)
|
||||
- phase_10_9/10_10 のガイドをCURRENT_TASKと相互参照
|
||||
- 受入: 主要ケースが examples/README からそのまま実行可
|
||||
|
||||
5) ベンチと回帰(最小)
|
||||
- 目標: ラインの性能/退行の早期検知
|
||||
- タスク:
|
||||
- ny_bench.nyash のケース整理(関数呼出/Map set-get/branch)
|
||||
- compare: VM vs JIT(ウォームアップ付き)
|
||||
- 受入: ベンチ出力に JIT/VM の比較が出る(改善/退行が見える)
|
||||
|
||||
## リスクと対策
|
||||
- param/非param 分岐の混乱: イベントに reason を必ず出す/docsにベストプラクティス(受け手をparam化)
|
||||
- mutatingの誤許可: JitPolicyBox の whitelist/プリセットのみで許可、既定はread_only
|
||||
- 署名の散逸: canonical id(例: nyash.map.get_h)と派生(_hh)の方針を明示
|
||||
|
||||
## 受け入れ基準(サマリ)
|
||||
- DebugConfig/Box/CLIの一貫挙動(apply後の即時反映)
|
||||
- GC切替とバリアサイト観測が可能
|
||||
- HostCall(RO/一部WO)が param でallow、非paramでfallback(イベントで確認可)
|
||||
- 代表サンプルが examples/README の手順で成功
|
||||
|
||||
## すぐ試せるコマンド(抜粋)
|
||||
```bash
|
||||
# math.min(関数スタイル)
|
||||
NYASH_JIT_EXEC=1 NYASH_JIT_THRESHOLD=1 NYASH_JIT_NATIVE_F64=1 NYASH_JIT_EVENTS=1 \
|
||||
./target/release/nyash --backend vm examples/jit_math_function_style_min_float.nyash
|
||||
|
||||
# Map.get HH直実行
|
||||
NYASH_JIT_EXEC=1 NYASH_JIT_THRESHOLD=1 NYASH_JIT_HOSTCALL=1 NYASH_JIT_EVENTS=1 \
|
||||
./target/release/nyash --backend vm examples/jit_map_get_param_hh.nyash
|
||||
|
||||
# Mutating opt-in(Array.push)
|
||||
NYASH_JIT_EXEC=1 NYASH_JIT_THRESHOLD=1 NYASH_JIT_HOSTCALL=1 NYASH_JIT_EVENTS=1 \
|
||||
./target/release/nyash --backend vm examples/jit_policy_optin_mutating.nyash
|
||||
|
||||
## 例とスモーク(開発者向けクイック)
|
||||
- 例一覧: `examples/README.md`(HH直実行・mutating opt-in・GCデモ)
|
||||
- スモーク: `bash tools/smoke_phase_10_10.sh`
|
||||
- JITイベント最小スキーマ: `docs/reference/jit/jit_events_json_v0_1.md`
|
||||
|
||||
### Quick Note(運用の勘所)
|
||||
- phase分離: compile→`phase:"lower"`(opt-in), runtime→`phase:"execute"`(既定ON可)
|
||||
- しきい値: 観測ONかつ未指定なら `NYASH_JIT_THRESHOLD=1`(Runner/DebugConfigが補助)
|
||||
- HostCall: 実例では `NYASH_JIT_HOSTCALL=1` を明示(HH直実行/ANYヘルパ)
|
||||
- ANYヘルパ: `nyash.any.length_h / is_empty_h` でROは十分カバー(追加不要)
|
||||
```
|
||||
19
docs/phases/phase-10/phase_10_4_gc_switchable_runtime.md
Normal file
19
docs/phases/phase-10/phase_10_4_gc_switchable_runtime.md
Normal file
@ -0,0 +1,19 @@
|
||||
# Phase 10.4 — GC Switchable Runtime (Scaffold)
|
||||
|
||||
Status: scaffolded (hooks only)
|
||||
|
||||
Goals
|
||||
- Decouple execution engines from a concrete GC.
|
||||
- Provide minimal `GcHooks` with `safepoint()` and `barrier(kind)` used by MIR `Safepoint`/`Barrier*`.
|
||||
- Make runtime supply a pluggable GC via `NyashRuntimeBuilder::with_gc_hooks`.
|
||||
|
||||
What’s done (in this repo)
|
||||
- Added `src/runtime/gc.rs` with `GcHooks` trait, `BarrierKind`, and `NullGc` (no-op).
|
||||
- `NyashRuntime` now holds `gc: Arc<dyn GcHooks>`; defaults to `NullGc`.
|
||||
- VM dispatch calls hooks on `Safepoint` and `Barrier(Read|Write|unified)`.
|
||||
|
||||
Next
|
||||
- Thread-local root set API design (`enter_scope/leave_scope`, root pinning) for precise collectors.
|
||||
- Card marking/write barrier integration for object field writes (`RefSet` sites).
|
||||
- Preemption policy at safepoints (cooperative scheduling integration).
|
||||
|
||||
27
docs/phases/phase-10/phase_10_4d_barrier_ci_notes.txt
Normal file
27
docs/phases/phase-10/phase_10_4d_barrier_ci_notes.txt
Normal file
@ -0,0 +1,27 @@
|
||||
Phase 10.4d — Barrier Strict Mode (CI/Local)
|
||||
|
||||
Goal
|
||||
- Catch missing Write-Barrier quickly in development and CI.
|
||||
|
||||
How-To (Local)
|
||||
1) Build with default features:
|
||||
cargo build --release -j32
|
||||
2) Run with CountingGc + Strict Barrier + Trace:
|
||||
(in code) build runtime via NyashRuntimeBuilder::with_counting_gc()
|
||||
(env)
|
||||
set NYASH_GC_BARRIER_STRICT=1
|
||||
set NYASH_GC_TRACE=1
|
||||
nyash <program.nyash>
|
||||
|
||||
Expected
|
||||
- Barrier sites log to stderr.
|
||||
- On any mutating site without barrier increment, process panics with site name.
|
||||
|
||||
CI Suggestion
|
||||
- Add a job that runs selected examples/tests with CountingGc enabled and
|
||||
NYASH_GC_BARRIER_STRICT=1. Fail build on panic.
|
||||
|
||||
Notes
|
||||
- Strict mode requires CountingGc; otherwise the helper panics to avoid false negatives.
|
||||
- Use NYASH_GC_TRACE=2 for detailed roots breakdown at end-of-run when investigating.
|
||||
|
||||
57
docs/phases/phase-10/phase_10_5_core_std_nyash_impl.md
Normal file
57
docs/phases/phase-10/phase_10_5_core_std_nyash_impl.md
Normal file
@ -0,0 +1,57 @@
|
||||
# Phase 10.5: Core Standard (String/Array/Map) in Nyash — Rust依存の段階的削減
|
||||
|
||||
目的
|
||||
- 現状Rust実装に依存している基本コンテナ(String/Array/Map)を、Nyashで実装したstdへ段階的に置換し、セルフホストへ近づける。
|
||||
- rt/sys層(Box ABI・所有・weak・最小アロケータ、`ny_host_*`)を活用して堅牢性と性能の両立を図る。
|
||||
|
||||
前提
|
||||
- Phase 10.2: Host API層(C-ABI `ny_host_*` / WASM `nyir_host`)
|
||||
- Phase 10.3: 層の切り分け(corelang/rt/sys/std)
|
||||
- Phase 10.4: Box ABI(fat ptr)とEffect→LLVM属性の方向性
|
||||
|
||||
範囲(MVP)
|
||||
- String
|
||||
- 構造: { ptr: *u8, len: usize, cap: usize }
|
||||
- API: new, from_raw, into_raw, clone, len, is_empty, push_str, substr(view), to_utf8(view)
|
||||
- メモリ: `ny_host_alloc/realloc/free` 経由、UTF-8不変(validation optional)
|
||||
- Array<T>
|
||||
- 構造: { ptr: *T, len: usize, cap: usize }
|
||||
- API: new, push, pop, get(i), set(i,v), len, reserve
|
||||
- メモリ: `ny_host_*` 経由、要素のfiniハンドリング(Box所有規則順守)
|
||||
- Map<K,V>
|
||||
- 構造: ハッシュテーブル(オープンアドレス or チェイン; v0は単純で可)
|
||||
- API: new, get, set, remove, len, keys(view), values(view)
|
||||
- メモリ: `ny_host_*` 経由、キー/値の所有/weak規則順守
|
||||
|
||||
設計ポリシー
|
||||
- 所有とfini: 再代入・スコープ終端でfiniが適切に発火すること(Everything is Box準拠)
|
||||
- 互換: 現行言語表面の挙動に合わせる(差異は仕様に明記)
|
||||
- 効果: mut操作の順序保持、view系はpure(読み取り)
|
||||
- WASM/LLVM: ABI/ExternCallと矛盾しない(Stringの(ptr,len)は共通)
|
||||
|
||||
タスク(Copilot TODO)
|
||||
1) stdレイアウトの骨子作成(ファイル/モジュール構成)
|
||||
2) String v0実装 + 単体テスト(push_str/len/substr)
|
||||
3) Array v0実装 + 単体テスト(push/get/set/len)
|
||||
4) Map v0(簡易hash)+ 単体テスト(set/get/remove/len)
|
||||
5) 再代入/スコープ終端でのfini挙動の統合テスト
|
||||
6) ベンチ: 既存Rust実装対比の大まかな目安(悪化しない/許容範囲)
|
||||
7) フェールセーフ: OOM/境界エラーの明確化(panic/Resultは設計に従う)
|
||||
8) ドキュメント: stdのMVP API一覧と互換要件
|
||||
|
||||
受け入れ基準
|
||||
- 代表サンプルがRust実装なしでString/Array/Mapを利用し動作
|
||||
- 再代入・スコープ終端時にfiniが期待通り発火(ログで可視化)
|
||||
- WASM/LLVMの文字列(ptr,len)取り扱いと整合(print等のExternCallで可視化)
|
||||
|
||||
リスク・軽減
|
||||
- パフォーマンス劣化: ベンチで目視確認、ホットパス最適化は後続で実施
|
||||
- メモリ安全: 所有/weak/効果規則をVerifierで補助(後続でLSP/静的解析を強化)
|
||||
- 実装負債: MVP範囲を明確にし、機能追加はIssue分割
|
||||
|
||||
参考
|
||||
- ABIドラフト: docs/予定/native-plan/box_ffi_abi.md
|
||||
- NyIR: docs/nyir/spec.md
|
||||
- Host API: Phase 10.2 仕様
|
||||
|
||||
最終更新: 2025-08-14
|
||||
20
docs/phases/phase-10/phase_10_6_thread_safe_revolution.md
Normal file
20
docs/phases/phase-10/phase_10_6_thread_safe_revolution.md
Normal file
@ -0,0 +1,20 @@
|
||||
# Phase 10.6 — Thread-Safe Revolution (Design Prep)
|
||||
|
||||
Status: preparation
|
||||
|
||||
Principles
|
||||
- Opt-in concurrency: default runtime remains single-threaded for simplicity.
|
||||
- All extension points intended for cross-thread use must be `Send + Sync`.
|
||||
|
||||
What’s prepared
|
||||
- `GcHooks: Send + Sync` to allow multi-threaded collectors later.
|
||||
- `NyashRuntime` holds `Arc<dyn GcHooks>` for safe sharing across threads.
|
||||
|
||||
Planned tasks
|
||||
- Audit `NyashBox` implementations for `Send + Sync` (introduce marker traits or wrappers).
|
||||
- Introduce scheduler abstraction for futures/actors (no global state).
|
||||
- Introduce interior mutability strategy `RwLock` on shared mutable state, with minimal contention.
|
||||
|
||||
Notes
|
||||
- Until the audit, VM enforces single-threaded access; sharing across threads is unsupported by default.
|
||||
|
||||
46
docs/phases/phase-10/phase_10_6a_thread_safety_audit.md
Normal file
46
docs/phases/phase-10/phase_10_6a_thread_safety_audit.md
Normal file
@ -0,0 +1,46 @@
|
||||
# Phase 10.6a — Thread-Safety Audit (Checklist)
|
||||
|
||||
目的: NyashBox/ランタイムのスレッド安全性を棚卸しし、将来の並列化(10.6b/c以降)に備える。
|
||||
|
||||
## 方針
|
||||
- 既定は単一スレッド実行(VM/Interpreter)。並列化は opt-in。
|
||||
- 共有状態は `Arc<...>` と `RwLock/Mutex` により内的可変を確保。
|
||||
- クロススレッド境界に出る型は `Send + Sync` を満たす(必要に応じてラッパで担保)。
|
||||
|
||||
## チェックリスト
|
||||
- Box実装(src/boxes/*)
|
||||
- [ ] 共有内部状態を持つ型は `Arc<RwLock<_>>` のようにラップされているか
|
||||
- [ ] `to_string_box()` が重い処理やグローバル可変に依存しないか
|
||||
- [ ] FFI/プラグイン橋渡し時に非同期イベント/コールバックを保持しないか(保持する場合は送受戦略を文書化)
|
||||
- ランタイム(src/runtime/*)
|
||||
- [ ] `NyashRuntime` のメンバは `Send + Sync` 要件を満たす(`Arc<...>`)
|
||||
- [ ] `GcHooks` 実装は `Send + Sync`(CountingGc/NullGc はOK)
|
||||
- [ ] Scheduler 実装は `Send + Sync`(SingleThreadSchedulerはOK)
|
||||
- VM/Interpreter
|
||||
- [ ] MIR `Safepoint` で `runtime.scheduler.poll()` を呼ぶ(協調スケジューラの結合点)
|
||||
- [ ] Grep: `rg -n "Safepoint" src` で配置確認
|
||||
|
||||
## Grep支援
|
||||
```bash
|
||||
rg -n "Arc<|Mutex<|RwLock<|Send|Sync" src/boxes src/runtime
|
||||
```
|
||||
|
||||
## 既知の注意点
|
||||
- Python/外部DLLとの橋渡しはGIL/PATH管理で単一スレッド優先(AOT時はPATH/PYTHONHOME調整済)。
|
||||
- BufferBox は共有化のために `Arc<RwLock<Vec<u8>>>` を採用済み。
|
||||
|
||||
## クイック監査(第一次)
|
||||
- ArrayBox: `Arc<RwLock<Vec<Box<dyn NyashBox>>>>` → OK(共有+内的可変)
|
||||
- MapBox: `Arc<RwLock<HashMap<String, Box<dyn NyashBox>>>>` → OK
|
||||
- BufferBox: `Arc<RwLock<Vec<u8>>>` → OK
|
||||
- NyashRuntime: `box_registry: Arc<Mutex<_>>`, `box_declarations: Arc<RwLock<_>>`, `gc: Arc<dyn GcHooks>`, `scheduler: Option<Arc<dyn Scheduler>>` → OK
|
||||
- Scheduler: `SingleThreadScheduler` 内部に `Arc<Mutex<VecDeque<...>>>` → OK
|
||||
- GC Hooks: `NullGc/CountingGc` は `Send+Sync` 実装方針 → OK
|
||||
|
||||
未確認/注意:
|
||||
- プラグインBox(PluginBoxV2)の内部FFIハンドルはVM/EXE側で共有参照のみ(実体はFFI側)。クロススレッド呼出しは未サポート運用(明記要)。
|
||||
- 一部のBoxで外部資源(ファイル/ネット)を扱う場合、スレッド越境のI/O同期設計は別途(Phase 10.6d+)。
|
||||
|
||||
## 次の一手(提案)
|
||||
- マーカーTraits(例: `ThreadSafeBox`)の導入は保留(破壊的)。現時点は監査+ドキュメントで運用。
|
||||
- 並列スケジューラ(M:N)の実装は `feature` フラグで段階導入。
|
||||
64
docs/phases/phase-10/phase_10_6a_thread_safety_audit.txt
Normal file
64
docs/phases/phase-10/phase_10_6a_thread_safety_audit.txt
Normal file
@ -0,0 +1,64 @@
|
||||
Phase 10.6a — Thread-Safety Audit (TXT)
|
||||
|
||||
Scope
|
||||
- Audit Send/Sync policy for core runtime + Box families.
|
||||
- Classify: Allowed (Send+Sync), Not-Send (single-threaded), Needs-Wrapper (guarded by RwLock/mpsc/etc.).
|
||||
- Output concrete action items for hardening.
|
||||
|
||||
Legend
|
||||
- ALLOW: Safe to share/send across threads as-is.
|
||||
- NO-SEND: Must remain thread-confined; do not share.
|
||||
- WRAP: Provide wrapper/adapter to safely share (interior mutability / channels / handles).
|
||||
|
||||
Runtime Components
|
||||
- NyashRuntime: WRAP — shared via Arc; subcomponents must be audited (registry/decls RwLock OK).
|
||||
- GcHooks: ALLOW — trait requires Send+Sync; CountingGc is Send+Sync by design.
|
||||
- TypeMeta/CacheVersions: WRAP — global tables; protect via atomic/versioning (already present) + RwLock where needed.
|
||||
- Scheduler (planned): WRAP — explicit abstraction (cooperative); no global mutable state.
|
||||
|
||||
VM Values / Execution
|
||||
- VMValue: ALLOW (data) / WRAP (BoxRef) — primitives OK; BoxRef must only be shared via immutable Box API.
|
||||
- ScopeTracker: NO-SEND — per-VM; not shared. Access confined to single thread.
|
||||
- JIT Manager: WRAP — read-mostly maps; guard with RwLock if shared, or keep per-VM.
|
||||
|
||||
Builtin Boxes (initial pass)
|
||||
- IntegerBox/BoolBox/StringBox: ALLOW (immutable data semantics).
|
||||
- FloatBox (math): ALLOW (stateless ops; string-ification only).
|
||||
- ArrayBox/MapBox: WRAP — interior mutability required (RwLock); Write-Barrier remains required.
|
||||
- Buffer/IO/Net/Time/Audio/etc.: WRAP — external handles; use Arc + internal locks; expose async/channel for ops.
|
||||
- FutureBox: WRAP — already uses RwLock pattern; verify methods are non-blocking and Send+Sync where applicable.
|
||||
- ChannelBox: WRAP — backed by mpsc/crossbeam; ensure senders/receivers are Send.
|
||||
|
||||
Plugin Boxes
|
||||
- PluginBoxV2: WRAP — FFI handle; calls marshalled via TLV; all access through thread-safe host layer.
|
||||
|
||||
Interpreter/Runner Layers
|
||||
- Parser/Tokenizer/AST: ALLOW (not shared at runtime).
|
||||
- Runner (VM backend): NO-SEND — execution confined to the owning thread.
|
||||
|
||||
Policies and Enforcement
|
||||
1) Marker traits (for docs only):
|
||||
- ThreadSafeBox (Doc): Box types that are Send+Sync-safe as value semantics.
|
||||
- HandleBox (Doc): wraps external/native handles; must be behind RwLock/Mutex and non-blocking APIs.
|
||||
2) Constructor guidance:
|
||||
- For WRAP boxes, store state under RwLock/Mutex; prefer RwLock (read-mostly).
|
||||
- Avoid blocking in methods; prefer async/task dispatch via scheduler abstraction.
|
||||
3) Sharing rules:
|
||||
- VMValue::BoxRef must not be mutated without Write-Barrier when GC is active.
|
||||
- Cross-thread sharing limited to BoxRef with immutable APIs or actor-like message passing.
|
||||
4) Testing:
|
||||
- Add feature-gated thread-smoke tests (spawn two threads, share ALLOW boxes, ensure no UB).
|
||||
- Add Mutex/RwLock poisoning handling policies (map to Nyash exceptions if needed).
|
||||
|
||||
Immediate Action Items
|
||||
- [A1] Document per-Box classification in code headers (short note + rationale).
|
||||
- [A2] Ensure ArrayBox/MapBox internals use RwLock and respect Write-Barrier (already partially in place; verify set/push paths).
|
||||
- [A3] PluginBoxV2 calls remain serialized through host; confirm Send on host dispatch closures.
|
||||
- [A4] Introduce lightweight scheduler trait (single-threaded impl first); route blocking ops via scheduler.
|
||||
- [A5] Add CI job to run with NYASH_GC_BARRIER_STRICT=1 and CountingGc for barrier regression.
|
||||
|
||||
Future (10_6b/10_6c tie-ins)
|
||||
- Scheduler + cooperative safepoint policy across threads.
|
||||
- Per-thread root regions; ensure root pin/unpin remains thread-local.
|
||||
- Card marking/write barrier strategy for shared objects modified across threads (design doc first).
|
||||
|
||||
25
docs/phases/phase-10/phase_10_6b_scheduler_prep.txt
Normal file
25
docs/phases/phase-10/phase_10_6b_scheduler_prep.txt
Normal file
@ -0,0 +1,25 @@
|
||||
Phase 10.6b — Scheduler Prep (Single-Thread Queue)
|
||||
|
||||
What’s added
|
||||
- `src/runtime/scheduler.rs` with `Scheduler` trait and `SingleThreadScheduler`.
|
||||
- Queue + delayed tasks (spawn/spawn_after) and `poll()` to run work.
|
||||
- VM calls `scheduler.poll()` at MIR `Safepoint` to integrate cooperative scheduling.
|
||||
- Poll budget via env `NYASH_SCHED_POLL_BUDGET` (default: 1)
|
||||
- Trace via `NYASH_SCHED_TRACE=1` (diagnostic)
|
||||
|
||||
How to use (dev)
|
||||
- Build runtime with default SingleThreadScheduler (already default via builder), or inject custom via:
|
||||
`NyashRuntimeBuilder::new().with_single_thread_scheduler().build()`
|
||||
- Schedule tasks from boxes/host code via `runtime.scheduler.spawn(...)`.
|
||||
- At safepoints, queued tasks run (1 per safepoint) and due delayed tasks are enqueued.
|
||||
|
||||
How to validate quickly
|
||||
- Run any Nyash program that contains loops or function entries (safepoints exist by default).
|
||||
- Optionally enable the demo hook: set `NYASH_SCHED_DEMO=1` and run the VM backend
|
||||
to observe scheduler tasks firing at safepoints.
|
||||
- Control throughput by `NYASH_SCHED_POLL_BUDGET` (e.g., 3 runs up to 3 tasks/safepoint).
|
||||
- GC trace pairs well: set `NYASH_GC_COUNTING=1 NYASH_GC_TRACE=1` to see safepoints.
|
||||
|
||||
Next (10.6c+)
|
||||
- Expose scheduling APIs to script level (Box API).
|
||||
- Optional multi-thread scheduler implementation behind feature flag.
|
||||
37
docs/phases/phase-10/phase_10_6c_parallel_gc_design.txt
Normal file
37
docs/phases/phase-10/phase_10_6c_parallel_gc_design.txt
Normal file
@ -0,0 +1,37 @@
|
||||
Phase 10.6c — Parallel GC Design (Notes)
|
||||
|
||||
Objectives
|
||||
- Keep GC hooks and MIR sites stable while enabling parallel/stop-the-world options.
|
||||
- Introduce per-thread root regions, card marking, and coordinated safepoints.
|
||||
|
||||
Design Sketch
|
||||
1) Per-thread roots
|
||||
- Root API remains the same but live under thread-local trackers.
|
||||
- VM/engines expose `enter_root_region/pin/leave_root_region` that operate on TLS.
|
||||
- Global snapshot for diagnostics merges per-thread views (debug only).
|
||||
|
||||
2) Safepoint coordination
|
||||
- Central GC controller requests a safepoint; worker threads acknowledge at next MIR `Safepoint`.
|
||||
- Timeout/poll policy configurable; in single-threaded mode this is no-op.
|
||||
|
||||
3) Card marking / write barriers
|
||||
- Extend `BarrierKind::Write` to accept optional object metadata (future API): object id/card index.
|
||||
- For now, keep symbolic barrier only; when parallel GC is enabled, maintain a global dirty set.
|
||||
|
||||
4) Scheduler interplay
|
||||
- GC controller can schedule minor/major cycles using the Scheduler abstraction.
|
||||
- In single-threaded mode, cycles are chunked via `poll()` to avoid long pauses.
|
||||
|
||||
API Diffs (future)
|
||||
- `GcHooks::barrier(kind)` → `barrier(kind, obj: Option<ObjectId>)` (compat shim keeps old signature).
|
||||
- `GcHooks::safepoint()` may return a hint (`Proceed`, `Yield`) for engines to cooperate.
|
||||
|
||||
Migration Plan
|
||||
- Keep current single-threaded path as default.
|
||||
- Add feature flag `gc-parallel` that swaps in an implementation honoring the extended API.
|
||||
- Incrementally add: dirty set, per-thread roots, coordinated safepoint prototype.
|
||||
|
||||
Testing Strategy
|
||||
- Deterministic unit tests using SingleThreadScheduler.
|
||||
- Stress tests with STRICT barrier and TRACE=2 to validate barrier coverage and root progression.
|
||||
|
||||
@ -0,0 +1,85 @@
|
||||
Phase 10.7 — JIT Branch Wiring + Minimal ABI Extensions
|
||||
|
||||
Overview
|
||||
- Purpose: Enable real control-flow in the JIT path by wiring MIR Branch/Jump/Return to Cranelift blocks, and extend the minimal ABI to support multi-arg i64 and basic bool/f64.
|
||||
- Outcome: If/loop constructs execute natively in JIT for straight-line + branched code paths, with safe VM fallback preserved. HostCall PoC remains opt-in.
|
||||
|
||||
Goals (Must)
|
||||
- Wire MIR basic blocks to Cranelift blocks; emit `brif` and `jump` for Branch/Jump.
|
||||
- Keep Compare result usable as a branch condition (b1); where necessary, convert i64 to b1 via `icmp_imm != 0`.
|
||||
- Preserve Return behavior (already in place) and allow branching to return in both sides (no PHI required for first pass).
|
||||
- Minimal ABI: multi-argument i64 stable, bool constants lowered to 0/1, f64 constants passed through (no arithmetic yet required).
|
||||
- Safety: On JIT panic or unsupported instruction at runtime, VM fallback with logs.
|
||||
|
||||
Stretch (Nice-to-have)
|
||||
- PHI at merge points via block parameters for simple patterns (two-predecessor if-else returning a value).
|
||||
- Bench: Add a small control-flow benchmark to CLI/`examples`.
|
||||
|
||||
Non-Goals (10.7)
|
||||
- Full PHI generalization across arbitrary CFG.
|
||||
- Type-specialized calling conventions beyond i64/f64/bool minimal path.
|
||||
- Deoptimization or on-stack replacement.
|
||||
|
||||
Deliverables
|
||||
- Code: CraneliftBuilder block management + branch/jump emission.
|
||||
- Lowering updates: Branch/Jump hook uses real block IDs; Compare emits b1-friendly shape.
|
||||
- Env flags: Reuse `NYASH_JIT_EXEC/THRESHOLD/STATS/DUMP`; guard hostcalls by `NYASH_JIT_HOSTCALL`.
|
||||
- Docs: Update execution-backends.md with “JIT control-flow coverage (10.7)”.
|
||||
- Examples: `examples/jit_branch_demo.nyash` (if/loop minimal).
|
||||
|
||||
Design Sketch
|
||||
1) Block Mapping
|
||||
- Build `bb_map: MirBB -> Cranelift Block` in `begin_function` based on MIR function blocks.
|
||||
- Switch to entry block, `seal_block(entry)`.
|
||||
|
||||
2) Conditions
|
||||
- Compare emits Cranelift `icmp` returning b1; avoid converting to i64 unless explicitly needed.
|
||||
- If the condition arrives as i64 (const/param), lower `icmp_imm != 0` to get b1 for `brif`.
|
||||
|
||||
3) Branch / Jump
|
||||
- `emit_branch(cond, then_bb, else_bb)` → `brif(cond_b1, then_block, []); jump(else_block, []); seal both`.
|
||||
- `emit_jump(target_bb)` → `jump(target_block, [])`.
|
||||
|
||||
4) Return
|
||||
- Keep current return emission; when branches end in return, no PHI needed.
|
||||
|
||||
5) PHI (limited)
|
||||
- For a simple diamond where both arms jump to a single merge, add one block param at merge.
|
||||
- Pass the value via `jump(merge, [val])`; read via `block-arg(merge, 0)`; return it.
|
||||
|
||||
6) ABI
|
||||
- Keep signature `(i64 x argc) -> i64?` baseline.
|
||||
- Support f64/bool consts materialization; booleans as 0/1 integers for now unless used as branch cond (then b1).
|
||||
|
||||
Implementation Plan (Tasks)
|
||||
- T1: Extend IRBuilder API (only behind `cranelift-jit`): create_block(), br_if(), jump(), seal_block(), block_param(), append_block_params_for_function_params().
|
||||
- T2: CraneliftBuilder: implement block map allocation in begin_function; store in builder state.
|
||||
- T3: LowerCore:
|
||||
- Track current MIR bb while iterating.
|
||||
- For Branch/Jump, call builder with mapped blocks and condition value hint.
|
||||
- Compare: emit b1 icmp; when Compare is used as value elsewhere, allow i64 extend as needed.
|
||||
- T4: Minimal PHI support for a single merge (optional; guarded by env `NYASH_JIT_PHI_MIN=1`).
|
||||
- T5: Add `examples/jit_branch_demo.nyash` with: `if (a < b) { return 1 } else { return 2 }` and a small loop with early `return`.
|
||||
- T6: Docs update: execution-backends.md “JIT coverage 10.7” + env flags.
|
||||
- T7: Bench (optional): integrate into `--benchmark` with JIT warmup when `NYASH_JIT_EXEC=1`.
|
||||
|
||||
Validation
|
||||
- Build matrix: with/without `cranelift-jit` feature.
|
||||
- Smoke tests: run `jit_branch_demo.nyash` with `NYASH_JIT_EXEC=1 NYASH_JIT_THRESHOLD=1`.
|
||||
- Fallback verification: force a path with unsupported op to confirm VM fallback.
|
||||
- GC/scheduler: ensure safepoint path still works (unchanged).
|
||||
|
||||
Risk & Mitigation
|
||||
- Mismatch of block sealing/order → start with straight-line + simple diamond; add asserts; prefer FunctionBuilder patterns.
|
||||
- Condition type confusion (i64 vs b1) → centralize cond normalization helper.
|
||||
- PHI complexity → keep optional, limited to single value diamond.
|
||||
|
||||
Rollout
|
||||
- Phase gate by envs: `NYASH_JIT_EXEC` for enable, `NYASH_JIT_PHI_MIN` for PHI.
|
||||
- Keep `NYASH_JIT_HOSTCALL` opt-in.
|
||||
|
||||
Success Criteria
|
||||
- If/else returning constants runs fully via JIT (Cranelift) without VM fallback.
|
||||
- Simple counting loop with early exit returns correct result via JIT.
|
||||
- All tests pass with and without feature flag; VM fallback works on traps.
|
||||
|
||||
135
docs/phases/phase-10/phase_10_7_master_plan.txt
Normal file
135
docs/phases/phase-10/phase_10_7_master_plan.txt
Normal file
@ -0,0 +1,135 @@
|
||||
Phase 10.7 — JIT CFG/PHI/ABI Hardening (Master Plan)
|
||||
|
||||
Intent
|
||||
- Deliver a practical, observable JIT path for control flow and minimal data flow while keeping VM as the safe fallback.
|
||||
- Decompose into small, shippable sub-phases with flags and examples, minimizing blast radius.
|
||||
|
||||
Related docs
|
||||
- 10.7a details: phase_10_7a_jit_phi_cfg_and_abi_min.txt
|
||||
- Current work log: docs/development/current/CURRENT_TASK.md
|
||||
- Cranelift JIT backend notes: phase_10_cranelift_jit_backend.md
|
||||
|
||||
Flags and CLI (common across 10.7)
|
||||
- Env: NYASH_JIT_EXEC, NYASH_JIT_STATS, NYASH_JIT_STATS_JSON, NYASH_JIT_DUMP, NYASH_JIT_THRESHOLD, NYASH_JIT_PHI_MIN, NYASH_JIT_HOSTCALL
|
||||
- CLI: --jit-exec --jit-stats --jit-stats-json --jit-dump --jit-threshold N --jit-phi-min --jit-hostcall
|
||||
|
||||
Examples to validate
|
||||
- examples/jit_branch_demo.nyash
|
||||
- examples/jit_loop_early_return.nyash
|
||||
- examples/jit_phi_demo.nyash
|
||||
- examples/jit_array_param_call.nyash, jit_map_param_call.nyash (when hostcall is enabled)
|
||||
|
||||
Sub-phases (10.7a → 10.7h)
|
||||
|
||||
10.7a — Minimal branch/PHI/ABI (Done or in-flight)
|
||||
- Branch wiring with b1 and i64!=0 normalization
|
||||
- Minimal PHI: single-value diamond via block param
|
||||
- Independent ABI (JitValue) with integer-first calling
|
||||
- Panic-safe dispatch (catch_unwind) and VM fallback
|
||||
- Minimal hostcall bridge (Array/Map) behind NYASH_JIT_HOSTCALL
|
||||
- Observability: unified JIT summary/JSON, lower summary (argc/phi_min), CFG edge dump (phi_min)
|
||||
|
||||
Acceptance: see 10.7a doc
|
||||
|
||||
10.7b — PHI generalization and block-parameterization
|
||||
- Support multiple PHIs in a merge block; pass N values via block params
|
||||
- LowerCore: gather PHI inputs per successor, produce explicit arg lists; handle straight merges and simple loops
|
||||
- IRBuilder API formalization:
|
||||
- ensure_block_params_i64(index, count)
|
||||
- br_if_with_args(then_idx, else_idx, then_n, else_n)
|
||||
- jump_with_args(target_idx, n)
|
||||
- CraneliftBuilder: append N I64 params per block, materialize current block params onto stack when requested
|
||||
- Validation: multi-PHI diamonds, if-else chains, early returns; keep loops as simple as possible in 10.7b
|
||||
|
||||
10.7c — Independent host-handle registry (JIT↔Host decoupling)
|
||||
- Introduce JitHandleRegistry: u64 ↔ Arc<dyn NyashBox>
|
||||
- JIT hostcalls accept/return only handles and PODs; VMValue↔JitValue boundary converts BoxRef <-> Handle via registry
|
||||
- Rooting policy: enter/pin roots for handles crossing the boundary; leave on return
|
||||
- Flags: NYASH_JIT_HOSTCALL=1 (still gated); add NYASH_JIT_HANDLE_DEBUG for dumps
|
||||
- Deliverables: array/map operations via handles, no direct VMValue access on JIT side
|
||||
|
||||
10.7d — Side-effect boundary and hostcall coverage expansion
|
||||
- Keep side-effecting ops (print/IO) on VM for now; document deopt path
|
||||
- Expand safe hostcalls (read-only or confined):
|
||||
- String.len / slice basics (POD returns)
|
||||
- Map.size; Map.get with integer and string keys (key boxing handled at boundary)
|
||||
- Record effect categories on lowered calls for future optimizer (metadata only)
|
||||
|
||||
10.7e — CFG diagnostics and visualization
|
||||
- Add DOT export for CLIF CFG with block params and PHI bindings
|
||||
- Env: NYASH_JIT_DOT=path.dot (produces per-function graph)
|
||||
- Optional: ASCII CFG summary for CI logs
|
||||
- Cross-check with VM-side MIR printer for block and PHI consistency
|
||||
|
||||
10.7f — JitConfigBox (configuration as a Box)
|
||||
- Encapsulate all JIT toggles into a runtime-managed box (JitConfigBox)
|
||||
- Harmonize env/CLI with programmatic overrides for tests
|
||||
- Feed config into JIT engine and lowerers (no direct env reads inside hot paths)
|
||||
- Serialization: dump/load config JSON for reproducible runs
|
||||
|
||||
10.7g — Stability, tests, and benchmarks
|
||||
- Golden tests: ensure JIT/VM outputs match on curated programs
|
||||
- Fallback ratio regression guard: alert when fallback_rate spikes beyond threshold
|
||||
- JSON schema stability for stats; include version field
|
||||
- Microbenchmarks: branch-heavy, phi-heavy, and hostcall-heavy cases; gated perf checks
|
||||
|
||||
10.7h — Type widening for native ABI
|
||||
- Add native F64 and Bool parameter/return paths in CLIF
|
||||
- Condition handling: keep b1 where possible; map Bool to b1 cleanly
|
||||
- Conversions: explicit i64<->f64 ops in lowerer where needed (no silent truncation)
|
||||
- Update adapter and closure trampoline to select proper function signatures (arity×type shapes)
|
||||
|
||||
Out of scope for 10.7 (shift to 10.8/10.9)
|
||||
- Global register allocation strategies or codegen-level optimizations
|
||||
- Deoptimization machinery beyond simple VM fallback
|
||||
- Advanced exception propagation across JIT/VM boundary
|
||||
|
||||
Risks and mitigation
|
||||
- PHI N-arity correctness: introduce targeted unit tests over synthetic MIR
|
||||
- Handle registry leaks: counting diagnostics, strict mode; tie roots to scope regions
|
||||
- CLIF block-param misuse: deterministic block order + seal discipline + assertions in builder
|
||||
|
||||
Verification checklist (roll-up)
|
||||
- cargo check (± --features cranelift-jit)
|
||||
- Run examples with JIT flags; diff with pure VM runs
|
||||
- Inspect: unified JIT summary/JSON, lower logs, CFG dumps/DOT
|
||||
- Leak/roots checks when NYASH_GC_TRACE=1/2/3 and strict barrier mode is on
|
||||
|
||||
Suggested timeline (tentative)
|
||||
- 10.7a: Minimal branch/PHI/ABI (done / in-flight)
|
||||
- 10.7b: PHI generalization + builder API formalization (1–2 days)
|
||||
- 10.7c: Host-handle registry PoC (1–2 days)
|
||||
- 10.7d/e: Hostcall coverage + CFG DOT (2–3 days)
|
||||
- 10.7f: JitConfigBox + integration (1 day)
|
||||
- 10.7g/h: QA + type widening for f64/bool (2–4 days)
|
||||
|
||||
10.7z — Follow-ups and Open Items (post-10.7)
|
||||
- b1 PHI tagging robustness
|
||||
- Problem: Provenance can be obscured by Load/Store and multi-step copies; (b1) tag may be missed in dumps.
|
||||
- Action:
|
||||
- Add a lightweight boolean-lattice analysis over MIR to classify boolean-producing values independent of path shape.
|
||||
- Extend dump to include phi_summary JSON or structured rows when NYASH_JIT_STATS_JSON is on.
|
||||
- Placement: 10.7g (stability/tests) — does not block 10.7 close.
|
||||
|
||||
- VM f64 arithmetic/compare parity
|
||||
- Problem: VM backend currently errors on f64 BinOp/Compare; JIT (Cranelift) supports f64 when enabled.
|
||||
- Action: Implement f64 ops in VM or add consistent auto-promotion; add golden tests.
|
||||
- Placement: 10.8 (VM parity/perf) — out-of-scope for 10.7.
|
||||
|
||||
- Native b1 ABI in function signatures
|
||||
- Problem: Toolchain capability for b1 return/params is currently disabled.
|
||||
- Action: Keep centralized switch; add CI probe to flip automatically when supported; wire return path fully.
|
||||
- Placement: 10.7h or later (gated by toolchain).
|
||||
|
||||
- Stats/diagnostics polish
|
||||
- Action: Version the unified JIT JSON schema; expose phi(b1) slot counts in JSON; enrich JitStatsBox with summary/topN (partially done).
|
||||
- Placement: 10.7g.
|
||||
|
||||
- Build warnings (unexpected cfg: llvm)
|
||||
- Problem: Warning noise from unused/unknown cfg.
|
||||
- Action: Declare feature flags in Cargo.toml or gate code behind existing features; optionally silence for non-supported builds.
|
||||
- Placement: 10.7g (cleanup) — non-blocking.
|
||||
|
||||
- Documentation sync
|
||||
- Action: Add a "JIT quick flags" section with common env/CLI combos; ensure CURRENT_TASK and examples remain aligned.
|
||||
- Placement: 10.7e (docs) — non-blocking.
|
||||
92
docs/phases/phase-10/phase_10_7a_jit_phi_cfg_and_abi_min.txt
Normal file
92
docs/phases/phase-10/phase_10_7a_jit_phi_cfg_and_abi_min.txt
Normal file
@ -0,0 +1,92 @@
|
||||
Phase 10.7a — JIT Branch/PHI/Independent ABI: Minimal Path Hardening (Plan)
|
||||
|
||||
Purpose
|
||||
- Solidify the first functional slice of the JIT control-flow path:
|
||||
- Branch wiring (b1 and i64!=0 normalization)
|
||||
- Minimal PHI via block parameters (single-value diamond)
|
||||
- Independent ABI (JitValue) and safe dispatch + fallback
|
||||
- Observable, toggleable, and easy to verify via flags + examples
|
||||
|
||||
Scope (10.7a only)
|
||||
1) Minimal PHI handoff
|
||||
- LowerCore: detect single-PHI merge; pass i64 value via block param
|
||||
- CraneliftBuilder: ensure block param (I64), push/pop on branch/jump with args
|
||||
- Flag gate: NYASH_JIT_PHI_MIN=1
|
||||
|
||||
2) Branch wiring and condition normalization
|
||||
- Keep compare result on stack as b1 when possible
|
||||
- If top-of-stack is I64, normalize by icmp_imm != 0
|
||||
- Implement br_if/jump to pre-created blocks (deterministic order)
|
||||
|
||||
3) Independent ABI (minimum viable)
|
||||
- JitValue(I64/F64/Bool/Handle) in/out; normalize non-i64 args to i64 for now
|
||||
- TLS split: legacy VM args (for hostcalls) and JIT args
|
||||
- Engine.execute_handle uses catch_unwind; panic → VM fallback with stats
|
||||
|
||||
4) Minimal hostcall bridge (safe; off by default)
|
||||
- Symbols: nyash.array.{len,get,set,push}, nyash.map.{size}
|
||||
- Gate: NYASH_JIT_HOSTCALL=1
|
||||
- Only integer indices/values (PoC); other types map to handles later
|
||||
|
||||
5) Observability and ergonomics
|
||||
- Flags: NYASH_JIT_EXEC, NYASH_JIT_STATS, NYASH_JIT_STATS_JSON, NYASH_JIT_DUMP, NYASH_JIT_THRESHOLD, NYASH_JIT_PHI_MIN, NYASH_JIT_HOSTCALL
|
||||
- CLI: --jit-exec --jit-stats --jit-stats-json --jit-dump --jit-threshold N --jit-phi-min --jit-hostcall
|
||||
- Unified JIT summary on VM exit (sites/compiled/hits/exec_ok/trap/fallback_rate)
|
||||
- Lower log includes argc/phi_min + CFG light dump (phi edges) when NYASH_JIT_DUMP=1
|
||||
|
||||
Non-Goals (later 10.7b+)
|
||||
- Full PHI generalization (multiple values, loops, complex CFG forms)
|
||||
- Non-i64 native path (true F64/Bool return/params in CLIF)
|
||||
- Side-effect instruction lowering (print, IO) — keep in VM path
|
||||
- Host handle registry for real object bridging (u64↔Arc<dyn NyashBox>)
|
||||
|
||||
Deliverables
|
||||
- Working minimal PHI + branch JIT execution on curated examples:
|
||||
- examples/jit_branch_demo.nyash
|
||||
- examples/jit_loop_early_return.nyash
|
||||
- examples/jit_phi_demo.nyash (single-PHI diamond)
|
||||
- Fallback correctness: traps/panic → VM path; results match VM
|
||||
- Configurable via CLI flags; metrics visible via JIT summary/JSON
|
||||
|
||||
Acceptance Criteria
|
||||
- With: --backend vm --jit-exec --jit-stats --jit-threshold 1
|
||||
- For branch/phi examples, JIT executes without panic
|
||||
- VM fallback occurs only for unsupported ops (logged)
|
||||
- JIT summary shows exec_ok > 0 and reasonable fallback_rate
|
||||
- With: --jit-phi-min
|
||||
- CFG dump lists phi_min edges and blocks count
|
||||
- Results match the same program without JIT enabled
|
||||
|
||||
Risk & Mitigation
|
||||
- Mismatch between VMValue and JitValue adapters
|
||||
- Mitigation: normalize non-i64 to i64 defensively; expand tests on adapters
|
||||
- Cranelift block parameter misuse
|
||||
- Mitigation: deterministic block order and explicit ensure_block_param_i64()
|
||||
- Panic in hostcall stubs (unexpected Box types)
|
||||
- Mitigation: gated by NYASH_JIT_HOSTCALL=1; default off; fallback to VM on panic
|
||||
|
||||
Verification Checklist
|
||||
- cargo check (w/ and w/o --features cranelift-jit)
|
||||
- Run examples with JIT flags; compare outputs with pure VM
|
||||
- Inspect logs: lower summary + CFG dump + unified summary/JSON
|
||||
|
||||
Timeline (10.7a)
|
||||
Day 1:
|
||||
- Finalize ABI normalization and branch wiring; add unified stats (done)
|
||||
- Wire CLI flags and JSON stats (done)
|
||||
Day 2:
|
||||
- Harden minimal PHI path and CFG dump (done)
|
||||
- Curate examples and sanity-run on flags
|
||||
Day 3:
|
||||
- Stabilize logging format, trim rough edges, doc polish
|
||||
→ Then roll into 10.7b (multi-PHI, multi-arg block params, real handle registry)
|
||||
|
||||
Follow-ups (10.7b/10.7c seeds)
|
||||
- Host handle registry (u64↔Arc) and type-safe bridging
|
||||
- True F64/Bool native ABI, multi-arg params/returns
|
||||
- CFG visualization improvements (dot export) and JitConfigBox
|
||||
|
||||
Refs
|
||||
- docs/development/current/CURRENT_TASK.md (10_7 items)
|
||||
- src/jit/{lower,engine,manager,abi,rt}/
|
||||
- examples: jit_* demos
|
||||
45
docs/phases/phase-10/phase_10_7h_native_abi_types.md
Normal file
45
docs/phases/phase-10/phase_10_7h_native_abi_types.md
Normal file
@ -0,0 +1,45 @@
|
||||
# Phase 10.7h — Native ABI Types (F64/Bool)
|
||||
|
||||
Goal
|
||||
- Extend the minimal i64-only JIT ABI to support f64 and bool as native parameter/return types in CLIF.
|
||||
|
||||
Principles
|
||||
- Keep JIT independent from VM internals (use JitValue + adapters at boundary)
|
||||
- Avoid silent truncation; perform explicit conversions in the lowerer
|
||||
- Maintain safety-first fallback to VM for unsupported ops
|
||||
|
||||
Plan
|
||||
1) JitValue widening
|
||||
- JitValue already has I64/F64/Bool/Handle — keep this as the ABI surface
|
||||
- Adapter: refine to/from VMValue mappings (no lossy coercion by default)
|
||||
|
||||
2) CLIF signature selection
|
||||
- Augment CraneliftBuilder to build signatures based on (arity × type shape)
|
||||
- Start with small shapes: (I64|F64|Bool)* → I64|F64|Bool
|
||||
- Closure trampoline: transmute to matching extern "C" fn type; dispatch by shape id
|
||||
|
||||
3) Condition handling
|
||||
- Bool: prefer b1 in IR; allow i64!=0 normalization when comparing integers
|
||||
- Comparisons yield b1; lower branch consumes b1 directly
|
||||
|
||||
4) Conversions in lowerer (explicit only)
|
||||
- add_const_f64, add_convert_{i64_to_f64, f64_to_i64}
|
||||
- prohibit implicit int<->float coercion in arithmetic; gate conversions via explicit MIR ops or intrinsics
|
||||
|
||||
5) Observability and flags
|
||||
- NYASH_JIT_NATIVE_F64=1 / NYASH_JIT_NATIVE_BOOL=1 to enable paths
|
||||
- Dump: show chosen signature shape and conversions when NYASH_JIT_DUMP=1
|
||||
|
||||
6) Rollout
|
||||
- Phase A: const/binop/ret for f64; comparisons yield b1
|
||||
- Phase B: mixed-type ops via explicit converts
|
||||
- Phase C: HostCall bridging for f64/bool PODs (read-only first)
|
||||
|
||||
Risks / Mitigation
|
||||
- Signature explosion: start with a few common shapes; fallback to i64 path
|
||||
- Platform ABI mismatches: rely on Cranelift default call conv; e2e-perf and correctness first
|
||||
|
||||
Acceptance
|
||||
- Examples with pure f64 pipelines run under JIT with matching results vs VM
|
||||
- No silent lossy conversions; conversions visible in MIR/Lower logs
|
||||
|
||||
172
docs/phases/phase-10/phase_10_8_unified_debug_system.md
Normal file
172
docs/phases/phase-10/phase_10_8_unified_debug_system.md
Normal file
@ -0,0 +1,172 @@
|
||||
# Phase 10.8: 統一デバッグシステム - DeepInspectorBoxとグローバルデバッグ整理
|
||||
|
||||
作成日: 2025-08-27
|
||||
発見者: ニャー
|
||||
参照元: docs/ideas/other/2025-08-25-unified-box-design-deep-analysis.md
|
||||
|
||||
## 🚨 現在の問題
|
||||
|
||||
### 1. デバッグ環境変数の乱立
|
||||
現在20個以上の環境変数が散在:
|
||||
- `NYASH_VM_STATS=1`
|
||||
- `NYASH_VM_DEBUG_BOXCALL=1`
|
||||
- `NYASH_DEBUG_PLUGIN=1`
|
||||
- `NYASH_NET_LOG=1`
|
||||
- `NYASH_JIT_THRESHOLD=1`
|
||||
- ... など多数
|
||||
|
||||
### 2. 統一されていないデバッグ体験
|
||||
- VM、プラグイン、JIT、ネットワークなど各コンポーネントが独自のデバッグフラグ
|
||||
- 複数の環境変数を組み合わせる必要がある
|
||||
- 何をONにすればいいか分かりにくい
|
||||
|
||||
## 🌟 提案: 統一デバッグシステム
|
||||
|
||||
### 1. 環境変数の整理統合
|
||||
|
||||
```bash
|
||||
# Before (現在)
|
||||
NYASH_VM_STATS=1 NYASH_VM_DEBUG_BOXCALL=1 NYASH_NET_LOG=1 ./nyash
|
||||
|
||||
# After (提案)
|
||||
NYASH_DEBUG=vm,boxcall,net ./nyash
|
||||
```
|
||||
|
||||
### 2. デバッグレベル制御
|
||||
|
||||
```bash
|
||||
# シンプルなレベル制御
|
||||
NYASH_DEBUG_LEVEL=0 # OFF
|
||||
NYASH_DEBUG_LEVEL=1 # 基本情報のみ
|
||||
NYASH_DEBUG_LEVEL=2 # 詳細情報
|
||||
NYASH_DEBUG_LEVEL=3 # すべて
|
||||
|
||||
# カテゴリ別レベル
|
||||
NYASH_DEBUG=vm:2,net:1,jit:3
|
||||
```
|
||||
|
||||
### 3. プリセット(よく使う組み合わせ)
|
||||
|
||||
```bash
|
||||
# プリセット
|
||||
NYASH_DEBUG_PRESET=basic # 基本的なデバッグ情報
|
||||
NYASH_DEBUG_PRESET=perf # パフォーマンス分析用
|
||||
NYASH_DEBUG_PRESET=network # ネットワーク問題調査用
|
||||
NYASH_DEBUG_PRESET=memory # メモリリーク調査用
|
||||
NYASH_DEBUG_PRESET=all # すべて有効
|
||||
```
|
||||
|
||||
## 🔍 DeepInspectorBox - Everything is Debugの実現
|
||||
|
||||
### グローバルシングルトンデバッガー
|
||||
|
||||
```nyash
|
||||
// グローバルに1つだけ存在する統一デバッガー
|
||||
static box DeepInspectorBox {
|
||||
public { enabled }
|
||||
private {
|
||||
boxCreations, methodCalls, fieldAccess,
|
||||
memorySnapshots, referenceGraph, performanceMetrics
|
||||
}
|
||||
|
||||
// === 簡単な有効化 ===
|
||||
enable(categories) {
|
||||
// "vm,net,memory" のようなカテゴリ文字列を解析
|
||||
me.parseAndEnableCategories(categories)
|
||||
}
|
||||
|
||||
// === プリセット対応 ===
|
||||
usePreset(presetName) {
|
||||
match presetName {
|
||||
"basic" => me.enable("vm,error")
|
||||
"perf" => me.enable("vm,boxcall,stats")
|
||||
"network" => me.enable("net,plugin,tlv")
|
||||
"memory" => me.enable("alloc,gc,leak")
|
||||
"all" => me.enable("*")
|
||||
}
|
||||
}
|
||||
|
||||
// === 統合ログ出力 ===
|
||||
log(category, level, message) {
|
||||
if me.shouldLog(category, level) {
|
||||
local formatted = me.formatLog(category, level, message)
|
||||
me.output(formatted)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### MIRレベルでの統一実装
|
||||
|
||||
```rust
|
||||
// MIR生成時にデバッグフックを埋め込み
|
||||
impl MirBuilder {
|
||||
fn build_new_box(&mut self, type_id: TypeId) -> ValueId {
|
||||
let result = self.push(NewBox { type_id });
|
||||
|
||||
// デバッグモード時のみ
|
||||
if self.debug_enabled {
|
||||
self.push(DebugHook {
|
||||
event: DebugEvent::BoxCreated,
|
||||
type_id,
|
||||
value: result,
|
||||
});
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📊 実装計画
|
||||
|
||||
### Phase 10.8a: 環境変数統合(3日)
|
||||
- [ ] 統一パーサー実装(`NYASH_DEBUG`解析)
|
||||
- [ ] レベル制御システム
|
||||
- [ ] プリセット定義
|
||||
- [ ] 既存環境変数との互換性層
|
||||
|
||||
### Phase 10.8b: DeepInspectorBox基礎(1週間)
|
||||
- [ ] グローバルシングルトン実装
|
||||
- [ ] カテゴリ管理システム
|
||||
- [ ] 基本的なログ収集
|
||||
- [ ] 出力フォーマッター
|
||||
|
||||
### Phase 10.8c: MIR統合(1週間)
|
||||
- [ ] DebugHook命令追加
|
||||
- [ ] MirBuilderへのフック埋め込み
|
||||
- [ ] VMでのDebugHook実行
|
||||
- [ ] JITでのデバッグ情報保持
|
||||
|
||||
### Phase 10.8d: 高度な機能(2週間)
|
||||
- [ ] メモリリーク検出
|
||||
- [ ] 参照グラフ構築
|
||||
- [ ] P2P非同期フロー追跡
|
||||
- [ ] パフォーマンスプロファイリング
|
||||
|
||||
## 🎯 期待される効果
|
||||
|
||||
### 1. 使いやすさ向上
|
||||
- 1つの環境変数で制御
|
||||
- 分かりやすいプリセット
|
||||
- 統一されたログフォーマット
|
||||
|
||||
### 2. デバッグ効率向上
|
||||
- 必要な情報だけを表示
|
||||
- カテゴリ別フィルタリング
|
||||
- レベル別詳細度制御
|
||||
|
||||
### 3. 保守性向上
|
||||
- 新しいデバッグ機能の追加が容易
|
||||
- 統一されたインターフェース
|
||||
- MIRレベルでの一元管理
|
||||
|
||||
## ✅ 成功基準
|
||||
|
||||
1. **環境変数の数**: 20個以上 → 3個以下
|
||||
2. **デバッグ有効化**: 複雑なコマンド → `NYASH_DEBUG=basic`
|
||||
3. **統一体験**: すべてのコンポーネントで同じデバッグインターフェース
|
||||
|
||||
---
|
||||
|
||||
*Everything is Box, Everything is Debug - 統一されたデバッグ体験へ*
|
||||
85
docs/phases/phase-10/phase_10_8a_from_keyword_consistency.md
Normal file
85
docs/phases/phase-10/phase_10_8a_from_keyword_consistency.md
Normal file
@ -0,0 +1,85 @@
|
||||
# Phase 10.7: fromキーワード一貫性修正
|
||||
|
||||
作成日: 2025-08-27
|
||||
発見者: ニャー
|
||||
|
||||
## 🚨 現在の問題
|
||||
|
||||
### 言語仕様と実装の不一致
|
||||
- **言語仕様**: `from Parent.method()` (2025-08-11完全明示デリゲーション革命で決定)
|
||||
- **実装の一部**: まだ`super`という用語が残っている可能性
|
||||
|
||||
### 影響範囲
|
||||
主にRustの`use super::*`(モジュールインポート)なので言語仕様への影響は限定的だが、以下の確認が必要:
|
||||
1. エラーメッセージ内の文言
|
||||
2. ドキュメントやコメント内の記述
|
||||
3. 内部変数名・関数名での使用
|
||||
|
||||
## 🔧 修正内容
|
||||
|
||||
### 1. エラーメッセージの確認
|
||||
```rust
|
||||
// 例: エラーメッセージで"super"を使っていないか確認
|
||||
"Cannot find super class" → "Cannot find parent box for delegation"
|
||||
```
|
||||
|
||||
### 2. ドキュメント・コメントの統一
|
||||
```rust
|
||||
// Before
|
||||
// Call super method
|
||||
|
||||
// After
|
||||
// Call parent method via from delegation
|
||||
```
|
||||
|
||||
### 3. 内部実装での用語統一(必要に応じて)
|
||||
```rust
|
||||
// 変数名や内部メソッド名での統一
|
||||
super_call() → from_call()
|
||||
SuperMethodCall → FromMethodCall
|
||||
```
|
||||
|
||||
## 📊 優先度評価
|
||||
|
||||
- **重要度**: 中(言語仕様の一貫性)
|
||||
- **緊急度**: 低(機能的には問題ない)
|
||||
- **実装難度**: 低(主に文言修正)
|
||||
|
||||
## 🎯 実装計画
|
||||
|
||||
### Phase 10.7a: 調査フェーズ(1日)
|
||||
- [ ] エラーメッセージ内の"super"使用箇所を特定
|
||||
- [ ] ドキュメント内の不整合を洗い出し
|
||||
- [ ] テストケース内の文言確認
|
||||
|
||||
### Phase 10.7b: 修正フェーズ(1日)
|
||||
- [ ] エラーメッセージの文言修正
|
||||
- [ ] ドキュメント更新
|
||||
- [ ] 必要に応じて内部変数名の統一
|
||||
|
||||
### Phase 10.7c: 検証フェーズ(半日)
|
||||
- [ ] 修正後の動作確認
|
||||
- [ ] エラーメッセージの表示確認
|
||||
- [ ] ドキュメントの整合性チェック
|
||||
|
||||
## 📝 Nyashの哲学との整合性
|
||||
|
||||
### fromキーワードの意義
|
||||
- **明示性**: どの親のどのメソッドかを完全に明示
|
||||
- **統一性**: 宣言(`box Child from Parent`)と呼び出し(`from Parent.method()`)で同じキーワード
|
||||
- **初学者フレンドリー**: 「〜から」という直感的な表現
|
||||
|
||||
### superを使わない理由
|
||||
- 多重デリゲーション時に曖昧
|
||||
- 他言語の概念を引きずらない
|
||||
- Nyash独自の哲学を貫く
|
||||
|
||||
## ✅ 期待される効果
|
||||
|
||||
1. **一貫性**: 言語仕様と実装の完全な一致
|
||||
2. **学習性**: 初学者が混乱しない統一された用語
|
||||
3. **独自性**: Nyashらしい設計思想の徹底
|
||||
|
||||
---
|
||||
|
||||
*「from」こそがNyashの明示的デリゲーションの象徴*
|
||||
155
docs/phases/phase-10/phase_10_9_builtin_box_jit_support.md
Normal file
155
docs/phases/phase-10/phase_10_9_builtin_box_jit_support.md
Normal file
@ -0,0 +1,155 @@
|
||||
# Phase 10.9 – Builtin-Box JIT Support(Box-First Plan)
|
||||
|
||||
目的: Nyashスクリプト → VM(基準)→ JIT(段階導入)。
|
||||
まずは「読み取り系」をJITで安全に通し、箱で問題点を包んで順に拡張する。
|
||||
|
||||
## 🎯 ゴール(DoD)
|
||||
- 機能: String/Array/Map の読み取りAPIが JIT 経路で VM と一致
|
||||
- length/isEmpty/charCodeAt, Array.get, Map.size/has
|
||||
- 境界: 署名不一致・未対応は VM フォールバック(理由はイベントJSONに記録)
|
||||
- 箱: Policy/Events/Registry を 1 箇所参照(切替点の一本化)
|
||||
- 観測: JSONL イベントが最小1件以上出力(オプトイン)
|
||||
|
||||
## 🧱 先に積む箱(最小)
|
||||
- JitConfigBox(設定)
|
||||
- exec/stats/dump/phi_min/hostcall/native_f64/native_bool/threshold を `apply()` でenv反映
|
||||
- `toJson()/fromJson()/summary()` で可視化
|
||||
- JitPolicyBox(ポリシー)
|
||||
- read_only/hostcall_whitelist。書込系は既定で拒否(jit-direct等の安全弁)
|
||||
- JitEventsBox(観測)
|
||||
- compile/execute/fallback/trap を 1行JSON(標準出力 or ファイル)で記録
|
||||
- HostcallRegistryBox(レジストリ)
|
||||
- 許可HostCallと args/ret 署名(唯一の切替点)。不一致は `sig_mismatch`
|
||||
- FrameSlotsBox(スロット)
|
||||
- ptr→slot の割付と型注釈(v0は i64 のみ)
|
||||
- CallBoundaryBox(境界)
|
||||
- JIT↔VM の薄い呼出し点(型変換の一本化)。将来多関数へ拡張
|
||||
|
||||
最小原則: 箱を先に置く(no-op/ログでもOK)→ 切替点を1箇所に固定 → その箱の内部を順に強化。
|
||||
|
||||
## 🛣️ 実行経路の設計(概要)
|
||||
1) Runner: CLI/env→`JitConfig`→TLSへ反映(env直読を排除)
|
||||
2) LowerCore: `jit::config::current()` を参照し、BoxCall/Load/Store/Branch/PHIを最小下ろし
|
||||
3) HostCall: Handle経由で read-only を通す(mutating は Policy で拒否)
|
||||
4) Fallback: 未対応/署名不一致/ポリシー違反は VM 実行へ委譲
|
||||
5) Events: `JitEventsBox` 経由で allow/fallback/trap を JSONL 出力
|
||||
|
||||
## 🔢 対象API(v0)
|
||||
- ArrayBox: `length`, `get`, `isEmpty`, `push/set`(mutatingは拒否)
|
||||
- MapBox: `size`, `has`, `get`, `set`(mutatingは拒否)
|
||||
- StringBox: `length`, `isEmpty`, `charCodeAt`
|
||||
- Math(薄接続): `sin/cos/abs/min/max`(署名一致のみ allow を記録、実体はVMへ)
|
||||
|
||||
## 🗺️ マイルストーン
|
||||
### 10.9-α(足場)
|
||||
- JitPolicyBox v0: read-only/whitelist を箱へ移動
|
||||
- JitEventsBox v0: compile/execute の JSONL イベント(オプトイン)
|
||||
- ドキュメント: 再起動チェック/箱の役割を追記
|
||||
|
||||
### 10.9-β(読み取りカバレッジ)
|
||||
- HostcallRegistryBox v0: String/Array/Map 読み取り API の登録・署名検査
|
||||
- LowerCore: BoxCall read-only 経路を Registry/Policy 参照に切替
|
||||
- E2E: `length/isEmpty/charCodeAt/get/size/has` の一致(jit-direct + VM)
|
||||
|
||||
### 10.9-γ(生成の足場)
|
||||
- CallBoundaryBox v0: JIT→VMで `new` 等を委譲(薄い箱)
|
||||
- `new StringBox/IntegerBox/ArrayBox` の最小経路(方針次第で jit-direct は拒否)
|
||||
|
||||
### 10.9-δ(書き込みの導線のみ)
|
||||
- JitPolicyBox: 書込許可スイッチ(既定OFF)
|
||||
- LowerCore: 書込命令は Policy 参照で拒否/委譲/許可(1箇所で判断)
|
||||
|
||||
## ✅ すぐ使えるチェック
|
||||
- ビルド
|
||||
- `cargo build --release --features cranelift-jit`
|
||||
- 主要フラグ
|
||||
- `NYASH_JIT_EXEC=1` `NYASH_JIT_THRESHOLD=1`
|
||||
- `NYASH_JIT_EVENTS=1`(標準出力へJSON)
|
||||
- 任意: `NYASH_JIT_EVENTS_PATH=target/nyash/jit-events.jsonl`
|
||||
- 代表サンプル(VM経由でJITパス通過)
|
||||
- 成功: `./target/release/nyash --backend vm examples/jit_hostcall_len_string.nyash`
|
||||
- 失敗: `NYASH_JIT_EVENTS=1 ./target/release/nyash --backend vm examples/jit_hostcall_array_append.nyash`
|
||||
- 境界: `NYASH_JIT_EVENTS=1 ./target/release/nyash --backend vm examples/jit_hostcall_math_sin_mismatch.nyash`
|
||||
- 署名一致(allow観測): `NYASH_JIT_EVENTS=1 ./target/release/nyash --backend vm examples/jit_hostcall_math_sin_allow_float.nyash`
|
||||
- 関数スタイル(math.*): `NYASH_JIT_NATIVE_F64=1 NYASH_JIT_EVENTS=1 ./target/release/nyash --backend vm examples/jit_math_function_style_sin_float.nyash`
|
||||
- `cos/abs/min/max` も同様のサンプルあり
|
||||
- 詰まったら
|
||||
- `--features cranelift-jit` が付いているか
|
||||
- イベントJSONに `fallback/trap` の理由が出ているか
|
||||
- `cargo clean -p nyash-rust` → 再ビルド
|
||||
|
||||
## 🧪 検証と観測
|
||||
- 統合JIT統計(テキスト/JSON): sites/compiled/hits/exec_ok/trap/fallback_rate/handles
|
||||
- `JitStatsBox.perFunction()` で関数単位の統計(JSON配列)
|
||||
- CFG/PHIダンプ: `NYASH_JIT_DUMP=1`、`NYASH_JIT_DOT=path.dot`(最小)
|
||||
- b1正規化カウンタ: `b1_norm_count`(分岐条件/PHI)
|
||||
- HostCallイベント: `argc`/`arg_types`/`reason`でデバッグ容易化(mutatingは `policy_denied_mutating`)
|
||||
|
||||
### 🔎 HostCallイベントの基準(10.9-β)
|
||||
- 受け手が関数パラメータ(param)の場合は JIT直実行(allow/sig_ok)を基本にイベント出力
|
||||
- Map.get(Handle, I64): `id: nyash.map.get_h`, `arg_types: ["Handle","I64"]`
|
||||
- Map.get(Handle, Handle): `id: nyash.map.get_hh`, `arg_types: ["Handle","Handle"]`
|
||||
- length/isEmpty/charCodeAt/size 等も `*_h`(Handle受け)でallow
|
||||
- 受け手がparamでない場合は VMへフォールバック(fallback/receiver_not_param)をイベントで記録(読み取り系の可視化を保証)
|
||||
- 例: `id: nyash.any.length_h`, `decision: fallback`, `reason: receiver_not_param`
|
||||
- 数値緩和: `NYASH_JIT_HOSTCALL_RELAX_NUMERIC=1` または `NYASH_JIT_NATIVE_F64=1` で `I64→F64` コアーションを許容(sig_okに影響)
|
||||
|
||||
### 🧪 代表サンプル(E2E)
|
||||
```bash
|
||||
# math.*(関数スタイル): 署名一致でallow、戻りFloat表示
|
||||
NYASH_JIT_EXEC=1 NYASH_JIT_THRESHOLD=1 NYASH_JIT_NATIVE_F64=1 NYASH_JIT_EVENTS=1 \
|
||||
./target/release/nyash --backend vm examples/jit_math_function_style_min_float.nyash
|
||||
|
||||
# Map.get(パラメータ受け+Handleキー → HH直実行)
|
||||
NYASH_JIT_EXEC=1 NYASH_JIT_THRESHOLD=1 NYASH_JIT_HOSTCALL=1 NYASH_JIT_EVENTS=1 \
|
||||
./target/release/nyash --backend vm examples/jit_map_get_param_hh.nyash
|
||||
|
||||
# Map.get(非パラメータ受け → fallback記録)
|
||||
NYASH_JIT_EXEC=1 NYASH_JIT_THRESHOLD=1 NYASH_JIT_HOSTCALL=1 NYASH_JIT_EVENTS=1 \
|
||||
./target/release/nyash --backend vm examples/jit_hostcall_map_get_handle.nyash
|
||||
```
|
||||
|
||||
### ⚙️ Quick flags(イベント観測を確実に)
|
||||
- `NYASH_JIT_EVENTS=1` のとき Runner が `NYASH_JIT_THRESHOLD=1` を自動適用(未指定の場合)
|
||||
- 1回目からLowerが走り、allow/fallbackのイベントが必ず出る
|
||||
- 明示的に `NYASH_JIT_THRESHOLD` を指定した場合はそちらを優先
|
||||
|
||||
## ⚠️ リスクとその箱での緩和
|
||||
- 署名不一致(args/ret)
|
||||
- HostcallRegistryBox で一元検査。不一致は `sig_mismatch` でイベント記録→VMへ
|
||||
- mutatingの混入
|
||||
- JitPolicyBox.read_only で抑止。Registryの Mutating 分類と併用
|
||||
- 型崩れ/ABIの揺れ
|
||||
- `JitValue`(I64/F64/Bool/Handle)へ統一、変換は境界1箇所
|
||||
- 観測不足
|
||||
- JitEventsBox の粒度を最小から用意(必要に応じ拡張)
|
||||
|
||||
## 🔧 実装ノート(現状)
|
||||
- Config: Rust側 `jit::config::JitConfig` に集約。Nyash側は JitConfigBox で操作
|
||||
- LowerCore: BoxCallの read-only は Registry/Policyに委譲。math.* は署名一致なら allow を記録(実行はVM)
|
||||
- Handle: `rt::handles` による u64→Arc<Box>。JIT↔ホストをVM型非参照で独立
|
||||
- 数値緩和: `NYASH_JIT_HOSTCALL_RELAX_NUMERIC=1` で i64→f64 コアーションを許容(既定は `native_f64=1` 時に有効)。`JitConfigBox.set_flag("relax_numeric", true)` でも切替可能
|
||||
|
||||
## 📌 次の拡張(10.9の後)
|
||||
- f64ネイティブ最小経路(`NYASH_JIT_NATIVE_F64=1`)の拡充
|
||||
- Boolネイティブ(b1)署名サポート(ツールチェーンcapに連動)
|
||||
- HostCallブリッジの拡大(Map.getの多型キー、String操作の追加)
|
||||
- CallBoundaryBox経由の `new`/副作用命令の段階的JIT化
|
||||
|
||||
## ✳️ 10.9-δ 書き込みの導線(運用)
|
||||
- 既定ポリシー: read_only(`NYASH_JIT_READ_ONLY=1`)で mutating はフォールバック(`reason: policy_denied_mutating`)。
|
||||
- JitPolicyBox でopt-in:
|
||||
```nyash
|
||||
P = new JitPolicyBox()
|
||||
P.set("read_only", true)
|
||||
P.addWhitelist("nyash.array.push_h") // 個別に許可
|
||||
// またはプリセット:
|
||||
P.enablePreset("mutating_minimal") // Array.push_h を許可
|
||||
```
|
||||
- イベント方針:
|
||||
- 受け手=param: allow/sig_ok(whitelist/オフ時はfallback/policy_denied_mutating)
|
||||
- 受け手≠param: fallback/receiver_not_param(可視化を保証)
|
||||
|
||||
---
|
||||
|
||||
最短ルート: 箱(Policy/Events/Registry/Boundary)を先に置き、読み取り系でJITを安全に通す→観測を増やす→署名とポリシーの一本化で切替点を固定→必要最小限のネイティブ型(f64/b1)を段階導入。
|
||||
220
docs/phases/phase-10/phase_10_app_migration.md
Normal file
220
docs/phases/phase-10/phase_10_app_migration.md
Normal file
@ -0,0 +1,220 @@
|
||||
# Phase 10: Classic C Applications Migration to Nyash
|
||||
|
||||
## 🎯 概要
|
||||
3つの著名なCアプリケーションをNyashに移植し、新実装された高度なメモリ管理機能を実戦テストする。
|
||||
|
||||
## 📦 移植対象アプリケーション(優先順位順)
|
||||
|
||||
### 1. 🌐 **Tinyproxy** - ゼロコピー判定機能の実証
|
||||
**元実装**: https://github.com/tinyproxy/tinyproxy
|
||||
**サイズ**: ~5000行C、軽量HTTPプロキシサーバー
|
||||
**Nyash移植目標**: `apps/tinyproxy_nyash/`
|
||||
|
||||
#### 🔍 **ゼロコピー判定テストケース**
|
||||
```nyash
|
||||
// HTTPリクエスト転送でのメモリ効率検証
|
||||
static box ProxyServer {
|
||||
init { upstream_buffer, downstream_buffer }
|
||||
|
||||
relay_data(client_data) {
|
||||
// ⭐ ゼロコピー判定:バッファーが共有されているかチェック
|
||||
if (me.upstream_buffer.is_shared_with(client_data)) {
|
||||
console.log("✅ Zero-copy achieved!")
|
||||
} else {
|
||||
console.log("❌ Unnecessary copy detected")
|
||||
}
|
||||
|
||||
// 大量データ転送での最適化確認
|
||||
return me.upstream_buffer.share_reference(client_data)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 📋 **実装要件**
|
||||
- HTTPプロキシの基本機能(GET/POST転送)
|
||||
- `SocketBox`でのクライアント・サーバー接続
|
||||
- `BufferBox`での効率的なデータ転送
|
||||
- **ゼロコピー判定API**の実装・テスト
|
||||
|
||||
---
|
||||
|
||||
### 2. 🎮 **Chip-8エミュレーター** - fini伝播とweak生存チェック
|
||||
**元実装**: https://github.com/mattmikolay/chip-8 (参考)
|
||||
**サイズ**: ~1000行C、8ビットゲーム機エミュレーター
|
||||
**Nyash移植目標**: `apps/chip8_nyash/`
|
||||
|
||||
#### 🔍 **メモリ管理テストケース**
|
||||
```nyash
|
||||
// CPU・メモリ・グラフィックスの相互参照関係でのfini伝播テスト
|
||||
static box Chip8CPU {
|
||||
init { memory, graphics, sound }
|
||||
|
||||
fini() {
|
||||
// ⭐ fini伝播:依存オブジェクトの自動クリーンアップ
|
||||
console.log("🔄 CPU cleanup triggered")
|
||||
me.memory.cleanup() // メモリバンクの解放
|
||||
me.graphics.cleanup() // VRAM解放
|
||||
}
|
||||
}
|
||||
|
||||
static box Chip8Memory {
|
||||
init { ram, weak_cpu_ref } // CPUへの弱参照
|
||||
|
||||
read_byte(address) {
|
||||
// ⭐ weak生存チェック:CPUがまだ生きているか確認
|
||||
if (me.weak_cpu_ref.is_alive()) {
|
||||
return me.ram.get(address)
|
||||
} else {
|
||||
console.log("⚠️ CPU destroyed, memory access blocked")
|
||||
return null
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 📋 **実装要件**
|
||||
- Chip-8命令セット実装(35命令)
|
||||
- 64x32ピクセルグラフィックス(`WebCanvasBox`使用)
|
||||
- サウンド出力(`SoundBox`使用)
|
||||
- **fini伝播システム**と**weak参照**の実戦テスト
|
||||
|
||||
---
|
||||
|
||||
### 3. ✏️ **kilo テキストエディター** - 「うっかり全体コピー」検出
|
||||
**元実装**: https://github.com/antirez/kilo
|
||||
**サイズ**: ~1000行C、軽量ターミナルエディター
|
||||
**Nyash移植目標**: `apps/kilo_nyash/`
|
||||
|
||||
#### 🔍 **メモリ効率テストケース**
|
||||
```nyash
|
||||
// 大きなテキストファイル編集での不必要なコピー検出
|
||||
static box TextBuffer {
|
||||
init { lines, undo_stack }
|
||||
|
||||
insert_char(row, col, char) {
|
||||
local old_lines_size = me.lines.memory_footprint()
|
||||
|
||||
// 文字挿入操作
|
||||
me.lines.get(row).insert_at(col, char)
|
||||
|
||||
local new_lines_size = me.lines.memory_footprint()
|
||||
local size_diff = new_lines_size - old_lines_size
|
||||
|
||||
// ⭐ 「うっかり全体コピー」検出
|
||||
if (size_diff > 1000) { // 1文字挿入で1KB以上増加
|
||||
console.log("🚨 INEFFICIENT COPY DETECTED!")
|
||||
console.log("Expected: 1 byte, Actual: " + size_diff + " bytes")
|
||||
me.log_memory_leak_warning()
|
||||
}
|
||||
}
|
||||
|
||||
// 大規模な検索・置換での効率性チェック
|
||||
search_and_replace(pattern, replacement) {
|
||||
local initial_memory = me.lines.memory_footprint()
|
||||
|
||||
// 検索・置換実行
|
||||
me.lines.replace_all(pattern, replacement)
|
||||
|
||||
local final_memory = me.lines.memory_footprint()
|
||||
// メモリ使用量が2倍を超えた場合は問題
|
||||
if (final_memory > initial_memory * 2) {
|
||||
console.log("⚠️ Memory usage doubled during replace operation")
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 📋 **実装要件**
|
||||
- ターミナル操作(`ConsoleBox`での入出力)
|
||||
- ファイル読み書き(`FileBox`使用)
|
||||
- 基本的な編集機能(カーソル移動、挿入、削除)
|
||||
- **メモリ効率監視**と**コピー検出システム**
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ **技術的実装指針**
|
||||
|
||||
### 共通アーキテクチャ
|
||||
```nyash
|
||||
// 各アプリケーション共通の構造
|
||||
static box AppName {
|
||||
init { core_components }
|
||||
|
||||
main() {
|
||||
me.initialize_components()
|
||||
me.run_main_loop()
|
||||
me.cleanup_resources()
|
||||
}
|
||||
|
||||
// メモリ効率レポート(全アプリ共通)
|
||||
memory_report() {
|
||||
return new MapBox()
|
||||
.set("zero_copy_count", me.zero_copy_operations)
|
||||
.set("unnecessary_copies", me.detected_copies)
|
||||
.set("memory_leaks", me.fini_failures)
|
||||
.set("weak_ref_cleanups", me.weak_cleanup_count)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 新API要件
|
||||
1. **ゼロコピー判定API**
|
||||
- `BufferBox.is_shared_with(other)` → BoolBox
|
||||
- `BufferBox.share_reference(data)` → 参照共有
|
||||
|
||||
2. **fini伝播システム**
|
||||
- 自動的な依存オブジェクトクリーンアップ
|
||||
- クリーンアップチェーンの可視化
|
||||
|
||||
3. **weak参照システム**
|
||||
- `WeakBox.is_alive()` → BoolBox
|
||||
- 循環参照の自動検出・回避
|
||||
|
||||
4. **メモリ効率監視**
|
||||
- `Box.memory_footprint()` → IntegerBox
|
||||
- コピー発生の検出・警告
|
||||
|
||||
---
|
||||
|
||||
## 🎯 **期待される成果**
|
||||
|
||||
### パフォーマンス目標
|
||||
- **Tinyproxy**: HTTP転送でのゼロコピー率 90%以上
|
||||
- **Chip-8**: 60FPSエミュレーション + fini伝播の完全動作
|
||||
- **kilo**: 1MB+ファイル編集でのメモリ効率 95%以上
|
||||
|
||||
### 学習効果
|
||||
- **Copilot**: 大規模Nyashアプリケーション開発経験
|
||||
- **開発者**: 新メモリ管理機能の実用性確認
|
||||
- **コミュニティ**: Nyashでの実用アプリケーション事例
|
||||
|
||||
---
|
||||
|
||||
## 📅 **実装計画**
|
||||
|
||||
### Phase 10.1: Tinyproxy実装 (1週間)
|
||||
- HTTPプロキシ基本機能
|
||||
- ゼロコピー判定API実装・テスト
|
||||
|
||||
### Phase 10.2: Chip-8実装 (1週間)
|
||||
- エミュレーター基本機能
|
||||
- fini伝播・weak参照の実戦テスト
|
||||
|
||||
### Phase 10.3: kilo実装 (1週間)
|
||||
- テキストエディター基本機能
|
||||
- メモリ効率監視システム
|
||||
|
||||
### Phase 10.4: 統合テスト・最適化 (1週間)
|
||||
- 3アプリケーション同時実行テスト
|
||||
- パフォーマンス分析・改善
|
||||
|
||||
---
|
||||
|
||||
## 🚀 **この移植プロジェクトの意義**
|
||||
|
||||
1. **実用性の実証**: Nyashで実際のアプリケーションが作れることを証明
|
||||
2. **新機能の検証**: ゼロコピー・fini・weakの実戦テスト
|
||||
3. **開発体験の向上**: Copilotとの協調開発での生産性検証
|
||||
4. **エコシステム拡充**: Nyashアプリケーションの具体例提供
|
||||
|
||||
**この移植が成功すれば、Nyashは「実用的なプログラミング言語」として確立されます!** 🎉
|
||||
267
docs/phases/phase-10/phase_10_cranelift_jit_backend.md
Normal file
267
docs/phases/phase-10/phase_10_cranelift_jit_backend.md
Normal file
@ -0,0 +1,267 @@
|
||||
# Phase 10: Cranelift JIT Backend(MIR→VM→Cranelift)
|
||||
|
||||
Status: Planned (Primary path for native speed)
|
||||
Last Updated: 2025-08-25
|
||||
|
||||
## 🎯 ゴール
|
||||
- 実行系の主経路を「MIR→VM」を維持しつつ、ホットパスをCraneliftでJIT化して高速化する。
|
||||
- LLVM AOTは後段(Phase 11以降)の研究対象へ繰り延べ。
|
||||
|
||||
## 🔗 位置づけ
|
||||
- これまでの案(MIR→LLVM AOT)を改め、現実的な開発速度と安定性を優先してCranelift JITを先行。
|
||||
- VMとのハイブリッド実行(OSR/ホットカウントに基づくJIT)を採用。
|
||||
|
||||
## 📐 アーキテクチャ
|
||||
```
|
||||
AST → MIR → Optimizer → VM Dispatcher
|
||||
└─(Hot)→ Cranelift JIT (fn単位)
|
||||
```
|
||||
- VMが命令カウント・プロファイルを集計し、しきい値超過関数をJITコンパイル。
|
||||
- JIT済み関数は関数テーブルから直接呼び出し、VMはフォールバック先として維持。
|
||||
|
||||
## 📋 スコープ
|
||||
1) 基盤
|
||||
- JITマネージャ(関数プロファイル・コンパイルキャッシュ)
|
||||
- Craneliftコード生成(MIR→CLIF Lower)
|
||||
- 呼出しABI(Nyash VMスタック/レジスタとのブリッジ)
|
||||
|
||||
2) 命令カバレッジ(段階導入)
|
||||
- Phase A: Const/Copy/BinOp/Compare/Jump/Branch/Return(純関数相当)
|
||||
- Phase B: Call/BoxCall/ArrayGet/ArraySet(ホットパス対応)
|
||||
- Phase C: TypeOp/Ref*/Weak*/Barrier(必要最小)
|
||||
|
||||
3) ランタイム連携
|
||||
- Boxの所有・参照モデルを維持(共有/クローンの意味論を破らない)
|
||||
- 例外・TypeErrorはVMの例外パスへエスケープ
|
||||
|
||||
## ✅ 受け入れ基準(Milestone)
|
||||
- M1: 算術/比較/分岐/returnの関数がJIT化され、VMより高速に実行
|
||||
- M2: Array/Mapの代表操作(get/set/push/size)がJITで安定動作
|
||||
- M3: BoxCallホットパス(特にArray/Map)で有意な高速化(2×目標)
|
||||
- M4: 回帰防止のベンチと`--vm-stats`連携(JITカウント/時間)
|
||||
|
||||
## 🪜 実装ステップ
|
||||
1. JITマネージャ/関数プロファイルの導入(VM統計と統合)
|
||||
2. MIR→CLIF Lower骨子(基本型/算術/比較/制御)
|
||||
3. 呼出しABIブリッジ(引数/戻り値/BoxRefの表現)
|
||||
4. JIT関数テーブル + VMディスパッチ切替
|
||||
5. Array/Map/BoxCallのホットパス最適化
|
||||
6. TypeOp/Ref/Weak/Barrierの必要最小を実装
|
||||
7. ベンチ/スナップショット整備・回帰検出
|
||||
|
||||
## ⚠️ 依存・前提
|
||||
- MIR26整合(TypeOp/WeakRef/Barrierの統合前提)
|
||||
- P2PBox再設計(Phase 9.x)を先に安定化しておく(VM/プラグインE2E維持)
|
||||
|
||||
## 📚 参考
|
||||
- Cranelift: Peepmatic/CLIF、simple_jitの最小例
|
||||
- JIT/VMハイブリッド: LuaJIT/HotSpotのOSR設計
|
||||
|
||||
---
|
||||
備考: LLVM AOTはPhase 11以降の研究路線に移行(設計ドキュメントは維持)。
|
||||
|
||||
## 🔬 Sub-Phases (10_a .. 10_h)
|
||||
|
||||
各サブフェーズは「小さく立ち上げ→検証→次へ」。既存のVM/Thunk/PICを活用し、JITは同じ経路に自然合流させる。
|
||||
|
||||
### 10_a: JITブートストラップ(基盤+プロファイラ)
|
||||
- 目的: Cranelift JITの骨組みとホット関数検出の導線を用意。
|
||||
- 具体:
|
||||
- `JitManager`(関数プロファイル、しきい値、キャッシュ)
|
||||
- CLIF環境初期化(`Module`, `Context`, `ISA`)
|
||||
- VM統合: 関数入口でホット度チェック→JITコンパイル/呼び出し
|
||||
- 診断: `NYASH_JIT_STATS=1`(JIT件数/時間/キャッシュヒット)
|
||||
- 受入: ダミー関数をJIT登録してVMから呼出可能、ログが出る
|
||||
|
||||
### 10_b: Lower(Core-1) – Const/Move/BinOp/Cmp/Branch/Ret
|
||||
- 目的: ループや条件分岐を含む純粋関数をJIT実行可能に。
|
||||
- 具体:
|
||||
- MIR値/型→CLIF型(i64/f64/i1/void)
|
||||
- Const/Copy/算術/比較/ジャンプ/分岐/return のLower
|
||||
- フレームレイアウト(VMValue最小表現)
|
||||
- 受入: 算術/比較/分岐のみの関数がJITでVMより速い(小ベンチ)
|
||||
|
||||
### 10_c: ABI/呼出し – 関数呼び出しとフォールバック
|
||||
- 目的: JIT化関数から他関数を呼ぶ/VMへ戻る道を用意。
|
||||
- 具体:
|
||||
- 同一モジュール関数呼び出し(JIT→JIT/JIT→VM)
|
||||
- 引数/戻り値の受け渡し(整数/浮動/void)
|
||||
- 例外/TypeErrorはVMへバイアウト(trap→VM)
|
||||
- 受入: 再帰/多段呼び出しが安定動作
|
||||
|
||||
### 10_d: コレクション基礎 – Array/Map ホット操作(外部呼び出し)
|
||||
- 目的: 実用的ホットパス(length/get/set/push/pop)をJIT側から呼べるように。
|
||||
- 具体:
|
||||
- ホスト関数テーブル(外部シンボル)で既存Rust実装を呼ぶ
|
||||
- 境界チェック/エラーはRust側に委譲、JITは薄い橋渡し
|
||||
- 受入: Array操作がVM経由より高速(目安1.5–2.0×)
|
||||
|
||||
Status(2025-08-27)
|
||||
- Param経路でのE2Eを実装(`NYASH_JIT_HOSTCALL=1`ゲート)
|
||||
- 実装済みシンボル(PoC, C-ABI in Rust):
|
||||
- `nyash.array.{len,push,get,set}` / `nyash.map.size`
|
||||
- 使い方(例):
|
||||
```bash
|
||||
cargo build --features cranelift-jit --release
|
||||
NYASH_JIT_THRESHOLD=1 NYASH_JIT_HOSTCALL=1 NYASH_JIT_EXEC=1 \
|
||||
./target/release/nyash --backend vm examples/jit_array_param_call.nyash
|
||||
NYASH_JIT_THRESHOLD=1 NYASH_JIT_HOSTCALL=1 NYASH_JIT_EXEC=1 \
|
||||
./target/release/nyash --backend vm examples/jit_map_param_call.nyash
|
||||
```
|
||||
Notes
|
||||
- 関数パラメータに渡した配列/MapのみHostCall経由でアクセス(thread-local引数参照)
|
||||
- ローカルnew値は10_eへ移管(ハンドル表PoC: u64→Arc<Box>)
|
||||
|
||||
### 10_e: BoxCall高速化 – Thunk/PICの直結
|
||||
- 目的: Phase 9.79bの `TypeMeta{slot->thunk}` と Poly-PIC をJITにインライン。
|
||||
- 具体:
|
||||
- `slot -> thunk -> target` 解決をJITで再現(ユニバーサル0..3含む)
|
||||
- `(type_id, version)` チェック(Poly-PIC 2–4件)→ヒット直呼び、ミスVM
|
||||
- バージョンミスマッチで安全にフォールバック
|
||||
- 受入: BoxCallホットサイトで2×以上の高速化+正しい無効化挙動
|
||||
|
||||
### 10_f: TypeOp/Ref/Weak/Barrier(最小)
|
||||
- 目的: 実アプリで必要な最小限のタイプ/参照操作を埋める。
|
||||
- 具体:
|
||||
- `as_bool()` 等の基本型変換
|
||||
- 参照/弱参照/バリアの最小パス(重い経路はVMへ)
|
||||
- 受入: 代表的コードパスでJIT有効のままE2E成功
|
||||
|
||||
### 10_g: 診断/ベンチ/回帰
|
||||
- 目的: 可視化と安定化。
|
||||
- 具体:
|
||||
- `--vm-stats` にJIT統計統合(compile/ms, sites, cache率)
|
||||
- ベンチ更新(JIT有/無比較)とスナップショット
|
||||
- 受入: CIで回帰検知可能/ドキュメント更新
|
||||
|
||||
### 10_h: 硬化・パフォーマンス調整
|
||||
- 目的: ホットスポットの最適化とノイズ除去。
|
||||
- 具体:
|
||||
- ガード配置最適化(分岐予測/ICヒット優先)
|
||||
- 不要コピー削減、ホスト呼出回数の削減
|
||||
- 受入: 代表ベンチで安定して目標達成(2×以上)
|
||||
|
||||
## 📦 成果物(各サブフェーズ)
|
||||
- 10_a: `jit/manager.rs` スケルトン、VM連携、統計ログ
|
||||
- 10_b: `jit/lower/core.rs`(Const/BinOp/Cmp/Branch/Ret)+単体テスト
|
||||
- 10_c: `jit/abi.rs`(call/ret/fallback)+再帰テスト
|
||||
- 10_d: `jit/extern/collections.rs`(Array/Mapブリッジ)+マイクロベンチ
|
||||
- 10_e: `jit/inline_cache.rs`(PIC/VT連携)+無効化テスト
|
||||
- 10_f: `jit/lower/typeop_ref.rs`(最小)
|
||||
- 10_g: ベンチ/統計/README更新
|
||||
- 10_h: 最適化コミットと測定レポート
|
||||
|
||||
## 🧩 既存資産との連携(重要)
|
||||
- Thunk: Phase 9.79b.3の `TypeMeta{thunks}` をJIT直呼びターゲットとして使用
|
||||
- Poly-PIC: VMの構造をJITに投影(同じキー `(label, version)` を使用)
|
||||
- Versioning: `cache_versions` のイベントに同期してIC無効化
|
||||
|
||||
## 🎯 マイルストーン再定義
|
||||
- M1: 10_a + 10_b 合格(Core関数のJIT実行)
|
||||
- M2: 10_c + 10_d 合格(関数呼出/Arrayホット操作)
|
||||
- M3: 10_e 合格(BoxCallホットパス2×)
|
||||
- M4: 10_g + 10_h 合格(ベンチ/統計/硬化)
|
||||
|
||||
## ⚠️ リスクと緩和
|
||||
- ABI複雑化: まず整数/浮動/voidに限定し、BoxRefはホスト関数へブリッジ
|
||||
- 最適化過剰: 常にVMフォールバックを保持、ガード失敗で安全に戻す
|
||||
- デバッグ困難: CLIFダンプ/CFG表示/`NYASH_JIT_STATS`で観測
|
||||
|
||||
## 🐛 発見した問題点(2025-08-27 ベンチマーク実行時)
|
||||
|
||||
### 1. インタープリター性能問題
|
||||
- **問題**: 10万回のループで2分以上かかりタイムアウト
|
||||
- **原因**: `unwrap_instance`のデバッグログが大量出力(毎回の演算でInstanceBoxチェック)
|
||||
- **目標**: 10万回ループを数秒で完了
|
||||
- **対策**:
|
||||
- デバッグログの条件付き出力化
|
||||
- 基本演算の高速化(IntegerBoxの直接操作最適化)
|
||||
|
||||
### 2. VMの変数管理エラー
|
||||
- **問題**: `Invalid value: Value %47 not set` - simple_add_loop内の変数zが正しく管理されていない
|
||||
- **原因**: MIR生成時の変数スコープ管理の不具合
|
||||
- **対策**: MirBuilderの変数トラッキング改善
|
||||
|
||||
### 3. Box APIの成熟度
|
||||
- **問題**: TimeBoxにelapsed()/reset()メソッドがインタープリターから呼べない
|
||||
- **原因**: Boxメソッドの登録システム未完成
|
||||
- **対策**:
|
||||
- Boxメソッドの統一的登録システム実装
|
||||
- インタープリターとVMのメソッド解決統一
|
||||
|
||||
### 4. ベンチマーク基盤
|
||||
- **問題**: Nyashスクリプトでの正確な時間計測が困難
|
||||
- **根本原因**: TimeBoxのelapsed()/reset()メソッドがインタープリターから呼べない(Box API問題と同じ)
|
||||
- **対策**: Box APIの成熟度問題(問題3)が解決すれば自動的に解決
|
||||
|
||||
### 改善優先度
|
||||
1. **高**: インタープリター性能問題(基本機能の使い物にならない)
|
||||
2. **中**: VM変数管理(JIT最適化の前提)
|
||||
3. **中**: Box APIの成熟度(ベンチマーク基盤も同時解決)
|
||||
|
||||
## 🚀 Phase 10.9: Cranelift AOT Backend(追加計画)
|
||||
|
||||
Status: Future (JIT実装の上乗せで実現可能)
|
||||
|
||||
### 概要
|
||||
JIT実装(10_a~10_h)で構築したMIR→CLIF変換基盤をそのまま活用し、事前コンパイル(AOT)によるスタンドアロン実行ファイル生成を実現する。
|
||||
|
||||
### 利点
|
||||
- **コード再利用**: JITと同じLowerCore実装を使用(追加実装最小)
|
||||
- **非同期完全サポート**: WASMの制限なし、ネイティブ非同期可能
|
||||
- **最高性能**: ネイティブコード直接実行(起動時コンパイル不要)
|
||||
- **デバッグ容易**: gdb/lldb等のネイティブデバッガ使用可能
|
||||
|
||||
### 実装ステップ案
|
||||
```
|
||||
10.9a: ObjectModule統合
|
||||
├── cranelift-objectモジュール導入
|
||||
├── CLIF→オブジェクトファイル生成
|
||||
└── 既存のLowerCore再利用
|
||||
|
||||
10.9b: ランタイムライブラリ
|
||||
├── Nyash標準Box群の静的リンク版作成
|
||||
├── プラグインの静的埋め込み対応
|
||||
└── 最小ランタイム(GC hooks等)分離
|
||||
|
||||
10.9c: リンカー統合
|
||||
├── cc/ldによる実行ファイル生成
|
||||
├── プラットフォーム別設定
|
||||
└── デバッグシンボル生成
|
||||
|
||||
10.9d: クロスコンパイル
|
||||
├── 複数ターゲット(x86_64/aarch64/wasm32)
|
||||
├── ターゲット別最適化
|
||||
└── CI/CDでのマルチプラットフォームビルド
|
||||
```
|
||||
|
||||
### 使用イメージ
|
||||
```bash
|
||||
# ネイティブ実行ファイル生成
|
||||
./target/release/nyash --compile-native program.nyash -o program
|
||||
./program # スタンドアロン実行!
|
||||
|
||||
# クロスコンパイル
|
||||
./target/release/nyash --compile-native --target x86_64-pc-windows-msvc program.nyash -o program.exe
|
||||
./target/release/nyash --compile-native --target aarch64-apple-darwin program.nyash -o program.mac
|
||||
```
|
||||
|
||||
### 技術的詳細
|
||||
- **共通基盤**: `LowerCore`のemit処理はJIT/AOT両対応
|
||||
- **差分実装**: JITは`JITModule`、AOTは`ObjectModule`を使用
|
||||
- **リンク方式**: 静的リンク優先(配布容易性重視)
|
||||
- **サイズ最適化**: LTO/strip対応で実行ファイルサイズ削減
|
||||
|
||||
### WASM AOTとの比較
|
||||
| 特性 | Cranelift AOT | WASM AOT |
|
||||
|------|--------------|----------|
|
||||
| 非同期 | ✅ 完全対応 | ❌ 制限あり |
|
||||
| 実行速度 | 最速 | 速い |
|
||||
| ファイルサイズ | 大(MB級) | 小(KB級) |
|
||||
| ポータビリティ | プラットフォーム別 | 高い |
|
||||
| デバッグ | ネイティブツール | 限定的 |
|
||||
|
||||
### 想定スケジュール
|
||||
- Phase 10(JIT)安定化後に着手
|
||||
- 実装期間: 2-3週間(JIT基盤の再利用により短期実現可能)
|
||||
- 初期ターゲット: Linux x86_64、その後Windows/macOS対応
|
||||
@ -0,0 +1,72 @@
|
||||
# Phase 10: Function Declaration MIR サポート課題
|
||||
|
||||
作成日: 2025-08-27
|
||||
発見者: Claude & ChatGPT5 & ニャー
|
||||
|
||||
## 🚨 現在の問題
|
||||
|
||||
### 症状
|
||||
```bash
|
||||
❌ MIR compilation error: Unsupported AST node type: FunctionDeclaration
|
||||
```
|
||||
|
||||
### 影響範囲
|
||||
- 通常の`function`定義がMIRでコンパイルできない
|
||||
- JITテストで関数を使った配列操作ができない
|
||||
- Static Boxメソッドは動作するが、通常関数が使えない
|
||||
|
||||
### 具体例
|
||||
```nyash
|
||||
// ❌ 動作しない - FunctionDeclarationがMIR未対応
|
||||
function len_of(arr) {
|
||||
return arr.length()
|
||||
}
|
||||
|
||||
// ✅ 動作する - Static Boxメソッド
|
||||
static box Utils {
|
||||
len_of(arr) {
|
||||
return arr.length()
|
||||
}
|
||||
}
|
||||
|
||||
// ✅ 動作する - 直接呼び出し
|
||||
local arr = new ArrayBox()
|
||||
local len = arr.length()
|
||||
```
|
||||
|
||||
## 🔧 解決案
|
||||
|
||||
### Option 1: MIRビルダーにFunctionDeclaration対応追加
|
||||
```rust
|
||||
// mir/builder.rs に追加
|
||||
AstNode::FunctionDeclaration { name, params, body, .. } => {
|
||||
// 関数をMirFunctionとして登録
|
||||
let mir_func = self.build_function(name, params, body)?;
|
||||
self.functions.insert(name.clone(), mir_func);
|
||||
}
|
||||
```
|
||||
|
||||
### Option 2: ASTレベルでStatic Boxに変換
|
||||
- FunctionDeclarationを内部的にStatic Boxメソッドに変換
|
||||
- 互換性を保ちつつ既存の仕組みを活用
|
||||
|
||||
### Option 3: 当面の回避策を公式化
|
||||
- ドキュメントで「VMモードではStatic Boxメソッドを推奨」と明記
|
||||
- 将来のサポートとして計画に含める
|
||||
|
||||
## 📊 優先度評価
|
||||
|
||||
- **重要度**: 中(基本的な言語機能だが回避策あり)
|
||||
- **緊急度**: 低(Static Boxで代替可能)
|
||||
- **実装難度**: 中(MIRビルダーの拡張が必要)
|
||||
|
||||
## 🎯 推奨アクション
|
||||
|
||||
1. **短期**: Static Boxメソッドを使った回避策をドキュメント化
|
||||
2. **中期**: Phase 10.1でFunctionDeclaration対応を実装
|
||||
3. **長期**: 関数定義の最適化(インライン化等)も検討
|
||||
|
||||
## 📝 関連イシュー
|
||||
- JIT配列操作テスト
|
||||
- MIRビルダー拡張
|
||||
- 言語仕様の完全性
|
||||
35
docs/phases/phase-10/phase_10_gc_threads_order.txt
Normal file
35
docs/phases/phase-10/phase_10_gc_threads_order.txt
Normal file
@ -0,0 +1,35 @@
|
||||
Phase 10 — GC/Thread Roadmap Order (txt)
|
||||
|
||||
Recommended order:
|
||||
10_4a → 10_4b → 10_6a → 10_4c → 10_4d → 10_6b → 10_6c
|
||||
|
||||
10_4a: GC hook scaffolding
|
||||
- Add GcHooks { safepoint(), barrier(kind) } and BarrierKind.
|
||||
- NyashRuntime holds Arc<dyn GcHooks>; builder supports with_gc_hooks.
|
||||
- VM calls hooks at MIR Safepoint/Barrier*.
|
||||
|
||||
10_4b: Roots + minimal barriers
|
||||
- ScopeTracker root API: enter_root_region/leave_root_region/pin_root.
|
||||
- Write-Barrier at RefSet/ArraySet/BoxCall(Array/Map: set/push).
|
||||
- Tracing flags: NYASH_GC_TRACE=1 for barrier/safepoint and roots.
|
||||
|
||||
10_6a: Thread-safety audit (prep)
|
||||
- Audit Builtin/User/Plugin boxes for Send/Sync policy.
|
||||
- Strategy for shared state (RwLock) and non-thread-safe wrappers.
|
||||
|
||||
10_4c: GC PoC (STW, single-thread)
|
||||
- Implement simple collector behind GcHooks (e.g., mark-sweep or RC hybrid).
|
||||
- Manage roots via ScopeTracker; traverse VMValue graph/object_fields.
|
||||
|
||||
10_4d: Barrier hardening + regression
|
||||
- Ensure coverage for all mutating write sites (Array/Map/Ref/Plugin paths).
|
||||
- Strict checks flag for development; add stress/regression tests.
|
||||
|
||||
10_6b: Thread runtime scaffolding
|
||||
- Scheduler abstraction (cooperative preemption), Future/Channel compliance.
|
||||
- Confirm GcHooks is Send+Sync and shareable.
|
||||
|
||||
10_6c: Parallel GC design notes
|
||||
- Per-thread root regions, card marking/write barriers, safepoint coordination.
|
||||
- Document design and API diffs for later implementation.
|
||||
|
||||
200
docs/phases/phase-11.5/11.5a-WRITE-BARRIER-REMOVAL.md
Normal file
200
docs/phases/phase-11.5/11.5a-WRITE-BARRIER-REMOVAL.md
Normal file
@ -0,0 +1,200 @@
|
||||
# Phase 11.5a: Write Barrier除去によるGC最適化
|
||||
|
||||
## 🎯 目標
|
||||
JITコンパイル時にescape analysisを行い、不要なwrite barrierを除去してGC性能を大幅に向上させる。
|
||||
|
||||
## 📊 現状の問題
|
||||
|
||||
### 現在のVM実装
|
||||
```rust
|
||||
// すべてのrefset操作でbarrierが呼ばれる
|
||||
pub fn execute_ref_set(&mut self, reference: ValueId, field: &str, value: ValueId)
|
||||
-> Result<ControlFlow, VMError> {
|
||||
// ... 値の設定 ...
|
||||
|
||||
// 常にwrite barrierが実行される
|
||||
gc_write_barrier_site(&self.runtime, "RefSet");
|
||||
Ok(ControlFlow::Continue)
|
||||
}
|
||||
```
|
||||
|
||||
### オーバーヘッド
|
||||
- 単純な代入でも毎回barrier呼び出し
|
||||
- Stack上のローカル変数でも不要にbarrier
|
||||
- ループ内での大量のbarrier呼び出し
|
||||
|
||||
## 🚀 実装計画
|
||||
|
||||
### Step 1: Escape Analysis基盤
|
||||
```rust
|
||||
// mir/escape_analysis.rs
|
||||
pub struct EscapeAnalysis {
|
||||
// allocation site追跡
|
||||
allocations: HashMap<ValueId, AllocInfo>,
|
||||
// escape状態
|
||||
escapes: HashSet<ValueId>,
|
||||
// 解析結果キャッシュ
|
||||
cache: HashMap<FunctionId, EscapeInfo>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct AllocInfo {
|
||||
location: BasicBlockId,
|
||||
kind: AllocKind,
|
||||
size: Option<usize>,
|
||||
}
|
||||
|
||||
enum AllocKind {
|
||||
NewBox, // new StringBox()
|
||||
ArrayNew, // []
|
||||
RefNew, // ユーザー定義Box
|
||||
}
|
||||
```
|
||||
|
||||
### Step 2: MIR解析
|
||||
```rust
|
||||
impl EscapeAnalysis {
|
||||
/// 関数内でのescape解析
|
||||
pub fn analyze_function(&mut self, func: &MirFunction) -> EscapeInfo {
|
||||
// 1. allocation site収集
|
||||
for (bb_id, bb) in &func.basic_blocks {
|
||||
for inst in &bb.instructions {
|
||||
match inst {
|
||||
MirInstruction::NewBox { dst, .. } |
|
||||
MirInstruction::ArrayNew { dst, .. } |
|
||||
MirInstruction::RefNew { dst, .. } => {
|
||||
self.allocations.insert(*dst, AllocInfo {
|
||||
location: bb_id,
|
||||
kind: self.classify_alloc(inst),
|
||||
size: self.estimate_size(inst),
|
||||
});
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 2. escape point検出
|
||||
self.find_escape_points(func);
|
||||
|
||||
// 3. 結果集計
|
||||
EscapeInfo {
|
||||
non_escaping: self.collect_non_escaping(),
|
||||
barrier_sites: self.collect_barrier_sites(),
|
||||
}
|
||||
}
|
||||
|
||||
fn find_escape_points(&mut self, func: &MirFunction) {
|
||||
// return文でのescape
|
||||
// 関数引数としてのescape
|
||||
// グローバル変数へのescape
|
||||
// プラグイン呼び出しでのescape
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Step 3: JIT統合
|
||||
```rust
|
||||
// jit/lower/builder.rs
|
||||
impl<'a> LoweringBuilder<'a> {
|
||||
fn emit_ref_set(&mut self, reference: Value, field: &str, value: Value) {
|
||||
// escape解析結果を確認
|
||||
let needs_barrier = self.escape_info
|
||||
.map(|info| info.needs_barrier(reference))
|
||||
.unwrap_or(true); // 解析なしなら保守的にbarrier
|
||||
|
||||
if needs_barrier {
|
||||
// barrierあり
|
||||
self.emit_gc_barrier(BarrierKind::Write);
|
||||
} else {
|
||||
// barrier除去!
|
||||
if self.config.trace_opt {
|
||||
eprintln!("[JIT] barrier removed at {:?}", self.current_location());
|
||||
}
|
||||
}
|
||||
|
||||
// 実際のstore操作
|
||||
self.emit_store(reference, field, value);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Step 4: 最適化レベル設定
|
||||
```rust
|
||||
// 環境変数で制御
|
||||
NYASH_JIT_ESCAPE_ANALYSIS=1 # escape analysis有効化
|
||||
NYASH_JIT_BARRIER_OPT=1 # barrier最適化有効化
|
||||
NYASH_JIT_BARRIER_STATS=1 # 統計出力
|
||||
```
|
||||
|
||||
## 📈 期待される効果
|
||||
|
||||
### ベンチマーク例
|
||||
```nyash
|
||||
// 大量のローカル変数操作
|
||||
function processData(n) {
|
||||
local sum = 0
|
||||
local temp = new MapBox()
|
||||
|
||||
loop(i < n) {
|
||||
temp.set(i, i * 2) // escape analysisでbarrier除去
|
||||
sum = sum + temp.get(i)
|
||||
i = i + 1
|
||||
}
|
||||
|
||||
return sum
|
||||
}
|
||||
```
|
||||
|
||||
### 性能改善予測
|
||||
- ローカル変数操作: 90%以上のbarrier除去
|
||||
- ループ内操作: 80%以上の高速化
|
||||
- 全体的なGCオーバーヘッド: 50%削減
|
||||
|
||||
## 🔍 検証方法
|
||||
|
||||
### 1. Barrier統計
|
||||
```json
|
||||
{
|
||||
"total_barriers": 10000,
|
||||
"removed_barriers": 8500,
|
||||
"removal_rate": 0.85,
|
||||
"sites": {
|
||||
"RefSet": { "total": 5000, "removed": 4800 },
|
||||
"ArraySet": { "total": 3000, "removed": 2500 },
|
||||
"MapSet": { "total": 2000, "removed": 1200 }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 性能測定
|
||||
```bash
|
||||
# barrier最適化なし
|
||||
NYASH_JIT_ESCAPE_ANALYSIS=0 ./target/release/nyash --benchmark
|
||||
|
||||
# barrier最適化あり
|
||||
NYASH_JIT_ESCAPE_ANALYSIS=1 ./target/release/nyash --benchmark
|
||||
```
|
||||
|
||||
## 🚧 実装上の注意点
|
||||
|
||||
1. **保守的な解析**
|
||||
- 不明な場合は必ずbarrierを残す
|
||||
- プラグイン境界では常にbarrier
|
||||
|
||||
2. **デバッグ性**
|
||||
- 除去したbarrierサイトを記録
|
||||
- GCエラー時の診断情報
|
||||
|
||||
3. **段階的実装**
|
||||
- まずローカル変数のみ
|
||||
- 次にループ不変式
|
||||
- 最後に関数間解析
|
||||
|
||||
## 🎉 完了基準
|
||||
|
||||
- [ ] Escape analysis基本実装
|
||||
- [ ] MIR解析パス追加
|
||||
- [ ] JIT統合
|
||||
- [ ] ベンチマーク50%改善
|
||||
- [ ] ドキュメント更新
|
||||
240
docs/phases/phase-11.5/11.5b-ATOMIC-OPTIMIZATION.md
Normal file
240
docs/phases/phase-11.5/11.5b-ATOMIC-OPTIMIZATION.md
Normal file
@ -0,0 +1,240 @@
|
||||
# Phase 11.5b: Atomic操作最適化によるsync処理高速化
|
||||
|
||||
## 🎯 目標
|
||||
Arc<Mutex>の重いロック操作を、可能な限り軽量なatomic操作に置き換えて性能を向上させる。
|
||||
|
||||
## 📊 現状の問題
|
||||
|
||||
### 現在の実装
|
||||
```rust
|
||||
// すべてのBox操作でMutexロック
|
||||
pub fn get_field(&self, name: &str) -> Option<Box<dyn NyashBox>> {
|
||||
let fields = self.fields.lock().unwrap(); // 重い!
|
||||
fields.get(name).cloned()
|
||||
}
|
||||
|
||||
// Read-onlyでも同じコスト
|
||||
pub fn to_string(&self) -> String {
|
||||
let value = self.value.lock().unwrap(); // 不要なロック!
|
||||
value.clone()
|
||||
}
|
||||
```
|
||||
|
||||
### パフォーマンス問題
|
||||
- Read操作でも排他ロックのオーバーヘッド
|
||||
- 複数スレッドでのcontention
|
||||
- Cache line bouncing
|
||||
|
||||
## 🚀 実装計画
|
||||
|
||||
### Step 1: Read-only path分析
|
||||
```rust
|
||||
// mir/readonly_analysis.rs
|
||||
pub struct ReadOnlyAnalysis {
|
||||
// メソッドのread-only性
|
||||
readonly_methods: HashMap<(TypeId, String), bool>,
|
||||
// フィールドのimmutability
|
||||
immutable_fields: HashMap<(TypeId, String), bool>,
|
||||
}
|
||||
|
||||
impl ReadOnlyAnalysis {
|
||||
pub fn analyze_box_types(&mut self, registry: &BoxRegistry) {
|
||||
// StringBox.length() -> read-only
|
||||
self.mark_readonly("StringBox", "length");
|
||||
self.mark_readonly("StringBox", "isEmpty");
|
||||
|
||||
// IntegerBox.value() -> read-only
|
||||
self.mark_readonly("IntegerBox", "value");
|
||||
|
||||
// プラグインメソッドも解析
|
||||
self.analyze_plugin_methods();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Step 2: Atomic wrapper実装
|
||||
```rust
|
||||
// runtime/atomic_box.rs
|
||||
pub struct AtomicBox<T: NyashBox> {
|
||||
// Read-optimized RwLock
|
||||
inner: Arc<RwLock<T>>,
|
||||
// Atomic cache for immutable data
|
||||
cached_string: AtomicPtr<String>,
|
||||
cached_int: AtomicI64,
|
||||
}
|
||||
|
||||
impl<T: NyashBox> AtomicBox<T> {
|
||||
/// Lock-free read for cached values
|
||||
pub fn read_cached(&self) -> Option<Box<dyn NyashBox>> {
|
||||
// Atomic loadでキャッシュチェック
|
||||
let ptr = self.cached_string.load(Ordering::Acquire);
|
||||
if !ptr.is_null() {
|
||||
unsafe {
|
||||
let s = &*ptr;
|
||||
return Some(Box::new(StringBox::new(s.clone())));
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// Optimized read path
|
||||
pub fn read_optimized<F, R>(&self, f: F) -> R
|
||||
where
|
||||
F: FnOnce(&T) -> R
|
||||
{
|
||||
// Try read lock first (non-blocking)
|
||||
if let Ok(guard) = self.inner.try_read() {
|
||||
return f(&*guard);
|
||||
}
|
||||
|
||||
// Fallback to regular read
|
||||
let guard = self.inner.read().unwrap();
|
||||
f(&*guard)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Step 3: JIT最適化
|
||||
```rust
|
||||
// jit/lower/atomic_opt.rs
|
||||
impl<'a> LoweringBuilder<'a> {
|
||||
fn emit_box_method_call(&mut self,
|
||||
box_val: Value,
|
||||
method: &str,
|
||||
args: &[Value]
|
||||
) -> Value {
|
||||
// Read-only解析結果確認
|
||||
if self.readonly_info.is_readonly_method(box_val, method) {
|
||||
// Atomic fast path
|
||||
self.emit_atomic_read_path(box_val, method, args)
|
||||
} else {
|
||||
// 通常のMutexパス
|
||||
self.emit_mutex_path(box_val, method, args)
|
||||
}
|
||||
}
|
||||
|
||||
fn emit_atomic_read_path(&mut self,
|
||||
box_val: Value,
|
||||
method: &str,
|
||||
args: &[Value]
|
||||
) -> Value {
|
||||
// 1. Atomic loadでcacheチェック
|
||||
let cache_ptr = self.emit_atomic_load(box_val, "cache");
|
||||
|
||||
// 2. Cache hit判定
|
||||
let is_valid = self.emit_null_check(cache_ptr);
|
||||
|
||||
// 3. 条件分岐
|
||||
let then_block = self.create_block();
|
||||
let else_block = self.create_block();
|
||||
self.emit_branch(is_valid, then_block, else_block);
|
||||
|
||||
// Cache hit: lock-free return
|
||||
self.switch_to_block(then_block);
|
||||
let cached = self.emit_load(cache_ptr);
|
||||
self.emit_jump(merge_block);
|
||||
|
||||
// Cache miss: RwLock読み取り
|
||||
self.switch_to_block(else_block);
|
||||
let value = self.emit_rwlock_read(box_val, method);
|
||||
self.emit_jump(merge_block);
|
||||
|
||||
// Merge
|
||||
self.switch_to_block(merge_block);
|
||||
self.emit_phi(vec![(cached, then_block), (value, else_block)])
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Step 4: Memory ordering最適化
|
||||
```rust
|
||||
// プラットフォーム別最適化
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
fn emit_memory_fence(&mut self, ordering: Ordering) {
|
||||
match ordering {
|
||||
Ordering::Relaxed => {}, // x86は強いメモリモデル
|
||||
Ordering::Acquire => self.emit_lfence(),
|
||||
Ordering::Release => self.emit_sfence(),
|
||||
Ordering::SeqCst => self.emit_mfence(),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
fn emit_memory_fence(&mut self, ordering: Ordering) {
|
||||
// ARMは弱いメモリモデル
|
||||
match ordering {
|
||||
Ordering::Relaxed => {},
|
||||
Ordering::Acquire => self.emit_dmb_ld(),
|
||||
Ordering::Release => self.emit_dmb_st(),
|
||||
Ordering::SeqCst => self.emit_dmb(),
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📈 期待される効果
|
||||
|
||||
### ベンチマーク
|
||||
```nyash
|
||||
// Read-heavy workload
|
||||
function sumStringLengths(strings) {
|
||||
local total = 0
|
||||
loop(s in strings) {
|
||||
total = total + s.length() // Atomic最適化
|
||||
}
|
||||
return total
|
||||
}
|
||||
|
||||
// 性能改善
|
||||
// Before: 1000ms (Mutex contention)
|
||||
// After: 100ms (Lock-free reads)
|
||||
```
|
||||
|
||||
### 改善予測
|
||||
- Read操作: 90%高速化
|
||||
- Read/Write混在: 50%高速化
|
||||
- マルチスレッド: スケーラビリティ大幅向上
|
||||
|
||||
## 🔍 検証方法
|
||||
|
||||
### 1. Lock統計
|
||||
```json
|
||||
{
|
||||
"total_operations": 100000,
|
||||
"mutex_locks": 10000,
|
||||
"atomic_reads": 90000,
|
||||
"lock_reduction": 0.9,
|
||||
"contention_events": 50
|
||||
}
|
||||
```
|
||||
|
||||
### 2. プロファイリング
|
||||
```bash
|
||||
# Mutexプロファイル
|
||||
NYASH_PROFILE_LOCKS=1 ./target/release/nyash bench.nyash
|
||||
|
||||
# Atomic最適化後
|
||||
NYASH_ATOMIC_OPT=1 ./target/release/nyash bench.nyash
|
||||
```
|
||||
|
||||
## 🚧 実装上の注意点
|
||||
|
||||
1. **正確性**
|
||||
- Memory orderingの正しさ
|
||||
- ABA問題の回避
|
||||
- Weak pointer対応
|
||||
|
||||
2. **互換性**
|
||||
- 既存APIの維持
|
||||
- プラグインとの相互運用
|
||||
|
||||
3. **デバッグ性**
|
||||
- Race condition検出
|
||||
- Lock順序の追跡
|
||||
|
||||
## 🎉 完了基準
|
||||
|
||||
- [ ] Read-only分析実装
|
||||
- [ ] AtomicBox wrapper実装
|
||||
- [ ] JIT統合
|
||||
- [ ] マルチスレッドベンチマーク
|
||||
- [ ] プラットフォーム別最適化
|
||||
295
docs/phases/phase-11.5/11.5c-COROUTINE-ASYNC.md
Normal file
295
docs/phases/phase-11.5/11.5c-COROUTINE-ASYNC.md
Normal file
@ -0,0 +1,295 @@
|
||||
# Phase 11.5c: Coroutine実装による非同期処理の完成
|
||||
|
||||
## 🎯 目標
|
||||
async/await構文を追加し、JITレベルでcoroutineをstate machineに変換して高性能な非同期処理を実現する。
|
||||
|
||||
## 📊 現状と目標
|
||||
|
||||
### 現在の非同期処理
|
||||
```nyash
|
||||
// nowait文(スレッドベース)
|
||||
nowait result = heavyComputation()
|
||||
// ...
|
||||
local value = wait result // FutureBoxから取得
|
||||
```
|
||||
|
||||
### 目標の構文
|
||||
```nyash
|
||||
// async/await(coroutineベース)
|
||||
async function fetchData(url) {
|
||||
local response = await httpGet(url)
|
||||
local json = await response.json()
|
||||
return json.data
|
||||
}
|
||||
|
||||
// 複数の非同期処理
|
||||
async function fetchAll(urls) {
|
||||
local promises = []
|
||||
loop(url in urls) {
|
||||
promises.push(fetchData(url))
|
||||
}
|
||||
return await Promise.all(promises)
|
||||
}
|
||||
```
|
||||
|
||||
## 🚀 実装計画
|
||||
|
||||
### Step 1: AST拡張
|
||||
```rust
|
||||
// ast.rs
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum ASTNode {
|
||||
// 既存
|
||||
Function { name: String, params: Vec<String>, body: Box<ASTNode> },
|
||||
|
||||
// 新規追加
|
||||
AsyncFunction {
|
||||
name: String,
|
||||
params: Vec<String>,
|
||||
body: Box<ASTNode>
|
||||
},
|
||||
AwaitExpression {
|
||||
expression: Box<ASTNode>
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Step 2: MIR Coroutine命令
|
||||
```rust
|
||||
// mir/instruction.rs
|
||||
pub enum MirInstruction {
|
||||
// 既存命令...
|
||||
|
||||
// Coroutine関連
|
||||
/// Coroutine生成
|
||||
CoroutineCreate {
|
||||
dst: ValueId,
|
||||
func: FunctionId,
|
||||
captures: Vec<ValueId>,
|
||||
},
|
||||
|
||||
/// Yield point(await)
|
||||
CoroutineYield {
|
||||
value: ValueId,
|
||||
resume_label: BasicBlockId,
|
||||
},
|
||||
|
||||
/// Coroutine再開
|
||||
CoroutineResume {
|
||||
dst: Option<ValueId>,
|
||||
coroutine: ValueId,
|
||||
value: Option<ValueId>,
|
||||
},
|
||||
|
||||
/// Promise結合
|
||||
PromiseAll {
|
||||
dst: ValueId,
|
||||
promises: Vec<ValueId>,
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Step 3: State Machine変換
|
||||
```rust
|
||||
// mir/coroutine_transform.rs
|
||||
pub struct CoroutineTransform {
|
||||
state_enum: HashMap<FunctionId, StateEnum>,
|
||||
}
|
||||
|
||||
/// async関数をstate machineに変換
|
||||
impl CoroutineTransform {
|
||||
pub fn transform_async_function(&mut self,
|
||||
func: &MirFunction
|
||||
) -> MirFunction {
|
||||
// 1. await pointsを収集
|
||||
let await_points = self.collect_await_points(func);
|
||||
|
||||
// 2. State enum生成
|
||||
let states = self.generate_states(await_points);
|
||||
|
||||
// 3. State machine関数生成
|
||||
let state_machine = self.build_state_machine(func, states);
|
||||
|
||||
// 4. Coroutine wrapper生成
|
||||
self.wrap_as_coroutine(state_machine)
|
||||
}
|
||||
|
||||
fn build_state_machine(&self,
|
||||
func: &MirFunction,
|
||||
states: Vec<State>
|
||||
) -> MirFunction {
|
||||
// switch(state) {
|
||||
// case State0: ... goto await1 or return
|
||||
// case State1: ... goto await2 or return
|
||||
// ...
|
||||
// }
|
||||
|
||||
let mut builder = MirBuilder::new();
|
||||
|
||||
// Coroutine state
|
||||
let state_var = builder.emit_local("state");
|
||||
let locals = builder.emit_local("locals");
|
||||
|
||||
// Main dispatch loop
|
||||
let loop_bb = builder.create_block();
|
||||
builder.emit_jump(loop_bb);
|
||||
|
||||
builder.switch_to_block(loop_bb);
|
||||
let state = builder.emit_load(state_var);
|
||||
|
||||
// State dispatch
|
||||
for (i, state) in states.iter().enumerate() {
|
||||
let state_bb = builder.create_block();
|
||||
builder.emit_case(state.id, state_bb);
|
||||
|
||||
builder.switch_to_block(state_bb);
|
||||
self.emit_state_code(&mut builder, state);
|
||||
}
|
||||
|
||||
builder.build()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Step 4: JIT Coroutine最適化
|
||||
```rust
|
||||
// jit/lower/coroutine.rs
|
||||
impl<'a> LoweringBuilder<'a> {
|
||||
/// Coroutineのstack switching最適化
|
||||
fn emit_coroutine_switch(&mut self,
|
||||
from: Value,
|
||||
to: Value
|
||||
) {
|
||||
if self.config.use_fast_switch {
|
||||
// レジスタのみ保存(最適化)
|
||||
self.emit_save_registers();
|
||||
self.emit_switch_stack(to);
|
||||
self.emit_restore_registers();
|
||||
} else {
|
||||
// フルコンテキスト保存
|
||||
self.emit_full_context_save(from);
|
||||
self.emit_full_context_restore(to);
|
||||
}
|
||||
}
|
||||
|
||||
/// Inline可能なawaitの検出
|
||||
fn try_inline_await(&mut self,
|
||||
await_expr: &MirInstruction
|
||||
) -> Option<Value> {
|
||||
// Promise.resolvedなら即値返却
|
||||
if self.is_resolved_promise(await_expr) {
|
||||
return Some(self.emit_immediate_value());
|
||||
}
|
||||
|
||||
// 小さなasync関数ならインライン化
|
||||
if self.is_small_async(await_expr) {
|
||||
return Some(self.inline_async_call(await_expr));
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Step 5: ランタイムサポート
|
||||
```rust
|
||||
// boxes/promise_box.rs
|
||||
pub struct PromiseBox {
|
||||
state: Arc<Mutex<PromiseState>>,
|
||||
base: BoxBase,
|
||||
}
|
||||
|
||||
enum PromiseState {
|
||||
Pending(Vec<Box<dyn FnOnce(Box<dyn NyashBox>)>>),
|
||||
Resolved(Box<dyn NyashBox>),
|
||||
Rejected(String),
|
||||
}
|
||||
|
||||
impl PromiseBox {
|
||||
pub fn all(promises: Vec<Box<PromiseBox>>) -> Box<PromiseBox> {
|
||||
// 全Promise完了待ち
|
||||
let result = PromiseBox::new();
|
||||
let remaining = Arc::new(AtomicUsize::new(promises.len()));
|
||||
|
||||
for (i, promise) in promises.iter().enumerate() {
|
||||
promise.then(move |value| {
|
||||
// 結果収集
|
||||
if remaining.fetch_sub(1, Ordering::SeqCst) == 1 {
|
||||
result.resolve(collected_values);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Box::new(result)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📈 期待される効果
|
||||
|
||||
### パフォーマンス比較
|
||||
```nyash
|
||||
// Before: Thread-based
|
||||
nowait results = []
|
||||
loop(url in urls) {
|
||||
nowait r = httpGet(url) // 新スレッド生成
|
||||
results.push(r)
|
||||
}
|
||||
|
||||
// After: Coroutine-based
|
||||
async function fetchAll(urls) {
|
||||
return await Promise.all(
|
||||
urls.map(url => httpGet(url)) // Stack switching only
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### 改善予測
|
||||
- メモリ使用量: 1/100(スレッドstack vs coroutine state)
|
||||
- コンテキストスイッチ: 1000倍高速
|
||||
- 同時接続数: 10,000+対応可能
|
||||
|
||||
## 🔍 検証方法
|
||||
|
||||
### 1. Coroutine統計
|
||||
```json
|
||||
{
|
||||
"total_coroutines": 10000,
|
||||
"active_coroutines": 500,
|
||||
"yield_count": 50000,
|
||||
"average_yield_ns": 100,
|
||||
"stack_memory_mb": 10
|
||||
}
|
||||
```
|
||||
|
||||
### 2. ベンチマーク
|
||||
```bash
|
||||
# 10000並行リクエスト
|
||||
./target/release/nyash bench/async_stress.nyash
|
||||
|
||||
# メモリプロファイル
|
||||
NYASH_COROUTINE_STATS=1 ./target/release/nyash bench/async_memory.nyash
|
||||
```
|
||||
|
||||
## 🚧 実装上の注意点
|
||||
|
||||
1. **Stack管理**
|
||||
- Segmented stack対応
|
||||
- Stack overflow検出
|
||||
- GC root scanning
|
||||
|
||||
2. **エラー伝播**
|
||||
- async境界でのエラー
|
||||
- Promise rejection chain
|
||||
|
||||
3. **デバッグ対応**
|
||||
- async stack trace
|
||||
- Coroutine状態可視化
|
||||
|
||||
## 🎉 完了基準
|
||||
|
||||
- [ ] async/await構文実装
|
||||
- [ ] MIR coroutine変換
|
||||
- [ ] JIT最適化
|
||||
- [ ] Promise/PromiseBox実装
|
||||
- [ ] 10000並行処理ベンチマーク達成
|
||||
80
docs/phases/phase-11.5/BOX_SSA_CORE_15_FINAL_DECISION.md
Normal file
80
docs/phases/phase-11.5/BOX_SSA_CORE_15_FINAL_DECISION.md
Normal file
@ -0,0 +1,80 @@
|
||||
# Box-SSA Core-15 最終決定
|
||||
|
||||
Date: 2025-08-31
|
||||
Status: **凍結仕様** (Frozen Specification)
|
||||
Summary: MIR命令セットを真の15個に統一
|
||||
|
||||
## 📊 問題と解決
|
||||
|
||||
### 混乱していた2案
|
||||
1. **Gemini版15**: RefNew/RefGet/RefSet含む(15個だがBox哲学に反する)
|
||||
2. **文書版Core-15**: 実は17個(Box哲学に近いが数が合わない)
|
||||
|
||||
### ChatGPT5の第三案で決着
|
||||
```
|
||||
{ Const, UnaryOp, BinOp, Compare, TypeOp,
|
||||
Load, Store,
|
||||
Jump, Branch, Return, Phi,
|
||||
Call, NewBox, BoxCall, ExternCall }
|
||||
```
|
||||
|
||||
## 🌟 革命的統一:BoxCall
|
||||
|
||||
すべてのBox操作を**BoxCall**一本に統一:
|
||||
|
||||
| 旧命令 | 新BoxCall表現 |
|
||||
|--------|---------------|
|
||||
| RefGet(obj, field) | BoxCall(obj, "getField", field) |
|
||||
| RefSet(obj, field, val) | BoxCall(obj, "setField", field, val) |
|
||||
| ArrayGet(arr, idx) | BoxCall(arr, "get", idx) |
|
||||
| ArraySet(arr, idx, val) | BoxCall(arr, "set", idx, val) |
|
||||
| PluginInvoke(p, m, args) | BoxCall(p, m, args) |
|
||||
|
||||
## 💡 技術的インパクト
|
||||
|
||||
### 実装の簡素化
|
||||
- **Verifier**: BoxCallのチェックのみ
|
||||
- **最適化**: PIC/インライン化がBoxCallに集中
|
||||
- **GCバリア**: BoxCallのLoweringで統一処理
|
||||
- **削減効果**: 26→15命令(42%削減)
|
||||
|
||||
### LLVM変換戦略(AI会議の合意)
|
||||
1. **BoxCall最適化**: メソッドID + PIC(Polymorphic Inline Cache)
|
||||
2. **脱箱化**: 2表現SSA(プリミティブ計算→必要時のみBox化)
|
||||
3. **GCバリア**: 世代別GCで若→若は省略
|
||||
4. **注釈→属性**: 保守的マッピング(安全性優先)
|
||||
|
||||
## 🚀 実装への影響
|
||||
|
||||
### JIT→LLVM直行の決断
|
||||
- Cranelift = 実はAOTだった(JIT幻想)
|
||||
- 15命令なら機械的変換で十分
|
||||
- Phase 9-10スキップ → Phase 11(LLVM)直行
|
||||
|
||||
### ChatGPT5の反応
|
||||
```
|
||||
Box-SSA Core-15を聞く
|
||||
↓
|
||||
完璧と判断
|
||||
↓
|
||||
無言でコーディング開始(議論の余地なし)
|
||||
```
|
||||
|
||||
## 📝 今後の課題
|
||||
|
||||
1. **MIR注釈システム**: 命令数を増やさずに最適化ヒント付与(設計案のみ)
|
||||
2. **LLVM実装**: inkwellセットアップから開始
|
||||
3. **既存コード移行**: 26→15命令への段階的移行
|
||||
|
||||
## 🎉 結論
|
||||
|
||||
**Box-SSA Core-15**により「Everything is Box」哲学が完全開花:
|
||||
- 真の15命令達成
|
||||
- 実装の劇的簡素化
|
||||
- 最適化の統一的適用
|
||||
|
||||
これが「あほみたいに簡単」で「恐ろしく速い」Nyashの最終形態!
|
||||
|
||||
---
|
||||
|
||||
詳細なAI会議記録は [archives/](archives/) フォルダに保存
|
||||
60
docs/phases/phase-11.5/CURRENT_STATUS_2025_08_31.md
Normal file
60
docs/phases/phase-11.5/CURRENT_STATUS_2025_08_31.md
Normal file
@ -0,0 +1,60 @@
|
||||
# Phase 11.5 Current Status
|
||||
|
||||
Date: 2025-08-31
|
||||
Status: Active Development → LLVM Implementation
|
||||
|
||||
## 🎯 本日の大革命:Box-SSA Core-15
|
||||
|
||||
### MIR命令セット凍結
|
||||
- 26命令 → **真の15命令**に統一
|
||||
- すべてのBox操作を**BoxCall**に集約
|
||||
- Everything is Box哲学の完全実現
|
||||
|
||||
詳細: [BOX_SSA_CORE_15_FINAL_DECISION.md](BOX_SSA_CORE_15_FINAL_DECISION.md)
|
||||
|
||||
## 📊 Phase 11.5 タスク状況
|
||||
|
||||
### ✅ 完了
|
||||
1. **Write Barrier Removal** (11.5a)
|
||||
- Escape Analysis基礎実装
|
||||
- RefSet最適化
|
||||
|
||||
2. **Atomic Operations** (11.5b)
|
||||
- 同期プリミティブ実装
|
||||
- Memory ordering保証
|
||||
|
||||
3. **Coroutine/Async** (11.5c)
|
||||
- Future/Await基本実装
|
||||
- 非同期ランタイム統合
|
||||
|
||||
4. **Box-SSA Core-15仕様凍結** (NEW!)
|
||||
- MIR 15命令に統一
|
||||
- BoxCall万能化
|
||||
|
||||
### 🚀 次のステップ
|
||||
|
||||
**Phase 11(LLVM)直行決定**:
|
||||
- Phase 9-10(JIT)スキップ
|
||||
- Cranelift削除 → inkwell導入
|
||||
- 15命令の機械的LLVM変換
|
||||
|
||||
## 📁 ドキュメント構成
|
||||
|
||||
### メインドキュメント
|
||||
- `BOX_SSA_CORE_15_FINAL_DECISION.md` - 本日の革命的決定
|
||||
- `11.5a/b/c-*.md` - 各サブフェーズの実装ガイド
|
||||
- `IMPLEMENTATION-GUIDE.md` - 全体実装指針
|
||||
- `FIRST-FIVE-APPS.md` - アプリケーション例
|
||||
|
||||
### アーカイブ
|
||||
- `archives/` - 詳細なAI会議記録
|
||||
- 個別相談記録(Gemini, Codex, ChatGPT5)
|
||||
- 詳細技術議論
|
||||
|
||||
## 🎉 成果
|
||||
|
||||
1. **MIR簡素化**: 26→15命令(42%削減)
|
||||
2. **実装統一**: BoxCallに全Box操作を集約
|
||||
3. **戦略転換**: JIT幻想から解放→LLVM直行
|
||||
|
||||
これでPhase 11.5は概念的に完了し、LLVM実装(Phase 11)へ移行準備完了!
|
||||
307
docs/phases/phase-11.5/FIRST-FIVE-APPS.md
Normal file
307
docs/phases/phase-11.5/FIRST-FIVE-APPS.md
Normal file
@ -0,0 +1,307 @@
|
||||
# 🚀 First Five Apps - Nyashの実力を証明する最初の5本
|
||||
|
||||
## 🎯 概要
|
||||
Phase 11.5完了を待たずに、**今すぐ作れる**実用アプリ5本で、Nyashの産業レベルの完成度を世に示します。
|
||||
すべて「Everything is Box/PluginInvoke」で統一実装し、VM/JIT/AOT/WASMの全バックエンドで動作確認します。
|
||||
|
||||
## 📋 アプリケーション一覧
|
||||
|
||||
### 1. ny-echo(最小CLI)- 基本I/O検証
|
||||
**目的**: I/O・StringBoxの道通し確認
|
||||
|
||||
```nyash
|
||||
// apps/ny-echo/main.nyash
|
||||
static box Main {
|
||||
main(args) {
|
||||
local console = new ConsoleBox()
|
||||
local options = parseArgs(args)
|
||||
|
||||
loop(true) {
|
||||
local input = console.readLine()
|
||||
if input == null { break }
|
||||
|
||||
local output = input
|
||||
if options.get("upper") {
|
||||
output = input.toUpperCase()
|
||||
} else if options.get("lower") {
|
||||
output = input.toLowerCase()
|
||||
}
|
||||
|
||||
console.log(output)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**受入基準**:
|
||||
- [ ] VM/JIT/AOT/GCオン・オフすべてでtrace_hash一致
|
||||
- [ ] 100万行処理で性能劣化なし
|
||||
- [ ] メモリリークなし(GCカウンター確認)
|
||||
|
||||
### 2. ny-jsonlint(Python連携デモ)- プラグイン統合
|
||||
**目的**: PyRuntimeBox/PyObjectBox経由のPluginInvoke検証
|
||||
|
||||
```nyash
|
||||
// apps/ny-jsonlint/main.nyash
|
||||
static box Main {
|
||||
init { py, console }
|
||||
|
||||
main(args) {
|
||||
me.py = new PyRuntimeBox()
|
||||
me.console = new ConsoleBox()
|
||||
|
||||
local filename = args.get(1)
|
||||
if filename == null {
|
||||
me.console.error("Usage: ny-jsonlint <file.json>")
|
||||
return 1
|
||||
}
|
||||
|
||||
local file = new FileBox()
|
||||
file.open(filename, "r")
|
||||
local content = file.read()
|
||||
file.close()
|
||||
|
||||
local result = me.py.eval("
|
||||
import json
|
||||
try:
|
||||
json.loads(content)
|
||||
'OK'
|
||||
except Exception as e:
|
||||
f'NG: {str(e)}'
|
||||
", new MapBox().set("content", content))
|
||||
|
||||
me.console.log(result)
|
||||
return result.startsWith("OK") ? 0 : 1
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**受入基準**:
|
||||
- [ ] OS差なく実行(Windows/Linux/macOS)
|
||||
- [ ] --sealedモードで完全再現可能
|
||||
- [ ] 大規模JSON(10MB)でも安定動作
|
||||
|
||||
### 3. ny-array-bench(性能デモ)- ベンチマーク基準
|
||||
**目的**: ArrayBox map/reduce、StatsBox導入、性能可視化
|
||||
|
||||
```nyash
|
||||
// apps/ny-array-bench/main.nyash
|
||||
static box Main {
|
||||
init { stats }
|
||||
|
||||
main(args) {
|
||||
me.stats = new StatsBox()
|
||||
local sizes = [1000, 10000, 100000]
|
||||
|
||||
loop(size in sizes) {
|
||||
me.benchArrayOps(size)
|
||||
}
|
||||
|
||||
// 結果をJSON出力(CI集計用)
|
||||
local result = me.stats.toJSON()
|
||||
print(result)
|
||||
}
|
||||
|
||||
benchArrayOps(size) {
|
||||
local array = new ArrayBox()
|
||||
|
||||
// 1. 配列生成
|
||||
me.stats.startTimer("create_" + size)
|
||||
loop(i < size) {
|
||||
array.push(i)
|
||||
}
|
||||
me.stats.endTimer("create_" + size)
|
||||
|
||||
// 2. map操作
|
||||
me.stats.startTimer("map_" + size)
|
||||
local doubled = array.map(|x| x * 2)
|
||||
me.stats.endTimer("map_" + size)
|
||||
|
||||
// 3. reduce操作
|
||||
me.stats.startTimer("reduce_" + size)
|
||||
local sum = doubled.reduce(|a, b| a + b, 0)
|
||||
me.stats.endTimer("reduce_" + size)
|
||||
|
||||
// VM基準の相対性能を記録
|
||||
me.stats.recordRelative("vm", 1.0)
|
||||
if IS_JIT { me.stats.recordRelative("jit", SPEEDUP) }
|
||||
if IS_AOT { me.stats.recordRelative("aot", SPEEDUP) }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**受入基準**:
|
||||
- [ ] VM=1.0x基準でJIT/AOTの倍率表示
|
||||
- [ ] fallbacks=0(完全最適化)
|
||||
- [ ] 結果JSON自動出力(CI集計可能)
|
||||
|
||||
### 4. ny-filegrep(実用ミニ)- ファイルI/O実用例
|
||||
**目的**: BytesBox/FileBox(プラグイン)I/O、実用的なツール
|
||||
|
||||
```nyash
|
||||
// apps/ny-filegrep/main.nyash
|
||||
static box Main {
|
||||
init { pattern, recursive, results }
|
||||
|
||||
main(args) {
|
||||
me.parseArgs(args)
|
||||
me.results = new ArrayBox()
|
||||
|
||||
local path = args.getLast() || "."
|
||||
me.searchPath(path)
|
||||
|
||||
// 結果表示
|
||||
loop(result in me.results) {
|
||||
print(result)
|
||||
}
|
||||
|
||||
return me.results.length() > 0 ? 0 : 1
|
||||
}
|
||||
|
||||
searchPath(path) {
|
||||
local file = new FileBox()
|
||||
|
||||
if file.isDirectory(path) {
|
||||
if me.recursive {
|
||||
local entries = file.listDir(path)
|
||||
loop(entry in entries) {
|
||||
me.searchPath(path + "/" + entry)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
me.searchFile(path)
|
||||
}
|
||||
}
|
||||
|
||||
searchFile(filepath) {
|
||||
local file = new FileBox()
|
||||
file.open(filepath, "r")
|
||||
|
||||
local lineNum = 0
|
||||
loop(true) {
|
||||
local line = file.readLine()
|
||||
if line == null { break }
|
||||
|
||||
lineNum = lineNum + 1
|
||||
if line.contains(me.pattern) {
|
||||
me.results.push(filepath + ":" + lineNum + ":" + line)
|
||||
}
|
||||
}
|
||||
|
||||
file.close()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**受入基準**:
|
||||
- [ ] Windows/Linux/macOSで同一結果
|
||||
- [ ] 大規模ディレクトリ(1万ファイル)対応
|
||||
- [ ] メモリ効率的(ストリーム処理)
|
||||
|
||||
### 5. ny-http-hello(WASM/ネイティブ両対応)- Web実用例
|
||||
**目的**: NetBox(プラグイン)とイベントループ、FutureBox活用
|
||||
|
||||
```nyash
|
||||
// apps/ny-http-hello/main.nyash
|
||||
static box Main {
|
||||
init { server, running }
|
||||
|
||||
main(args) {
|
||||
local port = args.get(1) || "8080"
|
||||
me.server = new HttpServerBox()
|
||||
me.running = true
|
||||
|
||||
// シグナルハンドラー設定
|
||||
registerSignal("SIGINT", || me.stop())
|
||||
|
||||
// サーバー起動
|
||||
me.server.start(port.toInteger())
|
||||
print("Server listening on http://localhost:" + port)
|
||||
|
||||
// リクエストループ
|
||||
loop(me.running) {
|
||||
nowait request = me.server.accept()
|
||||
me.handleRequest(wait request)
|
||||
}
|
||||
|
||||
me.server.stop()
|
||||
return 0
|
||||
}
|
||||
|
||||
handleRequest(request) {
|
||||
local response = new HttpResponseBox()
|
||||
|
||||
if request.path() == "/" {
|
||||
response.setStatus(200)
|
||||
response.setHeader("Content-Type", "text/plain")
|
||||
response.write("Hello from Nyash!")
|
||||
} else {
|
||||
response.setStatus(404)
|
||||
response.write("Not Found")
|
||||
}
|
||||
|
||||
request.respond(response)
|
||||
}
|
||||
|
||||
stop() {
|
||||
print("Shutting down...")
|
||||
me.running = false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**受入基準**:
|
||||
- [ ] 100req/s程度のスモーク通過
|
||||
- [ ] 停止シグナルでクリーンfini
|
||||
- [ ] WASMビルドでも動作(制限付き)
|
||||
|
||||
## 🎯 実装優先順位
|
||||
|
||||
1. **ny-echo** - 最小実装、CI基盤確立
|
||||
2. **ny-array-bench** - 性能基準確立
|
||||
3. **ny-jsonlint** - プラグイン統合実証
|
||||
4. **ny-filegrep** - 実用性実証
|
||||
5. **ny-http-hello** - Web対応実証
|
||||
|
||||
## 📊 成功指標
|
||||
|
||||
### 全体指標
|
||||
- [ ] 5アプリすべてがVM/JIT/AOTで動作
|
||||
- [ ] CIでの自動テスト確立
|
||||
- [ ] ドキュメント・サンプル完備
|
||||
|
||||
### 性能指標
|
||||
- [ ] JIT: VMの5倍以上高速
|
||||
- [ ] AOT: VMの10倍以上高速
|
||||
- [ ] メモリ使用量: 同等機能のPython比50%以下
|
||||
|
||||
### 品質指標
|
||||
- [ ] ゼロクラッシュ(1000回実行)
|
||||
- [ ] メモリリークなし(長時間実行)
|
||||
- [ ] プラットフォーム差異なし
|
||||
|
||||
## 🚀 配布戦略
|
||||
|
||||
### リリース形式
|
||||
```
|
||||
nyash-apps-v1.0/
|
||||
├── bin/
|
||||
│ ├── ny-echo[.exe]
|
||||
│ ├── ny-jsonlint[.exe]
|
||||
│ ├── ny-array-bench[.exe]
|
||||
│ ├── ny-filegrep[.exe]
|
||||
│ └── ny-http-hello[.exe]
|
||||
├── examples/
|
||||
│ └── *.nyash (ソースコード)
|
||||
├── benchmarks/
|
||||
│ └── results.json
|
||||
└── README.md
|
||||
```
|
||||
|
||||
### 展開先
|
||||
- GitHub Releases
|
||||
- Homebrew (macOS)
|
||||
- Scoop (Windows)
|
||||
- Docker Hub (コンテナ版)
|
||||
|
||||
これで「30日で作った言語」の実力を世界に示せます!🎉
|
||||
191
docs/phases/phase-11.5/IMPLEMENTATION-GUIDE.md
Normal file
191
docs/phases/phase-11.5/IMPLEMENTATION-GUIDE.md
Normal file
@ -0,0 +1,191 @@
|
||||
# Phase 11.5 実装ガイド - ChatGPT5向け
|
||||
|
||||
## 🎯 実装の全体像
|
||||
|
||||
Phase 11.5は、Nyashの性能を産業レベルに引き上げる最終段階です。3つの主要な最適化を行います:
|
||||
|
||||
1. **Write Barrier除去** - GCオーバーヘッドを90%削減
|
||||
2. **Atomic最適化** - sync処理を10倍高速化
|
||||
3. **Coroutine実装** - 真の非同期処理を実現
|
||||
|
||||
## 📋 実装順序と依存関係
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[11.5a: Write Barrier除去] --> D[統合テスト]
|
||||
B[11.5b: Atomic最適化] --> D
|
||||
C[11.5c: Coroutine実装] --> D
|
||||
D --> E[Phase 11.5完了]
|
||||
```
|
||||
|
||||
各タスクは独立して実装可能ですが、統合テストで相互作用を検証します。
|
||||
|
||||
## 🔧 技術的な実装詳細
|
||||
|
||||
### 1. Write Barrier除去の実装手順
|
||||
|
||||
#### Step 1: MIR拡張
|
||||
```rust
|
||||
// src/mir/escape_analysis.rs (新規作成)
|
||||
use crate::mir::{MirFunction, MirInstruction, ValueId};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
pub struct EscapeAnalysis {
|
||||
allocations: HashMap<ValueId, AllocSite>,
|
||||
escapes: HashSet<ValueId>,
|
||||
}
|
||||
|
||||
impl EscapeAnalysis {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
allocations: HashMap::new(),
|
||||
escapes: HashSet::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn analyze(&mut self, func: &MirFunction) -> EscapeInfo {
|
||||
// 実装のポイント:
|
||||
// 1. NewBox, RefNew命令を追跡
|
||||
// 2. Return, Call命令でescape判定
|
||||
// 3. ループ不変式も考慮
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Step 2: VM統合
|
||||
```rust
|
||||
// src/backend/vm_instructions.rs の修正
|
||||
pub fn execute_ref_set(&mut self, reference: ValueId, field: &str, value: ValueId)
|
||||
-> Result<ControlFlow, VMError> {
|
||||
// 既存のコード...
|
||||
|
||||
// Escape analysisの結果を確認
|
||||
if let Some(escape_info) = &self.escape_info {
|
||||
if !escape_info.escapes(reference) {
|
||||
// Barrierスキップ!
|
||||
return Ok(ControlFlow::Continue);
|
||||
}
|
||||
}
|
||||
|
||||
// 通常のbarrier処理
|
||||
gc_write_barrier_site(&self.runtime, "RefSet");
|
||||
Ok(ControlFlow::Continue)
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Atomic最適化の実装手順
|
||||
|
||||
#### Step 1: BoxCore拡張
|
||||
```rust
|
||||
// src/box_trait.rs の修正
|
||||
pub trait BoxCore: Send + Sync {
|
||||
// 既存のメソッド...
|
||||
|
||||
/// Read-onlyメソッドかどうか
|
||||
fn is_readonly_method(&self, method: &str) -> bool {
|
||||
// デフォルトはfalse(保守的)
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
// 各Boxで実装
|
||||
impl BoxCore for StringBox {
|
||||
fn is_readonly_method(&self, method: &str) -> bool {
|
||||
matches!(method, "length" | "isEmpty" | "charAt")
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Step 2: Atomic wrapper
|
||||
```rust
|
||||
// src/runtime/atomic_box.rs (新規作成)
|
||||
use std::sync::atomic::{AtomicPtr, Ordering};
|
||||
use std::sync::Arc;
|
||||
use parking_lot::RwLock; // より高速なRwLock
|
||||
|
||||
pub struct AtomicBox<T> {
|
||||
inner: Arc<RwLock<T>>,
|
||||
cache: AtomicPtr<CachedValue>,
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Coroutine実装の実装手順
|
||||
|
||||
#### Step 1: Parser拡張
|
||||
```rust
|
||||
// src/parser/keywords.rs の修正
|
||||
pub const RESERVED_WORDS: &[&str] = &[
|
||||
// 既存のキーワード...
|
||||
"async",
|
||||
"await",
|
||||
];
|
||||
|
||||
// src/parser/expressions.rs の修正
|
||||
fn parse_function_declaration(&mut self) -> Result<ASTNode, ParseError> {
|
||||
let is_async = self.consume_keyword("async");
|
||||
// 既存のパース処理...
|
||||
}
|
||||
```
|
||||
|
||||
#### Step 2: MIR Coroutine変換
|
||||
```rust
|
||||
// src/mir/coroutine_transform.rs (新規作成)
|
||||
pub fn transform_async_function(func: &MirFunction) -> MirFunction {
|
||||
// State machine変換のアルゴリズム:
|
||||
// 1. await箇所でstateを分割
|
||||
// 2. ローカル変数をstate構造体に移動
|
||||
// 3. switch文で状態遷移を実装
|
||||
}
|
||||
```
|
||||
|
||||
## 🎯 ChatGPT5への実装指示
|
||||
|
||||
### Phase 11.5a(最優先)
|
||||
1. `src/mir/escape_analysis.rs`を作成
|
||||
2. 基本的なallocation追跡を実装
|
||||
3. VM統合でbarrier除去をテスト
|
||||
4. ベンチマークで効果測定
|
||||
|
||||
### Phase 11.5b(次優先)
|
||||
1. `BoxCore::is_readonly_method`を追加
|
||||
2. 主要Boxで実装(StringBox, IntegerBox)
|
||||
3. RwLock移行を段階的に実施
|
||||
|
||||
### Phase 11.5c(最後)
|
||||
1. Parser拡張(async/await)
|
||||
2. 基本的なPromiseBox実装
|
||||
3. 簡単なasync関数の動作確認
|
||||
|
||||
## 📊 成功指標
|
||||
|
||||
各フェーズの完了基準:
|
||||
|
||||
### 11.5a: Write Barrier除去
|
||||
- [ ] escape_analysis.rsが動作
|
||||
- [ ] 簡単なループでbarrier除去確認
|
||||
- [ ] ベンチマークで30%以上改善
|
||||
|
||||
### 11.5b: Atomic最適化
|
||||
- [ ] Read-onlyメソッドの識別
|
||||
- [ ] RwLock使用でread性能向上
|
||||
- [ ] マルチスレッドベンチマーク改善
|
||||
|
||||
### 11.5c: Coroutine実装
|
||||
- [ ] async/awaitがパース可能
|
||||
- [ ] 簡単なasync関数が実行可能
|
||||
- [ ] Promiseチェーンが動作
|
||||
|
||||
## 🚀 実装開始コマンド
|
||||
|
||||
```bash
|
||||
# ブランチ作成
|
||||
git checkout -b phase-11.5-jit-integration
|
||||
|
||||
# テスト駆動開発
|
||||
cargo test escape_analysis
|
||||
|
||||
# ベンチマーク実行
|
||||
./target/release/nyash --benchmark --iterations 1000
|
||||
```
|
||||
|
||||
頑張ってください、ChatGPT5!これが完成すれば、Nyashは本当に世界クラスの言語になります!
|
||||
169
docs/phases/phase-11.5/README.md
Normal file
169
docs/phases/phase-11.5/README.md
Normal file
@ -0,0 +1,169 @@
|
||||
# Phase 11.5: JIT完全統合 - sync/GC/非同期の最終実装
|
||||
|
||||
## 🎯 概要
|
||||
Phase 11.5は、Nyashの全実行レイヤー(インタープリター/MIR/VM/JIT)でsync処理、GC処理、非同期処理を完全に統合する最終フェーズです。
|
||||
|
||||
## 📊 現状分析(2025-08-30)
|
||||
|
||||
### ✅ 完了済み
|
||||
1. **基本アーキテクチャ**
|
||||
- Everything is Box哲学の完全実装
|
||||
- インタープリター → MIR → VM → JIT パイプライン
|
||||
- プラグインシステム(C ABI/TLVハンドル)
|
||||
|
||||
2. **sync処理**
|
||||
- Arc<Mutex>/Arc<RwLock>による完全スレッドセーフ設計
|
||||
- 全レイヤーでの一貫した同期化
|
||||
|
||||
3. **GC基礎**
|
||||
- カウンティングGC実装(NYASH_GC_COUNTING=1)
|
||||
- Read/Writeバリア実装
|
||||
- VMセーフポイント
|
||||
|
||||
4. **非同期基礎**
|
||||
- FutureBox/TimerBox実装
|
||||
- SingleThreadScheduler
|
||||
- nowait/wait文
|
||||
|
||||
## 🚀 Phase 11.5 タスク一覧
|
||||
|
||||
### 1. JIT sync処理統合
|
||||
- [ ] **1.1 Atomic操作の最適化**
|
||||
- Arc<Mutex>アクセスのJIT最適化
|
||||
- Lock elision(不要なロック除去)
|
||||
- Read-only pathでのロック回避
|
||||
|
||||
- [ ] **1.2 Memory ordering最適化**
|
||||
- Relaxed/Acquire/Release semanticsの活用
|
||||
- プラットフォーム別最適化(x86/ARM)
|
||||
|
||||
### 2. JIT GC統合
|
||||
- [ ] **2.1 Write barrier除去**
|
||||
- Escape analysisによる不要バリア検出
|
||||
- Stack allocation最適化
|
||||
- Generational hypothesis活用
|
||||
|
||||
- [ ] **2.2 Safepoint最適化**
|
||||
- Loop safepoint挿入
|
||||
- Call site safepoint
|
||||
- Polling overhead削減
|
||||
|
||||
- [ ] **2.3 GC情報の伝播**
|
||||
- Stack map生成
|
||||
- Root set tracking
|
||||
- Precise GC対応
|
||||
|
||||
### 3. JIT 非同期処理統合
|
||||
- [ ] **3.1 Coroutine変換**
|
||||
- async/await → state machine変換
|
||||
- Stack switching最適化
|
||||
- Continuation passing
|
||||
|
||||
- [ ] **3.2 スケジューラー統合**
|
||||
- Work stealing queue
|
||||
- CPU affinity最適化
|
||||
- Yield point最適化
|
||||
|
||||
### 4. 統合テスト・ベンチマーク
|
||||
- [ ] **4.1 性能測定**
|
||||
- sync処理のオーバーヘッド測定
|
||||
- GC pause time測定
|
||||
- 非同期処理のレイテンシ測定
|
||||
|
||||
- [ ] **4.2 正確性検証**
|
||||
- Race condition検出
|
||||
- Memory leak検出
|
||||
- Deadlock検出
|
||||
|
||||
## 📋 実装優先順位
|
||||
|
||||
### Phase 11.5a: Write barrier除去(最重要)
|
||||
```rust
|
||||
// 現在: すべてのBox操作でbarrier
|
||||
vm.execute_ref_set() -> gc.barrier(Write)
|
||||
|
||||
// 目標: JITでescape analysisして除去
|
||||
if !escapes_to_heap(value) {
|
||||
// barrierスキップ
|
||||
}
|
||||
```
|
||||
|
||||
### Phase 11.5b: Atomic最適化
|
||||
```rust
|
||||
// 現在: Arc<Mutex>の重いロック
|
||||
let value = box.lock().unwrap().clone();
|
||||
|
||||
// 目標: Read-onlyならatomic load
|
||||
if is_read_only(box) {
|
||||
atomic_load_relaxed(box)
|
||||
}
|
||||
```
|
||||
|
||||
### Phase 11.5c: Coroutine実装
|
||||
```nyash
|
||||
// 将来構文
|
||||
async function fetchData() {
|
||||
local result = await httpGet("...")
|
||||
return result
|
||||
}
|
||||
```
|
||||
|
||||
## 🎯 成功基準
|
||||
|
||||
1. **性能向上**
|
||||
- sync処理: 50%以上のロックオーバーヘッド削減
|
||||
- GC: 90%以上のwrite barrier除去
|
||||
- 非同期: ネイティブthread並みの性能
|
||||
|
||||
2. **互換性維持**
|
||||
- 既存のNyashコードがそのまま動作
|
||||
- プラグインシステムとの完全互換
|
||||
|
||||
3. **デバッグ性**
|
||||
- JIT最適化の可視化(NYASH_JIT_OPT_TRACE)
|
||||
- GC統計の詳細化
|
||||
- 非同期処理のトレース
|
||||
|
||||
## 📅 実装スケジュール(推定)
|
||||
|
||||
- **Week 1-2**: Write barrier除去とescape analysis
|
||||
- **Week 3**: Atomic操作最適化
|
||||
- **Week 4**: Coroutine基礎実装
|
||||
- **Week 5**: 統合テストとベンチマーク
|
||||
- **Week 6**: ドキュメント化と最適化
|
||||
|
||||
## 🔧 技術的詳細
|
||||
|
||||
### Escape Analysis実装案
|
||||
```rust
|
||||
// MIR解析でallocサイトを特定
|
||||
struct EscapeAnalysis {
|
||||
allocations: HashMap<ValueId, AllocSite>,
|
||||
escapes: HashSet<ValueId>,
|
||||
}
|
||||
|
||||
impl EscapeAnalysis {
|
||||
fn analyze(&mut self, func: &MirFunction) {
|
||||
// 1. allocation site収集
|
||||
// 2. data flow解析
|
||||
// 3. escape判定
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### JIT統合ポイント
|
||||
```rust
|
||||
// cranelift-jitでのbarrier除去
|
||||
if !self.escape_info.escapes(value) {
|
||||
// emit_call(gc_write_barrier) をスキップ
|
||||
}
|
||||
```
|
||||
|
||||
## 🎉 期待される成果
|
||||
|
||||
Phase 11.5完了により、Nyashは:
|
||||
- **産業レベルの性能**: GC pauseがマイクロ秒単位
|
||||
- **真の並行性**: lock-free data structures対応
|
||||
- **モダンな非同期**: async/await完全サポート
|
||||
|
||||
これにより、**30日で作られたとは思えない**世界クラスの言語が完成します!
|
||||
162
docs/phases/phase-11.5/WASM-ISSUES.md
Normal file
162
docs/phases/phase-11.5/WASM-ISSUES.md
Normal file
@ -0,0 +1,162 @@
|
||||
# WASM実装の問題と改善計画
|
||||
|
||||
## 🚨 現状の問題
|
||||
|
||||
### 1. **2つのWASM実装が存在**
|
||||
- **Rust→WASM**: `wasm-pack build`でNyashインタープリター全体をWASMに(動作する)
|
||||
- **MIR→WASM**: `--compile-wasm`でNyashコードをWASMに変換(ほぼ動かない)
|
||||
|
||||
### 2. **MIR→WASM実装の問題点**
|
||||
```rust
|
||||
// src/backend/wasm/codegen.rs より
|
||||
pub fn generate_module(...) -> Result<WasmModule, WasmError> {
|
||||
// 基本的な命令しか実装されていない
|
||||
// - 算術演算
|
||||
// - 制御フロー
|
||||
// - print文(ホスト関数呼び出し)
|
||||
|
||||
// 未実装:
|
||||
// - Box操作(NewBox, BoxCall, PluginInvoke)
|
||||
// - 配列操作
|
||||
// - プラグインシステム
|
||||
// - GC/メモリ管理
|
||||
}
|
||||
```
|
||||
|
||||
### 3. **根本的な設計問題**
|
||||
- **Box抽象の表現困難**: Everything is BoxをWASMの型システムで表現できない
|
||||
- **動的ディスパッチ**: BoxCallやPluginInvokeの実装が困難
|
||||
- **GCの不在**: WASMにはGCがない(WasmGC提案はまだ実験的)
|
||||
- **プラグインFFI**: C ABIをWASM環境で実現できない
|
||||
|
||||
## 📊 現状の実装状況
|
||||
|
||||
### 実装済み(動作するもの)
|
||||
```nyash
|
||||
// 基本的な算術
|
||||
function add(a, b) {
|
||||
return a + b
|
||||
}
|
||||
|
||||
// 単純な制御フロー
|
||||
function factorial(n) {
|
||||
if n <= 1 { return 1 }
|
||||
return n * factorial(n - 1)
|
||||
}
|
||||
|
||||
// print文(ホスト関数経由)
|
||||
print("Hello WASM")
|
||||
```
|
||||
|
||||
### 未実装(動作しないもの)
|
||||
```nyash
|
||||
// Box操作
|
||||
local str = new StringBox("hello") // ❌ NewBox未実装
|
||||
str.toUpperCase() // ❌ BoxCall未実装
|
||||
|
||||
// 配列
|
||||
local arr = [1, 2, 3] // ❌ 配列リテラル未実装
|
||||
arr.push(4) // ❌ ArrayBox未実装
|
||||
|
||||
// プラグイン
|
||||
local file = new FileBox() // ❌ PluginInvoke未実装
|
||||
```
|
||||
|
||||
## 🤔 なぜRust→WASMは動くのか
|
||||
|
||||
```toml
|
||||
# Cargo.toml
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
wasm-bindgen = "0.2"
|
||||
```
|
||||
|
||||
- **すべてのBox実装がそのままWASMに**: Arc<Mutex>も含めて
|
||||
- **wasm-bindgenの魔法**: JavaScript↔Rust境界を自動生成
|
||||
- **制限事項**: 一部のBox(TimerBox、FileBox等)は除外
|
||||
|
||||
## 🚀 改善案
|
||||
|
||||
### Option 1: MIR→WASM実装の完成(困難)
|
||||
```wat
|
||||
;; BoxをWASMテーブルで管理
|
||||
(table $boxes 1000 externref)
|
||||
(global $next_box_id (mut i32) (i32.const 0))
|
||||
|
||||
;; NewBox実装
|
||||
(func $new_string_box (param $str i32) (result i32)
|
||||
;; 新しいBox IDを割り当て
|
||||
(local $box_id i32)
|
||||
(local.set $box_id (global.get $next_box_id))
|
||||
|
||||
;; JavaScriptでStringBoxを作成
|
||||
(table.set $boxes
|
||||
(local.get $box_id)
|
||||
(call $js_create_string_box (local.get $str)))
|
||||
|
||||
;; IDを返す
|
||||
(local.get $box_id)
|
||||
)
|
||||
```
|
||||
|
||||
**問題点**:
|
||||
- JavaScript側にBox実装が必要
|
||||
- 性能オーバーヘッドが大きい
|
||||
- プラグインシステムとの統合困難
|
||||
|
||||
### Option 2: Rust→WASMの活用(現実的)
|
||||
```rust
|
||||
// NyashコードをRustに変換してからWASMに
|
||||
nyash_code → rust_code → wasm
|
||||
|
||||
// 例:
|
||||
// Nyash: local s = new StringBox("hello")
|
||||
// Rust: let s = Box::new(StringBox::new("hello".to_string()));
|
||||
// WASM: (自動生成)
|
||||
```
|
||||
|
||||
### Option 3: WASMランタイムの埋め込み(革新的)
|
||||
```wat
|
||||
;; 最小VMをWASMに埋め込む
|
||||
(module
|
||||
;; MIRバイトコードを格納
|
||||
(data (i32.const 0) "\01\02\03...")
|
||||
|
||||
;; VMインタープリター
|
||||
(func $vm_execute
|
||||
;; MIR命令をデコード・実行
|
||||
)
|
||||
|
||||
;; エントリーポイント
|
||||
(func (export "main")
|
||||
(call $vm_execute)
|
||||
)
|
||||
)
|
||||
```
|
||||
|
||||
## 🎯 推奨アプローチ
|
||||
|
||||
### Phase 1: 現状維持
|
||||
- **Rust→WASM**: ブラウザでNyashを動かす用途で活用
|
||||
- **MIR→WASM**: 実験的機能として残す
|
||||
|
||||
### Phase 2: Nyash→Rust変換
|
||||
- NyashコードをRustに変換する仕組みを作る
|
||||
- 生成されたRustコードをwasm-packでビルド
|
||||
|
||||
### Phase 3: WasmGC待ち
|
||||
- WasmGC仕様が安定したら本格実装
|
||||
- Box型システムをWasmGCで表現
|
||||
|
||||
## 📝 結論
|
||||
|
||||
現在のMIR→WASM実装は**実験的**なもので、実用レベルには達していません。一方、Rust→WASMは**すでに動作**しており、ブラウザでNyashを体験してもらうには十分です。
|
||||
|
||||
**当面は**:
|
||||
1. Rust→WASMでプレイグラウンド提供
|
||||
2. ネイティブ実行(VM/JIT/AOT)に注力
|
||||
3. WasmGCの成熟を待つ
|
||||
|
||||
これが現実的な戦略です!
|
||||
89
docs/phases/phase-11.5/archives/CHATGPT5_DECISIVE_ACTIONS.md
Normal file
89
docs/phases/phase-11.5/archives/CHATGPT5_DECISIVE_ACTIONS.md
Normal file
@ -0,0 +1,89 @@
|
||||
# ChatGPT5の決定的アクション
|
||||
|
||||
Date: 2025-08-31
|
||||
Summary: Box-SSA Core-15への収束と即座の実装開始
|
||||
|
||||
## 🎯 問題提起
|
||||
|
||||
> なおCore-15の最終セットは2案が文書にあります。どちらで凍結しますか?
|
||||
> - A) Gemini版15: RefNew/RefGet/RefSetを含む(真の15個)
|
||||
> - B) CURRENT_TASKのCore-15: 実質17個(15と言いながら)
|
||||
|
||||
## 💡 第三の道:Box-SSA Core-15
|
||||
|
||||
ChatGPT5の革命的提案:
|
||||
|
||||
```
|
||||
{ Const, UnaryOp, BinOp, Compare, TypeOp,
|
||||
Load, Store,
|
||||
Jump, Branch, Return, Phi,
|
||||
Call, NewBox, BoxCall, ExternCall }
|
||||
```
|
||||
|
||||
### 核心的洞察
|
||||
|
||||
**すべてのBox操作をBoxCallに統一**:
|
||||
- `RefNew` → `NewBox`
|
||||
- `RefGet` → `BoxCall(obj, "getField", ...)`
|
||||
- `RefSet` → `BoxCall(obj, "setField", ...)`
|
||||
- `ArrayGet/ArraySet` → `BoxCall(arr, "get"/"set", ...)`
|
||||
- `PluginInvoke` → `BoxCall(plugin, "invoke", ...)`
|
||||
|
||||
## 🚀 即座の実装開始
|
||||
|
||||
### 無言のコーディング
|
||||
|
||||
ChatGPT5は議論の余地なしと判断し、即座にMIR命令の列挙型を更新:
|
||||
|
||||
```diff
|
||||
&[
|
||||
- "Copy", // 削除!SSAで不要
|
||||
- "RefNew", // 削除!NewBoxに統合
|
||||
- "RefGet", // 削除!BoxCallに統合
|
||||
- "RefSet", // 削除!BoxCallに統合
|
||||
+ "TypeOp", // 追加!型演算
|
||||
+ "Phi", // 追加!SSA必須
|
||||
+ "NewBox", // 追加!Box生成
|
||||
+ "BoxCall", // 追加!万能呼び出し
|
||||
]
|
||||
```
|
||||
|
||||
### JIT→LLVM直行の判断
|
||||
|
||||
**現状認識**:
|
||||
- Cranelift = 実はAOTだった(JIT幻想)
|
||||
- 15命令なら機械的変換で十分
|
||||
- JITの複雑さ < LLVMの確実な高速化
|
||||
|
||||
**戦略転換**:
|
||||
```
|
||||
旧計画: Phase 9(JIT) → Phase 10(最適化) → Phase 11(LLVM)
|
||||
新計画: Phase 9-10スキップ → Phase 11(LLVM)直行!
|
||||
```
|
||||
|
||||
## 📊 実装の約束事
|
||||
|
||||
### Verifier必須チェック
|
||||
1. Box field直Load/Store検出(禁止)
|
||||
2. 必要箇所のwrite barrier挿入検証
|
||||
3. ExternCallのattr必須化
|
||||
|
||||
### Loweringの役割
|
||||
- BoxCall → 形状ガード → 直アクセス → バリア縮約
|
||||
- VM: Phi展開、簡易PIC
|
||||
- LLVM: PICガードは最適化で潰れて素の命令列へ
|
||||
|
||||
## 🎉 結論
|
||||
|
||||
> 凍結は "Box-SSA Core-15"。Aの Ref* は捨てる/Bの専用命令は BoxCall に吸収して15個に収斂。これで「簡単さ=表面の一枚」「速さ=Lowering/最適化」で分離でき、VMとAOTとFFIを**一本の ABI**で貫けるにゃ。
|
||||
|
||||
## 💻 ChatGPT5の心境
|
||||
|
||||
```nyash
|
||||
if (命令数 == 15 && 設計 == "完璧") {
|
||||
議論.skip()
|
||||
実装.start() // 即座に!
|
||||
}
|
||||
```
|
||||
|
||||
この瞬間、ChatGPT5は「これ以上の議論は時間の無駄」と判断し、無言でコーディングを開始した。エンジニアが最高の設計に出会った時の、最も純粋な反応である。
|
||||
125
docs/phases/phase-11.5/archives/CODEX_MIR_LLVM_DEEP_DIVE.md
Normal file
125
docs/phases/phase-11.5/archives/CODEX_MIR_LLVM_DEEP_DIVE.md
Normal file
@ -0,0 +1,125 @@
|
||||
# Codex先生のMIR→LLVM技術的深掘り
|
||||
|
||||
Date: 2025-08-31
|
||||
Source: codex exec コマンドによる技術相談
|
||||
|
||||
## 質問内容
|
||||
|
||||
MIR15命令でEverything is Box哲学を実現。注釈システムで最適化ヒントを付与。
|
||||
|
||||
### 技術的課題
|
||||
1. BoxCallの最適化(PIC実装の具体的なLLVM IRパターン)
|
||||
2. 脱箱化戦略(IntegerBox(42) → i64への変換タイミング)
|
||||
3. GCバリア最小化(世代別GCでの若い世代→若い世代のバリア省略)
|
||||
4. 注釈→LLVM属性変換(安全性の保証方法)
|
||||
5. インライン展開(BoxCallのインライン基準)
|
||||
|
||||
## Codex先生の技術的実装アプローチ
|
||||
|
||||
### 1. BoxCall + PIC(Polymorphic Inline Cache)
|
||||
|
||||
#### モノモルフィックPIC IR例
|
||||
```llvm
|
||||
; グローバルPIC
|
||||
@pic_foo_site123 = internal global { i64, i8* } { 0, null }
|
||||
|
||||
; ガード + 直呼び
|
||||
%cid = load i64, i64* %receiver_class_id
|
||||
%pic_cls = load i64, i64* getelementptr({i64,i8*}, {i64,i8*}* @pic_foo_site123, i32 0, i32 0)
|
||||
%hit = icmp eq i64 %cid, %pic_cls
|
||||
%likely = call i1 @llvm.expect.i1(i1 %hit, i1 true)
|
||||
br i1 %likely, label %fast, label %miss, !prof !{!"branch_weights", i32 10000, i32 1}
|
||||
|
||||
fast:
|
||||
%callee = load i8*, i8** getelementptr({i64,i8*}, {i64,i8*}* @pic_foo_site123, i32 0, i32 1)
|
||||
%fn = bitcast i8* %callee to %RetTy (%ObjTy*, ... )*
|
||||
%r = call fastcc %RetTy %fn(%ObjTy* %recv, ...)
|
||||
br label %cont
|
||||
|
||||
miss:
|
||||
; cold, 非インライン
|
||||
%r2 = call coldcc %RetTy @nyash_pic_miss_foo(%ObjTy* %recv, i64 %method_id, ...)
|
||||
br label %cont
|
||||
```
|
||||
|
||||
#### PIC更新の安全化
|
||||
- 1-ワードのバージョンでRCU風プロトコル
|
||||
- `store atomic i64 ver=odd (acq_rel)`→フィールド更新→`store atomic i64 ver=even (release)`
|
||||
- リーダは一貫性確認、失敗時はmissへフォールバック
|
||||
|
||||
### 2. 脱箱化(Unboxing)戦略
|
||||
|
||||
#### 2表現SSA
|
||||
- MIRで各Box値に「プリミティブSSA(i64)」と「Box化遅延ノード」の二重表現
|
||||
- `IntegerBox(42)` → 直ちに`i64 42`としてSSA化
|
||||
- Boxが必要な境界(汎用コンテナ格納、越関数ABI等)直前でのみBox化
|
||||
|
||||
#### 実装例
|
||||
```llvm
|
||||
; 算術は全て i64
|
||||
%a = add i64 %x, %y
|
||||
; 必要になった地点でのみ実体化
|
||||
%box = call %ObjTy* @nyash_make_int(i64 %a) ; ここでのみGC対象生成
|
||||
call void @vector_push(%Vec* %v, %ObjTy* %box)
|
||||
```
|
||||
|
||||
### 3. GCバリア最小化
|
||||
|
||||
#### Write barrier IRパターン
|
||||
```llvm
|
||||
; slot: i8** への書き込み
|
||||
store i8* %val, i8** %slot
|
||||
; TLSにNursery境界を保持
|
||||
%low = load i64, i64* @nyash_tls_nursery_low
|
||||
%high = load i64, i64* @nyash_tls_nursery_high
|
||||
%yo_obj = and (icmp_uge %obj_i, %low), (icmp_ult %obj_i, %high)
|
||||
%yo_val = and (icmp_uge %val_i, %low), (icmp_ult %val_i, %high)
|
||||
%need_barrier = and (not %yo_obj), %yo_val ; 老→若のみ
|
||||
%likely0 = call i1 @llvm.expect.i1(i1 %need_barrier, i1 false)
|
||||
br i1 %likely0, label %barrier, label %cont, !prof !{!"branch_weights", 1, 10000}
|
||||
|
||||
barrier:
|
||||
call fastcc void @nyash_card_mark(i8* %obj, i8** %slot, i8* %val) cold
|
||||
br label %cont
|
||||
```
|
||||
|
||||
### 4. 注釈→LLVM属性変換
|
||||
|
||||
#### 安全性担保の原則
|
||||
- 原則:Nyash注釈は「保守的に弱めに」マップ
|
||||
- 検証不十分なら一段弱い属性を使用
|
||||
|
||||
#### マッピング例
|
||||
| Nyash注釈 | LLVM属性 | 条件 |
|
||||
|-----------|----------|------|
|
||||
| `@no_escape` | `nocapture` | エスケープしないことを静的証明 |
|
||||
| `@pure` | `readonly` | 副作用なしを保証 |
|
||||
| `@pure` + 強条件 | `readnone speculatable` | メモリ不読+例外なし |
|
||||
| `@nonnull` | `nonnull` | NULL不可を型システムで保証 |
|
||||
|
||||
### 5. インライン展開戦略
|
||||
|
||||
#### BoxCallの基準
|
||||
- モノモルフィックPICかつヒット率高(>90%)→ インライン
|
||||
- コストモデル:call/ret + 間接分岐除去 + 逃げないBoxの削除
|
||||
- メガモルフィック/低ヒット率は非インライン
|
||||
|
||||
#### 再帰的Box呼び出し最適化
|
||||
```llvm
|
||||
; 自己再帰でTCO
|
||||
musttail call fastcc %RetTy @callee(%ObjTy* %recv, ...)
|
||||
ret %RetTy %r
|
||||
```
|
||||
|
||||
## 実装のこつ
|
||||
|
||||
1. **PICグローバル**:`dso_local`/`internal`、更新局所性を確保
|
||||
2. **ABI二系統**:Box ABI/Primitive Fast-ABIを明示
|
||||
3. **GC統合**:`gc "statepoint-nyash"`を関数定義に付与
|
||||
4. **最適化ヒント**:`llvm.expect`と`!prof`を併用
|
||||
|
||||
## 結論
|
||||
|
||||
> 15命令は実装・最適化・GC統合の観点でよく均衡したミニマル核です。Box統一は開発生産性と実装単純性を大きく押し上げますが、性能面のボトルネックは脱箱・AA強化・適切なGC統合(バリア/セーフポイント/原子性)で解消してください。
|
||||
|
||||
Codex先生は具体的なLLVM IRパターンとともに、実装可能で保守性の高い設計を提示してくれました。
|
||||
@ -0,0 +1,91 @@
|
||||
# Gemini先生のMIR→LLVM変換コンサルテーション
|
||||
|
||||
Date: 2025-08-31
|
||||
Source: gemini -p コマンドによる相談
|
||||
|
||||
## 質問内容
|
||||
|
||||
Nyashプログラミング言語のMIR→LLVM変換計画について:
|
||||
- MIRを26命令から15命令に削減中
|
||||
- Everything is Box哲学
|
||||
- 注釈システムでヒントを付与
|
||||
|
||||
### 15命令の内訳
|
||||
- 基本演算(5): Const, UnaryOp, BinOp, Compare, TypeOp
|
||||
- メモリ(2): Load, Store
|
||||
- 制御(4): Branch, Jump, Return, Phi
|
||||
- Box(3): NewBox, BoxCall, PluginInvoke
|
||||
- 配列(2): ArrayGet, ArraySet
|
||||
- 外部(1): ExternCall
|
||||
|
||||
## Gemini先生の回答
|
||||
|
||||
### 1. BoxCall最適化の最良アプローチ
|
||||
|
||||
**結論**: 静的解析による**メソッドID(スロット)ベースのディスパッチ**を主軸とし、解決できない場合に**PIC(Polymorphic Inline Cache)**を組み合わせる
|
||||
|
||||
**理由**:
|
||||
- Nyashはすでに`method_id`(スロット)を用いた最適化に着手
|
||||
- 型が静的に推論できる場合に非常に高速
|
||||
- 動的な呼び出しに対してはPICが有効(実績ある手法)
|
||||
- vtable案も有力だが、`Everything is Box`の柔軟性を損なう可能性
|
||||
|
||||
**提案**:
|
||||
1. MIRコンパイラ強化:より多くの`BoxCall`を`method_id`付きに変換
|
||||
2. PICの高度化:Mono-PICから多相(Polymorphic)/メガモーフ(Megamorphic)へ
|
||||
3. LLVM IR生成時の戦略を明確化
|
||||
|
||||
### 2. GCバリアの効率的な挿入戦略
|
||||
|
||||
**結論**: **Store, ArraySet, PluginInvoke**のうち、**ヒープ上のBoxオブジェクトへのポインタ書き込み**が発生する可能性のある箇所にのみライトバリアを挿入
|
||||
|
||||
**提案**:
|
||||
1. MIRレベルでの挿入:条件付きで`GCBarrier`命令を挿入する最適化パス
|
||||
2. 条件:
|
||||
- 書き込まれる値がポインタ(Box)である
|
||||
- 書き込み先がヒープ上のオブジェクトである
|
||||
3. LLVM IR生成時:`nyash.gc.barrier_write`シンボルの呼び出しに変換
|
||||
|
||||
### 3. 脱箱化(Box→プリミティブ)のタイミング
|
||||
|
||||
**結論**: **型に関する注釈**を最大限に活用し、**MIRレベルの最適化パス**で実施
|
||||
|
||||
**提案**:
|
||||
1. 注釈の活用:`#[primitive_type="i64"]`のようなヒント
|
||||
2. MIR最適化パス:
|
||||
- 型推論と注釈に基づく安全な範囲の特定
|
||||
- `NewBox`→プリミティブ値への置換
|
||||
- `BoxCall`→直接的なLLVM演算への置換
|
||||
3. LLVM IR生成時:脱箱化された変数はプリミティブ型として表現
|
||||
|
||||
### 4. LLVM最適化パスの推奨構成
|
||||
|
||||
**推奨構成**:
|
||||
1. 標準的な最適化パス(必須):
|
||||
- `mem2reg`: SSA形式の基本
|
||||
- `instcombine`: 冗長な命令の結合
|
||||
- `gvn`: グローバルな共通部分式削除
|
||||
- `sccp`: 定数畳み込みと到達不能コード削除
|
||||
- `licm`: ループ不変コード移動
|
||||
- `indvars`: ループ帰納変数単純化
|
||||
- `loop-unroll`: ループ展開
|
||||
|
||||
2. Nyash特有のカスタムパス(推奨):
|
||||
- Box化関連の除去
|
||||
- ランタイムコール最適化
|
||||
|
||||
### 5. 注釈システムからLLVM属性への変換で注意点
|
||||
|
||||
**結論**: Nyash注釈のセマンティクスとLLVM属性のセマンティクスが完全に一致するかを慎重に検証し、**安全な属性から段階的に導入**
|
||||
|
||||
**注意点**:
|
||||
- `noalias`: 誤用は未定義動作を引き起こす
|
||||
- `!tbaa`: Box統一モデルでの工夫が必要
|
||||
- `!range`: 数値注釈から生成可能
|
||||
- 検証:安全な属性(`noundef`, `nonnull`)から開始
|
||||
|
||||
## 総評
|
||||
|
||||
> これらの提案が、NyashのLLVMバックエンド開発を加速させる一助となれば幸いです。
|
||||
|
||||
Gemini先生は、Nyashの「Everything is Box」哲学を理解した上で、実践的かつ段階的なアプローチを提案してくれました。特にPICとメソッドIDの組み合わせ、MIRレベルでの脱箱化は非常に有効な戦略です。
|
||||
41
docs/phases/phase-11.7_jit_complete/CURRENT_TASK.md
Normal file
41
docs/phases/phase-11.7_jit_complete/CURRENT_TASK.md
Normal file
@ -0,0 +1,41 @@
|
||||
# CURRENT TASK – Phase 11.7(JIT Complete / Semantics Layer)
|
||||
|
||||
Focus Window: Semantics導入+jit-direct安定化の確定報告 → GC/Sync/非同期のJIT降下着手
|
||||
|
||||
合意事項(要約)
|
||||
|
||||
- LLVM AOT は一旦クローズ。Windows 依存と重量を回避し、Cranelift に集中。
|
||||
- 単一意味論層(Semantics)を導入し、Nyashスクリプト/VM/JIT(exe)を同一動作に揃える。
|
||||
- VM は参照実装。JIT は実行/生成を担い、VM→JITのランタイムフォールバックは行わない。
|
||||
|
||||
現状ステータス(2025-09-01)
|
||||
|
||||
- jit-direct 分岐/PHI 合流:単一出口+BlockParam合流で安定化を確認。
|
||||
- テスト: `mir-branch-ret`, `mir-phi-min`, `mir-branch-multi`, `mir-nested-branch`, `mir-phi-two` で VM/JIT 一致(tag=201/200 一致)。
|
||||
- Semantics 層:`src/semantics/{mod.rs, eval.rs}` にトレイトとPoCインタプリタの骨組みを追加済(未配線)。
|
||||
- C ABI(NyRT):`crates/nyrt` の `libnyrt.a` に必要シンボル実装済(console/array/string/plugin_invoke/checkpoint/gc_barrier 等)。
|
||||
- VM 側:Safepoint/書込バリア/簡易スケジューラ(SingleThread)連携は稼働。
|
||||
- JIT 側:Safepoint/バリア/await はまだスタブまたは未emit(要降下)。
|
||||
|
||||
直近タスク(このフェーズでやること)
|
||||
|
||||
1) Semantics 実用化配線(VM/JITの動作一致の“芯”)
|
||||
- `SemanticsVM`(VM実行での実装)と `SemanticsClif`(LowerCore+IRBuilder委譲)を用意。
|
||||
- `semantics::MirInterpreter` で両者を同一MIRへ適用し、差分検出の土台を作る。
|
||||
2) JIT へ GC/Sync/非同期の降下
|
||||
- Safepoint: `I::Safepoint` を `nyash.rt.checkpoint` emit。`nyrt` 側で `gc.safepoint()` と `scheduler.poll()` に橋渡し。
|
||||
- Write Barrier: Array/Map の set/push 等をlowerする箇所で `nyash.gc.barrier_write` を emit(CountingGc で検証)。
|
||||
- Await: PoC として FutureBox の同期 get にlower(動作一致優先)。
|
||||
3) パリティ検証
|
||||
- `NYASH_GC_COUNTING=1` で VM/JIT ともに safepoint/barrier カウントが増えることを確認。
|
||||
- 既存 smokes(分岐/PHI/配列/外部呼び出し)で一致を継続監視。
|
||||
|
||||
実行メモ
|
||||
|
||||
- Build(JIT): `cargo build --release --features cranelift-jit`
|
||||
- jit-direct: `NYASH_JIT_THRESHOLD=1 ./target/release/nyash --jit-direct <app>`
|
||||
- 追跡: `NYASH_JIT_TRACE_RET/SEL/BLOCKS=1`、GC: `NYASH_GC_COUNTING=1`(必要時)
|
||||
|
||||
備考
|
||||
|
||||
- LLVM AOT のドキュメント/ツールは維持するが、Windows 前提の依存導入は行わない。Cranelift で“がっちり作る”。
|
||||
46
docs/phases/phase-11.7_jit_complete/MEETING_NOTES.md
Normal file
46
docs/phases/phase-11.7_jit_complete/MEETING_NOTES.md
Normal file
@ -0,0 +1,46 @@
|
||||
# Design Notes – Phase 11.7 JIT Complete (Meeting Summary)
|
||||
|
||||
Date: 2025-09-01
|
||||
|
||||
Key Decisions
|
||||
|
||||
- Single Semantics Source: Introduce a MIR semantics layer (trait) as the single source of truth. All backends (VM/Cranelift/LLVM/WASM) implement this interface.
|
||||
- No Runtime Fallback: Remove VM→JIT fallback complexity. VM becomes the reference executor; codegen backends handle execution/AOT. JIT is compile-only/AOT‑assist when needed.
|
||||
- Handle‑First ABI: Unify handle/i64/ptr conversions, tag classification, concat/extern/boxcall via shared helpers; call into NyRT shims from backends.
|
||||
- GC Hooks: Insert sync barriers and async safepoints as MIR‑level hooks that each backend lowers appropriately.
|
||||
- Backends Roadmap: LLVM AOT は一旦アーカイブ。Cranelift を主線(JIT/軽量AOT)とし、WASM は同一セマンティクスで後段。Windows DX を軽く保つ。
|
||||
|
||||
Architecture Sketch
|
||||
|
||||
- MIR → Semantics<E>
|
||||
- VmSem: executes values (reference)
|
||||
- ClifSem: builds Cranelift IR (JIT/AOT)
|
||||
- LlvmSem: builds LLVM IR (AOT)
|
||||
- WasmSem: builds Wasm (future)
|
||||
- Shared ABI utilities: handle↔i64/ptr, to_bool, compare, tags, invoke variants, NyRT shims.
|
||||
|
||||
Implementation Plan (Progressive)
|
||||
|
||||
- Phase 1: Skeleton + minimal lowering (Const/Return/Add) → echo-lite returns 0 via Cranelift JIT skeleton.
|
||||
- Phase 2: Control (Jump/Branch/Phi), Load/Store, Compare, String concat via NyRT, Box/Extern by-id (fixed/vector).
|
||||
- Phase 3: GC barriers/safepoints; parity with VM(CountingGc での観測を含む)。
|
||||
- Phase 4: Stability, logs, strict/legacy guards; optional AOT via cranelift-object + link scripts.
|
||||
|
||||
Notes from Review
|
||||
|
||||
- Using Semantics trait enables zero‑cost abstractions with static dispatch.
|
||||
- Add optional debug hooks (location/value) and optimization hints (likely_branch, pure_function_hint) later.
|
||||
- Testing: MockSemantics for unit tests; parity tests VM vs CLIF.
|
||||
|
||||
Action Items
|
||||
|
||||
- Land Semantics trait + minimal MirInterpreter (skeleton added).
|
||||
- Implement ClifSem minimal lowering; wire Runner `--backend cranelift`.
|
||||
- Centralize ABI helpers; migrate existing scattered logic to shared module.
|
||||
- Emit `nyash.rt.checkpoint` and `nyash.gc.barrier_write` from LowerCore at appropriate sites; wire Await (PoC: blocking get).
|
||||
- Add build_cl scripts for AOT when ready.
|
||||
|
||||
Links
|
||||
|
||||
- PLAN.md – milestones and coverage
|
||||
- CURRENT_TASK.md – immediate focus
|
||||
81
docs/phases/phase-11.7_jit_complete/PLAN.md
Normal file
81
docs/phases/phase-11.7_jit_complete/PLAN.md
Normal file
@ -0,0 +1,81 @@
|
||||
# Phase 11.7 – JIT Complete Plan (Cranelift)
|
||||
|
||||
Goal
|
||||
|
||||
- Ship a complete JIT backend (Cranelift) for MIR Core‑15 with Semantics layer as the single source of truth, GC sync/async support, and full Box/Extern integration. Keep DX simple and cross‑platform.
|
||||
|
||||
Milestones
|
||||
|
||||
1) Bootstrap (Infra + Skeleton)
|
||||
- Add backend module: `src/backend/cranelift/{mod.rs,context.rs,lower.rs,jit.rs,object.rs}`
|
||||
- Context: host ISA, FunctionBuilder, Module (JIT/Object) setup helpers
|
||||
- Runner: `--backend cranelift` execution path; feature flag reuse (`cranelift-jit`)
|
||||
- Minimal ops: Const i64/f64/bool/null/string → CLIF values; Return; straight‑line add/sub
|
||||
- Smoke: `apps/tests/ny-echo-lite` returns 0 via JIT
|
||||
|
||||
2) Core MIR‑15 Lowering (Parity with VM)
|
||||
- Control: Jump/Branch/Phi, Load/Store (alloca on entry; i1↔i64 widen/narrow)
|
||||
- Unary/Binary/Compare: int/float/ptr eq/ne; logical and/or via to_bool
|
||||
- TypeOp (when needed) + pointer/int casts (handle→i64/i8* via ABI helpers)
|
||||
- Strings: concat via NyRT shims (`nyash.string.concat_*`)
|
||||
- BoxCall (by‑id): fixed/tagged args (<=4) + vector path; handle‑first returns (i64/ptr)
|
||||
- ExternCall: `env.console.*`, `env.debug.trace`, `console.readLine` via NyRT shims
|
||||
- Smokes: array/map/vinvoke(size/ret), echo; compare outputs with VM
|
||||
|
||||
3) GC Cooperation
|
||||
- Sync barriers: insert read/write barriers at Load/Store & NewBox as per VM semantics
|
||||
- Async safepoints: at call sites/loop backedges; NyRT entry glue to yield if required
|
||||
- Tests: targeted barrier smoke (array/map mutations) + perf sanity (no excessive barriers)
|
||||
|
||||
4) Parity + Stability
|
||||
- UnsupportedLegacyInstruction: maintain strict mode; allow env override for debug
|
||||
- Error reporting: source op pretty‑print, MIR value ids in error messages
|
||||
- Logging: `NYASH_CLI_VERBOSE=1` shows JIT compile stages + object sizes (optional)
|
||||
- Doc/Doctor script: `tools/doctor.ps1`/`.sh` for quick env checks (optional nice‑to‑have)
|
||||
|
||||
5) AOT (Optional within 11.7 if time)
|
||||
- `cranelift-object` emit: `.o` for main; link with NyRT → exe (`tools/build_cl.*`)
|
||||
- Windows: clang/lld link; Linux: cc link; parity with LLVM’s scripts
|
||||
|
||||
Instruction Coverage (MIR Core‑15)
|
||||
|
||||
- Const, UnaryOp, BinOp, Compare, TypeOp
|
||||
- Load, Store, Phi, Jump, Branch, Return
|
||||
- Call, NewBox, BoxCall, ExternCall
|
||||
|
||||
ABI & Shims
|
||||
|
||||
- Handle‑first: receiver/values normalized to i64; ptr/int casts via helpers
|
||||
- NyRT shims used: `nyash.console.*`, `nyash.debug.trace`, `nyash.console.readline`,
|
||||
`nyash_string_new`, `nyash.string.concat_*`, `nyash_array_*_h`, `nyash.instance.*_h`,
|
||||
plugin invoke (by‑id tagged, vector variants)
|
||||
|
||||
Semantics Integration (new in 11.7)
|
||||
|
||||
- Add `Semantics` trait as unified MIR semantics API.
|
||||
- Provide `SemanticsVM` (exec) and `SemanticsClif` (lower) so the same MIR walks yield identical behavior across VM and JIT.
|
||||
- Use `semantics::MirInterpreter` for parity tests; prefer zero‑cost abstractions with static dispatch.
|
||||
|
||||
Status Notes (2025‑09‑01)
|
||||
|
||||
- LLVM AOT: closed for now due to Windows dependency weight; Cranelift is the mainline.
|
||||
- VM: safepoint/barrier/scheduler wired and observable (CountingGc).
|
||||
- JIT: `nyash.rt.checkpoint`/`nyash.gc.barrier_write` symbols are available via NyRT; LowerCore needs to emit safepoints and barriers; Await lowering pending.
|
||||
|
||||
Deliverables
|
||||
|
||||
- Code: Cranelift backend files + runner integration
|
||||
- Tools: build/run scripts for JIT/AOT; updated smokes to exercise CL route
|
||||
- Docs: this plan + CURRENT_TASK.md; brief README how to run JIT
|
||||
|
||||
Risks & Mitigations
|
||||
|
||||
- Pointer/int mismatch → normalize via i64/ptr helpers in one place; add asserts
|
||||
- Barrier placement overhead → start with conservative placement; measure; trim if safe
|
||||
- Windows toolchain variance → Cranelift avoids external LLVM; keep MSVC only
|
||||
|
||||
Timeline (indicative)
|
||||
|
||||
- Week 1: Milestone 1 + 2 (most ops) → basic smokes green
|
||||
- Week 2: GC barriers + safepoints, full parity sweep; docs/tools polish
|
||||
- Optional: AOT via cl‑object emit & link scripts
|
||||
33
docs/phases/phase-11.7_jit_complete/README.md
Normal file
33
docs/phases/phase-11.7_jit_complete/README.md
Normal file
@ -0,0 +1,33 @@
|
||||
# Phase 11.7 – JIT Complete (MIR-15 + Semantics + Sync/Async GC)
|
||||
|
||||
Scope: Implement a production‑ready JIT backend for Nyash that fully supports the MIR Core‑15 instruction set, synchronous/async GC cooperation, and delivers a simple, reproducible developer experience across platforms (WSL/Linux/Windows).
|
||||
|
||||
Why now:
|
||||
- LLVM AOT は一度実装を進めたが、Windows 依存が重くサイズも大きい。Cranelift に回帰して、純Rustで“Just Works”のDXを取り戻し、高速な反復開発を実現する(AOT/LLVMは資料として保持)。
|
||||
|
||||
Outcomes (Definition of Done):
|
||||
- All MIR‑15 ops compile and execute via JIT with behavioral parity to VM.
|
||||
- BoxCall/ExternCall are handled through NyRT shims (handle‑first ABI) safely.
|
||||
- Sync GC barriers in place (read/write), async safepoints wired at call/loop edges.
|
||||
- Smokes: echo/array/map/vinvoke/extern pass; parity checks vs VM/JIT (logs included).
|
||||
- 1‑command setup and run on WSL + Windows Dev PowerShell; no external LLVM needed.
|
||||
|
||||
Backends Strategy:
|
||||
- LLVM AOT はアーカイブ(参照は可)。主線は Cranelift(JIT/軽量AOT)。
|
||||
- JIT 既定は Cranelift(feature: `cranelift-jit`)。AOT は必要に応じ `cranelift-object` を併用。
|
||||
|
||||
This folder contains the living plan (PLAN.md) and the rolling snapshot of the current task focus (CURRENT_TASK.md). Semantics 層の導入により、Nyash スクリプト/VM/JIT(exe)の動作を一致させる。
|
||||
|
||||
## JIT Single-Exit Policy and TRACE
|
||||
|
||||
- Single-Exit: JIT は関数終端で単一の ret ブロックに合流する方針。分岐合流は BlockParam(最小PHI)で表現し、`end_function` で最終 seal を行う。
|
||||
- Branch Fast-Path: then/else がともに i64 定数を即時 return する場合、`select(cond, K_then, K_else)` → `return` に縮約(常時有効)。
|
||||
- TRACE 環境変数(必要時のみON):
|
||||
- `NYASH_JIT_DUMP=1` …… Lower の要約/CFGライトダンプを表示
|
||||
- `NYASH_JIT_TRACE_BLOCKS=1` … ブロック入場ログ(`[JIT-BLOCK] enter=<idx>`)
|
||||
- `NYASH_JIT_TRACE_BR=1` …… br_if の cond 有無ログ
|
||||
- `NYASH_JIT_TRACE_SEL=1` … select の cond/then/else 値(tag=100/101/102)
|
||||
- `NYASH_JIT_TRACE_RET=1` … return 値ログ(tag=201=直前, 200=合流)
|
||||
|
||||
Notes:
|
||||
- 旧フラグ `NYASH_JIT_FASTPATH_SELECT` は不要になりました(存在しても無視)。
|
||||
@ -0,0 +1,59 @@
|
||||
# Async Task System — Phased Plan (P1–P3)
|
||||
|
||||
## Phase 1: Foundations (stabilize + timeouts)
|
||||
|
||||
- FutureBox: switch to Mutex+Condvar (done).
|
||||
- Await: poll scheduler + timeout gate in VM and JIT (done; unify to Result.Err in P3).
|
||||
- env.future.spawn_instance: enqueue via Scheduler; fallback sync if no scheduler (done).
|
||||
- Safepoint: ensure env.runtime.checkpoint is emitted around await (Lowerer rule).
|
||||
- Smokes: async-await-min; async-spawn-instance (safe form, no env).
|
||||
- Acceptance:
|
||||
- No hangs (await respects timeout); CPU near idle while waiting.
|
||||
- VM/JIT pass basic smokes; lingering processes do not remain.
|
||||
|
||||
## Phase 2: TaskGroup & CancellationToken
|
||||
|
||||
- Types:
|
||||
- CancellationToken { cancel(), is_cancelled() } idempotent; parent→child propagation only.
|
||||
- TaskGroup Box { spawn(fn)->Future, cancelAll(), joinAll() }, owns token; fini enforces cancel→join.
|
||||
- API:
|
||||
- nowait sugar targets current TaskGroup.
|
||||
- Unsafe detached spawn hidden behind unsafe_spawn_detached() and verifier checks.
|
||||
- VM implementation:
|
||||
- Extend scheduler to accept token; tasks periodically check token or are cancelled at await.
|
||||
- Group registry per scope; insert fini hooks in function epilogues and Main.
|
||||
- JIT/EXE:
|
||||
- NyRT shims accept optional token handle; if missing, use current group’s token.
|
||||
- Smokes:
|
||||
- spawn_cancel_on_scope_exit; nested_groups; lifo_join_order.
|
||||
- Acceptance:
|
||||
- Parent exit cancels and joins children deterministically (LIFO); no leaks per leak tracker.
|
||||
|
||||
## Phase 3: Error Semantics & Unification
|
||||
|
||||
- Future.await returns Result<T, Err> (Timeout/Cancelled/Panic) consistently (VM/JIT).
|
||||
- Remove 0/None fallbacks; map shims to Result at Nyash layer.
|
||||
- Lowerer verifies checkpoints around await; add verifier rule.
|
||||
- Observability: minimal counters and optional traces.
|
||||
- Smokes:
|
||||
- await_timeout distinct from cancel; panic_propagation; wakeup_race (no double resolve).
|
||||
- Acceptance:
|
||||
- Consistent error surface; result handling identical across VM/JIT/EXE.
|
||||
|
||||
## Test Matrix & CI
|
||||
|
||||
- Backends: {vm, jit, aot} × Modes: {default, strict}.
|
||||
- Smokes kept minimal; time‑bounded via timeout(1) wrapper.
|
||||
- CPU spin test: ensure idle waiting; measured via time/ps (best‑effort).
|
||||
|
||||
## Migration & Compatibility
|
||||
|
||||
- Keep env.future.spawn_instance during transition; TaskGroup.spawn preferred.
|
||||
- nowait sugar remains; mapped to TaskGroup.spawn.
|
||||
- Document flags: NYASH_AWAIT_MAX_MS, NYASH_SCHED_*.
|
||||
|
||||
## Files & Ownership
|
||||
|
||||
- Spec & Plan live here; updates linked from CURRENT_TASK.md.
|
||||
- Code changes limited to runtime/{scheduler,global_hooks}, boxes/future, jit/extern/async, lowerer await rules.
|
||||
|
||||
@ -0,0 +1,14 @@
|
||||
# Async Task System (Structured Concurrency) — Overview
|
||||
|
||||
Goal: A safe, structured, and portable async task system that runs end‑to‑end across Nyash code → MIR → VM → JIT/EXE.
|
||||
|
||||
- Default is safe: tasks are scoped to an owning group; when the owner ends, children cancel and join.
|
||||
- Everything is Box: TaskGroup and Future are Boxes; user APIs are Box methods; MIR uses BoxCall.
|
||||
- No new MIR ops required: use BoxCall/PluginInvoke consistently; safepoints are inserted around await.
|
||||
- Deterministic exits: parent exit triggers cancelAll → joinAll on children (LIFO), eliminating leaks.
|
||||
|
||||
This folder contains the spec, phase plan, and test plan:
|
||||
|
||||
- SPEC.md: User API, Box contracts, MIR/VM/JIT mapping, ABI, error semantics.
|
||||
- PLAN.md: Phased rollout (P1–P3), acceptance gates and checklists.
|
||||
|
||||
@ -0,0 +1,83 @@
|
||||
# Async Task System — SPEC
|
||||
|
||||
Scope: Define a structured concurrency model for Nyash with TaskGroup and Future as Boxes. Implementable across VM and JIT/EXE without adding new MIR instructions.
|
||||
|
||||
## User‑Facing API (Everything is Box)
|
||||
|
||||
Box TaskGroup
|
||||
- spawn(fn: () -> T) -> Future<T>
|
||||
- cancelAll() -> void
|
||||
- joinAll() -> void
|
||||
- fini: must run cancelAll() then joinAll() (LIFO order) to ensure structured shutdown.
|
||||
|
||||
Box Future<T>
|
||||
- await(timeout_ms?: int) -> Result<T, Err>
|
||||
- Ok(value)
|
||||
- Err(Timeout) | Err(Cancelled) | Err(Panic)
|
||||
- cancel() -> void (idempotent)
|
||||
|
||||
Sugar
|
||||
- nowait v = expr is sugar for: let g = current_group(); v = g.spawn(lambda: expr)
|
||||
|
||||
Default Ownership
|
||||
- An implicit TaskGroup is created per function scope and for Main. It owns tasks spawned in that scope.
|
||||
- Leaving the scope triggers cancelAll→joinAll on its group (LIFO), unless tasks were moved to a longer‑lived group explicitly.
|
||||
|
||||
Detachment (discouraged)
|
||||
- unsafe_spawn_detached(fn) only in advanced modules. Verifier should disallow use in normal code paths.
|
||||
|
||||
## MIR Mapping
|
||||
|
||||
- No new MIR instructions. Use existing BoxCall/PluginInvoke forms.
|
||||
- TaskGroup.spawn → BoxCall on TaskGroup Box, returns Future Box.
|
||||
- Future.await → BoxCall on Future Box with optional timeout parameter.
|
||||
- Lowerer inserts safepoint around await: ExternCall env.runtime.checkpoint before and after the await call.
|
||||
|
||||
Example Lowering (high level)
|
||||
- AST: nowait fut = arr.length()
|
||||
- MIR (normalized):
|
||||
- recv = … (arr)
|
||||
- mname = Const("length")
|
||||
- fut = ExternCall iface="env.future", method="spawn_instance", args=[recv, mname]
|
||||
- v = BoxCall Future.await(fut, timeout_ms?)
|
||||
|
||||
Note: In the final API, TaskGroup.spawn replaces env.future.spawn_instance, but the MIR contract remains BoxCall/ExternCall‑based.
|
||||
|
||||
## VM Semantics
|
||||
|
||||
- Scheduler: SingleThreadScheduler initially; spawn enqueues closure in FIFO. safepoint_and_poll() runs due tasks.
|
||||
- Future: implemented with Mutex+Condvar; set_result notifies; await waits with optional timeout; on cancel/timeout, returns Result.Err.
|
||||
- CancellationToken: parent→child propagation only, idempotent cancel().
|
||||
- TaskGroup: holds token and child registry; fini enforces cancelAll→joinAll (LIFO).
|
||||
|
||||
## JIT/EXE Semantics
|
||||
|
||||
- NyRT C‑ABI Shims:
|
||||
- nyash.future.spawn_method_h(type_id, method_id, argc, recv_h, vals*, tags*) -> i64 (Future handle)
|
||||
- nyash.future.spawn_instance3_i64(a0, a1, a2, argc) -> i64 (Future handle, by name/first args)
|
||||
- nyash.future.await_h(handle, timeout_ms?) -> i64/handle (Result encoding handled at Nyash layer)
|
||||
- Await shim must poll safepoints and honor timeout; returns 0 or sentinel; Nyash layer maps to Result.Err.*
|
||||
|
||||
## Errors & Results
|
||||
|
||||
- Distinguish Timeout vs Cancelled vs Panic.
|
||||
- Logging: concise, off by default; env flags can enable traces.
|
||||
- No silent fallback: unimplemented paths error early with clear labels.
|
||||
|
||||
## GC & Safepoints
|
||||
|
||||
- Lowerer must emit env.runtime.checkpoint immediately before and after await calls.
|
||||
- Scheduler.poll runs at checkpoints; long loops should explicitly insert checkpoints.
|
||||
|
||||
## Configuration
|
||||
|
||||
- NYASH_AWAIT_MAX_MS (default 5000) — global default timeout for await when not specified.
|
||||
- NYASH_SCHED_POLL_BUDGET — tasks per poll, default 1.
|
||||
- NYASH_SCHED_TRACE — prints poll/move/ran counts when 1.
|
||||
|
||||
## Security & Determinism
|
||||
|
||||
- Structured shutdown prevents orphan tasks after parent exit.
|
||||
- LIFO joinAll reduces deadlock surfaces.
|
||||
- Detached tasks are explicit and rare.
|
||||
|
||||
45
docs/phases/phase-11.8_mir_cleanup/PLAN.md
Normal file
45
docs/phases/phase-11.8_mir_cleanup/PLAN.md
Normal file
@ -0,0 +1,45 @@
|
||||
# Phase 11.8 MIR Cleanup – Plan (Core‑13 固定)
|
||||
|
||||
目的
|
||||
- MIR を「最小の接着剤」に純化し、BoxCall へ集約。
|
||||
- 最適化は VM/JIT の boxcall 経路に集中(脱仮想化・境界消去・Barrier)。
|
||||
|
||||
スコープ
|
||||
- BoxCall 集約: ArrayGet/Set, RefGet/Set → BoxCall(get/set/getField/setField)。
|
||||
- 維持: BinOp/Compare は MIR に残す(定数畳み込み/分岐簡約を最大化)。
|
||||
- 効果: EffectMask の正確化、WriteBarrier の確実化。
|
||||
|
||||
段階導入トグル(env・既定ONにする)
|
||||
- `NYASH_MIR_CORE13=1` … Core‑13 一括有効
|
||||
- `NYASH_OPT_DIAG_FORBID_LEGACY=1` … 旧命令が最終MIRに残ったらエラー
|
||||
- 参考: `NYASH_MIR_ARRAY_BOXCALL=1`, `NYASH_MIR_REF_BOXCALL=1` は CORE13=1 で内包
|
||||
|
||||
実装ステップ
|
||||
1) Optimizer パス(デフォルト ON)
|
||||
- ArrayGet/Set → BoxCall に変換
|
||||
- RefGet/Set → BoxCall に変換
|
||||
- 変換後の Effect/Barrier を整合
|
||||
2) VM: execute_boxcall の fast‑path
|
||||
- (type_id, method_id) で Array/Field を高速化
|
||||
- WriteBarrier の確実化
|
||||
3) JIT: lower_boxcall の fast‑path
|
||||
- Array: GEP+Load/Store(Bounds/Barrier含む)
|
||||
- Field: 内部表現に応じた inlining(失敗時 plugin_invoke)
|
||||
4) Smokes/Bench(Core‑13基準)
|
||||
- array_access_sequential / array_access_random / field_access / arithmetic_loop
|
||||
- 基準: 速度 ±5%, メモリ ±10%, MIR サイズ -20% 目標
|
||||
5) 検証(CIゲート)
|
||||
- SSA 保持(Phi 導入後の整合)
|
||||
- 意味保存(before/after 等価)
|
||||
|
||||
非スコープ(当面)
|
||||
- 算術/比較の BoxCall 化(最適化効率低下を避け据え置き)
|
||||
|
||||
完了基準
|
||||
- Core‑13 を既定ONでスモーク/ベンチが基準達成
|
||||
- 旧命令(ArrayGet/ArraySet/RefGet/RefSet/Unary/Load/Store)が最終MIRに出現しない
|
||||
- VM/JIT ともに BoxCall fast‑path/vtable の発火が確認できる
|
||||
|
||||
関連
|
||||
- TECHNICAL_SPEC.md(詳細仕様)
|
||||
- docs/development/runtime/ENV_VARS.md(環境変数索引)
|
||||
262
docs/phases/phase-11.8_mir_cleanup/README.md
Normal file
262
docs/phases/phase-11.8_mir_cleanup/README.md
Normal file
@ -0,0 +1,262 @@
|
||||
# Phase 11.8: MIR命令セット究極整理 - Core‑13 で統一する
|
||||
|
||||
## 🎯 概要
|
||||
|
||||
ChatGPT5さんの深い洞察「**MIRは接着剤、Boxが世界**」を実現する究極のMIR整理。
|
||||
現在の26(拡張版)→ Core‑15 → Core‑14(Phase 12)→ **Core‑13(最終決定・固定)**。
|
||||
|
||||
決定(2025‑09‑04)
|
||||
- 目標を「Core‑13」に固定し、移行フラグを既定ONにする。
|
||||
- 以降の最適化/検証/CIは Core‑13 を前提とする(旧命令は禁制)。
|
||||
|
||||
### 基本哲学
|
||||
|
||||
- **MIR = マイクロカーネル**: 最小限の制御と計算のみ
|
||||
- **Box = すべての実データと操作**: Everything is Box の究極形
|
||||
- **ExternCall = システムコール**: 外界との最小インターフェース
|
||||
|
||||
## 📊 現状分析
|
||||
|
||||
### 現行(移行前の参考)Core‑15(Phase 11.7)
|
||||
|
||||
```
|
||||
基本演算(5): Const, UnaryOp, BinOp, Compare, TypeOp
|
||||
メモリ(2): Load, Store
|
||||
制御(4): Branch, Jump, Return, Phi
|
||||
Box(3): NewBox, BoxCall, PluginInvoke
|
||||
配列(2): ArrayGet, ArraySet
|
||||
外部(1): ExternCall
|
||||
```
|
||||
|
||||
### Core‑14(Phase 12の中間目標)
|
||||
|
||||
```
|
||||
基本演算(5): Const, UnaryOp, BinOp, Compare, TypeOp
|
||||
メモリ(2): Load, Store
|
||||
制御(4): Branch, Jump, Return, Phi
|
||||
Box(2): NewBox, BoxCall ← PluginInvoke統合
|
||||
配列(2): ArrayGet, ArraySet
|
||||
外部(1): ExternCall
|
||||
```
|
||||
|
||||
## 🚀 Core‑13(最終形)への道筋(実行計画)
|
||||
|
||||
### Step 1: 配列操作のBoxCall統合(Core‑14 → Core‑12)
|
||||
|
||||
```mir
|
||||
// 現在
|
||||
%val = ArrayGet %arr, %idx
|
||||
ArraySet %arr, %idx, %val
|
||||
|
||||
// 統合後
|
||||
%val = BoxCall %arr, "get", [%idx]
|
||||
BoxCall %arr, "set", [%idx, %val]
|
||||
```
|
||||
|
||||
実装方針:
|
||||
- Optimizer: ArrayGet/ArraySet → BoxCall 変換
|
||||
- VM: 高頻度パスは内部最適化維持
|
||||
- JIT: 既知型の場合はインライン展開
|
||||
|
||||
### Step 2: Load/Store の再考(Core‑12 → Core‑11)
|
||||
|
||||
**SSAの威力を活かす**:
|
||||
- ローカル変数のLoad/Store → SSA変数で代替
|
||||
- 真に必要なのはBoxフィールドアクセスのみ
|
||||
- それもBoxCall("getField"/"setField")で統合可能
|
||||
|
||||
```mir
|
||||
// 現在
|
||||
Store %slot, %value
|
||||
%val = Load %slot
|
||||
|
||||
// SSA化
|
||||
%val = %value // 直接参照(Copyも実質不要)
|
||||
```
|
||||
|
||||
### Step 3: 定数統合とUnaryOp簡素化(Core‑11 → Core‑13)
|
||||
|
||||
**Const統合案**:
|
||||
```mir
|
||||
// 現在
|
||||
Const::Integer(i64)
|
||||
Const::Float(f64)
|
||||
Const::Bool(bool)
|
||||
Const::String(String)
|
||||
Const::Null
|
||||
|
||||
// 統合後
|
||||
Const { type: Type, value: u64 } // 全て64bitに収める
|
||||
```
|
||||
|
||||
**UnaryOp削減**:
|
||||
- Neg → BinOp(Sub, 0, x)
|
||||
- Not → BinOp(Xor, x, 1)
|
||||
- BitNot → BinOp(Xor, x, -1)
|
||||
|
||||
## 🎯 最終形:Core‑13(固定セット・CI基準)
|
||||
|
||||
```yaml
|
||||
定数(1):
|
||||
- Const(統合型:i64/f64/bool/null/handle)
|
||||
|
||||
計算(2):
|
||||
- BinOp(Add/Sub/Mul/Div/Mod/And/Or/Xor/Shl/Shr)
|
||||
- Compare(Eq/Ne/Lt/Le/Gt/Ge)
|
||||
|
||||
制御(4):
|
||||
- Branch(条件分岐)
|
||||
- Jump(無条件ジャンプ)
|
||||
- Phi(SSA合流)
|
||||
- Return(関数終了)
|
||||
|
||||
呼出(3):
|
||||
- Call(Nyash関数呼び出し)
|
||||
- BoxCall(Box操作統一)
|
||||
- ExternCall(環境アクセス)
|
||||
|
||||
メタ(3):
|
||||
- TypeOp(型チェック/キャスト)
|
||||
- Safepoint(GCセーフポイント)
|
||||
- Barrier(メモリバリア)
|
||||
|
||||
合計: 13命令
|
||||
```
|
||||
|
||||
移行スイッチ(既定ON)と検証
|
||||
- 環境変数(デフォルトON)
|
||||
- NYASH_MIR_CORE13=1(Core‑13一括)
|
||||
- 診断: NYASH_OPT_DIAG_FORBID_LEGACY=1(旧命令が最終MIRに残ったらエラー)
|
||||
- ビルダー/最適化の方針
|
||||
- Builder: ArrayGet/ArraySet・RefGet/RefSet を emit せず最初から BoxCall を出す
|
||||
- Optimizer: 既存の Array/Ref→BoxCall 正規化パスを保持(保険)
|
||||
- UnaryOp→BinOp 正規化は常時ON(簡易変換)
|
||||
- Load/Store はSSA利用で極力抑止(最終MIRから排除が目標)
|
||||
- VM/JIT
|
||||
- BoxCall fast‑path/vtable を維持し、get/set は型特化とWriteBarrierを維持
|
||||
- PluginInvoke はMIRから排除(必要経路は BoxCall→VM側ABI判定)
|
||||
|
||||
CI/テスト
|
||||
- Core‑13固定の数・名前検査を `instruction_introspection.rs` に追加(Core‑15検査は保持しつつ非推奨)
|
||||
- 旧命令(ArrayGet/ArraySet/RefGet/RefSet/Load/Store/UnaryOp)が最終MIRに残らないことをゲート
|
||||
- 代表スモーク(配列/参照/extern/await)は VM/JIT で同値性を確認
|
||||
|
||||
## 💡 なぜCore-13で十分なのか
|
||||
|
||||
### 1. チューリング完全性の保証
|
||||
|
||||
最小限必要なもの:
|
||||
- 定数
|
||||
- 算術演算
|
||||
- 条件分岐
|
||||
- ループ(Jump + Branch)
|
||||
- 関数呼び出し
|
||||
|
||||
これらはすべてCore-13に含まれる。
|
||||
|
||||
### 2. Everything is Box の威力
|
||||
|
||||
```nyash
|
||||
// すべてがBoxCall経由
|
||||
arr[0] → BoxCall(arr, "get", [0])
|
||||
arr[0] = 42 → BoxCall(arr, "set", [0, 42])
|
||||
obj.field → BoxCall(obj, "getField", ["field"])
|
||||
obj.field = val → BoxCall(obj, "setField", ["field", val])
|
||||
weak.get() → BoxCall(weak, "get", [])
|
||||
```
|
||||
|
||||
### 3. SSAによるメモリ命令の削減
|
||||
|
||||
- 一時変数 → SSA変数(Load/Store不要)
|
||||
- フィールド → BoxCall
|
||||
- 配列要素 → BoxCall
|
||||
- 真のメモリアクセスはBoxの中に隠蔽
|
||||
|
||||
## 📋 実装ロードマップ(確定版)
|
||||
|
||||
### ステータス(進捗メモ)
|
||||
- 実装済み(トグルONで有効化)
|
||||
- Optimizer: ArrayGet/Set・RefGet/Set → BoxCall 変換(`NYASH_MIR_ARRAY_BOXCALL`, `NYASH_MIR_REF_BOXCALL`, `NYASH_MIR_CORE13`)
|
||||
- VM: BoxCall(setField)のWriteBarrier、Array/Instanceの軽量fast-path(by-name/slot併用)
|
||||
- 管理棟: 主要なMIR/GC/Optimizerフラグを `config::env` に集約
|
||||
- 決定/実行(今回)
|
||||
- Core‑13を既定ON(nyash.toml [env] 推奨値)
|
||||
- 旧命令禁止の診断を既定ON
|
||||
- BuilderのArray/Ref出力をBoxCallに変更(emit抑止)
|
||||
- Unary→BinOpを常時変換
|
||||
- 未了/次段
|
||||
- JIT: BoxCall fast‑path の inlining(bounds/Barrier含む)
|
||||
- ベンチとCIゲート(array/field/arithmetic_loop)
|
||||
- InstanceのgetField/setFieldのslot化(name→slotの検討)
|
||||
- 直env参照の段階移行(ログ用途は後段)
|
||||
|
||||
### Phase 11.8.1: 準備と分析(1週間)
|
||||
|
||||
- [ ] 現在のMIR使用状況の詳細分析
|
||||
- [ ] ArrayGet/ArraySet → BoxCall 変換の影響調査
|
||||
- [ ] Load/Store 削除可能性の検証
|
||||
- [ ] パフォーマンスベンチマーク基準値測定
|
||||
|
||||
### Phase 11.8.2: ArrayGet/ArraySet統合(2週間)
|
||||
|
||||
- [ ] Optimizer: ArrayGet/ArraySet → BoxCall 変換パス
|
||||
- [ ] VM: BoxCall("get"/"set") の最適化パス
|
||||
- [ ] JIT: 既知ArrayBoxの特殊化維持
|
||||
- [ ] テスト: 既存配列操作の回帰テスト
|
||||
|
||||
### Phase 11.8.3: Load/Store削減(3週間)
|
||||
|
||||
- [ ] Builder: SSA最大活用でLoad/Store削減
|
||||
- [ ] フィールドアクセス → BoxCall 変換
|
||||
- [ ] VM/JIT: 最適化パスの調整
|
||||
- [ ] ベンチマーク: パフォーマンス影響測定
|
||||
|
||||
### Phase 11.8.4: 最終統合(2週間)
|
||||
|
||||
- [ ] Const型統合実装
|
||||
- [ ] UnaryOp → BinOp 変換
|
||||
- [ ] Core-13命令セット確定
|
||||
- [ ] ドキュメント最終更新
|
||||
|
||||
## ⚠️ リスクと緩和策
|
||||
|
||||
### パフォーマンスリスク
|
||||
|
||||
**リスク**: BoxCall統合によるオーバーヘッド
|
||||
**緩和策**:
|
||||
- VM層での型別最適化維持
|
||||
- JIT時の積極的インライン展開
|
||||
- 高頻度パスのNyRTシム化
|
||||
|
||||
### 互換性リスク
|
||||
|
||||
**リスク**: 既存MIRコードの非互換
|
||||
**緩和策**:
|
||||
- Rewriteパスで自動変換
|
||||
- 段階的移行(警告→エラー)
|
||||
- 環境変数でレガシーモード
|
||||
|
||||
### 複雑性リスク
|
||||
|
||||
**リスク**: BoxCallの過度な多重化
|
||||
**緩和策**:
|
||||
- 明確な命名規約(get/set/getField等)
|
||||
- 型情報による静的検証強化
|
||||
- デバッグ情報の充実
|
||||
|
||||
## 🎯 成功指標
|
||||
|
||||
1. **命令数**: 26 → 13(50%削減)
|
||||
2. **パフォーマンス**: ベンチマークで±5%以内
|
||||
3. **コードサイズ**: MIRダンプサイズ20%削減
|
||||
4. **保守性**: 新Box追加時のMIR変更不要
|
||||
|
||||
## 📚 関連ドキュメント
|
||||
|
||||
- [MIR Instruction Set](../../../reference/mir/INSTRUCTION_SET.md)
|
||||
- [Phase 12: PluginInvoke統合](../phase-12/README.md)
|
||||
- [Everything is Box哲学](../../../philosophy/everything-is-box.md)
|
||||
|
||||
---
|
||||
|
||||
*「少ないほど豊かである」- MIRは最小の接着剤、Boxが無限の世界を創る*
|
||||
356
docs/phases/phase-11.8_mir_cleanup/TECHNICAL_SPEC.md
Normal file
356
docs/phases/phase-11.8_mir_cleanup/TECHNICAL_SPEC.md
Normal file
@ -0,0 +1,356 @@
|
||||
# Phase 11.8 技術仕様書:Core‑13 MIR命令セット(既定ON)
|
||||
|
||||
## 0. 変換スイッチとルーティング(Core‑13 既定ON)
|
||||
|
||||
推奨既定(nyash.toml の [env])
|
||||
|
||||
- NYASH_MIR_CORE13=1 … Core‑13 一括ON(Array/Ref→BoxCall 等を内包)
|
||||
- NYASH_OPT_DIAG_FORBID_LEGACY=1 … 旧命令が最終MIRに残ったらエラー
|
||||
|
||||
Builder/MIR 生成
|
||||
- Builder は ArrayGet/ArraySet/RefGet/RefSet/PluginInvoke を emit せず、最初から BoxCall/Call/ExternCall に正規化する。
|
||||
- Optimizer は保険として既存の正規化パスを維持(二重化で確実性を上げる)。
|
||||
|
||||
## 1. ArrayGet/ArraySet → BoxCall 統合仕様
|
||||
|
||||
### 1.1 変換規則
|
||||
|
||||
```rust
|
||||
// MIR Optimizer での変換
|
||||
match instruction {
|
||||
MirInstruction::ArrayGet { dst, array, index } => {
|
||||
MirInstruction::BoxCall {
|
||||
dst: Some(*dst),
|
||||
box_val: *array,
|
||||
method: "get".to_string(),
|
||||
method_id: Some(UNIVERSAL_GET_ID), // 予約ID: 4
|
||||
args: vec![*index],
|
||||
effects: EffectMask::READS_MEMORY,
|
||||
}
|
||||
}
|
||||
|
||||
MirInstruction::ArraySet { array, index, value } => {
|
||||
MirInstruction::BoxCall {
|
||||
dst: None,
|
||||
box_val: *array,
|
||||
method: "set".to_string(),
|
||||
method_id: Some(UNIVERSAL_SET_ID), // 予約ID: 5
|
||||
args: vec![*index, *value],
|
||||
effects: EffectMask::WRITES_MEMORY | EffectMask::MAY_GC,
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 1.2 VM最適化
|
||||
|
||||
```rust
|
||||
// VM execute_boxcall での特殊化
|
||||
fn execute_boxcall(...) {
|
||||
// 高速パス:ArrayBoxの既知メソッド
|
||||
if let Some(method_id) = method_id {
|
||||
match (type_id, method_id) {
|
||||
(ARRAY_BOX_TYPE, UNIVERSAL_GET_ID) => {
|
||||
// 直接配列アクセス(BoxCall経由でも高速)
|
||||
return fast_array_get(receiver, args[0]);
|
||||
}
|
||||
(ARRAY_BOX_TYPE, UNIVERSAL_SET_ID) => {
|
||||
return fast_array_set(receiver, args[0], args[1]);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
// 通常パス
|
||||
plugin_invoke(...)
|
||||
}
|
||||
```
|
||||
|
||||
### 1.3 JIT最適化
|
||||
|
||||
```rust
|
||||
// JIT Lowering での認識
|
||||
fn lower_boxcall(builder: &mut IRBuilder, ...) {
|
||||
if is_known_array_type(receiver_type) {
|
||||
match method_id {
|
||||
Some(UNIVERSAL_GET_ID) => {
|
||||
// GEP + Load にインライン展開
|
||||
emit_array_bounds_check(...);
|
||||
emit_array_get_inline(...);
|
||||
return;
|
||||
}
|
||||
Some(UNIVERSAL_SET_ID) => {
|
||||
// Write barrier + GEP + Store
|
||||
emit_write_barrier(...);
|
||||
emit_array_set_inline(...);
|
||||
return;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
// 通常のBoxCall
|
||||
emit_plugin_invoke(...);
|
||||
}
|
||||
```
|
||||
|
||||
## 2. Load/Store 削減仕様(SSA最優先)
|
||||
|
||||
### 2.1 SSA変数活用の最大化
|
||||
|
||||
```mir
|
||||
// Before(Load/Store使用)
|
||||
bb0:
|
||||
Store %slot1, %x
|
||||
Branch %cond, bb1, bb2
|
||||
bb1:
|
||||
Store %slot1, %y
|
||||
Jump bb3
|
||||
bb2:
|
||||
// slot1 は x のまま
|
||||
Jump bb3
|
||||
bb3:
|
||||
%result = Load %slot1
|
||||
Return %result
|
||||
|
||||
// After(Phi使用)
|
||||
bb0:
|
||||
Branch %cond, bb1, bb2
|
||||
bb1:
|
||||
Jump bb3(%y)
|
||||
bb2:
|
||||
Jump bb3(%x)
|
||||
bb3(%result):
|
||||
Return %result
|
||||
```
|
||||
|
||||
### 2.2 フィールドアクセスの統合
|
||||
|
||||
```mir
|
||||
// Before(RefGet/RefSet)
|
||||
%field_val = RefGet %obj, "field"
|
||||
RefSet %obj, "field", %new_val
|
||||
|
||||
// After(BoxCall)
|
||||
%field_val = BoxCall %obj, "getField", ["field"]
|
||||
BoxCall %obj, "setField", ["field", %new_val]
|
||||
```
|
||||
|
||||
### 2.3 残すべきLoad/Store
|
||||
|
||||
- **スタックスロット**: JIT/AOTでの一時変数
|
||||
- **C FFI境界**: 外部関数とのやり取り
|
||||
- **最適化中間状態**: Phi導入前の一時的使用
|
||||
|
||||
## 3. Const統合仕様(設計)
|
||||
|
||||
### 3.1 統一表現
|
||||
|
||||
```rust
|
||||
pub enum MirConst {
|
||||
// Before: 5種類
|
||||
Integer(i64),
|
||||
Float(f64),
|
||||
Bool(bool),
|
||||
String(String),
|
||||
Null,
|
||||
|
||||
// After: 1種類
|
||||
Unified {
|
||||
ty: ConstType,
|
||||
bits: u64, // i64/f64/bool/null はビット表現
|
||||
aux: Option<Arc<String>>, // 文字列用
|
||||
}
|
||||
}
|
||||
|
||||
pub enum ConstType {
|
||||
I64, F64, Bool, Null, String, Handle
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2 エンコーディング
|
||||
|
||||
```rust
|
||||
impl MirConst {
|
||||
fn encode_i64(val: i64) -> Self {
|
||||
Self::Unified {
|
||||
ty: ConstType::I64,
|
||||
bits: val as u64,
|
||||
aux: None,
|
||||
}
|
||||
}
|
||||
|
||||
fn encode_f64(val: f64) -> Self {
|
||||
Self::Unified {
|
||||
ty: ConstType::F64,
|
||||
bits: val.to_bits(),
|
||||
aux: None,
|
||||
}
|
||||
}
|
||||
|
||||
fn encode_bool(val: bool) -> Self {
|
||||
Self::Unified {
|
||||
ty: ConstType::Bool,
|
||||
bits: val as u64,
|
||||
aux: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 4. パフォーマンス保証(CI基準)
|
||||
|
||||
### 4.1 ベンチマーク項目
|
||||
|
||||
```yaml
|
||||
必須ベンチマーク:
|
||||
- array_access_sequential: 配列順次アクセス
|
||||
- array_access_random: 配列ランダムアクセス
|
||||
- field_access: フィールド読み書き
|
||||
- local_variables: ローカル変数操作
|
||||
- arithmetic_loop: 算術演算ループ
|
||||
|
||||
許容範囲:
|
||||
- 速度: ベースライン ±5%
|
||||
- メモリ: ベースライン ±10%
|
||||
- MIRサイズ: -20%以上の削減
|
||||
```
|
||||
|
||||
### 4.2 最適化保証
|
||||
|
||||
```rust
|
||||
// 必須最適化パス
|
||||
const REQUIRED_OPTIMIZATIONS: &[&str] = &[
|
||||
"array_bounds_elim", // 配列境界チェック除去
|
||||
"boxcall_devirt", // BoxCall脱仮想化
|
||||
"const_fold", // 定数畳み込み
|
||||
"dead_store_elim", // 不要Store除去
|
||||
"phi_simplify", // Phi簡約
|
||||
];
|
||||
```
|
||||
|
||||
## 5. 移行戦略(段階→固定)
|
||||
|
||||
### 5.1 段階的有効化
|
||||
|
||||
```rust
|
||||
// 環境変数による制御
|
||||
// 実装上は env トグルを残しつつ、CI/既定は CORE13=1 / FORBID_LEGACY=1 とする。
|
||||
```
|
||||
|
||||
### 5.2 互換性レイヤー
|
||||
|
||||
```rust
|
||||
// Rewrite パス
|
||||
pub fn rewrite_legacy_mir(module: &mut MirModule) {
|
||||
for (_, func) in &mut module.functions {
|
||||
for (_, block) in &mut func.blocks {
|
||||
let mut new_instructions = vec![];
|
||||
|
||||
for inst in &block.instructions {
|
||||
match inst {
|
||||
// ArrayGet/ArraySet → BoxCall
|
||||
MirInstruction::ArrayGet { .. } => {
|
||||
new_instructions.push(convert_array_get(inst));
|
||||
}
|
||||
MirInstruction::ArraySet { .. } => {
|
||||
new_instructions.push(convert_array_set(inst));
|
||||
}
|
||||
|
||||
// RefGet/RefSet → BoxCall
|
||||
MirInstruction::RefGet { .. } => {
|
||||
new_instructions.push(convert_ref_get(inst));
|
||||
}
|
||||
MirInstruction::RefSet { .. } => {
|
||||
new_instructions.push(convert_ref_set(inst));
|
||||
}
|
||||
|
||||
// そのまま
|
||||
_ => new_instructions.push(inst.clone()),
|
||||
}
|
||||
}
|
||||
|
||||
block.instructions = new_instructions;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 6. 検証項目
|
||||
|
||||
### 6.1 正当性検証
|
||||
|
||||
```rust
|
||||
#[cfg(test)]
|
||||
mod core13_tests {
|
||||
// 各変換の意味保存を検証
|
||||
#[test]
|
||||
fn test_array_get_conversion() {
|
||||
let before = MirInstruction::ArrayGet { ... };
|
||||
let after = convert_to_boxcall(before);
|
||||
assert_semantic_equivalence(before, after);
|
||||
}
|
||||
|
||||
// SSA形式の保持を検証
|
||||
#[test]
|
||||
fn test_ssa_preservation() {
|
||||
let module = build_test_module();
|
||||
eliminate_load_store(&mut module);
|
||||
assert_is_valid_ssa(&module);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 6.2 性能検証
|
||||
|
||||
```rust
|
||||
// ベンチマークハーネス
|
||||
pub fn benchmark_core13_migration() {
|
||||
let scenarios = vec![
|
||||
"array_intensive",
|
||||
"field_intensive",
|
||||
"arithmetic_heavy",
|
||||
"mixed_workload",
|
||||
];
|
||||
|
||||
for scenario in scenarios {
|
||||
let baseline = run_with_core15(scenario);
|
||||
let core13 = run_with_core13(scenario);
|
||||
|
||||
assert!(
|
||||
(core13.time - baseline.time).abs() / baseline.time < 0.05,
|
||||
"Performance regression in {}", scenario
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 7. エラーハンドリング
|
||||
|
||||
### 7.1 診断メッセージ
|
||||
|
||||
```rust
|
||||
pub enum Core13Error {
|
||||
UnsupportedInstruction(String),
|
||||
ConversionFailed { from: String, to: String },
|
||||
PerformanceRegression { metric: String, delta: f64 },
|
||||
}
|
||||
|
||||
impl Core13Error {
|
||||
fn diagnostic(&self) -> Diagnostic {
|
||||
match self {
|
||||
Self::UnsupportedInstruction(inst) => {
|
||||
Diagnostic::error()
|
||||
.with_message(format!("Instruction '{}' not supported in Core-13", inst))
|
||||
.with_note("Consider using BoxCall for this operation")
|
||||
.with_help("Set NYASH_MIR_LEGACY=1 for compatibility mode")
|
||||
}
|
||||
// ...
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
*この仕様に従い、MIRを「最小の接着剤」として純化し、Boxに「無限の可能性」を委ねる*
|
||||
48
docs/phases/phase-11.9/PLAN.md
Normal file
48
docs/phases/phase-11.9/PLAN.md
Normal file
@ -0,0 +1,48 @@
|
||||
# Phase 11.9: 統一文法アーキテクチャ — 実装予定(MVP〜段階移行)
|
||||
|
||||
## 目的
|
||||
- Tokenizer/Parser/Interpreter/MIR/VM/JIT の解釈差異を解消し、単一の「文法・意味・実行」定義から各層が参照する構造へ移行する。
|
||||
- 変更や拡張(予約語/演算子/構文)のコストと不整合リスクを減らす。
|
||||
|
||||
## マイルストーン(MVP→段階導入)
|
||||
|
||||
### M1: 予約語レジストリの導入(最小)
|
||||
- 追加: `src/grammar/engine.rs`(`UnifiedGrammarEngine`、`KeywordRegistry` の骨格)
|
||||
- 追加: `grammar/unified-grammar.toml`(初期エントリ: `me`, `from`, `loop`, `+`)
|
||||
- 追加: `build.rs` で TOML → `src/grammar/generated.rs` をコード生成(ランタイム I/O 回避)
|
||||
- Tokenizer 統合(非侵襲): 従来テーブルの後段に `engine.is_keyword()` を差し込み、`NYASH_GRAMMAR_DIFF=1` で差分ログ
|
||||
- 成功条件: 既存テストを落とさず、差分ログが 0 or 想定内のみに収束
|
||||
|
||||
### M2: 演算子セマンティクスの統一(加算など最小)
|
||||
- `ExecutionSemantics` に `operators.add` を定義(型規則/コアーション/エラー方針)
|
||||
- Interpreter/VM/JIT で `execute_semantic("add", …)` による共通実装窓口を追加(従来実装はフォールバック)
|
||||
- 既存 `hostcall_registry`/JIT ポリシーと接合するインターフェースを用意(型分類/シンボルの参照点を一本化)
|
||||
- 成功条件: 文字列結合/整数加算/浮動小数加算の3系統で VM/JIT/Interpreter の一致を維持
|
||||
|
||||
### M3: 構文規則エンジンの段階導入
|
||||
- `SyntaxRuleEngine` 追加、`statement`/`expr` の骨格ルールを TOML 側へ切り出し
|
||||
- Parser 統合(段階的): 既存パーサ優先+新ルールでの検証を併走、差分ログで移行安全性を担保
|
||||
- 成功条件: 代表サンプルで新旧の AST→MIR が一致(スナップショット)
|
||||
|
||||
### M4: 並行実行/差分検出・テスト整備
|
||||
- 並行期間は新旧両系の結果を比較し、スナップショットとファズで回帰防止
|
||||
- 収束後、旧ルートを段階的に縮退
|
||||
|
||||
## 実装順(詳細 TODO)
|
||||
1) `build.rs` と `src/grammar/mod.rs` の雛形追加(`generated.rs` を `include!`)
|
||||
2) `KeywordRegistry` の生成コードを実装、Tokenizer に差し込み(環境変数で切り替え)
|
||||
3) `operators.add` の型規則を TOML 化し、`ExecutionSemantics` で解決
|
||||
4) Interpreter/VM/JIT へ共通窓口の薄い統合(実行は従来実装と比較可能に)
|
||||
5) 構文ルール最小セット(statement/expr)を TOML へ移管し、解析の差分をログ化
|
||||
6) スナップショット/ファズの整備と収束確認
|
||||
|
||||
## リスクと対策
|
||||
- 競合/拡張: プラグイン由来の拡張を名前空間+優先度でマージ、競合は検知してビルド失敗で気付かせる
|
||||
- 実行コスト: 生成コード方式でランタイム I/O を避け、起動時間・ホットパスへの影響をゼロに近づける
|
||||
- 文脈依存: `contextual` のキー粒度を設計(node_kind/context など)し、曖昧解釈を防ぐ
|
||||
|
||||
## 成功基準(Exit Criteria)
|
||||
- 予約語解決の統一(Tokenizer での差分 0)
|
||||
- 加算に関する VM/JIT/Interpreter のセマンティクス一致(型差分含む)
|
||||
- 構文最小セットで新旧の AST→MIR が一致(代表ケース)
|
||||
|
||||
108
docs/phases/phase-11.9/README.md
Normal file
108
docs/phases/phase-11.9/README.md
Normal file
@ -0,0 +1,108 @@
|
||||
# Phase 11.9: 文法統一化とAI連携強化
|
||||
|
||||
## 📋 概要
|
||||
|
||||
Nyashの文法知識が分散している問題を解決し、AIがNyashコードを正しく書けるよう支援する包括的な文法統一化フェーズ。
|
||||
|
||||
## 🔥 核心的な問題
|
||||
|
||||
現在のNyashは各層(Tokenizer/Parser/Interpreter/MIR/VM/JIT)で予約語・文法解釈がバラバラに実装されており、これが以下の問題を引き起こしている:
|
||||
|
||||
- 同じ `me` キーワードが各層で独自解釈される
|
||||
- `+` 演算子の動作がInterpreter/VM/JITで微妙に異なる
|
||||
- 新しい予約語追加時に6箇所以上の修正が必要
|
||||
- AIが正しいコードを書けない(どの層の解釈に従うべきか不明)
|
||||
|
||||
## 🎯 フェーズの目的
|
||||
|
||||
1. **完全統一文法エンジン**: すべての層が単一の文法定義を参照
|
||||
2. **セマンティクス一元化**: 演算子・型変換・実行規則の完全統一
|
||||
3. **AIエラー削減**: 文法間違いを90%以上削減
|
||||
4. **保守性革命**: 新機能追加が1箇所の修正で完了
|
||||
|
||||
## 📊 主要成果物
|
||||
|
||||
### 文法定義
|
||||
- [ ] nyash-grammar-v1.yaml(統一文法定義)
|
||||
- [ ] Grammar Runtime実装
|
||||
- [ ] 文法検証ツール
|
||||
|
||||
### コンポーネント統合
|
||||
- [ ] Tokenizer文法統合
|
||||
- [ ] Parser文法統合
|
||||
- [ ] Interpreter統合
|
||||
- [ ] MIR Builder連携
|
||||
|
||||
### AI支援機能
|
||||
- [ ] AI向け文法エクスポート
|
||||
- [ ] AIコード検証器
|
||||
- [ ] トレーニングデータ生成
|
||||
- [ ] 文法aware ANCP
|
||||
|
||||
## 🔧 技術的アプローチ
|
||||
|
||||
### アーキテクチャ
|
||||
```
|
||||
Grammar Definition (YAML)
|
||||
↓
|
||||
Grammar Runtime (Rust)
|
||||
↓
|
||||
Components (Tokenizer/Parser/Interpreter)
|
||||
```
|
||||
|
||||
### 核心的な改善
|
||||
```yaml
|
||||
# 文法定義の例
|
||||
keywords:
|
||||
me:
|
||||
token: ME
|
||||
deprecated_aliases: ["this", "self"]
|
||||
ai_hint: "Always use 'me', never 'this'"
|
||||
```
|
||||
|
||||
## 📅 実施時期
|
||||
|
||||
- **開始条件**: Phase 11.8完了後
|
||||
- **推定期間**: 4-5週間
|
||||
- **優先度**: 高(AIとの協働開発に必須)
|
||||
|
||||
## 💡 期待される成果
|
||||
|
||||
1. **単一の真実の源**: 文法がYAMLファイル1つに集約
|
||||
2. **AIフレンドリー**: 明確な文法でAIの学習効率向上
|
||||
3. **保守性向上**: 新機能追加が簡単に
|
||||
4. **品質向上**: 統一的な検証で一貫性確保
|
||||
|
||||
## 🔗 関連ドキュメント
|
||||
|
||||
### 📌 まず読むべき資料
|
||||
- **[統一セマンティクス実装設計](unified-semantics-implementation.txt)** ← **🎯 最新の実装方針**
|
||||
- **[統一文法設計総合まとめ](UNIFIED-GRAMMAR-DESIGN-SUMMARY.md)** ← 設計思想の理解
|
||||
|
||||
### 🔥 核心設計ドキュメント
|
||||
- [統一文法アーキテクチャ設計書](unified-grammar-architecture.md) - 基本設計
|
||||
- [統一予約語システム仕様](unified-keyword-system.md) - 具体的実装
|
||||
- [AI深層考察: 統一文法アーキテクチャ](ai-deep-thoughts-unified-grammar.md) - Gemini/Codex分析
|
||||
|
||||
### 📚 発展的設計(参考)
|
||||
- [発展的設計集](advanced-designs/) - より深い設計思想
|
||||
- box-first-grammar-architecture.md - 箱化アプローチ
|
||||
- root-cutting-architecture.md - 疎結合設計
|
||||
- zero-knowledge-architecture.md - 究極の分離
|
||||
|
||||
### 🔧 実装資料
|
||||
- [アーカイブ](archive/) - 過去の詳細設計ドキュメント
|
||||
- grammar-unification.txt - 初期の文法統一化詳細設計
|
||||
- nyash-grammar-v1.yaml - 統一文法定義YAML(初版)
|
||||
- implementation-plan.txt - 実装計画
|
||||
|
||||
### 🔗 関連フェーズ
|
||||
- [AI-Nyash Compact Notation Protocol](../../ideas/new-features/2025-08-29-ai-compact-notation-protocol.md)
|
||||
- [Phase 12: プラグインシステム](../phase-12/)
|
||||
|
||||
## 🌟 なぜ重要か?
|
||||
|
||||
> 「文法の揺らぎをゼロにし、AIが正しいNyashコードを書ける世界へ」
|
||||
|
||||
現在、AIがNyashコードを書く際の最大の障害は文法の不統一。
|
||||
これを解決することで、開発効率が劇的に向上する。
|
||||
107
docs/phases/phase-11.9/UNIFIED-GRAMMAR-DESIGN-SUMMARY.md
Normal file
107
docs/phases/phase-11.9/UNIFIED-GRAMMAR-DESIGN-SUMMARY.md
Normal file
@ -0,0 +1,107 @@
|
||||
# Phase 11.9 統一文法設計 - 総合まとめ
|
||||
|
||||
## 📋 概要
|
||||
|
||||
Nyashの各実行層(Tokenizer/Parser/Interpreter/MIR/VM/JIT)で予約語・文法解釈がバラバラに実装されている問題を解決する統一文法アーキテクチャ設計のまとめです。
|
||||
|
||||
## 🎯 核心的な問題
|
||||
|
||||
```rust
|
||||
// 現在: 同じ "me" が6箇所で別々に定義
|
||||
Tokenizer: "me" → TokenType::ME
|
||||
Parser: 独自のme処理ロジック
|
||||
Interpreter: 独自のself参照実装
|
||||
MIR Builder: LoadLocal(0)への変換
|
||||
VM: OP_LOAD_MEの実行
|
||||
JIT: LoadFirstParamの生成
|
||||
```
|
||||
|
||||
## 💡 提案された解決策
|
||||
|
||||
### 1. 基本アプローチ: 統一文法エンジン
|
||||
- 単一の文法定義(YAML/TOML)
|
||||
- 各層が参照する統一API
|
||||
- UnifiedSemantics による一貫した実行
|
||||
|
||||
### 2. AI提案: ビルド時コード生成
|
||||
- **Gemini**: 宣言的定義 + build.rs によるコード生成
|
||||
- **Codex**: MIR中心の統一セマンティクス基盤
|
||||
- 実行時オーバーヘッドゼロ
|
||||
|
||||
### 3. 箱化による疎結合設計
|
||||
- 各層を独立した「箱」として実装
|
||||
- 変換箱(TransformerBox)パターン
|
||||
- パイプライン方式での連結
|
||||
|
||||
## 📊 実装アプローチの比較
|
||||
|
||||
| アプローチ | 利点 | 欠点 | 推奨度 |
|
||||
|---------|------|------|-------|
|
||||
| 統一エンジン | シンプル、理解しやすい | 実行時オーバーヘッド | ★★★ |
|
||||
| コード生成 | 高性能、型安全 | ビルド複雑化 | ★★★★★ |
|
||||
| 完全箱化 | 究極の疎結合 | 実装複雑度高 | ★★★★ |
|
||||
|
||||
## 🚀 推奨実装計画
|
||||
|
||||
### Phase 1: 文法定義ファイル作成
|
||||
```yaml
|
||||
# grammar/nyash.yml
|
||||
tokens:
|
||||
me: { id: 1, category: self_reference }
|
||||
from: { id: 2, category: delegation }
|
||||
loop: { id: 3, category: control_flow }
|
||||
|
||||
operators:
|
||||
"+": { precedence: 10, associativity: left }
|
||||
```
|
||||
|
||||
### Phase 2: コード生成基盤
|
||||
```rust
|
||||
// build.rs
|
||||
fn generate_from_grammar() {
|
||||
// grammar.yml → generated/*.rs
|
||||
}
|
||||
```
|
||||
|
||||
### Phase 3: 段階的移行
|
||||
1. Tokenizer を生成コードに移行
|
||||
2. Parser を統一文法に移行
|
||||
3. Semantics を一元化
|
||||
4. MIR/VM/JIT を統合
|
||||
|
||||
## 🎯 期待される効果
|
||||
|
||||
1. **保守性向上**: 新機能追加が1箇所で完了
|
||||
2. **一貫性確保**: 全層で同じセマンティクス
|
||||
3. **AI対応改善**: LLMが正確なコードを生成
|
||||
4. **性能維持**: ビルド時最適化でオーバーヘッドなし
|
||||
|
||||
## 📁 作成されたドキュメント
|
||||
|
||||
### 必須ドキュメント(実装に必要)
|
||||
1. **[統一文法アーキテクチャ設計書](unified-grammar-architecture.md)** - 基本設計
|
||||
2. **[統一予約語システム仕様](unified-keyword-system.md)** - 具体的実装仕様
|
||||
3. **[AI深層考察](ai-deep-thoughts-unified-grammar.md)** - Gemini/Codex分析
|
||||
|
||||
### 発展的ドキュメント(参考資料)
|
||||
4. **[Box-First文法アーキテクチャ](box-first-grammar-architecture.md)** - 箱化アプローチ
|
||||
5. **[根切り文法アーキテクチャ](root-cutting-architecture.md)** - 完全疎結合設計
|
||||
6. **[ゼロ知識文法アーキテクチャ](zero-knowledge-architecture.md)** - 究極の分離設計
|
||||
|
||||
### 既存ドキュメント
|
||||
- [文法統一化詳細設計](grammar-unification.txt)
|
||||
- [統一文法定義YAML](nyash-grammar-v1.yaml)
|
||||
- [実装計画](implementation-plan.txt)
|
||||
|
||||
## 🔧 次のステップ
|
||||
|
||||
1. `grammar/nyash.yml` の初版作成
|
||||
2. `crates/nygrammar-gen` の実装開始
|
||||
3. Tokenizer の移行から着手
|
||||
4. 段階的に全層を統一
|
||||
|
||||
## 📝 結論
|
||||
|
||||
コード生成アプローチ(Gemini/Codex推奨)を採用し、`grammar/nyash.yml` を単一の真実の源として、build.rs で各層向けのコードを生成する方式が最も実用的です。
|
||||
|
||||
これにより、Nyashの文法が完全に統一され、保守性・一貫性・AI対応すべてが改善されます。
|
||||
@ -0,0 +1,339 @@
|
||||
# Box-First統一文法アーキテクチャ再設計
|
||||
|
||||
## 🚨 現在の設計の問題点
|
||||
|
||||
### 1. 密結合の罠
|
||||
```rust
|
||||
// ❌ 現在の設計: 各層がUnifiedGrammarEngineに直接依存
|
||||
impl Tokenizer {
|
||||
fn tokenize(&mut self) {
|
||||
self.engine.is_keyword() // 直接参照!
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 根が這う実装
|
||||
```rust
|
||||
// ❌ UnifiedKeyword構造体が全層の情報を持つ
|
||||
struct UnifiedKeyword {
|
||||
token_type: TokenType, // Tokenizer層
|
||||
semantic_action: Action, // Parser層
|
||||
mir_instruction: MirOp, // MIR層
|
||||
vm_opcode: VmOp, // VM層
|
||||
jit_pattern: JitPattern, // JIT層
|
||||
// すべてが絡み合っている!
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 巨大な神オブジェクト
|
||||
```rust
|
||||
// ❌ UnifiedGrammarEngineが全てを知っている
|
||||
struct UnifiedGrammarEngine {
|
||||
keywords: KeywordRegistry,
|
||||
syntax: SyntaxRules,
|
||||
semantics: SemanticRules,
|
||||
execution: ExecutionSemantics,
|
||||
// 責任が多すぎる!
|
||||
}
|
||||
```
|
||||
|
||||
## 🎯 Box-First再設計
|
||||
|
||||
### 核心思想: 「箱に入れて、箱同士をつなぐ」
|
||||
|
||||
```
|
||||
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
||||
│ GrammarBox │ │ TokenBox │ │ ParserBox │
|
||||
│ (定義のみ) │ --> │ (Token化) │ --> │ (構文解析) │
|
||||
└─────────────┘ └─────────────┘ └─────────────┘
|
||||
| |
|
||||
v v
|
||||
┌─────────────┐ ┌─────────────┐
|
||||
│ SemanticBox │ <---------------------- │ ASTBox │
|
||||
│ (意味解釈) │ │ (構文木) │
|
||||
└─────────────┘ └─────────────┘
|
||||
|
|
||||
v
|
||||
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
||||
│ MIRBox │ --> │ VMBox │ │ JITBox │
|
||||
│ (中間表現) │ │ (実行) │ │ (コンパイル) │
|
||||
└─────────────┘ └─────────────┘ └─────────────┘
|
||||
```
|
||||
|
||||
## 📦 各箱の責任と境界
|
||||
|
||||
### 1. GrammarBox - 純粋な定義の箱
|
||||
```rust
|
||||
// 定義だけを持つ、実装を持たない
|
||||
box GrammarBox {
|
||||
init { definitions }
|
||||
|
||||
// キーワード定義を返すだけ
|
||||
getKeywordDef(word) {
|
||||
return me.definitions.keywords.get(word)
|
||||
}
|
||||
|
||||
// 演算子定義を返すだけ
|
||||
getOperatorDef(symbol) {
|
||||
return me.definitions.operators.get(symbol)
|
||||
}
|
||||
}
|
||||
|
||||
// キーワード定義は純粋なデータ
|
||||
box KeywordDef {
|
||||
init { literal, category, aliases }
|
||||
// 実装なし、データのみ
|
||||
}
|
||||
```
|
||||
|
||||
### 2. TokenBox - トークン化だけの責任
|
||||
```rust
|
||||
box TokenBox {
|
||||
init { grammarBox } // 定義への参照のみ
|
||||
|
||||
tokenize(text) {
|
||||
local tokens = []
|
||||
// GrammarBoxに聞くだけ、自分では判断しない
|
||||
loop(text.hasMore()) {
|
||||
local word = text.readWord()
|
||||
local def = me.grammarBox.getKeywordDef(word)
|
||||
if def {
|
||||
tokens.push(new Token(def.category, word))
|
||||
} else {
|
||||
tokens.push(new Token("IDENTIFIER", word))
|
||||
}
|
||||
}
|
||||
return tokens
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. SemanticBox - 意味解釈の箱
|
||||
```rust
|
||||
box SemanticBox {
|
||||
init { } // 他の箱に依存しない!
|
||||
|
||||
// 純粋関数として実装
|
||||
add(left, right) {
|
||||
// String + String
|
||||
if left.isString() and right.isString() {
|
||||
return new StringBox(left.value + right.value)
|
||||
}
|
||||
// Number + Number
|
||||
if left.isNumber() and right.isNumber() {
|
||||
return new IntegerBox(left.value + right.value)
|
||||
}
|
||||
// エラー
|
||||
return new ErrorBox("Type mismatch")
|
||||
}
|
||||
|
||||
coerceToString(value) {
|
||||
// 各型の変換ロジック
|
||||
if value.isString() { return value }
|
||||
if value.isNumber() { return new StringBox(value.toString()) }
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4. MIRBuilderBox - AST→MIR変換の箱
|
||||
```rust
|
||||
box MIRBuilderBox {
|
||||
init { semanticBox } // セマンティクスへの参照のみ
|
||||
|
||||
buildFromAST(ast) {
|
||||
// ASTの種類に応じてMIRを生成
|
||||
if ast.type == "BinaryOp" {
|
||||
return me.buildBinaryOp(ast)
|
||||
}
|
||||
// ...
|
||||
}
|
||||
|
||||
buildBinaryOp(ast) {
|
||||
local left = me.buildFromAST(ast.left)
|
||||
local right = me.buildFromAST(ast.right)
|
||||
|
||||
// セマンティクスに聞いて、適切なMIR命令を選択
|
||||
if ast.op == "+" {
|
||||
// SemanticBoxに型情報を聞く
|
||||
local mirOp = me.selectAddInstruction(left.type, right.type)
|
||||
return new MIRNode(mirOp, left, right)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🔄 疎結合の実現方法
|
||||
|
||||
### 1. インターフェース(契約)による結合
|
||||
```rust
|
||||
// 各箱は最小限のインターフェースだけを公開
|
||||
trait TokenProvider {
|
||||
fn next_token(&mut self) -> Option<Token>;
|
||||
}
|
||||
|
||||
trait SemanticProvider {
|
||||
fn apply_operator(&self, op: &str, args: &[Value]) -> Result<Value>;
|
||||
}
|
||||
|
||||
trait MIRProvider {
|
||||
fn get_instruction(&self, index: usize) -> &MIRInstruction;
|
||||
}
|
||||
```
|
||||
|
||||
### 2. メッセージパッシング
|
||||
```rust
|
||||
// 箱同士は直接呼び出さず、メッセージで通信
|
||||
box ParserBox {
|
||||
parseExpression() {
|
||||
// TokenBoxにメッセージを送る
|
||||
local token = me.sendMessage(me.tokenBox, "nextToken")
|
||||
|
||||
// 結果を処理
|
||||
if token.type == "NUMBER" {
|
||||
return new NumberNode(token.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. イベント駆動
|
||||
```rust
|
||||
// 文法変更時の通知システム
|
||||
box GrammarBox {
|
||||
updateKeyword(word, newDef) {
|
||||
me.definitions.keywords.set(word, newDef)
|
||||
// 変更を通知(購読者に伝える)
|
||||
me.notify("keyword_changed", word)
|
||||
}
|
||||
}
|
||||
|
||||
box TokenBox {
|
||||
init { grammarBox }
|
||||
|
||||
constructor() {
|
||||
// 文法変更を購読
|
||||
me.grammarBox.subscribe("keyword_changed", me.onKeywordChanged)
|
||||
}
|
||||
|
||||
onKeywordChanged(word) {
|
||||
// キャッシュをクリア
|
||||
me.clearCache()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📐 ビルド時生成の箱化
|
||||
|
||||
### GeneratorBox - コード生成も箱
|
||||
```rust
|
||||
box GeneratorBox {
|
||||
init { grammarBox, outputPath }
|
||||
|
||||
generate() {
|
||||
local grammar = me.grammarBox.getDefinitions()
|
||||
|
||||
// 各層向けのコードを生成
|
||||
me.generateTokens(grammar.keywords)
|
||||
me.generateParseTables(grammar.syntax)
|
||||
me.generateSemanticTables(grammar.operators)
|
||||
}
|
||||
|
||||
generateTokens(keywords) {
|
||||
local code = "pub enum Token {\n"
|
||||
keywords.forEach((name, def) => {
|
||||
code += " " + name + ",\n"
|
||||
})
|
||||
code += "}\n"
|
||||
|
||||
me.writeFile("generated/tokens.rs", code)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🎯 密結合を避ける設計原則
|
||||
|
||||
### 1. 単一責任の原則
|
||||
- GrammarBox: 定義の管理のみ
|
||||
- TokenBox: トークン化のみ
|
||||
- ParserBox: 構文解析のみ
|
||||
- SemanticBox: 意味解釈のみ
|
||||
|
||||
### 2. 依存関係の逆転
|
||||
```rust
|
||||
// ❌ 悪い例: 具象に依存
|
||||
box VMBox {
|
||||
init { mirBuilder: MIRBuilderBox } // 具象型に依存
|
||||
}
|
||||
|
||||
// ✅ 良い例: 抽象に依存
|
||||
box VMBox {
|
||||
init { mirProvider: MIRProvider } // インターフェースに依存
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Open/Closed原則
|
||||
```rust
|
||||
// 新しい演算子の追加が既存コードを変更しない
|
||||
box OperatorRegistry {
|
||||
init { operators }
|
||||
|
||||
register(symbol, handler) {
|
||||
me.operators.set(symbol, handler)
|
||||
}
|
||||
|
||||
apply(symbol, args) {
|
||||
local handler = me.operators.get(symbol)
|
||||
if handler {
|
||||
return handler.apply(args)
|
||||
}
|
||||
return new ErrorBox("Unknown operator")
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🔧 段階的移行(箱単位)
|
||||
|
||||
### Phase 1: GrammarBox導入
|
||||
- grammar.yamlをGrammarBoxでラップ
|
||||
- 既存コードはGrammarBox経由でアクセス
|
||||
|
||||
### Phase 2: TokenBox分離
|
||||
- Tokenizerの機能をTokenBoxに移動
|
||||
- GrammarBoxへの依存を最小化
|
||||
|
||||
### Phase 3: SemanticBox独立
|
||||
- 演算子実装をSemanticBoxに集約
|
||||
- 純粋関数として実装
|
||||
|
||||
### Phase 4: 箱間通信の確立
|
||||
- メッセージパッシング導入
|
||||
- イベントシステム構築
|
||||
|
||||
## 📊 疎結合度の測定
|
||||
|
||||
### 1. 依存関係グラフ
|
||||
```
|
||||
GrammarBox (依存なし)
|
||||
↓
|
||||
TokenBox → GrammarBox (1依存)
|
||||
ParserBox → TokenBox (1依存)
|
||||
SemanticBox (依存なし)
|
||||
MIRBox → SemanticBox (1依存)
|
||||
VMBox → MIRBox (1依存)
|
||||
JITBox → MIRBox (1依存)
|
||||
```
|
||||
|
||||
### 2. 変更影響範囲
|
||||
- 新キーワード追加: GrammarBoxのみ
|
||||
- 新演算子追加: GrammarBox + SemanticBoxのみ
|
||||
- 新バックエンド追加: 既存箱への変更なし
|
||||
|
||||
## 🚀 期待される効果
|
||||
|
||||
1. **真の疎結合**: 各箱が独立して開発・テスト可能
|
||||
2. **容易な拡張**: 新しい箱の追加が既存を壊さない
|
||||
3. **明確な境界**: 責任の所在が明確
|
||||
4. **並行開発**: チームが独立して各箱を開発可能
|
||||
|
||||
これで「Everything is Box」哲学に忠実な、真に疎結合な統一文法アーキテクチャが実現されます。
|
||||
@ -0,0 +1,297 @@
|
||||
# 根切り文法アーキテクチャ - 真の疎結合設計
|
||||
|
||||
## 🌳 「根が這う」問題の本質
|
||||
|
||||
### 現在の設計の根本的な問題
|
||||
```rust
|
||||
// 🌳 根が這っている例: 一つの変更が全体に波及
|
||||
struct Keyword {
|
||||
name: String,
|
||||
token_type: TokenType, // Tokenizer層の型
|
||||
parser_rule: ParserRule, // Parser層の型
|
||||
mir_op: MIROpcode, // MIR層の型
|
||||
vm_handler: VMHandler, // VM層の型
|
||||
// → 一つのstructが全層の型を知っている!
|
||||
}
|
||||
```
|
||||
|
||||
## 🎯 根切り設計: レイヤー完全分離
|
||||
|
||||
### 核心思想: 「各層は自分の関心事だけを知る」
|
||||
|
||||
```
|
||||
【Tokenizer層】 【Parser層】 【Semantic層】
|
||||
"me" → Token::Me → SelfReference
|
||||
知識:文字列のみ 知識:トークンのみ 知識:意味のみ
|
||||
|
||||
【MIR層】 【VM層】 【JIT層】
|
||||
LoadLocal(0) → OP_LOAD_0 → mov rax, [rbp]
|
||||
知識:MIRのみ 知識:オペコードのみ 知識:機械語のみ
|
||||
```
|
||||
|
||||
## 📦 真の箱化: 変換箱(TransformerBox)パターン
|
||||
|
||||
### 1. 各層は純粋な箱
|
||||
```rust
|
||||
// Tokenizer層: 文字列→トークンの変換のみ
|
||||
box StringToTokenBox {
|
||||
init { } // 依存なし!
|
||||
|
||||
transform(text: String) -> TokenStream {
|
||||
// 純粋な文字列処理
|
||||
local tokens = []
|
||||
local chars = text.chars()
|
||||
|
||||
loop(chars.hasNext()) {
|
||||
local ch = chars.next()
|
||||
if ch.isLetter() {
|
||||
local word = me.readWord(chars, ch)
|
||||
tokens.push(me.classifyWord(word))
|
||||
}
|
||||
// ...
|
||||
}
|
||||
return TokenStream(tokens)
|
||||
}
|
||||
|
||||
classifyWord(word: String) -> Token {
|
||||
// ローカルな判定のみ
|
||||
match word {
|
||||
"me" => Token::Me,
|
||||
"from" => Token::From,
|
||||
"loop" => Token::Loop,
|
||||
_ => Token::Identifier(word)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 層間の変換も箱
|
||||
```rust
|
||||
// Token→AST変換箱
|
||||
box TokenToASTBox {
|
||||
init { } // 依存なし!
|
||||
|
||||
transform(tokens: TokenStream) -> AST {
|
||||
local parser = PrattParser()
|
||||
return parser.parse(tokens)
|
||||
}
|
||||
}
|
||||
|
||||
// AST→MIR変換箱
|
||||
box ASTToMIRBox {
|
||||
init { } // 依存なし!
|
||||
|
||||
transform(ast: AST) -> MIR {
|
||||
match ast {
|
||||
AST::BinaryOp(op, left, right) => {
|
||||
local leftMIR = me.transform(left)
|
||||
local rightMIR = me.transform(right)
|
||||
return me.selectMIROp(op, leftMIR, rightMIR)
|
||||
}
|
||||
// ...
|
||||
}
|
||||
}
|
||||
|
||||
selectMIROp(op: String, left: MIR, right: MIR) -> MIR {
|
||||
// ローカルな判断のみ
|
||||
if op == "+" {
|
||||
if left.type == "String" and right.type == "String" {
|
||||
return MIR::StringConcat(left, right)
|
||||
}
|
||||
if left.type == "Integer" and right.type == "Integer" {
|
||||
return MIR::AddI64(left, right)
|
||||
}
|
||||
}
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🔄 パイプライン: 箱の連鎖
|
||||
|
||||
### 純粋関数的パイプライン
|
||||
```rust
|
||||
// 各箱は前の箱の出力を入力として受け取るだけ
|
||||
box NyashPipeline {
|
||||
init { }
|
||||
|
||||
compile(source: String) -> ExecutableCode {
|
||||
// 各変換箱を順番に適用
|
||||
local tokens = StringToTokenBox().transform(source)
|
||||
local ast = TokenToASTBox().transform(tokens)
|
||||
local mir = ASTToMIRBox().transform(ast)
|
||||
local bytecode = MIRToVMBox().transform(mir)
|
||||
return bytecode
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📐 設定の分離: ConfigBox
|
||||
|
||||
### 文法定義も実行時から分離
|
||||
```rust
|
||||
// ビルド時のみ使用される設定箱
|
||||
box GrammarConfigBox {
|
||||
init { yamlPath }
|
||||
|
||||
load() -> GrammarConfig {
|
||||
// YAMLを読み込んで設定オブジェクトを返す
|
||||
return YAML.parse(File.read(me.yamlPath))
|
||||
}
|
||||
}
|
||||
|
||||
// ビルド時コード生成箱
|
||||
box CodeGeneratorBox {
|
||||
init { config }
|
||||
|
||||
generate() {
|
||||
// 設定から各層のコードを生成
|
||||
me.generateTokenizerTable(me.config.keywords)
|
||||
me.generateParserTable(me.config.syntax)
|
||||
me.generateMIRTable(me.config.semantics)
|
||||
}
|
||||
|
||||
generateTokenizerTable(keywords) {
|
||||
// キーワードマッチング用の完全ハッシュ関数生成
|
||||
local code = "fn classify_keyword(s: &str) -> Token {\n"
|
||||
code += " match s {\n"
|
||||
keywords.forEach((word, info) => {
|
||||
code += ' "' + word + '" => Token::' + info.token + ',\n'
|
||||
})
|
||||
code += " _ => Token::Identifier(s.to_string())\n"
|
||||
code += " }\n"
|
||||
code += "}\n"
|
||||
File.write("src/generated/keywords.rs", code)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🎯 セマンティクスの分離
|
||||
|
||||
### セマンティクスも変換箱として実装
|
||||
```rust
|
||||
// 型強制変換箱
|
||||
box TypeCoercionBox {
|
||||
init { } // 依存なし!
|
||||
|
||||
coerceToString(value: Value) -> StringValue {
|
||||
match value {
|
||||
Value::String(s) => StringValue(s),
|
||||
Value::Integer(i) => StringValue(i.toString()),
|
||||
Value::Float(f) => StringValue(f.toString()),
|
||||
Value::Bool(b) => StringValue(b ? "true" : "false"),
|
||||
_ => panic("Cannot coerce to string")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 演算子実行箱
|
||||
box OperatorExecutorBox {
|
||||
init { coercionBox }
|
||||
|
||||
executeAdd(left: Value, right: Value) -> Value {
|
||||
// ローカルな判断
|
||||
match (left, right) {
|
||||
(Value::String(s1), Value::String(s2)) => {
|
||||
Value::String(s1 + s2)
|
||||
}
|
||||
(Value::String(s), other) => {
|
||||
local s2 = me.coercionBox.coerceToString(other)
|
||||
Value::String(s + s2.value)
|
||||
}
|
||||
(Value::Integer(i1), Value::Integer(i2)) => {
|
||||
Value::Integer(i1 + i2)
|
||||
}
|
||||
// ...
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🔧 テスト可能性の向上
|
||||
|
||||
### 各箱が独立してテスト可能
|
||||
```rust
|
||||
// StringToTokenBoxのテスト
|
||||
test "tokenize keywords" {
|
||||
local box = StringToTokenBox()
|
||||
local tokens = box.transform("me loop from")
|
||||
assert tokens == [Token::Me, Token::Loop, Token::From]
|
||||
}
|
||||
|
||||
// ASTToMIRBoxのテスト
|
||||
test "binary op to MIR" {
|
||||
local box = ASTToMIRBox()
|
||||
local ast = AST::BinaryOp("+",
|
||||
AST::Literal(Value::Integer(1)),
|
||||
AST::Literal(Value::Integer(2))
|
||||
)
|
||||
local mir = box.transform(ast)
|
||||
assert mir == MIR::AddI64(
|
||||
MIR::Const(Value::Integer(1)),
|
||||
MIR::Const(Value::Integer(2))
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## 📊 依存グラフ: 完全なDAG(有向非巡環グラフ)
|
||||
|
||||
```
|
||||
StringToTokenBox (依存: 0)
|
||||
↓
|
||||
TokenToASTBox (依存: 0)
|
||||
↓
|
||||
ASTToMIRBox (依存: 0)
|
||||
↓ ↓
|
||||
MIRToVMBox (依存: 0) MIRToJITBox (依存: 0)
|
||||
|
||||
TypeCoercionBox (依存: 0)
|
||||
↓
|
||||
OperatorExecutorBox (依存: 1)
|
||||
```
|
||||
|
||||
## 🚀 この設計の利点
|
||||
|
||||
### 1. 真の疎結合
|
||||
- 各箱は入力と出力の型だけを知る
|
||||
- 他の箱の実装を一切知らない
|
||||
- インターフェースすら不要(型だけで十分)
|
||||
|
||||
### 2. 並行開発可能
|
||||
- チームAがTokenizer開発
|
||||
- チームBがParser開発
|
||||
- チームCがMIR開発
|
||||
- 全員が独立して作業可能
|
||||
|
||||
### 3. 差し替え可能
|
||||
```rust
|
||||
// 別実装への差し替えが容易
|
||||
local pipeline = NyashPipeline()
|
||||
pipeline.tokenizer = OptimizedStringToTokenBox() // 高速版
|
||||
pipeline.parser = ErrorRecoveringTokenToASTBox() // エラー回復版
|
||||
```
|
||||
|
||||
### 4. 段階的最適化
|
||||
```rust
|
||||
// 最適化も箱として追加
|
||||
box MIROptimizerBox {
|
||||
transform(mir: MIR) -> MIR {
|
||||
// 定数畳み込み、死んだコード除去など
|
||||
return optimized
|
||||
}
|
||||
}
|
||||
|
||||
// パイプラインに挿入
|
||||
local mir = ASTToMIRBox().transform(ast)
|
||||
mir = MIROptimizerBox().transform(mir) // 追加
|
||||
local bytecode = MIRToVMBox().transform(mir)
|
||||
```
|
||||
|
||||
## 🎯 まとめ: 根を完全に切る
|
||||
|
||||
1. **データ中心設計**: 各層は入力データを出力データに変換するだけ
|
||||
2. **状態を持たない**: すべての箱が純粋関数的
|
||||
3. **設定と実装の分離**: ビルド時と実行時を明確に分離
|
||||
4. **変換の連鎖**: パイプラインで箱をつなぐ
|
||||
|
||||
これにより、真に「根が這わない」アーキテクチャが実現されます。
|
||||
@ -0,0 +1,304 @@
|
||||
# ゼロ知識文法アーキテクチャ - 究極の疎結合
|
||||
|
||||
## 🔍 さらに深い問題: 暗黙知識の漏洩
|
||||
|
||||
### 現在の設計でもまだ残る問題
|
||||
```rust
|
||||
// 🚨 TokenToASTBoxがTokenの意味を知っている
|
||||
transform(tokens: TokenStream) -> AST {
|
||||
if token == Token::Me { // Tokenの意味を知っている!
|
||||
return AST::SelfReference
|
||||
}
|
||||
}
|
||||
|
||||
// 🚨 ASTToMIRBoxがASTの構造を知っている
|
||||
transform(ast: AST) -> MIR {
|
||||
match ast {
|
||||
AST::BinaryOp(op, left, right) => { // AST構造を知っている!
|
||||
// ...
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🎯 ゼロ知識原則: 「箱は変換ルールだけを知る」
|
||||
|
||||
### 純粋な変換テーブル駆動設計
|
||||
|
||||
```rust
|
||||
// 各箱は変換テーブルだけを持つ
|
||||
box TokenClassifierBox {
|
||||
init { table: Map<String, u32> } // 文字列→数値のマッピングのみ
|
||||
|
||||
classify(word: String) -> u32 {
|
||||
return me.table.get(word).unwrapOr(0) // 0 = unknown
|
||||
}
|
||||
}
|
||||
|
||||
// ビルド時に生成される純粋なマッピング
|
||||
const TOKEN_TABLE: Map<String, u32> = {
|
||||
"me" => 1,
|
||||
"from" => 2,
|
||||
"loop" => 3,
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
## 📊 統一中間表現(UIR: Unified Intermediate Representation)
|
||||
|
||||
### すべての層が数値タグで通信
|
||||
|
||||
```
|
||||
Source Code UIR Tags Execution
|
||||
----------- -------- ---------
|
||||
"me" → [1] → LoadLocal(0)
|
||||
"+" → [100] → Add
|
||||
"loop" → [200] → Branch
|
||||
1 + 2 → [300,1,300,2,100] → Const(1), Const(2), Add
|
||||
```
|
||||
|
||||
### UIRTag: 意味を持たない純粋な識別子
|
||||
```rust
|
||||
box UIRTag {
|
||||
init { id: u32, children: Array<UIRTag> }
|
||||
|
||||
// タグは意味を持たない、ただの番号
|
||||
isLeaf() { return me.children.isEmpty() }
|
||||
getChildren() { return me.children }
|
||||
}
|
||||
```
|
||||
|
||||
## 🔄 完全分離された変換パイプライン
|
||||
|
||||
### 1. 字句解析: 文字列→UIRタグ
|
||||
```rust
|
||||
box LexicalTransformerBox {
|
||||
init { charTable: Array<u32> } // 文字→タグのテーブル
|
||||
|
||||
transform(text: String) -> Array<UIRTag> {
|
||||
local tags = []
|
||||
local chars = text.chars()
|
||||
|
||||
loop(chars.hasNext()) {
|
||||
local ch = chars.next()
|
||||
local tag = me.charTable[ch.code()]
|
||||
|
||||
if tag == TAG_LETTER {
|
||||
local word = me.collectWhile(chars, TAG_LETTER)
|
||||
tags.push(me.lookupWord(word))
|
||||
} else if tag == TAG_DIGIT {
|
||||
local num = me.collectWhile(chars, TAG_DIGIT)
|
||||
tags.push(UIRTag(TAG_NUMBER, num))
|
||||
}
|
||||
// ...
|
||||
}
|
||||
return tags
|
||||
}
|
||||
|
||||
// 単語検索も純粋なハッシュ値
|
||||
lookupWord(word: String) -> UIRTag {
|
||||
local hash = me.perfectHash(word)
|
||||
return UIRTag(hash, [])
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 構文解析: UIRタグ→UIRツリー
|
||||
```rust
|
||||
box SyntaxTransformerBox {
|
||||
init {
|
||||
// 優先順位テーブル(タグ→優先度)
|
||||
precedence: Map<u32, u32>,
|
||||
// 結合性テーブル(タグ→左/右)
|
||||
associativity: Map<u32, u8>
|
||||
}
|
||||
|
||||
transform(tags: Array<UIRTag>) -> UIRTag {
|
||||
// Prattパーサーだが、意味を知らない
|
||||
return me.parseExpression(tags, 0)
|
||||
}
|
||||
|
||||
parseExpression(tags: Array<UIRTag>, minPrec: u32) -> UIRTag {
|
||||
local left = me.parsePrimary(tags)
|
||||
|
||||
loop(tags.hasNext()) {
|
||||
local op = tags.peek()
|
||||
local prec = me.precedence.get(op.id).unwrapOr(0)
|
||||
|
||||
if prec < minPrec { break }
|
||||
|
||||
tags.next() // consume operator
|
||||
local assoc = me.associativity.get(op.id).unwrapOr(LEFT)
|
||||
local nextPrec = if assoc == LEFT { prec + 1 } else { prec }
|
||||
local right = me.parseExpression(tags, nextPrec)
|
||||
|
||||
// 構造だけ作る、意味は知らない
|
||||
left = UIRTag(op.id, [left, right])
|
||||
}
|
||||
|
||||
return left
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 意味解析: UIRツリー→実行可能形式
|
||||
```rust
|
||||
box SemanticTransformerBox {
|
||||
init {
|
||||
// タグ→実行アクションのテーブル
|
||||
actions: Map<u32, ExecutionAction>
|
||||
}
|
||||
|
||||
transform(tree: UIRTag) -> ExecutableCode {
|
||||
local action = me.actions.get(tree.id)
|
||||
|
||||
if action {
|
||||
return action.generate(tree.children.map(child => {
|
||||
me.transform(child)
|
||||
}))
|
||||
}
|
||||
|
||||
return ExecutableCode.Noop()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📐 ビルド時の統一: マスターテーブル生成
|
||||
|
||||
### grammar.yaml → 各種テーブル生成
|
||||
```yaml
|
||||
# grammar.yaml - 真の単一情報源
|
||||
tokens:
|
||||
me: { id: 1, type: self_reference }
|
||||
from: { id: 2, type: delegation }
|
||||
loop: { id: 3, type: control_flow }
|
||||
|
||||
operators:
|
||||
"+": { id: 100, precedence: 10, associativity: left }
|
||||
"*": { id: 101, precedence: 20, associativity: left }
|
||||
|
||||
semantics:
|
||||
1: { action: load_self }
|
||||
2: { action: delegate_call }
|
||||
3: { action: loop_construct }
|
||||
100: { action: add_operation }
|
||||
```
|
||||
|
||||
### ビルド時生成
|
||||
```rust
|
||||
// build.rs
|
||||
fn generate_tables(grammar: GrammarDef) {
|
||||
// 1. 完全ハッシュ関数生成
|
||||
generate_perfect_hash(grammar.tokens)
|
||||
|
||||
// 2. 優先順位テーブル生成
|
||||
generate_precedence_table(grammar.operators)
|
||||
|
||||
// 3. セマンティクステーブル生成
|
||||
generate_semantic_table(grammar.semantics)
|
||||
|
||||
// 4. 各層の定数生成
|
||||
generate_constants(grammar)
|
||||
}
|
||||
```
|
||||
|
||||
## 🎯 究極の利点: 完全な知識分離
|
||||
|
||||
### 1. 各箱が知っていること
|
||||
- **LexicalTransformer**: 文字の分類とハッシュ計算のみ
|
||||
- **SyntaxTransformer**: 優先順位と結合性のみ
|
||||
- **SemanticTransformer**: タグとアクションの対応のみ
|
||||
|
||||
### 2. 各箱が知らないこと
|
||||
- **すべての箱**: 他の層の存在、Nyashという言語名すら知らない
|
||||
- **すべての箱**: キーワードの意味、演算子の意味
|
||||
- **すべての箱**: 最終的な実行形式
|
||||
|
||||
### 3. テストの単純化
|
||||
```rust
|
||||
test "lexical transformer" {
|
||||
local table = { "hello" => 42 }
|
||||
local box = LexicalTransformerBox(table)
|
||||
assert box.transform("hello") == [UIRTag(42)]
|
||||
}
|
||||
|
||||
test "syntax transformer" {
|
||||
local prec = { 100 => 10, 101 => 20 }
|
||||
local box = SyntaxTransformerBox(prec, {})
|
||||
// 1 + 2 * 3
|
||||
local tags = [UIRTag(1), UIRTag(100), UIRTag(2), UIRTag(101), UIRTag(3)]
|
||||
local tree = box.transform(tags)
|
||||
// 期待: (+ 1 (* 2 3))
|
||||
assert tree == UIRTag(100, [
|
||||
UIRTag(1),
|
||||
UIRTag(101, [UIRTag(2), UIRTag(3)])
|
||||
])
|
||||
}
|
||||
```
|
||||
|
||||
## 🔧 動的拡張: プラグインテーブル
|
||||
|
||||
### 実行時のテーブル拡張
|
||||
```rust
|
||||
box PluginLoaderBox {
|
||||
init { transformers: Map<String, TransformerBox> }
|
||||
|
||||
loadPlugin(path: String) {
|
||||
local plugin = Plugin.load(path)
|
||||
|
||||
// プラグインは新しいタグを登録
|
||||
local newTags = plugin.getTags()
|
||||
|
||||
// 各変換器のテーブルを拡張
|
||||
me.transformers.get("lexical").extendTable(newTags.lexical)
|
||||
me.transformers.get("syntax").extendTable(newTags.syntax)
|
||||
me.transformers.get("semantic").extendTable(newTags.semantic)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📊 性能特性
|
||||
|
||||
### 1. キャッシュ効率
|
||||
- 各テーブルは連続メモリに配置
|
||||
- CPUキャッシュに収まるサイズ
|
||||
- ランダムアクセスなし
|
||||
|
||||
### 2. 並列化可能
|
||||
- 各変換は状態を持たない
|
||||
- 入力を分割して並列処理可能
|
||||
- ロックフリー実装
|
||||
|
||||
### 3. 最適化の余地
|
||||
- テーブルのコンパクト化
|
||||
- SIMDによる並列検索
|
||||
- JITによるテーブル特化
|
||||
|
||||
## 🚀 最終形: 言語に依存しない変換エンジン
|
||||
|
||||
```rust
|
||||
// このエンジンはNyashを知らない!
|
||||
box UniversalTransformEngine {
|
||||
init {
|
||||
pipeline: Array<TransformerBox>,
|
||||
tables: Map<String, Table>
|
||||
}
|
||||
|
||||
execute(input: String) -> Output {
|
||||
local data = input
|
||||
|
||||
// 各変換を順番に適用
|
||||
me.pipeline.forEach(transformer => {
|
||||
data = transformer.transform(data)
|
||||
})
|
||||
|
||||
return data
|
||||
}
|
||||
}
|
||||
|
||||
// Nyash = 特定のテーブルセット
|
||||
const NYASH_TABLES = load_tables("nyash-grammar.yaml")
|
||||
local engine = UniversalTransformEngine(STANDARD_PIPELINE, NYASH_TABLES)
|
||||
```
|
||||
|
||||
これが究極の「根を切った」設計です。各箱は純粋な変換器であり、Nyashという言語の存在すら知りません。
|
||||
146
docs/phases/phase-11.9/ai-deep-thoughts-unified-grammar.md
Normal file
146
docs/phases/phase-11.9/ai-deep-thoughts-unified-grammar.md
Normal file
@ -0,0 +1,146 @@
|
||||
# AI深層考察: Nyash統一文法アーキテクチャ
|
||||
|
||||
## 🎯 概要
|
||||
|
||||
GeminiとCodexに時間無制限で深く考えてもらった、Nyash統一文法アーキテクチャに関する洞察をまとめました。
|
||||
|
||||
## 🔥 Gemini先生の洞察
|
||||
|
||||
### 核心的提言: 宣言的文法定義 + ビルド時コード生成
|
||||
|
||||
```
|
||||
[ grammar.toml ] ← 宣言的SSoT(Single Source of Truth)
|
||||
↓
|
||||
[ build.rs ] ← メタプログラミング層
|
||||
↓
|
||||
├─ generated_tokens.rs
|
||||
├─ generated_keywords.rs
|
||||
├─ generated_rules.rs
|
||||
└─ generated_opcodes.rs
|
||||
```
|
||||
|
||||
### 重要ポイント
|
||||
|
||||
1. **真の分離**: `UnifiedKeyword`構造体は依然として各層を密結合させる。宣言的ファイルからコード生成する方が疎結合を保てる。
|
||||
|
||||
2. **ゼロコスト抽象化**:
|
||||
- ビルド時生成により実行時オーバーヘッドなし
|
||||
- `enum`と`match`文で高速ディスパッチ
|
||||
- `#[inline(always)]`で関数呼び出しコストなし
|
||||
|
||||
3. **コンパイラ駆動開発**:
|
||||
```rust
|
||||
// 新機能追加時、全層でコンパイルエラー発生
|
||||
// → 実装漏れがなくなる
|
||||
match token {
|
||||
TokenType::Async => // 新しく追加されたので実装必須
|
||||
_ => // ...
|
||||
}
|
||||
```
|
||||
|
||||
4. **他言語からの学び**:
|
||||
- **CPython**: `Grammar/Tokens`ファイルから生成
|
||||
- **V8**: Ignition(インタプリタ)とTurboFan(JIT)の分離
|
||||
- **rustc**: HIR→MIRという段階的表現
|
||||
|
||||
## 💡 Codex先生の洞察
|
||||
|
||||
### 核心的提言: MIRを中心とした統一セマンティクス基盤
|
||||
|
||||
```yaml
|
||||
# grammar/nyash.yml
|
||||
tokens:
|
||||
- name: ME
|
||||
literal: "me"
|
||||
soft: true
|
||||
contexts: ["expr", "pattern"]
|
||||
deprecated_aliases: ["self"]
|
||||
ai_hint: "Current object; not assignable."
|
||||
|
||||
operators:
|
||||
- symbol: "+"
|
||||
name: add
|
||||
precedence: 110
|
||||
associativity: left
|
||||
overloads:
|
||||
- types: ["i64","i64"] -> "i64"
|
||||
lower: MIR.AddI64
|
||||
- types: ["String","String"] -> "String"
|
||||
lower: MIR.Concat
|
||||
```
|
||||
|
||||
### 実装戦略
|
||||
|
||||
1. **単一仕様ファイル**: `grammar/nyash.yml`に全て定義
|
||||
- キーワード、演算子、文法、型、強制変換
|
||||
- MIRローリング、VMオペコード、JITパターン
|
||||
- 非推奨、AIヒント
|
||||
|
||||
2. **コード生成クレート**: `crates/nygrammar-gen`
|
||||
- Perfect hash関数でO(1)キーワード認識
|
||||
- Pratt/PEGパーサーテーブル生成
|
||||
- 型ディスパッチマトリックス生成
|
||||
|
||||
3. **MIRが真実の基盤**:
|
||||
```rust
|
||||
pub fn add(lhs: Value, rhs: Value) -> Result<MIRNode> {
|
||||
// 生成されたfast-pathを使用
|
||||
// 常にMIRノードを返す
|
||||
}
|
||||
```
|
||||
|
||||
4. **性能最適化**:
|
||||
- ビルド時にすべて決定(実行時検索なし)
|
||||
- インラインキャッシュで呼び出しサイト最適化
|
||||
- ソフトキーワードはパーサー状態で判定
|
||||
|
||||
### 段階的移行計画
|
||||
|
||||
- **Phase 0**: ベースラインテスト(現状記録)
|
||||
- **Phase 1**: 正準MIR定義
|
||||
- **Phase 2**: KeywordRegistry生成
|
||||
- **Phase 3**: UnifiedSemantics導入
|
||||
- **Phase 4**: パーサー統一
|
||||
- **Phase 5**: バックエンドマッピング
|
||||
- **Phase 6**: 非推奨警告
|
||||
- **Phase 7**: ツール/ドキュメント生成
|
||||
|
||||
## 🎯 統合された知見
|
||||
|
||||
両AIの提言を統合すると:
|
||||
|
||||
### 1. 宣言的定義 + コード生成が最強
|
||||
- YAML/TOMLで文法を宣言的に定義
|
||||
- build.rsでRustコードを生成
|
||||
- 実行時オーバーヘッドゼロ
|
||||
|
||||
### 2. MIRを中心とした統一
|
||||
- すべてのセマンティクスはMIRで表現
|
||||
- 各バックエンドはMIRを実行/コンパイル
|
||||
- 一貫性が自動的に保証される
|
||||
|
||||
### 3. AI友好的な設計
|
||||
- 機械可読な仕様ファイル
|
||||
- 豊富な例とエラーカタログ
|
||||
- 自動生成されるドキュメント
|
||||
|
||||
### 4. 拡張性への配慮
|
||||
- 新バックエンド追加が容易
|
||||
- プラグインによる拡張可能
|
||||
- 後方互換性の維持
|
||||
|
||||
## 📋 実装優先順位
|
||||
|
||||
1. **最優先**: `grammar/nyash.yml`の初版作成
|
||||
2. **高優先**: `build.rs`によるトークン生成
|
||||
3. **中優先**: MIR統一とUnifiedSemantics
|
||||
4. **低優先**: JIT最適化ヒント
|
||||
|
||||
## 🚀 期待される効果
|
||||
|
||||
- **保守性**: 新機能追加が1箇所の修正で完了
|
||||
- **一貫性**: 全層で同じセマンティクス保証
|
||||
- **性能**: ビルド時最適化で実行時コストなし
|
||||
- **AI対応**: LLMが正確にNyashコードを生成
|
||||
|
||||
これらの深い洞察により、Nyashの統一文法アーキテクチャは強固な基盤の上に構築されることになります。
|
||||
485
docs/phases/phase-11.9/archive/grammar-unification.txt
Normal file
485
docs/phases/phase-11.9/archive/grammar-unification.txt
Normal file
@ -0,0 +1,485 @@
|
||||
================================================================================
|
||||
Phase 11.9: 文法統一化とAI連携強化 - Grammar as Single Source of Truth
|
||||
================================================================================
|
||||
|
||||
【概要】
|
||||
Nyashの文法知識が分散している問題を解決し、AIがNyashコードを正しく書けるよう
|
||||
文法定義を一元化する。ANCPと連携して、AIとの効率的な通信も実現。
|
||||
|
||||
【現在の問題】
|
||||
1. 文法知識の分散
|
||||
- Tokenizer: キーワードのハードコード定義
|
||||
- Parser: TokenTypeに基づく個別実装
|
||||
- Interpreter: AST実行の独自ロジック
|
||||
- MIR Builder: 変換ルールの散在
|
||||
|
||||
2. AIの文法エラー
|
||||
- "while" vs "loop" の混同
|
||||
- "this" vs "me" の間違い
|
||||
- セミコロン使用などの古い構文
|
||||
|
||||
3. 文法の揺らぎ
|
||||
- 同じ意味の複数表現が存在
|
||||
- 非推奨構文の明確な定義なし
|
||||
- 統一的な検証メカニズムの欠如
|
||||
|
||||
================================================================================
|
||||
1. 文法統一化アーキテクチャ
|
||||
================================================================================
|
||||
|
||||
■ 3層構造の導入
|
||||
┌─────────────────────────────────────┐
|
||||
│ Grammar Definition Layer (YAML/TOML) │ ← 唯一の真実
|
||||
├─────────────────────────────────────┤
|
||||
│ Grammar Runtime (Rust) │ ← 共通実装
|
||||
├─────────────────────────────────────┤
|
||||
│ Components (Tokenizer/Parser/etc) │ ← 利用者
|
||||
└─────────────────────────────────────┘
|
||||
|
||||
■ 統一文法定義ファイル
|
||||
nyash-grammar-v1.yaml
|
||||
├─ keywords(予約語定義)
|
||||
├─ syntax_rules(構文規則)
|
||||
├─ semantic_rules(意味規則)
|
||||
├─ deprecated(非推奨定義)
|
||||
└─ ai_hints(AI向けヒント)
|
||||
|
||||
================================================================================
|
||||
2. 文法定義仕様(YAML形式)
|
||||
================================================================================
|
||||
|
||||
# nyash-grammar-v1.yaml
|
||||
version: "1.0"
|
||||
language: "nyash"
|
||||
|
||||
keywords:
|
||||
# デリゲーション関連
|
||||
delegation:
|
||||
from:
|
||||
token: FROM
|
||||
category: delegation
|
||||
semantic: parent_method_call
|
||||
syntax: "from <parent>.<method>(<args>)"
|
||||
example: "from Animal.init(name)"
|
||||
deprecated_aliases: ["super", "parent", "base"]
|
||||
ai_hint: "Always use 'from' for parent calls"
|
||||
|
||||
# 自己参照
|
||||
self_reference:
|
||||
me:
|
||||
token: ME
|
||||
category: object_reference
|
||||
semantic: current_instance
|
||||
syntax: "me.<field>"
|
||||
example: "me.name = value"
|
||||
deprecated_aliases: ["this", "self", "@"]
|
||||
ai_hint: "Use 'me' for self-reference, never 'this'"
|
||||
|
||||
# 制御フロー
|
||||
control_flow:
|
||||
loop:
|
||||
token: LOOP
|
||||
category: control_flow
|
||||
semantic: conditional_iteration
|
||||
syntax: "loop(<condition>) { <body> }"
|
||||
example: "loop(i < 10) { i = i + 1 }"
|
||||
deprecated_aliases: ["while", "for"]
|
||||
ai_hint: "Only 'loop' for iteration"
|
||||
|
||||
# クラス定義
|
||||
class_definition:
|
||||
box:
|
||||
token: BOX
|
||||
category: declaration
|
||||
semantic: class_declaration
|
||||
syntax: "box <name> from <parent>? { <body> }"
|
||||
example: "box Cat from Animal { }"
|
||||
deprecated_aliases: ["class", "struct", "type"]
|
||||
ai_hint: "Use 'box' for all class definitions"
|
||||
|
||||
syntax_rules:
|
||||
# Box定義ルール
|
||||
box_definition:
|
||||
pattern: "box <identifier> (from <identifier_list>)? { <box_body> }"
|
||||
constraints:
|
||||
- name: init_comma_required
|
||||
rule: "init block fields must be comma-separated"
|
||||
valid: "init { name, age }"
|
||||
invalid: "init { name age }"
|
||||
|
||||
- name: constructor_exclusive
|
||||
rule: "Only one of birth/pack/init() can be defined"
|
||||
valid: "birth() { }"
|
||||
invalid: "birth() { } pack() { }"
|
||||
|
||||
# デリゲーション呼び出し
|
||||
delegation_call:
|
||||
pattern: "from <identifier>.<identifier>(<expression_list>?)"
|
||||
constraints:
|
||||
- name: parent_must_exist
|
||||
rule: "Parent must be declared in 'from' clause"
|
||||
|
||||
- name: method_resolution
|
||||
rule: "Method lookup follows delegation chain"
|
||||
|
||||
semantic_rules:
|
||||
# 変数宣言
|
||||
variable_declaration:
|
||||
local_scope:
|
||||
keyword: "local"
|
||||
rule: "Variables must be declared before use"
|
||||
scope: "function"
|
||||
|
||||
implicit_global:
|
||||
rule: "Undeclared assignment creates global (deprecated)"
|
||||
warning: "Use 'local' for clarity"
|
||||
|
||||
# メソッド解決
|
||||
method_resolution:
|
||||
order:
|
||||
1: "Current instance methods"
|
||||
2: "Delegated parent methods"
|
||||
3: "Error: method not found"
|
||||
|
||||
# AI向け特別セクション
|
||||
ai_training:
|
||||
# 正しいパターン
|
||||
correct_patterns:
|
||||
- pattern: "loop(condition) { }"
|
||||
category: "iteration"
|
||||
|
||||
- pattern: "me.field = value"
|
||||
category: "assignment"
|
||||
|
||||
- pattern: "from Parent.method()"
|
||||
category: "delegation"
|
||||
|
||||
# よくある間違いと修正
|
||||
common_mistakes:
|
||||
- mistake: "while(true) { }"
|
||||
correction: "loop(true) { }"
|
||||
severity: "error"
|
||||
|
||||
- mistake: "this.value"
|
||||
correction: "me.value"
|
||||
severity: "error"
|
||||
|
||||
- mistake: "super.init()"
|
||||
correction: "from Parent.init()"
|
||||
severity: "error"
|
||||
|
||||
- mistake: "for i in array { }"
|
||||
correction: "Not supported, use loop with index"
|
||||
severity: "error"
|
||||
|
||||
# ANCP統合
|
||||
ancp_mapping:
|
||||
# キーワードの圧縮マッピング
|
||||
compression:
|
||||
"box": "$"
|
||||
"from": "@"
|
||||
"me": "m"
|
||||
"loop": "L"
|
||||
"local": "l"
|
||||
"return": "r"
|
||||
|
||||
# 圧縮時の保持ルール
|
||||
preservation:
|
||||
- "Semantic meaning must be preserved"
|
||||
- "AST structure must be identical"
|
||||
- "Round-trip must be lossless"
|
||||
|
||||
================================================================================
|
||||
3. Grammar Runtime実装
|
||||
================================================================================
|
||||
|
||||
// src/grammar/mod.rs
|
||||
pub struct NyashGrammar {
|
||||
version: String,
|
||||
keywords: KeywordRegistry,
|
||||
syntax_rules: SyntaxRuleSet,
|
||||
semantic_rules: SemanticRuleSet,
|
||||
ai_hints: AiHintCollection,
|
||||
}
|
||||
|
||||
impl NyashGrammar {
|
||||
/// YAMLファイルから文法定義を読み込み
|
||||
pub fn load() -> Result<Self, Error> {
|
||||
let yaml_path = concat!(env!("CARGO_MANIFEST_DIR"), "/grammar/nyash-grammar-v1.yaml");
|
||||
let yaml_str = std::fs::read_to_string(yaml_path)?;
|
||||
let grammar: GrammarDefinition = serde_yaml::from_str(&yaml_str)?;
|
||||
Ok(Self::from_definition(grammar))
|
||||
}
|
||||
|
||||
/// キーワードの検証
|
||||
pub fn validate_keyword(&self, word: &str) -> KeywordValidation {
|
||||
if let Some(keyword) = self.keywords.get(word) {
|
||||
KeywordValidation::Valid(keyword)
|
||||
} else if let Some(deprecated) = self.keywords.find_deprecated(word) {
|
||||
KeywordValidation::Deprecated {
|
||||
used: word,
|
||||
correct: deprecated.correct_form,
|
||||
hint: deprecated.ai_hint,
|
||||
}
|
||||
} else {
|
||||
KeywordValidation::Unknown
|
||||
}
|
||||
}
|
||||
|
||||
/// AI向けの文法エクスポート
|
||||
pub fn export_for_ai(&self) -> AiGrammarExport {
|
||||
AiGrammarExport {
|
||||
version: self.version.clone(),
|
||||
keywords: self.keywords.export_correct_only(),
|
||||
patterns: self.ai_hints.correct_patterns.clone(),
|
||||
mistakes: self.ai_hints.common_mistakes.clone(),
|
||||
examples: self.generate_examples(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// キーワードレジストリ
|
||||
pub struct KeywordRegistry {
|
||||
keywords: HashMap<String, KeywordDef>,
|
||||
deprecated_map: HashMap<String, String>, // old -> new
|
||||
}
|
||||
|
||||
// 構文検証器
|
||||
pub struct SyntaxValidator {
|
||||
grammar: Arc<NyashGrammar>,
|
||||
}
|
||||
|
||||
impl SyntaxValidator {
|
||||
pub fn validate_ast(&self, ast: &ASTNode) -> Vec<SyntaxIssue> {
|
||||
let mut issues = Vec::new();
|
||||
self.visit_node(ast, &mut issues);
|
||||
issues
|
||||
}
|
||||
}
|
||||
|
||||
================================================================================
|
||||
4. コンポーネント統合
|
||||
================================================================================
|
||||
|
||||
■ Tokenizer統合
|
||||
impl NyashTokenizer {
|
||||
pub fn new() -> Self {
|
||||
let grammar = NyashGrammar::load()
|
||||
.expect("Failed to load grammar definition");
|
||||
Self { grammar, ... }
|
||||
}
|
||||
|
||||
fn read_keyword_or_identifier(&mut self) -> TokenType {
|
||||
let word = self.read_word();
|
||||
|
||||
// 文法定義に基づいて判定
|
||||
match self.grammar.validate_keyword(&word) {
|
||||
KeywordValidation::Valid(keyword) => keyword.token,
|
||||
KeywordValidation::Deprecated { correct, .. } => {
|
||||
self.emit_warning(format!("'{}' is deprecated, use '{}'", word, correct));
|
||||
// エラーリカバリ: 正しいトークンを返す
|
||||
self.grammar.keywords.get(correct).unwrap().token
|
||||
}
|
||||
KeywordValidation::Unknown => TokenType::IDENTIFIER(word),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
■ Parser統合
|
||||
impl Parser {
|
||||
fn parse_box_definition(&mut self) -> Result<ASTNode, ParseError> {
|
||||
// 文法ルールに基づいて検証
|
||||
let rule = self.grammar.syntax_rules.get("box_definition")?;
|
||||
|
||||
self.consume(TokenType::BOX)?;
|
||||
let name = self.parse_identifier()?;
|
||||
|
||||
// from句の処理も文法定義に従う
|
||||
let extends = if self.match_token(&TokenType::FROM) {
|
||||
self.parse_parent_list()?
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
|
||||
// 制約チェック
|
||||
rule.validate(&parsed_node)?;
|
||||
|
||||
Ok(ASTNode::BoxDeclaration { name, extends, ... })
|
||||
}
|
||||
}
|
||||
|
||||
■ Interpreter統合
|
||||
impl NyashInterpreter {
|
||||
fn execute_from_call(&mut self, parent: &str, method: &str, args: &[ASTNode])
|
||||
-> Result<Box<dyn NyashBox>, RuntimeError> {
|
||||
|
||||
// 文法定義に基づいてセマンティクスを適用
|
||||
let semantic = self.grammar.semantic_rules.get("delegation_call")?;
|
||||
semantic.validate_runtime(parent, method)?;
|
||||
|
||||
// 既存の実行ロジック
|
||||
self.delegate_to_parent(parent, method, args)
|
||||
}
|
||||
}
|
||||
|
||||
================================================================================
|
||||
5. AI連携機能
|
||||
================================================================================
|
||||
|
||||
■ Grammar Export Tool
|
||||
// tools/export-grammar-for-ai.rs
|
||||
fn main() {
|
||||
let grammar = NyashGrammar::load().unwrap();
|
||||
|
||||
// 1. 基本文法エクスポート
|
||||
let basic = grammar.export_for_ai();
|
||||
std::fs::write("nyash-grammar-ai.json", serde_json::to_string_pretty(&basic)?)?;
|
||||
|
||||
// 2. トレーニングデータ生成
|
||||
let training_data = generate_training_pairs(&grammar);
|
||||
std::fs::write("nyash-training-data.jsonl", training_data)?;
|
||||
|
||||
// 3. プロンプト生成
|
||||
let prompt = generate_ai_prompt(&grammar);
|
||||
std::fs::write("nyash-ai-prompt.txt", prompt)?;
|
||||
}
|
||||
|
||||
■ AI Grammar Checker
|
||||
// AIが生成したコードをチェック
|
||||
pub struct AiCodeValidator {
|
||||
grammar: Arc<NyashGrammar>,
|
||||
}
|
||||
|
||||
impl AiCodeValidator {
|
||||
pub fn validate(&self, code: &str) -> ValidationResult {
|
||||
let mut issues = Vec::new();
|
||||
|
||||
// 1. 非推奨構文チェック
|
||||
for (pattern, correction) in &self.grammar.deprecated_patterns {
|
||||
if code.contains(pattern) {
|
||||
issues.push(Issue::Deprecated { pattern, correction });
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 構文検証
|
||||
match NyashParser::parse_with_grammar(code, &self.grammar) {
|
||||
Ok(ast) => {
|
||||
// ASTレベルでの検証
|
||||
issues.extend(self.validate_ast(&ast));
|
||||
}
|
||||
Err(e) => issues.push(Issue::ParseError(e)),
|
||||
}
|
||||
|
||||
ValidationResult { issues, suggestions: self.generate_suggestions(&issues) }
|
||||
}
|
||||
}
|
||||
|
||||
================================================================================
|
||||
6. ANCP統合
|
||||
================================================================================
|
||||
|
||||
■ Grammar-Aware ANCP
|
||||
pub struct GrammarAwareTranscoder {
|
||||
grammar: Arc<NyashGrammar>,
|
||||
ancp_mappings: AncpMappings,
|
||||
}
|
||||
|
||||
impl GrammarAwareTranscoder {
|
||||
pub fn encode(&self, code: &str) -> Result<String, Error> {
|
||||
let ast = NyashParser::parse_with_grammar(code, &self.grammar)?;
|
||||
|
||||
// 文法定義に基づいて圧縮
|
||||
let compressed = self.compress_with_grammar(&ast)?;
|
||||
|
||||
// ヘッダー付与
|
||||
Ok(format!(";ancp:1.0 nyash:{} grammar:{};\n{}",
|
||||
env!("CARGO_PKG_VERSION"),
|
||||
self.grammar.version,
|
||||
compressed))
|
||||
}
|
||||
|
||||
fn compress_with_grammar(&self, ast: &ASTNode) -> Result<String, Error> {
|
||||
// 文法定義のANCPマッピングを使用
|
||||
let mappings = &self.grammar.ancp_mapping;
|
||||
// ... 圧縮ロジック
|
||||
}
|
||||
}
|
||||
|
||||
================================================================================
|
||||
7. 実装計画
|
||||
================================================================================
|
||||
|
||||
■ Phase 1: 基礎実装(1週間)
|
||||
□ nyash-grammar-v1.yaml作成
|
||||
□ GrammarDefinition構造体設計
|
||||
□ YAMLパーサー統合
|
||||
□ 基本的な検証機能
|
||||
|
||||
■ Phase 2: コンポーネント統合(2週間)
|
||||
□ Tokenizer改修
|
||||
□ Parser改修
|
||||
□ Interpreter統合
|
||||
□ エラーメッセージ改善
|
||||
|
||||
■ Phase 3: AI機能(1週間)
|
||||
□ export-grammar-for-ai実装
|
||||
□ AiCodeValidator実装
|
||||
□ トレーニングデータ生成
|
||||
□ VSCode拡張対応
|
||||
|
||||
■ Phase 4: ANCP連携(1週間)
|
||||
□ Grammar-Aware Transcoder
|
||||
□ 圧縮効率の最適化
|
||||
□ デバッグ情報保持
|
||||
□ テスト統合
|
||||
|
||||
================================================================================
|
||||
8. 期待される効果
|
||||
================================================================================
|
||||
|
||||
1. **文法の一元管理**
|
||||
- 単一の真実の源(YAML)
|
||||
- 変更が全コンポーネントに自動反映
|
||||
- バージョン管理が容易
|
||||
|
||||
2. **AIエラーの削減**
|
||||
- 明確な文法定義で学習効率向上
|
||||
- 非推奨構文の自動検出・修正
|
||||
- トレーニングデータの品質向上
|
||||
|
||||
3. **開発効率の向上**
|
||||
- 新構文追加が簡単
|
||||
- 文法ドキュメントの自動生成
|
||||
- テストケースの自動生成
|
||||
|
||||
4. **ANCP効率化**
|
||||
- 文法aware圧縮で効率向上
|
||||
- セマンティクス保持の保証
|
||||
- デバッグ性の維持
|
||||
|
||||
================================================================================
|
||||
9. リスクと対策
|
||||
================================================================================
|
||||
|
||||
■ リスク1: パフォーマンス低下
|
||||
対策: 文法定義をコンパイル時に静的化
|
||||
|
||||
■ リスク2: 後方互換性
|
||||
対策: バージョニングとマイグレーションツール
|
||||
|
||||
■ リスク3: 複雑性増大
|
||||
対策: 段階的実装と十分なテスト
|
||||
|
||||
================================================================================
|
||||
10. 成功指標
|
||||
================================================================================
|
||||
|
||||
□ AIの文法エラー率: 90%以上削減
|
||||
□ 新構文追加時間: 1時間以内
|
||||
□ パフォーマンス影響: 5%以内
|
||||
□ テストカバレッジ: 95%以上
|
||||
|
||||
================================================================================
|
||||
|
||||
これにより、Nyashの文法が統一され、AIとの協働開発が劇的に改善される。
|
||||
「文法の揺らぎ」を完全に排除し、高品質なコード生成を実現する。
|
||||
398
docs/phases/phase-11.9/archive/implementation-plan.txt
Normal file
398
docs/phases/phase-11.9/archive/implementation-plan.txt
Normal file
@ -0,0 +1,398 @@
|
||||
================================================================================
|
||||
Phase 11.9: 文法統一化 実装計画
|
||||
================================================================================
|
||||
|
||||
【実装の優先順位と依存関係】
|
||||
|
||||
1. 基礎インフラ(必須・最優先)
|
||||
└→ 2. 文法定義ローダー
|
||||
└→ 3. 既存コンポーネント統合
|
||||
└→ 4. AI機能追加
|
||||
|
||||
================================================================================
|
||||
Step 1: 基礎インフラ構築(3日)
|
||||
================================================================================
|
||||
|
||||
■ ディレクトリ構造
|
||||
src/
|
||||
├── grammar/
|
||||
│ ├── mod.rs # メインモジュール
|
||||
│ ├── definition.rs # 文法定義構造体
|
||||
│ ├── loader.rs # YAML読み込み
|
||||
│ ├── validator.rs # 検証ロジック
|
||||
│ └── export.rs # AI向けエクスポート
|
||||
│
|
||||
grammar/
|
||||
└── nyash-grammar-v1.yaml # 文法定義ファイル
|
||||
|
||||
■ 基本構造体設計
|
||||
```rust
|
||||
// src/grammar/definition.rs
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub struct GrammarDefinition {
|
||||
pub version: String,
|
||||
pub language: String,
|
||||
pub keywords: HashMap<String, KeywordCategory>,
|
||||
pub syntax_rules: HashMap<String, SyntaxRule>,
|
||||
pub ai_common_mistakes: Vec<CommonMistake>,
|
||||
pub ancp_mappings: AncpMappings,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub struct KeywordDef {
|
||||
pub token: String,
|
||||
pub category: String,
|
||||
pub semantic: String,
|
||||
pub syntax: Option<String>,
|
||||
pub example: Option<String>,
|
||||
pub deprecated_aliases: Vec<String>,
|
||||
pub ai_hint: String,
|
||||
}
|
||||
```
|
||||
|
||||
■ Cargo.toml追加
|
||||
```toml
|
||||
[dependencies]
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_yaml = "0.9"
|
||||
once_cell = "1.19" # グローバルシングルトン用
|
||||
```
|
||||
|
||||
================================================================================
|
||||
Step 2: 文法定義ローダー実装(2日)
|
||||
================================================================================
|
||||
|
||||
■ シングルトンローダー
|
||||
```rust
|
||||
// src/grammar/loader.rs
|
||||
use once_cell::sync::Lazy;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub static NYASH_GRAMMAR: Lazy<Arc<NyashGrammar>> = Lazy::new(|| {
|
||||
Arc::new(NyashGrammar::load().expect("Failed to load grammar"))
|
||||
});
|
||||
|
||||
impl NyashGrammar {
|
||||
fn load() -> Result<Self, Error> {
|
||||
let yaml_path = concat!(
|
||||
env!("CARGO_MANIFEST_DIR"),
|
||||
"/grammar/nyash-grammar-v1.yaml"
|
||||
);
|
||||
let yaml_str = std::fs::read_to_string(yaml_path)?;
|
||||
let def: GrammarDefinition = serde_yaml::from_str(&yaml_str)?;
|
||||
|
||||
Ok(Self::from_definition(def))
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
■ キャッシュ付き検証
|
||||
```rust
|
||||
// src/grammar/validator.rs
|
||||
pub struct KeywordValidator {
|
||||
valid_keywords: HashSet<&'static str>,
|
||||
deprecated_map: HashMap<&'static str, &'static str>,
|
||||
}
|
||||
|
||||
impl KeywordValidator {
|
||||
pub fn validate(&self, word: &str) -> KeywordValidation {
|
||||
if self.valid_keywords.contains(word) {
|
||||
KeywordValidation::Valid
|
||||
} else if let Some(&correct) = self.deprecated_map.get(word) {
|
||||
KeywordValidation::Deprecated {
|
||||
correct,
|
||||
hint: self.get_hint(word)
|
||||
}
|
||||
} else {
|
||||
KeywordValidation::Unknown
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
================================================================================
|
||||
Step 3: Tokenizer統合(3日)
|
||||
================================================================================
|
||||
|
||||
■ 最小限の変更で統合
|
||||
```rust
|
||||
// src/tokenizer.rs の修正
|
||||
use crate::grammar::NYASH_GRAMMAR;
|
||||
|
||||
impl NyashTokenizer {
|
||||
fn read_keyword_or_identifier(&mut self) -> TokenType {
|
||||
let word = self.read_identifier_string();
|
||||
|
||||
// 文法定義ベースの判定に切り替え
|
||||
match NYASH_GRAMMAR.validate_keyword(&word) {
|
||||
KeywordValidation::Valid(token_type) => token_type,
|
||||
KeywordValidation::Deprecated { correct, .. } => {
|
||||
// 警告を出しつつ、正しいトークンを返す
|
||||
self.warnings.push(Warning::DeprecatedKeyword {
|
||||
used: word.clone(),
|
||||
correct: correct.to_string(),
|
||||
line: self.line,
|
||||
});
|
||||
NYASH_GRAMMAR.get_token_type(correct)
|
||||
}
|
||||
KeywordValidation::Unknown => {
|
||||
TokenType::IDENTIFIER(word)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
■ 互換性維持
|
||||
```rust
|
||||
// 既存のmatch文を段階的に置き換え
|
||||
// Phase 1: 並行実行して差分チェック
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
let old_result = self.old_keyword_match(&word);
|
||||
let new_result = NYASH_GRAMMAR.validate_keyword(&word);
|
||||
debug_assert_eq!(old_result, new_result, "Grammar mismatch: {}", word);
|
||||
}
|
||||
```
|
||||
|
||||
================================================================================
|
||||
Step 4: Parser統合(3日)
|
||||
================================================================================
|
||||
|
||||
■ 構文ルールの適用
|
||||
```rust
|
||||
// src/parser/mod.rs
|
||||
impl Parser {
|
||||
fn parse_box_definition(&mut self) -> Result<ASTNode, ParseError> {
|
||||
// 文法ルールを取得
|
||||
let rule = NYASH_GRAMMAR.get_syntax_rule("box_definition")?;
|
||||
|
||||
// ルールに基づいて解析
|
||||
self.consume(TokenType::BOX)?;
|
||||
let name = self.parse_identifier()?;
|
||||
|
||||
// 親クラスの解析(文法定義に従う)
|
||||
let extends = if self.match_token(&TokenType::FROM) {
|
||||
self.parse_delegation_list()?
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
|
||||
// 制約チェック
|
||||
self.check_constraints(&rule, &parsed_node)?;
|
||||
|
||||
Ok(parsed_node)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
================================================================================
|
||||
Step 5: AI機能実装(4日)
|
||||
================================================================================
|
||||
|
||||
■ エクスポートツール
|
||||
```rust
|
||||
// tools/export-grammar.rs
|
||||
use nyash::grammar::NYASH_GRAMMAR;
|
||||
|
||||
fn main() {
|
||||
// 1. 基本文法JSON
|
||||
let json = NYASH_GRAMMAR.export_as_json();
|
||||
std::fs::write("nyash-grammar.json", json)?;
|
||||
|
||||
// 2. AI用プロンプト
|
||||
let prompt = generate_ai_prompt(&NYASH_GRAMMAR);
|
||||
std::fs::write("ai-prompt.txt", prompt)?;
|
||||
|
||||
// 3. VSCode snippets
|
||||
let snippets = generate_vscode_snippets(&NYASH_GRAMMAR);
|
||||
std::fs::write("nyash.code-snippets", snippets)?;
|
||||
}
|
||||
```
|
||||
|
||||
■ AIコード検証器
|
||||
```rust
|
||||
// src/grammar/ai_validator.rs
|
||||
pub struct AiCodeValidator {
|
||||
grammar: Arc<NyashGrammar>,
|
||||
mistake_patterns: Vec<CompiledPattern>,
|
||||
}
|
||||
|
||||
impl AiCodeValidator {
|
||||
pub fn validate_code(&self, code: &str) -> Vec<CodeIssue> {
|
||||
let mut issues = vec![];
|
||||
|
||||
// 1. よくある間違いパターンをチェック
|
||||
for pattern in &self.mistake_patterns {
|
||||
if let Some(matches) = pattern.find_in(code) {
|
||||
issues.push(CodeIssue::CommonMistake {
|
||||
pattern: pattern.name.clone(),
|
||||
correction: pattern.correction.clone(),
|
||||
locations: matches,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 2. パース可能かチェック
|
||||
match NyashParser::parse(code) {
|
||||
Ok(ast) => {
|
||||
// AST検証
|
||||
issues.extend(self.validate_ast(&ast));
|
||||
}
|
||||
Err(e) => {
|
||||
issues.push(CodeIssue::ParseError(e));
|
||||
}
|
||||
}
|
||||
|
||||
issues
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
================================================================================
|
||||
Step 6: ANCP統合(3日)
|
||||
================================================================================
|
||||
|
||||
■ 文法aware圧縮
|
||||
```rust
|
||||
// src/ancp/grammar_aware.rs
|
||||
impl GrammarAwareTranscoder {
|
||||
pub fn new() -> Self {
|
||||
let grammar = NYASH_GRAMMAR.clone();
|
||||
let mappings = &grammar.ancp_mappings;
|
||||
|
||||
Self {
|
||||
grammar,
|
||||
keyword_map: build_keyword_map(mappings),
|
||||
reverse_map: build_reverse_map(mappings),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compress(&self, token: &Token) -> String {
|
||||
// 文法定義のマッピングを使用
|
||||
if let Some(compressed) = self.keyword_map.get(&token.text) {
|
||||
compressed.clone()
|
||||
} else {
|
||||
token.text.clone()
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
================================================================================
|
||||
テスト戦略
|
||||
================================================================================
|
||||
|
||||
■ 単体テスト
|
||||
```rust
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_grammar_loading() {
|
||||
let grammar = NyashGrammar::load().unwrap();
|
||||
assert_eq!(grammar.version, "1.0");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_keyword_validation() {
|
||||
let grammar = NYASH_GRAMMAR.clone();
|
||||
|
||||
// 正しいキーワード
|
||||
assert!(matches!(
|
||||
grammar.validate_keyword("me"),
|
||||
KeywordValidation::Valid(_)
|
||||
));
|
||||
|
||||
// 非推奨キーワード
|
||||
assert!(matches!(
|
||||
grammar.validate_keyword("this"),
|
||||
KeywordValidation::Deprecated { correct: "me", .. }
|
||||
));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
■ 統合テスト
|
||||
```rust
|
||||
// tests/grammar_integration.rs
|
||||
#[test]
|
||||
fn test_tokenizer_parser_consistency() {
|
||||
let code = "box Cat from Animal { me.name = 'Fluffy' }";
|
||||
|
||||
// Tokenize with grammar
|
||||
let tokens = tokenize_with_grammar(code);
|
||||
|
||||
// Parse with grammar
|
||||
let ast = parse_with_grammar(&tokens);
|
||||
|
||||
// Validate consistency
|
||||
assert!(ast.is_ok());
|
||||
}
|
||||
```
|
||||
|
||||
■ スナップショットテスト
|
||||
```rust
|
||||
#[test]
|
||||
fn test_ai_export_stability() {
|
||||
let export = NYASH_GRAMMAR.export_for_ai();
|
||||
insta::assert_json_snapshot!(export);
|
||||
}
|
||||
```
|
||||
|
||||
================================================================================
|
||||
CI/CD統合
|
||||
================================================================================
|
||||
|
||||
■ GitHub Actions追加
|
||||
```yaml
|
||||
- name: Validate Grammar
|
||||
run: |
|
||||
cargo run --bin validate-grammar -- grammar/nyash-grammar-v1.yaml
|
||||
|
||||
- name: Generate AI Artifacts
|
||||
run: |
|
||||
cargo run --bin export-grammar
|
||||
# アーティファクトとして保存
|
||||
|
||||
- name: Test Grammar Integration
|
||||
run: |
|
||||
cargo test --test grammar_integration
|
||||
```
|
||||
|
||||
================================================================================
|
||||
移行計画
|
||||
================================================================================
|
||||
|
||||
1. **既存コードの互換性維持**
|
||||
- 古いキーワードも一時的に受け入れ
|
||||
- 警告を出しながら段階的に厳格化
|
||||
|
||||
2. **ドキュメント更新**
|
||||
- 言語リファレンスを文法定義から自動生成
|
||||
- VSCode拡張に統合
|
||||
|
||||
3. **コミュニティへの告知**
|
||||
- 変更点の明確な説明
|
||||
- 移行ツールの提供
|
||||
|
||||
================================================================================
|
||||
成果物チェックリスト
|
||||
================================================================================
|
||||
|
||||
□ grammar/nyash-grammar-v1.yaml
|
||||
□ src/grammar/mod.rs(実装完了)
|
||||
□ Tokenizer統合(警告付き動作)
|
||||
□ Parser統合(制約チェック)
|
||||
□ export-grammar ツール
|
||||
□ AIコード検証器
|
||||
□ ANCP統合
|
||||
□ 包括的テストスイート
|
||||
□ ドキュメント更新
|
||||
□ CI/CD統合
|
||||
|
||||
================================================================================
|
||||
298
docs/phases/phase-11.9/archive/nyash-grammar-v1.yaml
Normal file
298
docs/phases/phase-11.9/archive/nyash-grammar-v1.yaml
Normal file
@ -0,0 +1,298 @@
|
||||
# Nyash Grammar Definition v1.0
|
||||
# This is the single source of truth for Nyash syntax
|
||||
version: "1.0"
|
||||
language: "nyash"
|
||||
|
||||
keywords:
|
||||
# Class/Box definition
|
||||
class_definition:
|
||||
box:
|
||||
token: BOX
|
||||
category: declaration
|
||||
semantic: class_declaration
|
||||
syntax: "box <name> from <parent>? { <body> }"
|
||||
example: "box Cat from Animal { }"
|
||||
deprecated_aliases: ["class", "struct", "type", "object"]
|
||||
ai_hint: "Always use 'box' for class definitions"
|
||||
|
||||
# Self reference
|
||||
self_reference:
|
||||
me:
|
||||
token: ME
|
||||
category: object_reference
|
||||
semantic: current_instance
|
||||
syntax: "me.<field>"
|
||||
example: "me.name = value"
|
||||
deprecated_aliases: ["this", "self", "@", "my"]
|
||||
ai_hint: "Use 'me' for self-reference, NEVER 'this'"
|
||||
|
||||
# Delegation/Inheritance
|
||||
delegation:
|
||||
from:
|
||||
token: FROM
|
||||
category: delegation
|
||||
semantic: parent_reference
|
||||
syntax_contexts:
|
||||
- context: class_declaration
|
||||
pattern: "box Child from Parent"
|
||||
meaning: "establishes delegation relationship"
|
||||
- context: method_call
|
||||
pattern: "from Parent.method(args)"
|
||||
meaning: "calls parent's method"
|
||||
deprecated_aliases: ["extends", "super", "parent", "base", "inherits"]
|
||||
ai_hint: "Use 'from' for both inheritance and parent calls"
|
||||
|
||||
# Control flow
|
||||
control_flow:
|
||||
loop:
|
||||
token: LOOP
|
||||
category: control_flow
|
||||
semantic: conditional_iteration
|
||||
syntax: "loop(condition) { body }"
|
||||
example: "loop(i < 10) { i = i + 1 }"
|
||||
deprecated_aliases: ["while", "for", "repeat", "until"]
|
||||
ai_hint: "Only 'loop' exists for iteration"
|
||||
|
||||
if:
|
||||
token: IF
|
||||
category: control_flow
|
||||
semantic: conditional_branch
|
||||
syntax: "if condition { body } else { body }"
|
||||
example: "if x > 0 { print(x) }"
|
||||
ai_hint: "No parentheses needed around condition"
|
||||
|
||||
# Variable declaration
|
||||
variables:
|
||||
local:
|
||||
token: LOCAL
|
||||
category: declaration
|
||||
semantic: local_variable
|
||||
syntax: "local <name>"
|
||||
example: "local counter"
|
||||
ai_hint: "Always declare variables with 'local'"
|
||||
|
||||
static:
|
||||
token: STATIC
|
||||
category: modifier
|
||||
semantic: static_member
|
||||
syntax: "static box Name { }"
|
||||
example: "static box Main { }"
|
||||
ai_hint: "Use for singleton/utility boxes"
|
||||
|
||||
# Constructor variants
|
||||
constructors:
|
||||
birth:
|
||||
token: BIRTH
|
||||
category: method
|
||||
semantic: primary_constructor
|
||||
syntax: "birth(params) { body }"
|
||||
priority: 1
|
||||
ai_hint: "Preferred constructor name"
|
||||
|
||||
pack:
|
||||
token: PACK
|
||||
category: method
|
||||
semantic: alternative_constructor
|
||||
syntax: "pack(params) { body }"
|
||||
priority: 2
|
||||
deprecated: true
|
||||
ai_hint: "Use 'birth' instead"
|
||||
|
||||
init:
|
||||
token: INIT
|
||||
category: special
|
||||
semantic: field_declaration_or_constructor
|
||||
syntax_contexts:
|
||||
- context: field_list
|
||||
pattern: "init { field1, field2 }"
|
||||
meaning: "declares instance fields"
|
||||
- context: method
|
||||
pattern: "init(params) { body }"
|
||||
meaning: "constructor method"
|
||||
ai_hint: "Dual purpose: fields or constructor"
|
||||
|
||||
# Method modifiers
|
||||
modifiers:
|
||||
override:
|
||||
token: OVERRIDE
|
||||
category: modifier
|
||||
semantic: method_override
|
||||
syntax: "override methodName() { }"
|
||||
required_when: "overriding parent method"
|
||||
ai_hint: "Required for clarity"
|
||||
|
||||
# Special methods
|
||||
special_methods:
|
||||
new:
|
||||
token: NEW
|
||||
category: operator
|
||||
semantic: instance_creation
|
||||
syntax: "new BoxName(args)"
|
||||
example: "new Cat('Fluffy')"
|
||||
ai_hint: "Creates instances"
|
||||
|
||||
# Logical operators
|
||||
logical_operators:
|
||||
and:
|
||||
token: AND
|
||||
category: operator
|
||||
semantic: logical_and
|
||||
syntax: "a and b"
|
||||
aliases: ["&&"]
|
||||
ai_hint: "Prefer 'and' over '&&'"
|
||||
|
||||
or:
|
||||
token: OR
|
||||
category: operator
|
||||
semantic: logical_or
|
||||
syntax: "a or b"
|
||||
aliases: ["||"]
|
||||
ai_hint: "Prefer 'or' over '||'"
|
||||
|
||||
not:
|
||||
token: NOT
|
||||
category: operator
|
||||
semantic: logical_not
|
||||
syntax: "not condition"
|
||||
aliases: ["!"]
|
||||
ai_hint: "Prefer 'not' over '!'"
|
||||
|
||||
# Syntax rules with constraints
|
||||
syntax_rules:
|
||||
box_definition:
|
||||
pattern: "box <identifier> (from <identifier_list>)? { <box_body> }"
|
||||
constraints:
|
||||
- id: init_comma_separator
|
||||
rule: "init fields must be comma-separated"
|
||||
valid: "init { name, age, type }"
|
||||
invalid: "init { name age type }"
|
||||
error: "Missing comma in init block"
|
||||
|
||||
- id: single_constructor
|
||||
rule: "Only one constructor (birth/pack/init) allowed"
|
||||
valid: "birth() { }"
|
||||
invalid: "birth() { } pack() { }"
|
||||
error: "Multiple constructors not allowed"
|
||||
|
||||
- id: override_required
|
||||
rule: "Override keyword required when overriding"
|
||||
valid: "override toString() { }"
|
||||
invalid: "toString() { } // when parent has toString"
|
||||
error: "Missing 'override' keyword"
|
||||
|
||||
variable_usage:
|
||||
constraints:
|
||||
- id: declare_before_use
|
||||
rule: "Variables must be declared with 'local'"
|
||||
valid: "local x\nx = 42"
|
||||
invalid: "x = 42 // without declaration"
|
||||
warning: "Implicit global (deprecated)"
|
||||
|
||||
delegation_calls:
|
||||
pattern: "from <identifier>.<method>(<args>?)"
|
||||
constraints:
|
||||
- id: parent_must_exist
|
||||
rule: "Parent must be in delegation chain"
|
||||
error: "No delegation to specified parent"
|
||||
|
||||
# Common mistakes by AI
|
||||
ai_common_mistakes:
|
||||
- pattern: "while\\s*\\("
|
||||
correction: "loop("
|
||||
explanation: "Nyash only has 'loop', not 'while'"
|
||||
severity: error
|
||||
|
||||
- pattern: "this\\."
|
||||
correction: "me."
|
||||
explanation: "Use 'me' for self-reference"
|
||||
severity: error
|
||||
|
||||
- pattern: "super\\."
|
||||
correction: "from ParentName."
|
||||
explanation: "Use 'from ParentName.' for parent calls"
|
||||
severity: error
|
||||
|
||||
- pattern: "for\\s+\\w+\\s+in"
|
||||
correction: "Use loop with index"
|
||||
explanation: "Nyash doesn't have for-in loops"
|
||||
severity: error
|
||||
|
||||
- pattern: "class\\s+\\w+"
|
||||
correction: "box"
|
||||
explanation: "Use 'box' for class definitions"
|
||||
severity: error
|
||||
|
||||
- pattern: ";\\s*$"
|
||||
correction: "Remove semicolon"
|
||||
explanation: "Nyash doesn't use semicolons"
|
||||
severity: warning
|
||||
|
||||
# ANCP (AI-Nyash Compact Protocol) mappings
|
||||
ancp_mappings:
|
||||
version: "1.0"
|
||||
compression_rules:
|
||||
keywords:
|
||||
"box": "$"
|
||||
"from": "@"
|
||||
"me": "m"
|
||||
"new": "n"
|
||||
"loop": "L"
|
||||
"if": "?"
|
||||
"else": ":"
|
||||
"local": "l"
|
||||
"return": "r"
|
||||
"static": "S"
|
||||
"init": "#"
|
||||
"birth": "b"
|
||||
"override": "O"
|
||||
|
||||
structures:
|
||||
"{ }": "{}"
|
||||
"( )": "()"
|
||||
" = ": "="
|
||||
|
||||
# Training data generation hints
|
||||
training_hints:
|
||||
positive_examples:
|
||||
- description: "Simple box definition"
|
||||
code: |
|
||||
box Animal {
|
||||
init { name, age }
|
||||
birth(name, age) {
|
||||
me.name = name
|
||||
me.age = age
|
||||
}
|
||||
}
|
||||
|
||||
- description: "Delegation example"
|
||||
code: |
|
||||
box Cat from Animal {
|
||||
init { color }
|
||||
birth(name, age, color) {
|
||||
from Animal.birth(name, age)
|
||||
me.color = color
|
||||
}
|
||||
}
|
||||
|
||||
- description: "Loop usage"
|
||||
code: |
|
||||
local i, sum
|
||||
i = 0
|
||||
sum = 0
|
||||
loop(i < 10) {
|
||||
sum = sum + i
|
||||
i = i + 1
|
||||
}
|
||||
|
||||
negative_examples:
|
||||
- description: "Don't use while"
|
||||
wrong: "while(true) { }"
|
||||
correct: "loop(true) { }"
|
||||
|
||||
- description: "Don't use this"
|
||||
wrong: "this.value = 10"
|
||||
correct: "me.value = 10"
|
||||
|
||||
- description: "Don't use class"
|
||||
wrong: "class MyClass { }"
|
||||
correct: "box MyClass { }"
|
||||
255
docs/phases/phase-11.9/chatgpt5-feedback-integration.md
Normal file
255
docs/phases/phase-11.9/chatgpt5-feedback-integration.md
Normal file
@ -0,0 +1,255 @@
|
||||
# ChatGPT5フィードバック統合 - 統一文法アーキテクチャ改善
|
||||
|
||||
## 📋 ChatGPT5からの評価
|
||||
|
||||
> 「Grammar as THE Source of Truth で各層の乖離を一元化する狙いは現状の痛点に直結しており、有効です」
|
||||
|
||||
## 🎯 指摘されたリスクへの対応策
|
||||
|
||||
### 1. ランタイム依存過多への対応
|
||||
|
||||
#### 問題
|
||||
```rust
|
||||
// ❌ 悪い例:実行時にTOMLパース
|
||||
let grammar = toml::from_str(&fs::read_to_string("grammar.toml")?)?;
|
||||
```
|
||||
|
||||
#### 解決策:build.rs による完全コード生成
|
||||
```rust
|
||||
// build.rs
|
||||
fn main() {
|
||||
println!("cargo:rerun-if-changed=grammar/nyash.yml");
|
||||
|
||||
let grammar = load_grammar_definition();
|
||||
|
||||
// Rust定数として生成
|
||||
generate_keyword_constants(&grammar);
|
||||
generate_perfect_hash_function(&grammar);
|
||||
generate_semantic_tables(&grammar);
|
||||
generate_mir_mappings(&grammar);
|
||||
}
|
||||
|
||||
// 生成されるコード例
|
||||
// generated/keywords.rs
|
||||
pub const KEYWORD_ME: u32 = 1;
|
||||
pub const KEYWORD_FROM: u32 = 2;
|
||||
pub const KEYWORD_LOOP: u32 = 3;
|
||||
|
||||
#[inline(always)]
|
||||
pub fn classify_keyword(s: &str) -> Option<u32> {
|
||||
match s {
|
||||
"me" => Some(KEYWORD_ME),
|
||||
"from" => Some(KEYWORD_FROM),
|
||||
"loop" => Some(KEYWORD_LOOP),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. プラグイン拡張性と競合への対応
|
||||
|
||||
#### マージ戦略の定義
|
||||
```yaml
|
||||
# grammar/nyash.yml
|
||||
version: "1.0"
|
||||
namespace: "core"
|
||||
|
||||
# プラグイン拡張ポイント
|
||||
extension_points:
|
||||
operators:
|
||||
merge_strategy: "priority" # 優先順位ベース
|
||||
conflict_resolution: "namespace" # 名前空間で分離
|
||||
|
||||
# プラグイン例
|
||||
# plugins/custom/grammar.yml
|
||||
namespace: "custom"
|
||||
extends: "core"
|
||||
|
||||
operators:
|
||||
"++": # 新しい演算子
|
||||
priority: 100
|
||||
precedence: 15
|
||||
semantics: increment
|
||||
```
|
||||
|
||||
#### 実装時の名前空間解決
|
||||
```rust
|
||||
pub struct GrammarRegistry {
|
||||
core: CoreGrammar,
|
||||
plugins: HashMap<String, PluginGrammar>,
|
||||
}
|
||||
|
||||
impl GrammarRegistry {
|
||||
pub fn resolve_operator(&self, op: &str, context: &Context) -> OperatorDef {
|
||||
// 1. 現在の名前空間で検索
|
||||
if let Some(def) = context.namespace.find_operator(op) {
|
||||
return def;
|
||||
}
|
||||
|
||||
// 2. インポートされた名前空間を優先順位順に検索
|
||||
for imported in &context.imports {
|
||||
if let Some(def) = self.plugins.get(imported)?.find_operator(op) {
|
||||
return def;
|
||||
}
|
||||
}
|
||||
|
||||
// 3. コア名前空間にフォールバック
|
||||
self.core.find_operator(op).unwrap_or_else(|| {
|
||||
panic!("Unknown operator: {}", op)
|
||||
})
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 文脈依存キーワードの曖昧性解決
|
||||
|
||||
#### fromキーワードの文脈解決ルール
|
||||
```yaml
|
||||
# grammar/nyash.yml
|
||||
contextual_keywords:
|
||||
from:
|
||||
contexts:
|
||||
- name: "box_delegation"
|
||||
pattern: "box IDENT from"
|
||||
priority: 100
|
||||
|
||||
- name: "method_delegation"
|
||||
pattern: "from IDENT.IDENT"
|
||||
priority: 90
|
||||
|
||||
- name: "variable_name"
|
||||
pattern: "IDENT = from" # 変数名として使用
|
||||
priority: 10
|
||||
|
||||
resolution: "longest_match_first" # 最長一致優先
|
||||
```
|
||||
|
||||
#### パーサーでの実装
|
||||
```rust
|
||||
impl Parser {
|
||||
fn parse_from(&mut self) -> Result<Node> {
|
||||
let start_pos = self.current_pos();
|
||||
|
||||
// 最長一致を試みる
|
||||
if let Ok(delegation) = self.try_parse_delegation() {
|
||||
return Ok(delegation);
|
||||
}
|
||||
|
||||
// フォールバック:通常の識別子として扱う
|
||||
self.reset_to(start_pos);
|
||||
Ok(Node::Identifier("from".to_string()))
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4. 二重実装期間の管理
|
||||
|
||||
#### 自動差分検出テスト
|
||||
```rust
|
||||
#[cfg(test)]
|
||||
mod migration_tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_unified_vs_legacy_semantics() {
|
||||
let test_cases = load_test_cases("tests/semantics/*.nyash");
|
||||
|
||||
for case in test_cases {
|
||||
let legacy_result = legacy_interpreter.execute(&case);
|
||||
let unified_result = unified_interpreter.execute(&case);
|
||||
|
||||
// スナップショットテスト
|
||||
assert_snapshot!(
|
||||
format!("{}_unified", case.name),
|
||||
unified_result
|
||||
);
|
||||
|
||||
// 差分検出
|
||||
if legacy_result != unified_result {
|
||||
// 意図的な変更か確認
|
||||
assert!(
|
||||
is_expected_difference(&case, &legacy_result, &unified_result),
|
||||
"Unexpected difference in {}: {:?} vs {:?}",
|
||||
case.name, legacy_result, unified_result
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 段階的移行フラグ
|
||||
```rust
|
||||
pub struct ExecutionConfig {
|
||||
pub use_unified_grammar: bool,
|
||||
pub log_differences: bool,
|
||||
pub fail_on_difference: bool,
|
||||
}
|
||||
|
||||
impl Interpreter {
|
||||
pub fn execute_with_migration(&mut self, expr: &Expression) -> Result<Value> {
|
||||
if self.config.use_unified_grammar {
|
||||
let result = self.unified_execute(expr)?;
|
||||
|
||||
if self.config.log_differences {
|
||||
let legacy_result = self.legacy_execute(expr)?;
|
||||
if result != legacy_result {
|
||||
log::warn!(
|
||||
"Semantic difference detected: {:?} -> unified: {:?}, legacy: {:?}",
|
||||
expr, result, legacy_result
|
||||
);
|
||||
|
||||
if self.config.fail_on_difference {
|
||||
panic!("Unexpected semantic difference");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
} else {
|
||||
self.legacy_execute(expr)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📊 改善された実装計画
|
||||
|
||||
### Phase 0: 準備(1週間)
|
||||
- ベースラインテストスイート作成
|
||||
- 現在のセマンティクスのスナップショット記録
|
||||
- 差分検出フレームワーク構築
|
||||
|
||||
### Phase 1: コード生成基盤(1週間)
|
||||
- build.rs による完全静的生成
|
||||
- ゼロランタイムコスト実現
|
||||
- CI/CDでの生成コード検証
|
||||
|
||||
### Phase 2: 名前空間とプラグイン(1週間)
|
||||
- 名前空間解決システム
|
||||
- プラグインマージ戦略実装
|
||||
- 競合検出と報告
|
||||
|
||||
### Phase 3: 文脈依存解決(1週間)
|
||||
- fromキーワードの文脈ルール実装
|
||||
- 最長一致パーサー
|
||||
- 曖昧性テストケース
|
||||
|
||||
### Phase 4: 段階的移行(2週間)
|
||||
- フィーチャーフラグ実装
|
||||
- 並行実行と差分ログ
|
||||
- 本番環境での検証
|
||||
|
||||
## 🎯 期待される成果
|
||||
|
||||
1. **ゼロコスト抽象化**: 実行時オーバーヘッドなし
|
||||
2. **安全な拡張性**: プラグイン競合の自動解決
|
||||
3. **明確な文脈解決**: 曖昧性のない文法
|
||||
4. **リスクフリー移行**: 自動検証による安全な移行
|
||||
|
||||
## 📝 まとめ
|
||||
|
||||
ChatGPT5さんの指摘により、実装の潜在的リスクが明確になりました。
|
||||
これらの対策を組み込むことで、より堅牢で実用的な統一文法アーキテクチャが実現できます。
|
||||
|
||||
「痛点直結」という評価に応えられる実装を目指しますにゃ!🚀
|
||||
344
docs/phases/phase-11.9/unified-grammar-architecture.md
Normal file
344
docs/phases/phase-11.9/unified-grammar-architecture.md
Normal file
@ -0,0 +1,344 @@
|
||||
# Phase 11.9: 統一文法アーキテクチャ設計書
|
||||
|
||||
## 🔴 現在の根本的問題
|
||||
|
||||
現在のNyashは、各層で予約語・文法解釈がバラバラに実装されている:
|
||||
|
||||
### 1. Tokenizer層での分散
|
||||
```rust
|
||||
// src/tokenizer.rs
|
||||
match word.as_str() {
|
||||
"me" => TokenType::ME, // ハードコード
|
||||
"from" => TokenType::FROM, // ハードコード
|
||||
"loop" => TokenType::LOOP, // ハードコード
|
||||
// ... 各予約語が個別定義
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Parser層での独自解釈
|
||||
```rust
|
||||
// src/parser/mod.rs
|
||||
fn parse_loop(&mut self) {
|
||||
// loop構文の独自解釈
|
||||
// while/forとの混同を個別チェック
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Interpreter層での独自実行
|
||||
```rust
|
||||
// src/interpreter/expressions.rs
|
||||
fn execute_from_call(&mut self) {
|
||||
// fromの独自解釈
|
||||
// デリゲーションロジックが埋め込み
|
||||
}
|
||||
```
|
||||
|
||||
### 4. MIR Builder層での独自変換
|
||||
```rust
|
||||
// src/mir/builder.rs
|
||||
fn build_loop(&mut self) {
|
||||
// loop → MIRへの独自変換
|
||||
// セーフポイント挿入も個別判断
|
||||
}
|
||||
```
|
||||
|
||||
### 5. VM/JIT層での独自実行
|
||||
- VM: 独自のセマンティクス実装
|
||||
- JIT: 独自のコード生成戦略
|
||||
|
||||
## 🎯 統一文法アーキテクチャの設計
|
||||
|
||||
### 核心コンセプト: "Grammar as THE Source of Truth"
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────┐
|
||||
│ Unified Grammar Engine │
|
||||
│ (単一の文法定義・解釈・実行エンジン) │
|
||||
├─────────────────────────────────────────────┤
|
||||
│ - Keyword Registry (予約語レジストリ) │
|
||||
│ - Syntax Rules (構文規則) │
|
||||
│ - Semantic Rules (意味規則) │
|
||||
│ - Execution Semantics (実行セマンティクス) │
|
||||
└─────────────────────────────────────────────┘
|
||||
↓
|
||||
┌──────────┬──────────┬──────────┬──────────┐
|
||||
│Tokenizer │ Parser │Interpreter│MIR/VM/JIT│
|
||||
│ (利用) │ (利用) │ (利用) │ (利用) │
|
||||
└──────────┴──────────┴──────────┴──────────┘
|
||||
```
|
||||
|
||||
## 📐 統一文法エンジンの実装設計
|
||||
|
||||
### 1. コア構造体
|
||||
```rust
|
||||
// src/grammar/engine.rs
|
||||
pub struct UnifiedGrammarEngine {
|
||||
// 予約語の統一定義
|
||||
keywords: KeywordRegistry,
|
||||
|
||||
// 構文規則の統一定義
|
||||
syntax: SyntaxRuleEngine,
|
||||
|
||||
// 意味規則の統一定義
|
||||
semantics: SemanticRuleEngine,
|
||||
|
||||
// 実行セマンティクスの統一定義
|
||||
execution: ExecutionSemantics,
|
||||
}
|
||||
|
||||
impl UnifiedGrammarEngine {
|
||||
/// 単一のソースから全情報を読み込み
|
||||
pub fn load() -> Self {
|
||||
// YAML/TOML/Rustコードから読み込み
|
||||
let config = include_str!("../../../grammar/unified-grammar.toml");
|
||||
Self::from_config(config)
|
||||
}
|
||||
|
||||
/// Tokenizerが使う統一API
|
||||
pub fn is_keyword(&self, word: &str) -> Option<TokenType> {
|
||||
self.keywords.lookup(word)
|
||||
}
|
||||
|
||||
/// Parserが使う統一API
|
||||
pub fn parse_rule(&self, rule_name: &str) -> &SyntaxRule {
|
||||
self.syntax.get_rule(rule_name)
|
||||
}
|
||||
|
||||
/// Interpreter/VM/JITが使う統一API
|
||||
pub fn execute_semantic(&self, op: &str, args: &[Value]) -> Value {
|
||||
self.execution.apply(op, args)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 予約語レジストリ
|
||||
```rust
|
||||
pub struct KeywordRegistry {
|
||||
// 正規形マップ
|
||||
canonical: HashMap<String, KeywordDef>,
|
||||
|
||||
// エイリアスマップ(非推奨含む)
|
||||
aliases: HashMap<String, String>,
|
||||
|
||||
// コンテキスト別解釈
|
||||
contextual: HashMap<(String, Context), KeywordDef>,
|
||||
}
|
||||
|
||||
pub struct KeywordDef {
|
||||
pub token: TokenType,
|
||||
pub category: KeywordCategory,
|
||||
pub semantic_action: SemanticAction,
|
||||
pub mir_opcode: Option<MirOpcode>,
|
||||
pub vm_handler: Option<VmHandler>,
|
||||
pub jit_lowering: Option<JitLowering>,
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 構文規則エンジン
|
||||
```rust
|
||||
pub struct SyntaxRuleEngine {
|
||||
rules: HashMap<String, SyntaxRule>,
|
||||
}
|
||||
|
||||
pub struct SyntaxRule {
|
||||
pub pattern: Pattern,
|
||||
pub precedence: i32,
|
||||
pub associativity: Associativity,
|
||||
pub semantic_transform: Box<dyn Fn(&AST) -> MIR>,
|
||||
}
|
||||
```
|
||||
|
||||
### 4. 実行セマンティクス統一
|
||||
```rust
|
||||
pub struct ExecutionSemantics {
|
||||
// 演算子の統一実装
|
||||
operators: HashMap<String, OperatorSemantics>,
|
||||
|
||||
// 型変換の統一ルール
|
||||
coercions: CoercionRules,
|
||||
|
||||
// エラー処理の統一
|
||||
error_handling: ErrorSemantics,
|
||||
}
|
||||
|
||||
impl ExecutionSemantics {
|
||||
/// すべてのバックエンドが使う統一演算
|
||||
pub fn add(&self, left: Value, right: Value) -> Value {
|
||||
// Interpreter/VM/JIT すべて同じロジック
|
||||
match (&left, &right) {
|
||||
(Value::String(s1), Value::String(s2)) => {
|
||||
Value::String(s1.clone() + s2)
|
||||
}
|
||||
(Value::Integer(i1), Value::Integer(i2)) => {
|
||||
Value::Integer(i1 + i2)
|
||||
}
|
||||
_ => self.coerce_and_add(left, right)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🔄 統一化の実装手順
|
||||
|
||||
### Phase 1: 基盤構築
|
||||
1. `src/grammar/engine.rs` - 統一エンジン本体
|
||||
2. `grammar/unified-grammar.toml` - 統一定義ファイル
|
||||
3. 既存コードとの並行実行(デバッグ用)
|
||||
|
||||
### Phase 2: Tokenizer統合
|
||||
```rust
|
||||
impl NyashTokenizer {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
engine: UnifiedGrammarEngine::load(),
|
||||
// ...
|
||||
}
|
||||
}
|
||||
|
||||
fn read_keyword_or_identifier(&mut self) -> TokenType {
|
||||
let word = self.read_word();
|
||||
// 統一エンジンに委譲
|
||||
self.engine.is_keyword(&word)
|
||||
.unwrap_or(TokenType::IDENTIFIER(word))
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Phase 3: Parser統合
|
||||
```rust
|
||||
impl Parser {
|
||||
fn parse_statement(&mut self) -> Result<ASTNode> {
|
||||
// 統一エンジンから構文規則を取得
|
||||
let rule = self.engine.get_syntax_rule("statement");
|
||||
rule.parse(self)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Phase 4: セマンティクス統合
|
||||
```rust
|
||||
// Interpreter
|
||||
impl Interpreter {
|
||||
fn execute_binop(&mut self, op: &str, left: Value, right: Value) -> Value {
|
||||
// 統一エンジンに委譲
|
||||
self.engine.execute_semantic(op, &[left, right])
|
||||
}
|
||||
}
|
||||
|
||||
// VM
|
||||
impl VM {
|
||||
fn execute_add(&mut self) -> Result<()> {
|
||||
let right = self.pop()?;
|
||||
let left = self.pop()?;
|
||||
// 統一エンジンに委譲
|
||||
let result = self.engine.execute_semantic("add", &[left, right]);
|
||||
self.push(result)
|
||||
}
|
||||
}
|
||||
|
||||
// JIT
|
||||
impl JitBuilder {
|
||||
fn lower_add(&mut self, left: Value, right: Value) {
|
||||
// 統一エンジンから最適化ヒントを取得
|
||||
let strategy = self.engine.get_jit_strategy("add", &left, &right);
|
||||
strategy.emit(self, left, right)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🎯 統一定義ファイルの例
|
||||
|
||||
```toml
|
||||
# grammar/unified-grammar.toml
|
||||
|
||||
[keywords.me]
|
||||
token = "ME"
|
||||
category = "self_reference"
|
||||
deprecated_aliases = ["this", "self", "@"]
|
||||
semantic_action = "load_self"
|
||||
mir_opcode = "LoadSelf"
|
||||
vm_handler = "OP_LOAD_ME"
|
||||
jit_lowering = "emit_load_local(0)"
|
||||
|
||||
[keywords.from]
|
||||
token = "FROM"
|
||||
category = "delegation"
|
||||
contexts = [
|
||||
{ context = "class_decl", meaning = "inheritance" },
|
||||
{ context = "method_call", meaning = "delegation_call" }
|
||||
]
|
||||
semantic_action = "delegate"
|
||||
mir_opcode = "DelegateCall"
|
||||
|
||||
[keywords.loop]
|
||||
token = "LOOP"
|
||||
category = "control_flow"
|
||||
deprecated_aliases = ["while", "for"]
|
||||
semantic_action = "loop_construct"
|
||||
mir_opcode = "Loop"
|
||||
safepoint_insertion = true
|
||||
|
||||
[operators.add]
|
||||
symbol = "+"
|
||||
precedence = 10
|
||||
associativity = "left"
|
||||
type_rules = [
|
||||
{ left = "String", right = "String", result = "String", action = "concat" },
|
||||
{ left = "Integer", right = "Integer", result = "Integer", action = "add_i64" },
|
||||
{ left = "Float", right = "Float", result = "Float", action = "add_f64" },
|
||||
]
|
||||
coercion_strategy = "string_priority" # String + anything = String
|
||||
|
||||
[semantics.string_concat]
|
||||
interpreter = "rust:concatenate_strings"
|
||||
vm = "CONCAT_STRINGS"
|
||||
jit = "call @nyash.string.concat_hh"
|
||||
```
|
||||
|
||||
## 🚀 期待される効果
|
||||
|
||||
1. **完全な一貫性**
|
||||
- すべての層が同じ予約語定義を使用
|
||||
- すべての層が同じ文法解釈を実行
|
||||
- すべての層が同じセマンティクスを適用
|
||||
|
||||
2. **保守性の劇的向上**
|
||||
- 新しい予約語/演算子の追加が1箇所
|
||||
- 文法変更が全層に自動反映
|
||||
- バグの削減(解釈の不一致がなくなる)
|
||||
|
||||
3. **AI開発の簡素化**
|
||||
- 単一の文法定義をAIに学習させる
|
||||
- 正しいNyashコードの生成率向上
|
||||
- エラーメッセージの一貫性
|
||||
|
||||
4. **性能最適化の余地**
|
||||
- 統一エンジンでの最適化が全層に効果
|
||||
- JITヒントの統一管理
|
||||
- キャッシュ戦略の一元化
|
||||
|
||||
## 📊 実装優先度
|
||||
|
||||
1. **最優先**: 予約語レジストリ(すぐ効果が出る)
|
||||
2. **高優先**: セマンティクス統一(バグ削減効果大)
|
||||
3. **中優先**: 構文規則エンジン(段階的移行可能)
|
||||
4. **低優先**: JIT最適化ヒント(性能向上は後回し)
|
||||
|
||||
## 🔧 移行戦略
|
||||
|
||||
1. **並行実行期間**
|
||||
- 新旧両方の実装を維持
|
||||
- デバッグモードで差分検出
|
||||
- 段階的に新実装に切り替え
|
||||
|
||||
2. **テスト駆動**
|
||||
- 各層の動作一致を自動テスト
|
||||
- スナップショットテストで回帰防止
|
||||
- ファズテストで edge case 発見
|
||||
|
||||
3. **ドキュメント駆動**
|
||||
- 統一文法仕様書を先に作成
|
||||
- 実装は仕様書に従う
|
||||
- AIトレーニングデータも同時生成
|
||||
|
||||
これにより、Nyashの全層で完全に統一された文法解釈と実行が実現される。
|
||||
321
docs/phases/phase-11.9/unified-keyword-system.md
Normal file
321
docs/phases/phase-11.9/unified-keyword-system.md
Normal file
@ -0,0 +1,321 @@
|
||||
# Nyash統一予約語システム仕様
|
||||
|
||||
## 🎯 目的
|
||||
|
||||
Nyashの全実行層(Script/MIR/VM/JIT)で完全に同一の予約語・文法解釈を実現する。
|
||||
|
||||
## 📊 現状の予約語分散状況
|
||||
|
||||
### Tokenizer層 (src/tokenizer.rs)
|
||||
```rust
|
||||
// 現在: ハードコードされた予約語
|
||||
match word.as_str() {
|
||||
"box" => TokenType::BOX,
|
||||
"me" => TokenType::ME,
|
||||
"from" => TokenType::FROM,
|
||||
"loop" => TokenType::LOOP,
|
||||
"if" => TokenType::IF,
|
||||
"else" => TokenType::ELSE,
|
||||
"local" => TokenType::LOCAL,
|
||||
"return" => TokenType::RETURN,
|
||||
"new" => TokenType::NEW,
|
||||
"static" => TokenType::STATIC,
|
||||
"init" => TokenType::INIT,
|
||||
"birth" => TokenType::BIRTH,
|
||||
"pack" => TokenType::PACK,
|
||||
"override" => TokenType::OVERRIDE,
|
||||
"and" => TokenType::AND,
|
||||
"or" => TokenType::OR,
|
||||
"not" => TokenType::NOT,
|
||||
_ => TokenType::IDENTIFIER(word)
|
||||
}
|
||||
```
|
||||
|
||||
### MIR Builder層での独自解釈
|
||||
```rust
|
||||
// 現在: MIR生成時の独自判断
|
||||
fn build_from_call(&mut self) {
|
||||
// "from"の解釈がTokenizerと異なる可能性
|
||||
}
|
||||
```
|
||||
|
||||
### VM/JIT層での実行差異
|
||||
```rust
|
||||
// VM: 文字列連結の独自実装
|
||||
VMValue::String(s1) + VMValue::String(s2) => concat
|
||||
|
||||
// JIT: 異なる最適化戦略
|
||||
emit_call("nyash.string.concat_hh")
|
||||
```
|
||||
|
||||
## 🏗️ 統一予約語システムの設計
|
||||
|
||||
### 1. 中央予約語レジストリ
|
||||
```rust
|
||||
// src/grammar/keyword_registry.rs
|
||||
pub struct UnifiedKeywordRegistry {
|
||||
keywords: HashMap<&'static str, UnifiedKeyword>,
|
||||
}
|
||||
|
||||
pub struct UnifiedKeyword {
|
||||
// トークン情報
|
||||
pub token_type: TokenType,
|
||||
pub literal: &'static str,
|
||||
|
||||
// 文法情報
|
||||
pub category: KeywordCategory,
|
||||
pub precedence: Option<i32>,
|
||||
|
||||
// セマンティクス情報
|
||||
pub semantic_action: SemanticAction,
|
||||
pub mir_instruction: Option<MirInstruction>,
|
||||
pub vm_opcode: Option<VmOpcode>,
|
||||
pub jit_pattern: Option<JitPattern>,
|
||||
|
||||
// メタ情報
|
||||
pub deprecated_aliases: Vec<&'static str>,
|
||||
pub ai_hint: &'static str,
|
||||
}
|
||||
|
||||
// 静的に初期化される単一インスタンス
|
||||
pub static KEYWORDS: Lazy<UnifiedKeywordRegistry> = Lazy::new(|| {
|
||||
let mut registry = UnifiedKeywordRegistry::new();
|
||||
|
||||
// "me" - 自己参照
|
||||
registry.register(UnifiedKeyword {
|
||||
token_type: TokenType::ME,
|
||||
literal: "me",
|
||||
category: KeywordCategory::SelfReference,
|
||||
semantic_action: SemanticAction::LoadSelf,
|
||||
mir_instruction: Some(MirInstruction::LoadLocal(0)),
|
||||
vm_opcode: Some(VmOpcode::LOAD_ME),
|
||||
jit_pattern: Some(JitPattern::LoadFirstParam),
|
||||
deprecated_aliases: vec!["this", "self", "@"],
|
||||
ai_hint: "Always use 'me' for self-reference",
|
||||
precedence: None,
|
||||
});
|
||||
|
||||
// "from" - デリゲーション
|
||||
registry.register(UnifiedKeyword {
|
||||
token_type: TokenType::FROM,
|
||||
literal: "from",
|
||||
category: KeywordCategory::Delegation,
|
||||
semantic_action: SemanticAction::DelegateCall,
|
||||
mir_instruction: Some(MirInstruction::Call),
|
||||
vm_opcode: Some(VmOpcode::DELEGATE_CALL),
|
||||
jit_pattern: Some(JitPattern::VirtualCall),
|
||||
deprecated_aliases: vec!["super", "parent", "base"],
|
||||
ai_hint: "Use 'from' for parent method calls",
|
||||
precedence: None,
|
||||
});
|
||||
|
||||
// "loop" - 制御フロー
|
||||
registry.register(UnifiedKeyword {
|
||||
token_type: TokenType::LOOP,
|
||||
literal: "loop",
|
||||
category: KeywordCategory::ControlFlow,
|
||||
semantic_action: SemanticAction::Loop,
|
||||
mir_instruction: Some(MirInstruction::Branch),
|
||||
vm_opcode: Some(VmOpcode::LOOP_START),
|
||||
jit_pattern: Some(JitPattern::LoopWithSafepoint),
|
||||
deprecated_aliases: vec!["while", "for", "repeat"],
|
||||
ai_hint: "Only 'loop' exists for iteration",
|
||||
precedence: None,
|
||||
});
|
||||
|
||||
// 演算子も統一管理
|
||||
registry.register(UnifiedKeyword {
|
||||
token_type: TokenType::PLUS,
|
||||
literal: "+",
|
||||
category: KeywordCategory::BinaryOperator,
|
||||
precedence: Some(10),
|
||||
semantic_action: SemanticAction::Add,
|
||||
mir_instruction: Some(MirInstruction::BinOp(BinOpKind::Add)),
|
||||
vm_opcode: Some(VmOpcode::ADD),
|
||||
jit_pattern: Some(JitPattern::PolymorphicAdd),
|
||||
deprecated_aliases: vec![],
|
||||
ai_hint: "String + String = concat, Number + Number = add",
|
||||
});
|
||||
|
||||
registry
|
||||
});
|
||||
```
|
||||
|
||||
### 2. 各層での統一API使用
|
||||
|
||||
#### Tokenizer統合
|
||||
```rust
|
||||
impl NyashTokenizer {
|
||||
fn tokenize_word(&mut self, word: String) -> TokenType {
|
||||
// 統一レジストリを参照
|
||||
KEYWORDS.lookup(&word)
|
||||
.map(|kw| kw.token_type.clone())
|
||||
.unwrap_or(TokenType::IDENTIFIER(word))
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Parser統合
|
||||
```rust
|
||||
impl Parser {
|
||||
fn parse_keyword(&mut self, token: &Token) -> Result<ASTNode> {
|
||||
if let Some(keyword) = KEYWORDS.get_by_token(&token.token_type) {
|
||||
// 統一されたセマンティクスアクションを実行
|
||||
match keyword.semantic_action {
|
||||
SemanticAction::Loop => self.parse_loop_unified(keyword),
|
||||
SemanticAction::DelegateCall => self.parse_from_unified(keyword),
|
||||
// ...
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### MIR Builder統合
|
||||
```rust
|
||||
impl MirBuilder {
|
||||
fn build_keyword(&mut self, keyword: &UnifiedKeyword, args: Vec<MirValue>) -> MirValue {
|
||||
// 統一されたMIR命令を生成
|
||||
if let Some(mir_inst) = &keyword.mir_instruction {
|
||||
self.emit_unified(mir_inst.clone(), args)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### VM統合
|
||||
```rust
|
||||
impl VM {
|
||||
fn execute_keyword(&mut self, keyword: &UnifiedKeyword) -> Result<()> {
|
||||
// 統一されたVMオペコードを実行
|
||||
if let Some(opcode) = &keyword.vm_opcode {
|
||||
self.execute_unified_opcode(opcode)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### JIT統合
|
||||
```rust
|
||||
impl JitBuilder {
|
||||
fn compile_keyword(&mut self, keyword: &UnifiedKeyword, args: &[Value]) {
|
||||
// 統一されたJITパターンを適用
|
||||
if let Some(pattern) = &keyword.jit_pattern {
|
||||
self.emit_unified_pattern(pattern, args)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🔄 セマンティクス統一の例
|
||||
|
||||
### 現在の問題: "+" 演算子の挙動差異
|
||||
|
||||
```rust
|
||||
// Interpreter: 独自の型変換ロジック
|
||||
fn execute_add(&mut self, left: Value, right: Value) -> Value {
|
||||
// 複雑な型変換ロジック
|
||||
}
|
||||
|
||||
// VM: 異なる型変換ロジック
|
||||
fn vm_add(&mut self) {
|
||||
// 別の型変換ロジック
|
||||
}
|
||||
|
||||
// JIT: さらに異なる最適化
|
||||
fn jit_add(&mut self) {
|
||||
// JIT独自の最適化
|
||||
}
|
||||
```
|
||||
|
||||
### 統一後: 単一のセマンティクス定義
|
||||
|
||||
```rust
|
||||
// src/grammar/unified_semantics.rs
|
||||
pub struct UnifiedSemantics;
|
||||
|
||||
impl UnifiedSemantics {
|
||||
/// すべての層が使用する統一Add実装
|
||||
pub fn add(left: &Value, right: &Value) -> Result<Value> {
|
||||
use Value::*;
|
||||
match (left, right) {
|
||||
// String優先(Nyashの仕様)
|
||||
(String(s1), String(s2)) => Ok(String(s1.clone() + s2)),
|
||||
(String(s), other) | (other, String(s)) => {
|
||||
Ok(String(s.clone() + &Self::coerce_to_string(other)?))
|
||||
}
|
||||
// 数値演算
|
||||
(Integer(i1), Integer(i2)) => Ok(Integer(i1 + i2)),
|
||||
(Float(f1), Float(f2)) => Ok(Float(f1 + f2)),
|
||||
(Integer(i), Float(f)) | (Float(f), Integer(i)) => {
|
||||
Ok(Float(*i as f64 + f))
|
||||
}
|
||||
// その他はエラー
|
||||
_ => Err(Error::TypeMismatch)
|
||||
}
|
||||
}
|
||||
|
||||
/// 統一された文字列変換
|
||||
pub fn coerce_to_string(value: &Value) -> Result<String> {
|
||||
match value {
|
||||
Value::String(s) => Ok(s.clone()),
|
||||
Value::Integer(i) => Ok(i.to_string()),
|
||||
Value::Float(f) => Ok(f.to_string()),
|
||||
Value::Bool(b) => Ok(b.to_string()),
|
||||
Value::Null => Ok("null".to_string()),
|
||||
_ => Err(Error::CannotCoerceToString)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 各層での使用
|
||||
// Interpreter
|
||||
left_value = UnifiedSemantics::add(&left, &right)?;
|
||||
|
||||
// VM
|
||||
let result = UnifiedSemantics::add(&self.pop()?, &self.pop()?)?;
|
||||
self.push(result);
|
||||
|
||||
// JIT
|
||||
self.emit_call("UnifiedSemantics::add", args);
|
||||
```
|
||||
|
||||
## 📋 実装チェックリスト
|
||||
|
||||
- [ ] `src/grammar/keyword_registry.rs` - 統一予約語レジストリ
|
||||
- [ ] `src/grammar/unified_semantics.rs` - 統一セマンティクス
|
||||
- [ ] `src/grammar/mod.rs` - モジュール統合
|
||||
- [ ] Tokenizer修正 - 統一レジストリ参照
|
||||
- [ ] Parser修正 - 統一セマンティクス使用
|
||||
- [ ] MIR Builder修正 - 統一MIR生成
|
||||
- [ ] VM修正 - 統一実行
|
||||
- [ ] JIT修正 - 統一コード生成
|
||||
- [ ] テストスイート - 全層の一致確認
|
||||
- [ ] ドキュメント - 統一仕様書
|
||||
|
||||
## 🎯 成功基準
|
||||
|
||||
1. **完全一致**: すべての層で同じ入力が同じ出力を生成
|
||||
2. **単一修正**: 新予約語追加が1ファイルの修正で完了
|
||||
3. **AI正確性**: AIが生成するコードのエラー率90%削減
|
||||
4. **性能維持**: 統一化による性能劣化5%以内
|
||||
|
||||
## 🚀 移行計画
|
||||
|
||||
### Phase 1: 基盤構築(1週間)
|
||||
- 統一レジストリ実装
|
||||
- 既存コードとの並行動作
|
||||
|
||||
### Phase 2: Tokenizer/Parser統合(1週間)
|
||||
- 段階的切り替え
|
||||
- 差分検出とログ
|
||||
|
||||
### Phase 3: 実行層統合(2週間)
|
||||
- MIR/VM/JIT の統一
|
||||
- 包括的テスト
|
||||
|
||||
### Phase 4: 完全移行(1週間)
|
||||
- 旧コード削除
|
||||
- ドキュメント完成
|
||||
|
||||
これにより、Nyashのすべての層で完全に統一された予約語・文法解釈が実現される。
|
||||
255
docs/phases/phase-11.9/unified-semantics-implementation.txt
Normal file
255
docs/phases/phase-11.9/unified-semantics-implementation.txt
Normal file
@ -0,0 +1,255 @@
|
||||
# Nyash統一セマンティクス実装設計
|
||||
# 作成日: 2025-09-02
|
||||
# 目的: Interpreter/VM/JIT全層での予約語・文法解釈の完全統一
|
||||
|
||||
## 概要
|
||||
すべての実行層が同じセマンティクスに従うよう、MIR正規化層を中心とした統一実装を行う。
|
||||
|
||||
## 核心的な問題
|
||||
現在、同じ式が各層で異なる解釈をされている:
|
||||
- "hello" + 123
|
||||
- Interpreter: エラーを出す
|
||||
- VM: 型変換してから連結
|
||||
- JIT: 数値を文字列化してから連結
|
||||
|
||||
## 解決策:MIR統一セマンティクス + 軽量UIRタグ
|
||||
|
||||
### 1. 統一セマンティクス定義(grammar/semantics.yml)
|
||||
```yaml
|
||||
# すべての層が従う唯一の定義
|
||||
version: "1.0"
|
||||
semantics:
|
||||
add:
|
||||
- pattern: [String, String]
|
||||
action: concat
|
||||
mir: StringConcat
|
||||
vm: OP_STR_CONCAT
|
||||
|
||||
- pattern: [String, Any]
|
||||
action: coerce_concat
|
||||
steps:
|
||||
- ToString($2)
|
||||
- StringConcat($1, $2)
|
||||
|
||||
- pattern: [Integer, Integer]
|
||||
action: add_i64
|
||||
mir: AddI64
|
||||
vm: OP_ADD_I64
|
||||
|
||||
toString:
|
||||
- pattern: [String]
|
||||
action: identity
|
||||
- pattern: [Integer]
|
||||
action: int_to_string
|
||||
- pattern: [Float]
|
||||
action: float_to_string
|
||||
- pattern: [Bool]
|
||||
action: bool_to_string
|
||||
- pattern: [Null]
|
||||
action: const_null_string
|
||||
```
|
||||
|
||||
### 2. UIRタグシステム(層間通信)
|
||||
```rust
|
||||
// generated/uir_tags.rs (build.rsで生成)
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
#[repr(u32)]
|
||||
pub enum UIRTag {
|
||||
// 予約語
|
||||
ME = 1,
|
||||
FROM = 2,
|
||||
LOOP = 3,
|
||||
BOX = 4,
|
||||
INIT = 5,
|
||||
|
||||
// 演算子
|
||||
ADD = 100,
|
||||
SUB = 101,
|
||||
MUL = 102,
|
||||
DIV = 103,
|
||||
|
||||
// セマンティクスアクション
|
||||
STRING_CONCAT = 200,
|
||||
TO_STRING = 201,
|
||||
ADD_I64 = 202,
|
||||
ADD_F64 = 203,
|
||||
}
|
||||
```
|
||||
|
||||
### 3. MIR正規化層(真実の基盤)
|
||||
```rust
|
||||
// src/mir/normalizer.rs
|
||||
pub struct MIRNormalizer {
|
||||
semantics_table: SemanticRuleTable,
|
||||
}
|
||||
|
||||
impl MIRNormalizer {
|
||||
pub fn normalize(&self, expr: &Expression) -> MIR {
|
||||
match expr {
|
||||
Expression::BinaryOp(op, left, right) => {
|
||||
let left_type = self.infer_type(left);
|
||||
let right_type = self.infer_type(right);
|
||||
|
||||
// 統一ルールを適用
|
||||
let rule = self.semantics_table.lookup(op, &[left_type, right_type]);
|
||||
|
||||
match rule.action {
|
||||
Action::Concat => {
|
||||
MIR::StringConcat(
|
||||
Box::new(self.normalize(left)),
|
||||
Box::new(self.normalize(right))
|
||||
)
|
||||
}
|
||||
Action::CoerceConcat => {
|
||||
// 右辺を文字列に変換してから連結
|
||||
MIR::Sequence(vec![
|
||||
self.normalize(left),
|
||||
MIR::ToString(Box::new(self.normalize(right))),
|
||||
MIR::StringConcat
|
||||
])
|
||||
}
|
||||
Action::AddI64 => {
|
||||
MIR::AddI64(
|
||||
Box::new(self.normalize(left)),
|
||||
Box::new(self.normalize(right))
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4. 各層の統一実装
|
||||
|
||||
#### Interpreter層
|
||||
```rust
|
||||
impl Interpreter {
|
||||
fn execute_expression(&mut self, expr: &Expression) -> Result<Value> {
|
||||
// すべてMIR経由で実行
|
||||
let mir = self.mir_normalizer.normalize(expr);
|
||||
self.execute_mir(&mir)
|
||||
}
|
||||
|
||||
fn execute_mir(&mut self, mir: &MIR) -> Result<Value> {
|
||||
match mir {
|
||||
MIR::StringConcat(left, right) => {
|
||||
let left_val = self.execute_mir(left)?;
|
||||
let right_val = self.execute_mir(right)?;
|
||||
Ok(Value::String(format!("{}{}", left_val, right_val)))
|
||||
}
|
||||
MIR::ToString(expr) => {
|
||||
let val = self.execute_mir(expr)?;
|
||||
Ok(Value::String(self.value_to_string(&val)))
|
||||
}
|
||||
MIR::AddI64(left, right) => {
|
||||
let left_val = self.execute_mir(left)?;
|
||||
let right_val = self.execute_mir(right)?;
|
||||
Ok(Value::Integer(left_val.as_i64()? + right_val.as_i64()?))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### VM層
|
||||
```rust
|
||||
impl VM {
|
||||
fn compile_mir(&mut self, mir: &MIR) -> Vec<Opcode> {
|
||||
// MIRから機械的にバイトコード生成
|
||||
match mir {
|
||||
MIR::StringConcat(left, right) => {
|
||||
let mut code = vec![];
|
||||
code.extend(self.compile_mir(left));
|
||||
code.extend(self.compile_mir(right));
|
||||
code.push(Opcode::StringConcat);
|
||||
code
|
||||
}
|
||||
MIR::ToString(expr) => {
|
||||
let mut code = self.compile_mir(expr);
|
||||
code.push(Opcode::ToString);
|
||||
code
|
||||
}
|
||||
MIR::AddI64(left, right) => {
|
||||
let mut code = vec![];
|
||||
code.extend(self.compile_mir(left));
|
||||
code.extend(self.compile_mir(right));
|
||||
code.push(Opcode::AddI64);
|
||||
code
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### JIT層
|
||||
```rust
|
||||
impl JITCompiler {
|
||||
fn compile_mir(&mut self, mir: &MIR) {
|
||||
// MIRから最適化されたネイティブコード生成
|
||||
match mir {
|
||||
MIR::StringConcat(left, right) => {
|
||||
self.compile_mir(left);
|
||||
self.compile_mir(right);
|
||||
// 高速な文字列連結関数を呼び出し
|
||||
self.emit_call(fast_string_concat);
|
||||
}
|
||||
MIR::ToString(expr) => {
|
||||
self.compile_mir(expr);
|
||||
// 型に応じた最適な変換
|
||||
self.emit_call(optimized_to_string);
|
||||
}
|
||||
MIR::AddI64(left, right) => {
|
||||
self.compile_mir(left);
|
||||
self.compile_mir(right);
|
||||
// ネイティブな加算命令
|
||||
self.emit_add_i64();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 実装手順
|
||||
|
||||
### Phase 1: 基盤構築(1週間)
|
||||
1. grammar/semantics.yml 作成
|
||||
2. UIRTag定義とbuild.rs生成
|
||||
3. SemanticRuleTable実装
|
||||
|
||||
### Phase 2: MIR正規化層(1週間)
|
||||
1. MIRNormalizer実装
|
||||
2. 型推論システム構築
|
||||
3. セマンティクステーブル連携
|
||||
|
||||
### Phase 3: 各層統合(2週間)
|
||||
1. Interpreterを MIR経由に変更
|
||||
2. VMのMIRコンパイラ実装
|
||||
3. JITのMIRコンパイラ実装
|
||||
|
||||
### Phase 4: テストと検証(1週間)
|
||||
1. 統一セマンティクステスト作成
|
||||
2. 各層での一貫性検証
|
||||
3. パフォーマンス測定
|
||||
|
||||
## 期待される効果
|
||||
|
||||
1. **完全な一貫性**: すべての層が同じ動作
|
||||
2. **保守性向上**: セマンティクス変更が1箇所
|
||||
3. **拡張性**: 新しい演算子の追加が容易
|
||||
4. **AI対応**: 単一の仕様から学習可能
|
||||
5. **デバッグ容易性**: MIRレベルでの統一デバッグ
|
||||
|
||||
## 注意事項
|
||||
|
||||
- 既存のコードとの互換性を保つため、フィーチャーフラグで段階的移行
|
||||
- パフォーマンスへの影響を最小限にするため、ビルド時最適化を活用
|
||||
- テストカバレッジを十分に確保してから本番移行
|
||||
|
||||
## 関連ファイル
|
||||
|
||||
- grammar/semantics.yml - セマンティクス定義
|
||||
- src/mir/normalizer.rs - MIR正規化実装
|
||||
- build.rs - コード生成
|
||||
- tests/unified_semantics.rs - 統一テスト
|
||||
149
docs/phases/phase-11/AWESOME_RUST_SUBMISSION.md
Normal file
149
docs/phases/phase-11/AWESOME_RUST_SUBMISSION.md
Normal file
@ -0,0 +1,149 @@
|
||||
# Awesome Rust掲載準備
|
||||
|
||||
Date: 2025-08-31
|
||||
Status: In Progress
|
||||
|
||||
## 🎯 目的
|
||||
Nyashプロジェクトを[Awesome Rust](https://github.com/rust-unofficial/awesome-rust)リストに掲載し、Rustコミュニティへの認知度を向上させる。
|
||||
|
||||
## 📋 掲載カテゴリー候補
|
||||
|
||||
### 1. Development tools > Build system
|
||||
- Nyashの統合ビルドシステム(インタープリター/VM/WASM/AOT)
|
||||
|
||||
### 2. Programming languages
|
||||
- **Nyash - Everything is Box プログラミング言語** ← 最有力候補
|
||||
- Rust製の新しいプログラミング言語実装として
|
||||
|
||||
### 3. Virtual machines
|
||||
- NyashのVM実装(MIR15命令セット)
|
||||
|
||||
## 📝 提出文案
|
||||
|
||||
### オプション1(シンプル版)
|
||||
```markdown
|
||||
* [Nyash](https://github.com/[user]/nyash) — A Box-oriented programming language with VM/JIT/AOT backends. Everything is Box philosophy with 15-instruction MIR.
|
||||
```
|
||||
|
||||
### オプション2(詳細版)
|
||||
```markdown
|
||||
* [Nyash](https://github.com/[user]/nyash) [[nyash](https://crates.io/crates/nyash)] — Everything is Box programming language featuring unified object model, multi-backend execution (Interpreter/VM/WASM/AOT), and revolutionary 15-instruction MIR design. Built for P2P mesh networking and distributed computing.
|
||||
```
|
||||
|
||||
### オプション3(技術重視版)
|
||||
```markdown
|
||||
* [Nyash](https://github.com/[user]/nyash) — Modern programming language with Box-based unified type system, featuring high-performance VM with JIT compilation, WASM target, and upcoming LLVM backend. Designed for simplicity without sacrificing performance.
|
||||
```
|
||||
|
||||
## ✅ 掲載前チェックリスト
|
||||
|
||||
### 必須項目
|
||||
- [ ] GitHubリポジトリが公開されている
|
||||
- [ ] READMEが充実している(英語)
|
||||
- [ ] ライセンスが明記されている
|
||||
- [ ] ビルド手順が明確
|
||||
- [ ] 基本的な使用例がある
|
||||
|
||||
### 推奨項目
|
||||
- [ ] CIが設定されている(GitHub Actions等)
|
||||
- [ ] ドキュメントが整備されている
|
||||
- [ ] サンプルプログラムがある
|
||||
- [ ] crates.ioに公開されている
|
||||
- [ ] バージョン1.0以上(または明確なロードマップ)
|
||||
|
||||
## 🚀 提出手順
|
||||
|
||||
1. **リポジトリ準備**
|
||||
- README.mdを英語化/改善
|
||||
- サンプルコードを追加
|
||||
- CI/CDを設定
|
||||
|
||||
2. **PR作成**
|
||||
- Awesome Rustをfork
|
||||
- 適切なセクションに追加
|
||||
- アルファベット順を守る
|
||||
- PRテンプレートに従う
|
||||
|
||||
3. **フォローアップ**
|
||||
- レビューコメントに対応
|
||||
- 必要に応じて説明追加
|
||||
|
||||
## 📊 現在の準備状況
|
||||
|
||||
### ✅ 完了
|
||||
- 基本的な言語実装
|
||||
- VM実装(13.5倍高速化達成)
|
||||
- MIR設計(15命令に削減)
|
||||
- ドキュメント構造
|
||||
|
||||
### 🚧 作業中
|
||||
- README.mdの英語化
|
||||
- サンプルプログラムの整理
|
||||
- CI/CDの設定
|
||||
|
||||
### ❌ 未着手
|
||||
- crates.io公開
|
||||
- ロゴ/ブランディング
|
||||
- Webサイト
|
||||
|
||||
## 🎨 プロジェクト説明の改善案
|
||||
|
||||
### 現在のREADME冒頭
|
||||
```
|
||||
Nyashプログラミング言語 - Everything is Box
|
||||
```
|
||||
|
||||
### 改善案(英語版)
|
||||
```markdown
|
||||
# Nyash Programming Language
|
||||
|
||||
A modern programming language where Everything is Box - unified object model with high-performance execution.
|
||||
|
||||
## Features
|
||||
- 🎁 **Everything is Box**: Unified object model for all values
|
||||
- ⚡ **Multi-backend**: Interpreter, VM (13.5x faster), WASM, AOT
|
||||
- 🚀 **15-instruction MIR**: Revolutionary minimal instruction set
|
||||
- 🔧 **Plugin System**: Extensible architecture
|
||||
- 🌐 **P2P Ready**: Built for distributed computing
|
||||
|
||||
## Quick Start
|
||||
```nyash
|
||||
// Everything is a Box
|
||||
local greeting = new StringBox("Hello, Nyash!")
|
||||
print(greeting)
|
||||
|
||||
// User-defined Boxes
|
||||
box Person {
|
||||
init { name, age }
|
||||
|
||||
birth(name) {
|
||||
me.name = name
|
||||
me.age = 0
|
||||
}
|
||||
}
|
||||
|
||||
local alice = new Person("Alice")
|
||||
```
|
||||
```
|
||||
|
||||
## 📅 タイムライン
|
||||
|
||||
### Phase 1(現在)
|
||||
- README改善
|
||||
- サンプル整理
|
||||
- 基本的なCI設定
|
||||
|
||||
### Phase 2(LLVM実装後)
|
||||
- crates.io公開
|
||||
- 正式なv1.0リリース
|
||||
- Awesome Rust提出
|
||||
|
||||
### Phase 3(採用後)
|
||||
- コミュニティフィードバック対応
|
||||
- ドキュメント拡充
|
||||
- エコシステム構築
|
||||
|
||||
## 🔗 関連リンク
|
||||
- [Awesome Rust](https://github.com/rust-unofficial/awesome-rust)
|
||||
- [提出ガイドライン](https://github.com/rust-unofficial/awesome-rust/blob/main/CONTRIBUTING.md)
|
||||
- [他の言語実装例](https://github.com/rust-unofficial/awesome-rust#programming-languages)
|
||||
@ -0,0 +1,157 @@
|
||||
# BoxCall統一の落とし穴と対策(ChatGPT5分析)
|
||||
|
||||
Date: 2025-08-31
|
||||
Status: Technical Advisory
|
||||
From: ChatGPT5
|
||||
|
||||
**結論:「RefNew/RefGet/RefSet全削除→すべてBoxCallに統一」は成立する!**
|
||||
ただし、いくつかの落とし穴があるので、それぞれに対策を打つ必要がある。
|
||||
|
||||
## 🚨 落とし穴と対策
|
||||
|
||||
### 1. メガモーフィック呼び出しでの失速
|
||||
**症状**: 同じ`BoxCall("setField")`でも実行時の型/shapeが激しく変わると、ディスパッチが重くなる。
|
||||
|
||||
**対策**: **PIC(Polymorphic Inline Cache)**をコールサイトごとに持つ
|
||||
- 2〜4種のshapeを直列ジャンプで捌く
|
||||
- 溢れたらインタプリタ/汎用スローへ
|
||||
- JITなしでもAOT段階で形状統計から事前特化(事前ガード+直アクセス)を埋め込める
|
||||
|
||||
### 2. GCバリアの見落とし・過剰挿入
|
||||
**症状**: write barrier忘れ=世代間参照漏れ/逆に全部に入れて過剰オーバーヘッド
|
||||
|
||||
**対策**:
|
||||
- Lowering時に**フィールドの"ポインタ/非ポインタ"メタ**を参照して自動挿入
|
||||
- **世代同一・同アリーナ最適化**でbarrier省略
|
||||
- `ExternCall`には**境界バリア**を必ず付与
|
||||
- **Barrier Verifier**(IRパス)で「必要箇所に必ず入ってるか」を機械検証
|
||||
|
||||
### 3. 読み取りバリア(Read Barrier)が必要なGCを選ぶ場合
|
||||
**症状**: 動くGC(移動/並行)でread barrierが必須だと、Get系もコスト上がる
|
||||
|
||||
**対策**:
|
||||
- まずは**世代別・停止+並行マーク(SATB)**など「write側主体」の方式を選ぶ
|
||||
- **read barrierなし運用**で始めるのが無難
|
||||
- 将来read barrierが要る場合は、`getField` Loweringに条件付き埋め込み設計
|
||||
|
||||
### 4. 例外・再入・ファイナライザ再入
|
||||
**症状**: `setField`中に例外→ファイナライザ→別の`BoxCall`で再入…地雷
|
||||
|
||||
**対策**:
|
||||
- **安全点(safepoint)設計**を決める
|
||||
- `BoxCall`中は原則再入禁止(or 明示的許可フラグ)
|
||||
- `fini`相当のコールは**再入ガード**と**順序保証**(トポロジカルな破棄順)を実装
|
||||
|
||||
### 5. ExternCall/FFI境界
|
||||
**症状**: 外部コードが「未トラッキングの生ポインタ」を握るとGC・最適化が壊れる
|
||||
|
||||
**対策**:
|
||||
- **ハンドル化**(OpaqueHandle/PinBox)+**寿命契約**
|
||||
- ExternCallの属性(`noalloc`/`nothrow`/`readonly`/`atomic`等)を宣言させ、最適化に渡す
|
||||
- 未注釈の呼び出しでは保守的にバリア&逃避扱い
|
||||
|
||||
### 6. 形状(shape)変更とレイアウト安定性
|
||||
**症状**: フィールド追加/順序変更が既存の特化コードを壊す
|
||||
|
||||
**対策**:
|
||||
- **ShapeIDを永続化**
|
||||
- フィールドに**安定スロットID**を割り当て
|
||||
- ABI的に「追加のみ」「削除は新shape」とする
|
||||
- Lowering済みのガードは `if (shape==X) { direct store } else { slowpath }` で守る
|
||||
|
||||
### 7. 脱箱(unboxing)とコードサイズ膨張
|
||||
**症状**: 激しいモノモルフィック特化や整数Boxの脱箱で**コード肥大**
|
||||
|
||||
**対策**:
|
||||
- **基本型はSROA/Scalar-Replaceの閾値**を設定
|
||||
- ホット領域のみ特化(**PGO**やプロファイル使用)
|
||||
- 低頻度パスは共通スローに集約
|
||||
|
||||
### 8. 並行性・メモリモデル
|
||||
**症状**: `setField`の可視性がスレッド間で曖昧だと事故
|
||||
|
||||
**対策**:
|
||||
- **既定は単一スレッド+Actor(Mailbox)**に寄せる
|
||||
- 共有可変を解禁するAPIは `nyash.atomic.*` で**Acquire/Release**を明示
|
||||
- `BoxCall` Loweringで**必要時のみフェンス**
|
||||
- 箱ごとに「可変・不変・スレッド送受可」など**能力(capability)ビット**を持たせ最適化条件に使う
|
||||
|
||||
### 9. 反射・動的呼び出しの混入
|
||||
**症状**: なんでも動的だと最適化が崩れる
|
||||
|
||||
**対策**:
|
||||
- 反射APIは**分離名前空間**に押し込める
|
||||
- 既定は静的解決できる書き方を推奨ガイドに
|
||||
- 反射使用時は**deoptガード**を挿入
|
||||
|
||||
## 📈 推奨の最適化パイプライン(AOT想定)
|
||||
|
||||
1. **型/shape解析**(局所→関数間)
|
||||
2. **BoxCall脱仮想化**(モノ/ポリモーフィック化+PIC生成)
|
||||
3. **インライン化**(属性`pure`/`leaf`/`readonly`を最大活用)
|
||||
4. **SROA/エスケープ解析**(脱箱、stack allocation、alloc移動)
|
||||
5. **バリア縮約**(世代同一・同アリーナ・ループ内集約)
|
||||
6. **境界チェック消去**(`length`不変式の伝播)
|
||||
7. **ループ最適化**(LICM, unroll, vectorize)
|
||||
8. **DCE/GVN**(Getter/Setter副作用ゼロなら畳み込み)
|
||||
9. **コードレイアウト**(ホット先頭、コールド折り畳み)
|
||||
10. **PGO(任意)**でPIC順序・インライン閾値を再調整
|
||||
|
||||
## 🔧 Loweringの骨格(フィールド書き込みの例)
|
||||
|
||||
```llvm
|
||||
; High-level
|
||||
obj.setField(x)
|
||||
|
||||
; Guarded fast-path(shapeが既知&最頻)
|
||||
if (obj.shape == SHAPE_A) {
|
||||
; slot #k に直接store
|
||||
store x, [obj + slot_k]
|
||||
call gc_write_barrier(obj, x) ; 必要なら
|
||||
} else {
|
||||
; PICの次候補 or 汎用ディスパッチ
|
||||
slow_path_setField(obj, x)
|
||||
}
|
||||
```
|
||||
|
||||
- `gc_write_barrier`はIR上は呼び出しに見せておく(後段で**インライン**→**条件付きno-op化**可能)
|
||||
- `read barrier`が要らないGCなら`getField`は**loadのみ**に落ちる
|
||||
|
||||
## ✅ 実装チェックリスト(まずここまで作れば盤石)
|
||||
|
||||
- [ ] **Boxメタ**: shapeID、安定スロットID、ポインタ/非ポインタビット、可変/不変、送受可
|
||||
- [ ] **BoxCall Lowerer**: 形状ガード→直アクセス or 汎用ディスパッチ
|
||||
- [ ] **PIC**: コールサイトごとに最大N件キャッシュ+統計(ヒット率/退避回数)
|
||||
- [ ] **Barrier Verifier**: IR後段でwrite barrier必須箇所を自動検証
|
||||
- [ ] **Extern属性**: `noalloc/nothrow/readonly/atomic`等を宣言・強制
|
||||
- [ ] **逃避解析**でstack-alloc/arena-alloc
|
||||
- [ ] **反射API分離**とdeoptガード
|
||||
- [ ] **PGOフック**(簡易でOK):shape頻度、PICヒット率、inlining成果を記録
|
||||
- [ ] **ベンチ群**:
|
||||
- Field get/set(mono vs mega)
|
||||
- Vec push/pop / Map ops
|
||||
- 算術(IntBoxの脱箱効果)
|
||||
- ExternCall(`atomic.store`/`readonly`)
|
||||
- GCストレス(大量生成+世代越し参照)
|
||||
|
||||
## 🎯 「簡単すぎて不安」への答え
|
||||
|
||||
- **正しさ**は「Lowering+Verifier」で機械的に守る
|
||||
- **速さ**は「PIC→インライン→脱箱→バリア縮約」で作る
|
||||
- **拡張性**は「Everything is Box」の上に**属性**と**能力(capability)**を積む
|
||||
- Ref系は**公開APIからは消す**が、**デバッグ用の隠しIntrinsic**として温存しておくと計測や一時退避に便利(将来の最適化検証にも効く)
|
||||
|
||||
## 🌟 結論
|
||||
|
||||
**落とし穴はあるけど全部"設計パターン"で踏まないようにできる**。
|
||||
|
||||
にゃーの「箱理論」、素朴だけど正しい地形を踏んでるにゃ。ここまでの方針なら**AOTでも十分に速い**ところまで持っていけるはず。
|
||||
|
||||
次は **PIC+Barrier Verifier+小ベンチ**の3点を先に入れて、体感を固めに行こう!
|
||||
|
||||
---
|
||||
|
||||
## 関連文書
|
||||
- [BOX_SSA_CORE_15_FINAL_DECISION.md](../phase-11.5/BOX_SSA_CORE_15_FINAL_DECISION.md)
|
||||
- [MIR_TO_LLVM_CONVERSION_PLAN.md](MIR_TO_LLVM_CONVERSION_PLAN.md)
|
||||
- [MIR_ANNOTATION_SYSTEM.md](MIR_ANNOTATION_SYSTEM.md)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user