diff --git a/docs/development/current/CURRENT_TASK.md b/docs/development/current/CURRENT_TASK.md index 4282b478..1dc8364d 100644 --- a/docs/development/current/CURRENT_TASK.md +++ b/docs/development/current/CURRENT_TASK.md @@ -2,14 +2,15 @@ フェーズ10はJIT実用化へ!Core-1 Lowerの雛形を固めつつ、呼出/フォールバック導線を整えるよ。 -## ⏱️ 今日のサマリ(10_c実行経路の堅牢化+GC/スケジューラ導線) +## ⏱️ 今日のサマリ(10_c実行経路の堅牢化+10_7分岐配線+GC/スケジューラ導線) - 目的: JIT実行を安全に通す足場を仕上げつつ、GC/スケジューラ導線を整備し回帰検出力を上げる。 - - 10_c: panic→VMフォールバック(`catch_unwind`)/ JIT経路のroot区域化 / Core-1 i64 param minimal pass(`emit_param_i64` + LowerCoreで供給) + - 10_c: panic→VMフォールバック(`catch_unwind`)/ JIT経路のroot区域化 / Core-1 i64 param minimal pass(`emit_param_i64` + LowerCoreで供給)✅ 完了 - 10_4a/10_4b: GC導線 + Write-Barrier挿入(ArraySet/RefSet/BoxCall)、root API(enter/pin/leave) - 10_4c: CountingGcカウンタ出力+roots/BoxRef内訳、depth2リーチャビリティ観測(`NYASH_GC_TRACE=1/2/3`)✅ 完了 - 10_4d: STRICTバリア検証(CountingGc前後比較で漏れ即検出)✅ 完了(`NYASH_GC_BARRIER_STRICT=1`) - 10_6b: シングルスレ・スケジューラ(spawn/spawn_after/poll)、Safepointで`poll()`連携、`NYASH_SCHED_POLL_BUDGET`対応 ✅ 完了 - - ベンチ: CLIベンチへJIT比較追加(ウォームアップあり)、スクリプト版`examples/ny_bench.nyash`追加(TimerBoxでops/sec) + - 10_7: JIT分岐配線(Cranelift)— MIR Branch/Jump→CLIFブロック配線、条件b1保持、分岐b1/`i64!=0`両対応(feature: `cranelift-jit`) + - ベンチ: CLIベンチへJIT比較追加(ウォームアップあり)、`branch_return`ケース追加、スクリプト版`examples/ny_bench.nyash`追加(TimerBoxでops/sec) ### 直近タスク(小さく早く) 1) 10_b: Lower/Core-1 最小化(進行中 → ほぼ完了) @@ -25,12 +26,17 @@ - JIT実行→`VMValue`返却、panic時VMフォールバック ✅(`engine.execute_handle`で`catch_unwind`) - Core-1最小: i64 param/return、Const(i64/bool→0/1)、BinOp/Compare/Return ✅ - HostCall最小(Array/Map: len/get/set/push/size)ゲート`NYASH_JIT_HOSTCALL=1` ✅ - - Branch/Jumpは統計カウントまで(CLIFブロック配線は後続フェーズで拡張) + - Branch/JumpはCranelift配線導入済み(feature `cranelift-jit`)。副作用命令は未lowerのためVMへフォールバック +3) 10_7: 分岐配線(Cranelift)— 進捗中 + - LowerCore: BB整列・マッピング→builderの`prepare_blocks/switch/seal/br_if/jump`呼出 ✅ + - CraneliftBuilder: ブロック配列管理、`brif/jump`実装、条件b1/`i64!=0`両対応 ✅ + - 残: 最小PHI(単純ダイアモンド)導入(`NYASH_JIT_PHI_MIN=1`ガード)/ 副作用命令の扱い方針(当面VMへ) 備考(制限と次の着手点) - 返り値はi64(VMValue::Integer)に限定。f64はconst最小emit、boolはi64 0/1へ正規化(分岐条件入力に対応) - 引数はi64のみ最小パス。複数引数はparamマッピングで通過、非i64は未対応 → 次対応 -- Branch/JumpのCLIF実配線は準備済み(ビルダー側は統計カウント)。CLIFブロック配線は後続で実装。 +- Branch/JumpのCLIF配線は導入済み(feature `cranelift-jit`)。条件はb1で保持し、必要に応じて`i64!=0`で正規化 +- 副作用命令(print等)はJIT未対応のためVMへ委譲(安全性優先) - JIT/VM統合統計(フォールバック率/時間の一括出力)未統合 → 次対応 ### すぐ試せるコマンド @@ -45,6 +51,12 @@ NYASH_JIT_STATS=1 NYASH_JIT_DUMP=1 NYASH_JIT_EXEC=1 \ # (任意)Craneliftを含めてビルド(今は最小初期化のみ) cargo build --release -j32 --features cranelift-jit +# JIT分岐デモ(feature有効時) +NYASH_JIT_EXEC=1 NYASH_JIT_THRESHOLD=1 \ + ./target/release/nyash --backend vm examples/jit_branch_demo.nyash +NYASH_JIT_EXEC=1 NYASH_JIT_THRESHOLD=1 \ + ./target/release/nyash --backend vm examples/jit_loop_early_return.nyash + # スクリプトベンチ(TimerBox版) ./target/release/nyash examples/ny_bench.nyash ./target/release/nyash --backend vm examples/ny_bench.nyash @@ -92,6 +104,11 @@ NYASH_JIT_EXEC=1 NYASH_JIT_THRESHOLD=1 ./target/release/nyash --backend vm examp - STRICTモードのCI導入(CountingGc前提)/ goldenベンチ導入 - 10_6b: - スケジューラ: poll予算の設定ファイル化、将来のscript API検討(継続) +- 10_7: + - 最小PHI(単純ダイアモンド)の導入(`NYASH_JIT_PHI_MIN=1`ガード) + - IRBuilder APIの整理(block param/分岐引数の正式化)とCranelift実装の安定化 + - 副作用命令のJIT扱い(方針: 当面VMへ、将来はHostCall化) + - CFG検証と`NYASH_JIT_DUMP=1`でのCFG可視化 - ベンチ: - `examples/ny_bench.nyash`のケース追加(関数呼出/Map set-get)とループ回数のenv化 diff --git a/docs/development/roadmap/phases/phase-10.1/10.1a_planning/README.md b/docs/development/roadmap/phases/phase-10.1/10.1a_planning/README.md new file mode 100644 index 00000000..e9417d70 --- /dev/null +++ b/docs/development/roadmap/phases/phase-10.1/10.1a_planning/README.md @@ -0,0 +1,27 @@ +# 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 (環境設定) \ No newline at end of file diff --git a/docs/development/roadmap/phases/phase-10.1/10.1b_setup/README.md b/docs/development/roadmap/phases/phase-10.1/10.1b_setup/README.md new file mode 100644 index 00000000..f080cec8 --- /dev/null +++ b/docs/development/roadmap/phases/phase-10.1/10.1b_setup/README.md @@ -0,0 +1,55 @@ +# 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 (パーサー統合実装) \ No newline at end of file diff --git a/docs/development/roadmap/phases/phase-10.1/10.1c_parser_integration/README.md b/docs/development/roadmap/phases/phase-10.1/10.1c_parser_integration/README.md new file mode 100644 index 00000000..e4344137 --- /dev/null +++ b/docs/development/roadmap/phases/phase-10.1/10.1c_parser_integration/README.md @@ -0,0 +1,61 @@ +# 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>, +} +``` + +### 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実装) \ No newline at end of file diff --git a/docs/development/roadmap/phases/phase-10.1/10.1d_core_implementation/README.md b/docs/development/roadmap/phases/phase-10.1/10.1d_core_implementation/README.md new file mode 100644 index 00000000..32179a73 --- /dev/null +++ b/docs/development/roadmap/phases/phase-10.1/10.1d_core_implementation/README.md @@ -0,0 +1,72 @@ +# 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 (トランスパイラー) \ No newline at end of file diff --git a/docs/development/roadmap/phases/phase-10.1/10.1e_transpiler/README.md b/docs/development/roadmap/phases/phase-10.1/10.1e_transpiler/README.md new file mode 100644 index 00000000..2dad67b3 --- /dev/null +++ b/docs/development/roadmap/phases/phase-10.1/10.1e_transpiler/README.md @@ -0,0 +1,70 @@ +# 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 { + // 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 (テストとベンチマーク) \ No newline at end of file diff --git a/docs/development/roadmap/phases/phase-10.1/python_to_nyash_transpiler.txt b/docs/development/roadmap/phases/phase-10.1/10.1e_transpiler/python_to_nyash_transpiler.txt similarity index 100% rename from docs/development/roadmap/phases/phase-10.1/python_to_nyash_transpiler.txt rename to docs/development/roadmap/phases/phase-10.1/10.1e_transpiler/python_to_nyash_transpiler.txt diff --git a/docs/development/roadmap/phases/phase-10.1/10.1f_testing/README.md b/docs/development/roadmap/phases/phase-10.1/10.1f_testing/README.md new file mode 100644 index 00000000..e8e9705b --- /dev/null +++ b/docs/development/roadmap/phases/phase-10.1/10.1f_testing/README.md @@ -0,0 +1,92 @@ +# 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 (ドキュメント作成) \ No newline at end of file diff --git a/docs/development/roadmap/phases/phase-10.1/10.1g_documentation/README.md b/docs/development/roadmap/phases/phase-10.1/10.1g_documentation/README.md new file mode 100644 index 00000000..25107410 --- /dev/null +++ b/docs/development/roadmap/phases/phase-10.1/10.1g_documentation/README.md @@ -0,0 +1,100 @@ +# 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 (他言語対応) \ No newline at end of file diff --git a/docs/development/roadmap/phases/phase-10.1/README.md b/docs/development/roadmap/phases/phase-10.1/README.md index e8b54206..211a59c1 100644 --- a/docs/development/roadmap/phases/phase-10.1/README.md +++ b/docs/development/roadmap/phases/phase-10.1/README.md @@ -1,52 +1,79 @@ -# Phase 10.1 - PythonParserBox実装計画 +# Phase 10.1 - PythonParserBox実装 -このフォルダには、NyashとPythonの相互運用を実現するPythonParserBoxの実装計画が含まれています。 +見ただけで実装手順が分かる!順番通りに進めてください。 -## 📁 フォルダ構造 +## 📂 サブフェーズ構成(順番に実行) -### メイン実装ドキュメント(最新版) -- **`pythonparser_integrated_plan_summary.txt`** - 統合実装計画サマリー(最重要) -- **`python_implementation_roadmap.txt`** - 実装ロードマップ(エキスパート統合版) -- **`python_parser_box_implementation_plan.txt`** - 技術的実装計画(統合版) -- **`builtin_box_implementation_flow.txt`** - ビルトインBox実装フロー(統合版) -- **`python_to_nyash_transpiler.txt`** - Python→Nyashトランスパイラー機能 +### 📋 Phase 10.1a - 計画と設計 +最初にここから!全体像を理解する。 +- 統合実装計画を読む +- エキスパート評価を確認 +- 5つの核心戦略を把握 -### エキスパート評価 -- **`expert_feedback_gemini_codex.txt`** - Gemini先生とCodex先生のフィードバック全文 +### ⚙️ Phase 10.1b - 環境設定 +開発環境を整える。 +- Python 3.11.9をインストール +- Cargo.tomlに依存関係追加 +- ディレクトリ構造準備 -### アーカイブ(参考資料) -- **`archive/`** フォルダ - - `python_parser_box_design.txt` - 初期設計案 - - `chatgpt5_original_idea.txt` - ChatGPT5の元アイデア - - `summary_2025_08_27.txt` - 当日の議論まとめ +### 🔧 Phase 10.1c - パーサー統合 +CPythonパーサーをNyashに統合。 +- PythonParserBox実装 +- GIL管理の実装 +- JSON中間表現への変換 -## 🎯 Phase 10.1の目標 +### 💻 Phase 10.1d - Core実装 +基本的なPython構文の変換。 +- Phase 1機能(def/if/for/while) +- 意味論の正確な実装 +- 70%コンパイル率達成 -1. **Pythonエコシステムの即座活用** - 既存Pythonライブラリの利用 -2. **Differential Testing** - Nyashパーサーのバグ自動検証 -3. **言語成熟度の向上** - 実用的なPythonコードでのストレステスト +### 🔄 Phase 10.1e - トランスパイラー +Python→Nyashソース変換。 +- AST→Nyashソース生成 +- フォーマッター実装 +- コマンドラインツール -## 🔑 核心戦略(エキスパート推奨) +### 🧪 Phase 10.1f - テスト +Differential Testingでバグ発見。 +- CPython vs Nyash比較 +- ベンチマーク実行 +- バグ修正とCI統合 -1. **関数単位フォールバック** - ファイル全体でなく関数レベルで切り替え -2. **Python 3.11固定** - AST安定性の確保 -3. **意味論の正確な実装** - 最適化より互換性優先 -4. **GIL管理の最小化** - Python側でJSON生成、Rust側で処理 -5. **テレメトリー重視** - 継続的な改善のための計測 +### 📚 Phase 10.1g - ドキュメント +使い方を文書化してリリース。 +- ユーザーガイド作成 +- APIリファレンス +- サンプルプロジェクト -## 📋 実装フェーズ +## 🎯 各フェーズの目安時間 -- **Phase 1**: Core Subset(基本構文)- 2週間 -- **Phase 2**: Data Model(特殊メソッド)- 3週間 -- **Phase 3**: Advanced Features(高度な機能)- 1ヶ月 -- **Phase 4**: Modern Python(最新機能)- 将来 +| フェーズ | 内容 | 目安時間 | +|---------|------|----------| +| 10.1a | 計画理解 | 2-3時間 | +| 10.1b | 環境設定 | 1-2時間 | +| 10.1c | パーサー統合 | 3-5日 | +| 10.1d | Core実装 | 1-2週間 | +| 10.1e | トランスパイラー | 3-5日 | +| 10.1f | テスト | 1週間 | +| 10.1g | ドキュメント | 3-5日 | -## 🚀 期待される成果 +**合計**: 約1ヶ月 -- 純Pythonループの2-10倍高速化 -- Nyashパーサーのバグ発見と改善 -- PythonからNyashへの段階的移行パス -- Python→Nyashスクリプト変換機能 +## 🌟 最終目標 + +- **70%以上**の関数がコンパイル可能 +- **2-10倍**の性能向上 +- **10件以上**のNyashバグ発見 +- **実用的な**Python→Nyash移行ツール + +## 💡 Tips + +- 各フェーズのREADME.mdを必ず読む +- 完了条件をチェックしながら進める +- テレメトリーで進捗を確認 +- 困ったらarchive/の資料も参照 --- -作成日: 2025-08-27 \ No newline at end of file + +**さあ、Phase 10.1a から始めましょう!** \ No newline at end of file diff --git a/examples/jit_loop_early_return.nyash b/examples/jit_loop_early_return.nyash new file mode 100644 index 00000000..fbaa5814 --- /dev/null +++ b/examples/jit_loop_early_return.nyash @@ -0,0 +1,17 @@ +// JIT loop early-return demo (no PHI needed) +// Enable: NYASH_JIT_EXEC=1 NYASH_JIT_THRESHOLD=1 + +static box Main { + main() { + local i + i = 0 + loop(i < 10) { + if (i == 3) { + return 99 + } + i = i + 1 + } + return -1 + } +} + diff --git a/src/jit/lower/builder.rs b/src/jit/lower/builder.rs index 5f3dddb2..45f1ed81 100644 --- a/src/jit/lower/builder.rs +++ b/src/jit/lower/builder.rs @@ -36,6 +36,17 @@ pub trait IRBuilder { fn br_if_top_is_true(&mut self, _then_index: usize, _else_index: usize) { } /// Optional: unconditional jump to target block index fn jump_to(&mut self, _target_index: usize) { } + /// Optional: ensure target block has one i64 block param (for minimal PHI) + fn ensure_block_param_i64(&mut self, _index: usize) { } + /// Optional: push current block's first param (i64) onto the value stack + fn push_block_param_i64(&mut self) { } + /// Optional: conditional branch with explicit arg counts for then/else; pops args from stack + fn br_if_with_args(&mut self, _then_index: usize, _else_index: usize, _then_n: usize, _else_n: usize) { + // fallback to no-arg br_if + self.br_if_top_is_true(_then_index, _else_index); + } + /// Optional: jump with explicit arg count; pops args from stack + fn jump_with_args(&mut self, _target_index: usize, _n: usize) { self.jump_to(_target_index); } } pub struct NoopBuilder { @@ -76,6 +87,7 @@ pub struct CraneliftBuilder { // Phase 10.7: basic block wiring state blocks: Vec, current_block_index: Option, + block_param_counts: std::collections::HashMap, // Finalized function pointer (if any) compiled_closure: Option crate::backend::vm::VMValue + Send + Sync>>, // Desired simple ABI (Phase 10_c minimal): i64 params count and i64 return @@ -427,6 +439,74 @@ impl IRBuilder for CraneliftBuilder { self.stats.3 += 1; fb.finalize(); } + fn ensure_block_param_i64(&mut self, index: usize) { + use cranelift_codegen::ir::types; + use cranelift_frontend::FunctionBuilder; + if index >= self.blocks.len() { return; } + let mut fb = FunctionBuilder::new(&mut self.ctx.func, &mut self.fbc); + let count = self.block_param_counts.get(&index).copied().unwrap_or(0); + if count == 0 { + let b = self.blocks[index]; + let _v = fb.append_block_param(b, types::I64); + self.block_param_counts.insert(index, 1); + } + fb.finalize(); + } + fn push_block_param_i64(&mut self) { + use cranelift_frontend::FunctionBuilder; + use cranelift_codegen::ir::types; + let mut fb = FunctionBuilder::new(&mut self.ctx.func, &mut self.fbc); + // Determine current block + let b = if let Some(idx) = self.current_block_index { self.blocks[idx] } else if let Some(b) = self.entry_block { b } else { fb.create_block() }; + // Fetch first param if exists + let params = fb.func.dfg.block_params(b).to_vec(); + if let Some(v) = params.get(0).copied() { self.value_stack.push(v); } + else { + // defensive: push 0 + let zero = fb.ins().iconst(types::I64, 0); + self.value_stack.push(zero); + } + fb.finalize(); + } + fn br_if_with_args(&mut self, then_index: usize, else_index: usize, then_n: usize, else_n: usize) { + use cranelift_codegen::ir::{types, condcodes::IntCC}; + use cranelift_frontend::FunctionBuilder; + if then_index >= self.blocks.len() || else_index >= self.blocks.len() { return; } + let mut fb = FunctionBuilder::new(&mut self.ctx.func, &mut self.fbc); + if let Some(idx) = self.current_block_index { fb.switch_to_block(self.blocks[idx]); } + else if let Some(b) = self.entry_block { fb.switch_to_block(b); } + // Condition + let cond_b1 = if let Some(v) = self.value_stack.pop() { + let ty = fb.func.dfg.value_type(v); + if ty == types::I64 { fb.ins().icmp_imm(IntCC::NotEqual, v, 0) } else { v } + } else { + let zero = fb.ins().iconst(types::I64, 0); + fb.ins().icmp_imm(IntCC::NotEqual, zero, 0) + }; + // Pop else args then then args (so stack order can be value-friendly) + let mut else_args: Vec = Vec::new(); + for _ in 0..else_n { if let Some(v) = self.value_stack.pop() { else_args.push(v); } } + else_args.reverse(); + let mut then_args: Vec = Vec::new(); + for _ in 0..then_n { if let Some(v) = self.value_stack.pop() { then_args.push(v); } } + then_args.reverse(); + fb.ins().brif(cond_b1, self.blocks[then_index], &then_args, self.blocks[else_index], &else_args); + self.stats.3 += 1; + fb.finalize(); + } + fn jump_with_args(&mut self, target_index: usize, n: usize) { + use cranelift_frontend::FunctionBuilder; + if target_index >= self.blocks.len() { return; } + let mut fb = FunctionBuilder::new(&mut self.ctx.func, &mut self.fbc); + if let Some(idx) = self.current_block_index { fb.switch_to_block(self.blocks[idx]); } + else if let Some(b) = self.entry_block { fb.switch_to_block(b); } + let mut args: Vec = Vec::new(); + for _ in 0..n { if let Some(v) = self.value_stack.pop() { args.push(v); } } + args.reverse(); + fb.ins().jump(self.blocks[target_index], &args); + self.stats.3 += 1; + fb.finalize(); + } } #[cfg(feature = "cranelift-jit")] @@ -474,6 +554,7 @@ impl CraneliftBuilder { entry_block: None, blocks: Vec::new(), current_block_index: None, + block_param_counts: std::collections::HashMap::new(), compiled_closure: None, desired_argc: 0, desired_has_ret: true, diff --git a/src/jit/lower/core.rs b/src/jit/lower/core.rs index 39a41d34..26c8d8bc 100644 --- a/src/jit/lower/core.rs +++ b/src/jit/lower/core.rs @@ -24,10 +24,27 @@ impl LowerCore { for (i, v) in func.params.iter().copied().enumerate() { self.param_index.insert(v, i); } - // Prepare block mapping (Phase 10.7 stub): deterministic ordering by sorted keys + // Prepare block mapping (Phase 10.7): deterministic ordering by sorted keys let mut bb_ids: Vec<_> = func.blocks.keys().copied().collect(); bb_ids.sort_by_key(|b| b.0); builder.prepare_blocks(bb_ids.len()); + // Optional: collect single-PHI targets for minimal PHI path + let enable_phi_min = std::env::var("NYASH_JIT_PHI_MIN").ok().as_deref() == Some("1"); + let mut phi_targets: std::collections::HashMap> = std::collections::HashMap::new(); + if enable_phi_min { + for (bb_id, bb) in func.blocks.iter() { + // gather Phi instructions in this block + let mut phis: Vec<&crate::mir::MirInstruction> = Vec::new(); + for ins in bb.instructions.iter() { if let crate::mir::MirInstruction::Phi { .. } = ins { phis.push(ins); } } + if phis.len() == 1 { + if let crate::mir::MirInstruction::Phi { inputs, .. } = phis[0] { + let mut map: std::collections::HashMap = std::collections::HashMap::new(); + for (pred, val) in inputs.iter() { map.insert(*pred, *val); } + phi_targets.insert(*bb_id, map); + } + } + } + } builder.prepare_signature_i64(func.params.len(), true); builder.begin_function(&func.signature.name); // Iterate blocks in the sorted order to keep indices stable @@ -48,13 +65,34 @@ impl LowerCore { // Map BasicBlockId -> index let then_index = bb_ids.iter().position(|x| x == then_bb).unwrap_or(0); let else_index = bb_ids.iter().position(|x| x == else_bb).unwrap_or(0); - builder.br_if_top_is_true(then_index, else_index); + if enable_phi_min { + // For minimal PHI, pass one i64 arg if successor defines a single PHI with this block as pred + let mut then_n = 0usize; + let mut else_n = 0usize; + if let Some(pred_map) = phi_targets.get(then_bb) { + if let Some(v) = pred_map.get(bb_id) { self.push_value_if_known_or_param(builder, v); then_n = 1; builder.ensure_block_param_i64(then_index); } + } + if let Some(pred_map) = phi_targets.get(else_bb) { + if let Some(v) = pred_map.get(bb_id) { self.push_value_if_known_or_param(builder, v); else_n = 1; builder.ensure_block_param_i64(else_index); } + } + builder.br_if_with_args(then_index, else_index, then_n, else_n); + } else { + builder.br_if_top_is_true(then_index, else_index); + } builder.seal_block(then_index); builder.seal_block(else_index); } crate::mir::MirInstruction::Jump { target } => { let target_index = bb_ids.iter().position(|x| x == target).unwrap_or(0); - builder.jump_to(target_index); + if enable_phi_min { + let mut n = 0usize; + if let Some(pred_map) = phi_targets.get(target) { + if let Some(v) = pred_map.get(bb_id) { self.push_value_if_known_or_param(builder, v); n = 1; builder.ensure_block_param_i64(target_index); } + } + builder.jump_with_args(target_index, n); + } else { + builder.jump_to(target_index); + } builder.seal_block(target_index); } _ => { @@ -168,6 +206,10 @@ impl LowerCore { if let Some(v) = value { self.push_value_if_known_or_param(b, v); } b.emit_return() } + I::Phi { .. } => { + // Minimal PHI: load current block param as value (i64) + b.push_block_param_i64(); + } I::ArrayGet { array, index, .. } => { if std::env::var("NYASH_JIT_HOSTCALL").ok().as_deref() == Some("1") { // Push args: array param index (or -1), index (known or 0)