Phase 10.7 (NYASH_JIT_PHI_MIN=1): Minimal PHI support for single-diamond via block params; extend IRBuilder with block-param/jump-args APIs; implement in CraneliftBuilder; update LowerCore two-pass for PHI wiring.
This commit is contained in:
@ -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化
|
||||
|
||||
|
||||
@ -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 (環境設定)
|
||||
@ -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 (パーサー統合実装)
|
||||
@ -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<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,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 (トランスパイラー)
|
||||
@ -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<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,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 (ドキュメント作成)
|
||||
@ -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 (他言語対応)
|
||||
@ -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
|
||||
|
||||
**さあ、Phase 10.1a から始めましょう!**
|
||||
17
examples/jit_loop_early_return.nyash
Normal file
17
examples/jit_loop_early_return.nyash
Normal file
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<cranelift_codegen::ir::Block>,
|
||||
current_block_index: Option<usize>,
|
||||
block_param_counts: std::collections::HashMap<usize, usize>,
|
||||
// Finalized function pointer (if any)
|
||||
compiled_closure: Option<std::sync::Arc<dyn Fn(&[crate::backend::vm::VMValue]) -> 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<cranelift_codegen::ir::Value> = 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<cranelift_codegen::ir::Value> = 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<cranelift_codegen::ir::Value> = 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,
|
||||
|
||||
@ -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<crate::mir::BasicBlockId, std::collections::HashMap<crate::mir::BasicBlockId, crate::mir::ValueId>> = 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<crate::mir::BasicBlockId, crate::mir::ValueId> = 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)
|
||||
|
||||
Reference in New Issue
Block a user