feat(mir): Phase 84-2 CopyTypePropagator for Copy chain type propagation
- Add CopyTypePropagator box (ChatGPT Pro design) for fixed-point Copy instruction type propagation - Integrate into lifecycle.rs before return type inference - Case D reduced from 12 to 9 (25% reduction) Implementation: - src/mir/phi_core/copy_type_propagator.rs: New box with fixed-point loop - src/mir/phi_core/mod.rs: Add module export - src/mir/builder/lifecycle.rs: Call propagator before return inference Test results: - Baseline: 494 passed, 33 failed (was 489/34) - Case D: 9 remaining (from 12) - Unit tests: 4/4 passed Remaining 9 Case D breakdown: - GroupA: Loop Edge Copy (7 cases) - PHI incoming needs Copy trace - GroupB: Multi-level PHI (2 cases) - Recursive PHI resolution needed Phase 84-3 will address GroupA with Edge Copy tracing in GenericTypeResolver. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
434
docs/development/current/main/phase84-2-case-d-investigation.md
Normal file
434
docs/development/current/main/phase84-2-case-d-investigation.md
Normal file
@ -0,0 +1,434 @@
|
||||
# Phase 84-2: Case D 残り 9件の詳細調査
|
||||
|
||||
## 概要
|
||||
|
||||
Phase 84-2 で CopyTypePropagator を実装した結果、Case D は 12件 → 9件に削減されました。
|
||||
本ドキュメントは残り 9件の詳細分析結果をまとめます。
|
||||
|
||||
## 削減された 3件(Phase 84-2 で解決)
|
||||
|
||||
CopyTypePropagator により以下のパターンが解決されました:
|
||||
- **Copy チェーン伝播**: `r1 = Copy r0` → `r2 = PHI [r1, r3]` で r0 の型が r2 に伝播
|
||||
- **多段 Copy 追跡**: Copy 命令を遡って元の ValueId の型を発見
|
||||
|
||||
## 残り 9件の一覧
|
||||
|
||||
| # | テスト名 | ValueId | パターン分類 |
|
||||
|---|---------|---------|------------|
|
||||
| 1 | `test_lowering_await_expression` | ValueId(2) | GroupC: await 特殊パターン |
|
||||
| 2 | `loop_with_continue_and_break_edge_copy_merge` | ValueId(56) | GroupA: Loop + continue/break PHI |
|
||||
| 3 | `nested_loop_with_multi_continue_break_edge_copy_merge` | ValueId(135) | GroupA: Nested loop 複雑 PHI |
|
||||
| 4 | `loop_inner_if_multilevel_edge_copy` | ValueId(74) | GroupA: Loop + 多段 if |
|
||||
| 5 | `loop_break_and_early_return_edge_copy` | ValueId(40) | GroupA: Loop + early return |
|
||||
| 6 | `vm_exec_break_inside_if` | ValueId(27) | GroupA: Loop + if-break |
|
||||
| 7 | `loop_if_three_level_merge_edge_copy` | ValueId(75) | GroupA: Loop + 3段 if |
|
||||
| 8 | `mir_stage1_cli_emit_program_min_exec_hits_type_error` | ValueId(7) | GroupB: Stage1Cli 複雑型推論 |
|
||||
| 9 | `mir_stage1_cli_emit_program_min_compiles_and_verifies` | ValueId(7) | GroupB: Stage1Cli 複雑型推論 |
|
||||
|
||||
## パターン分類の詳細
|
||||
|
||||
### GroupA: Loop 制御フロー PHI(7件)
|
||||
|
||||
**共通特徴**:
|
||||
- `NYASH_MIR_NO_PHI=1` でテスト(PHI-off モード)
|
||||
- Loop + continue/break による複雑な制御フロー
|
||||
- Edge Copy が複数の経路から合流する PHI
|
||||
|
||||
**典型的な制御フロー**:
|
||||
```
|
||||
loop(condition) {
|
||||
if (cond1) { break } // → after_loop へ edge copy
|
||||
if (cond2) { continue } // → loop_header へ edge copy
|
||||
normal_path // → loop_header へ edge copy
|
||||
}
|
||||
return merged_value // ← PHI の型が未解決
|
||||
```
|
||||
|
||||
**問題の本質**:
|
||||
- PHI の incoming 値が全て Edge Copy の dst ValueId
|
||||
- Edge Copy の src ValueId は value_types に登録されている
|
||||
- しかし、GenericTypeResolver は **PHI の incoming 値の型** しか見ない
|
||||
- **Copy の src を遡る処理が不足**
|
||||
|
||||
**なぜ CopyTypePropagator で解決できなかったか**:
|
||||
```rust
|
||||
// CopyTypePropagator の現在のロジック
|
||||
if let Some(ty) = types.get(&src) {
|
||||
types.insert(dst, ty.clone()); // ← dst に型を登録
|
||||
}
|
||||
```
|
||||
|
||||
問題点:
|
||||
- PHI の incoming 値 (dst) に型を登録
|
||||
- しかし、GenericTypeResolver::resolve_from_phi() は **既に登録された型** を参照
|
||||
- **参照のタイミングが遅い**: lifecycle.rs が return 型を要求する時点で、
|
||||
CopyTypePropagator はまだ実行されていない
|
||||
|
||||
**具体例: loop_with_continue_and_break_edge_copy_merge**
|
||||
|
||||
```hako
|
||||
// 簡略化したコード
|
||||
i = 0
|
||||
sum = 0
|
||||
loop(i < 5) {
|
||||
i = i + 1
|
||||
if (i == 3) { break } // → edge copy: sum_final = sum
|
||||
if (i % 2 == 0) { continue } // → edge copy: sum_loop = sum
|
||||
sum = sum + i
|
||||
}
|
||||
return sum // ← ValueId(56) の型が未解決
|
||||
```
|
||||
|
||||
MIR 構造(推測):
|
||||
```
|
||||
Block1 (loop_header):
|
||||
%sum_header = PHI [%sum_init, %sum_loop, %sum_updated]
|
||||
|
||||
Block2 (break):
|
||||
%sum_final = Copy %sum_header ← value_types に型登録済み
|
||||
Jump after_loop
|
||||
|
||||
Block3 (continue):
|
||||
%sum_loop = Copy %sum_header ← value_types に型登録済み
|
||||
Jump loop_header
|
||||
|
||||
Block4 (after_loop):
|
||||
%56 = PHI [%sum_final] ← incoming の型が未登録!
|
||||
Return %56
|
||||
```
|
||||
|
||||
**テストファイルの所在**:
|
||||
- `src/tests/loop_continue_break_no_phi_tests.rs`
|
||||
- `src/tests/loop_nested_no_phi_tests.rs`
|
||||
- `src/tests/loop_return_no_phi_tests.rs`
|
||||
- `src/tests/mir_ctrlflow_break_continue.rs`
|
||||
|
||||
### GroupB: Stage1Cli 複雑型推論(2件)
|
||||
|
||||
**共通特徴**:
|
||||
- `mir_stage1_cli_emit_program_min.rs` の 2テスト
|
||||
- static box + env.get/set による複雑な型フロー
|
||||
- ValueId(7) が Main.main の戻り値
|
||||
|
||||
**コードの特徴**:
|
||||
```hako
|
||||
static box Stage1Cli {
|
||||
emit_program_json(source) {
|
||||
if source == null || source == "" { return null }
|
||||
return "{prog:" + source + "}"
|
||||
}
|
||||
|
||||
stage1_main(args) {
|
||||
local src = env.get("STAGE1_SOURCE")
|
||||
if src == null || src == "" { return 96 }
|
||||
local prog = me.emit_program_json(src)
|
||||
if prog == null { return 96 }
|
||||
print(prog)
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
static box Main {
|
||||
main(args) {
|
||||
env.set("STAGE1_SOURCE", "apps/tests/stage1_using_minimal.hako")
|
||||
return Stage1Cli.stage1_main(args) // ← ValueId(7) の型
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**問題の本質**:
|
||||
- 多段メソッド呼び出し: `Main.main` → `Stage1Cli.stage1_main` → `emit_program_json`
|
||||
- 複数の return 経路: null / 96 / 0
|
||||
- PHI が複数の経路から合流
|
||||
|
||||
**デバッグ情報**:
|
||||
```
|
||||
[DEBUG/build_block] Completed, returning value ValueId(14)
|
||||
[DEBUG/build_block] Completed, returning value ValueId(83)
|
||||
[DEBUG/build_block] Completed, returning value ValueId(95)
|
||||
[DEBUG/build_block] Completed, returning value ValueId(47)
|
||||
[DEBUG/build_block] Completed, returning value ValueId(63)
|
||||
[DEBUG/build_block] Completed, returning value ValueId(7)
|
||||
```
|
||||
|
||||
多数の ValueId が生成されており、PHI 合流が複雑であることを示唆。
|
||||
|
||||
**テストファイル**:
|
||||
- `src/tests/mir_stage1_cli_emit_program_min.rs`
|
||||
|
||||
### GroupC: await 特殊パターン(1件)
|
||||
|
||||
**テスト**: `test_lowering_await_expression`
|
||||
**ValueId**: ValueId(2)
|
||||
|
||||
**コードの特徴**:
|
||||
```rust
|
||||
// src/mir/mod.rs:363
|
||||
let ast = ASTNode::AwaitExpression {
|
||||
expression: Box::new(ASTNode::Literal {
|
||||
value: LiteralValue::Integer(1),
|
||||
span: crate::ast::Span::unknown(),
|
||||
}),
|
||||
span: crate::ast::Span::unknown(),
|
||||
};
|
||||
```
|
||||
|
||||
**問題の本質**:
|
||||
- await 式の MIR lowering が特殊な制御フローを生成
|
||||
- Core-13 pure mode では skip される(非同期システム未実装)
|
||||
- ValueId(2) は await の戻り値
|
||||
|
||||
**なぜ特殊か**:
|
||||
- await は将来的に Safepoint/Checkpoint 命令に変換される予定
|
||||
- 現在は簡易実装のため、型推論が不完全
|
||||
|
||||
**テストファイル**:
|
||||
- `src/mir/mod.rs:363-384`
|
||||
|
||||
## Phase 84-3 で必要な機能の推奨
|
||||
|
||||
### 推奨1: Edge Copy 追跡 PHI 型推論(優先度: 高)
|
||||
|
||||
**対象**: GroupA(7件)
|
||||
|
||||
**アルゴリズム**:
|
||||
```rust
|
||||
// GenericTypeResolver に追加
|
||||
pub fn resolve_from_phi_with_copy_trace(
|
||||
function: &MirFunction,
|
||||
ret_val: ValueId,
|
||||
types: &BTreeMap<ValueId, MirType>,
|
||||
) -> Option<MirType> {
|
||||
// 1. PHI 命令を探索
|
||||
for inst in find_phi_instructions(function, ret_val) {
|
||||
if let MirInstruction::Phi { inputs, .. } = inst {
|
||||
// 2. incoming 値ごとに Copy を遡る
|
||||
let mut inferred_types = Vec::new();
|
||||
for (_, incoming_val) in inputs {
|
||||
// 2-1. incoming_val の型を直接取得
|
||||
if let Some(ty) = types.get(incoming_val) {
|
||||
inferred_types.push(ty.clone());
|
||||
continue;
|
||||
}
|
||||
|
||||
// 2-2. incoming_val を定義する Copy 命令を探索
|
||||
if let Some(src_val) = find_copy_src(function, *incoming_val) {
|
||||
if let Some(ty) = types.get(&src_val) {
|
||||
inferred_types.push(ty.clone());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// 2-3. 多段 Copy を再帰的に遡る
|
||||
if let Some(ty) = trace_copy_chain(function, *incoming_val, types, 10) {
|
||||
inferred_types.push(ty);
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 全ての型が一致すれば返す
|
||||
if let Some(first) = inferred_types.first() {
|
||||
if inferred_types.iter().all(|t| t == first) {
|
||||
return Some(first.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn trace_copy_chain(
|
||||
function: &MirFunction,
|
||||
start: ValueId,
|
||||
types: &BTreeMap<ValueId, MirType>,
|
||||
max_depth: usize,
|
||||
) -> Option<MirType> {
|
||||
let mut current = start;
|
||||
for _ in 0..max_depth {
|
||||
if let Some(ty) = types.get(¤t) {
|
||||
return Some(ty.clone());
|
||||
}
|
||||
if let Some(src) = find_copy_src(function, current) {
|
||||
current = src;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
```
|
||||
|
||||
**実装箇所**:
|
||||
- `src/mir/join_ir/lowering/generic_type_resolver.rs`
|
||||
|
||||
**期待効果**:
|
||||
- GroupA の 7件を一気に解決
|
||||
- Loop + continue/break パターンの完全対応
|
||||
|
||||
### 推奨2: 多段 PHI 型推論(優先度: 中)
|
||||
|
||||
**対象**: GroupB(2件)
|
||||
|
||||
**問題**:
|
||||
```
|
||||
Block1:
|
||||
%a = PHI [const_96, const_0]
|
||||
|
||||
Block2:
|
||||
%b = PHI [%a, const_0]
|
||||
|
||||
Block3:
|
||||
%7 = PHI [%b] ← %b の型が未解決
|
||||
```
|
||||
|
||||
**アルゴリズム**:
|
||||
```rust
|
||||
pub fn resolve_from_phi_recursive(
|
||||
function: &MirFunction,
|
||||
ret_val: ValueId,
|
||||
types: &BTreeMap<ValueId, MirType>,
|
||||
visited: &mut HashSet<ValueId>,
|
||||
) -> Option<MirType> {
|
||||
if visited.contains(&ret_val) {
|
||||
return None; // 循環検出
|
||||
}
|
||||
visited.insert(ret_val);
|
||||
|
||||
// 1. 直接型推論を試みる
|
||||
if let Some(ty) = resolve_from_phi(function, ret_val, types) {
|
||||
return Some(ty);
|
||||
}
|
||||
|
||||
// 2. PHI の incoming 値を再帰的に解決
|
||||
for inst in find_phi_instructions(function, ret_val) {
|
||||
if let MirInstruction::Phi { inputs, .. } = inst {
|
||||
let mut inferred_types = Vec::new();
|
||||
for (_, incoming_val) in inputs {
|
||||
// 再帰的に型を解決
|
||||
if let Some(ty) = resolve_from_phi_recursive(
|
||||
function, *incoming_val, types, visited
|
||||
) {
|
||||
inferred_types.push(ty);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(first) = inferred_types.first() {
|
||||
if inferred_types.iter().all(|t| t == first) {
|
||||
return Some(first.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
```
|
||||
|
||||
**実装箇所**:
|
||||
- `src/mir/join_ir/lowering/generic_type_resolver.rs`
|
||||
|
||||
**期待効果**:
|
||||
- GroupB の 2件を解決
|
||||
- 多段メソッド呼び出しの型推論強化
|
||||
|
||||
### 推奨3: await 型推論特殊処理(優先度: 低)
|
||||
|
||||
**対象**: GroupC(1件)
|
||||
|
||||
**短期対応**:
|
||||
```rust
|
||||
// lifecycle.rs に特殊ケース追加
|
||||
if function_name == "main" && is_await_expression {
|
||||
// await の戻り値型は Unknown で許容
|
||||
return MirType::Unknown;
|
||||
}
|
||||
```
|
||||
|
||||
**長期対応**:
|
||||
- Phase 67+ で async/await システム完全実装
|
||||
- Safepoint/Checkpoint 命令の型推論統合
|
||||
|
||||
**実装箇所**:
|
||||
- `src/mir/builder/lifecycle.rs`
|
||||
|
||||
**期待効果**:
|
||||
- GroupC の 1件を解決(暫定)
|
||||
|
||||
## 推奨実装順序
|
||||
|
||||
### Phase 84-3: Edge Copy 追跡 PHI 型推論(1-2日)
|
||||
|
||||
**目標**: GroupA の 7件を解決
|
||||
|
||||
**ステップ**:
|
||||
1. `GenericTypeResolver::resolve_from_phi_with_copy_trace()` 実装
|
||||
2. `trace_copy_chain()` ヘルパー関数実装
|
||||
3. `find_copy_src()` ヘルパー関数実装
|
||||
4. lifecycle.rs から新関数を呼び出す
|
||||
5. テスト実行: 7件 → 0件 を確認
|
||||
|
||||
### Phase 84-4: 多段 PHI 型推論(1-2日)
|
||||
|
||||
**目標**: GroupB の 2件を解決
|
||||
|
||||
**ステップ**:
|
||||
1. `GenericTypeResolver::resolve_from_phi_recursive()` 実装
|
||||
2. 循環検出ロジック実装
|
||||
3. lifecycle.rs から新関数を呼び出す
|
||||
4. テスト実行: 2件 → 0件 を確認
|
||||
|
||||
### Phase 84-5: await 暫定対応(30分)
|
||||
|
||||
**目標**: GroupC の 1件を解決(暫定)
|
||||
|
||||
**ステップ**:
|
||||
1. lifecycle.rs に await 特殊ケース追加
|
||||
2. テスト実行: 1件 → 0件 を確認
|
||||
|
||||
## 完了条件
|
||||
|
||||
```bash
|
||||
# Phase 84-3 完了
|
||||
NYASH_PHI_FALLBACK_DISABLED=1 cargo test --release --lib 2>&1 | grep "Case D" | wc -l
|
||||
# 期待: 2 (GroupB のみ残存)
|
||||
|
||||
# Phase 84-4 完了
|
||||
NYASH_PHI_FALLBACK_DISABLED=1 cargo test --release --lib 2>&1 | grep "Case D" | wc -l
|
||||
# 期待: 1 (GroupC のみ残存)
|
||||
|
||||
# Phase 84-5 完了
|
||||
NYASH_PHI_FALLBACK_DISABLED=1 cargo test --release --lib 2>&1 | grep "Case D" | wc -l
|
||||
# 期待: 0 (全件解決)
|
||||
```
|
||||
|
||||
## ChatGPT Pro との設計相談ポイント
|
||||
|
||||
### 相談1: Edge Copy 追跡の最適化
|
||||
|
||||
**質問**:
|
||||
- Copy チェーンの追跡深度は 10 で十分か?
|
||||
- 循環 Copy 検出は必要か?(理論上は発生しないが)
|
||||
- パフォーマンス最適化(キャッシュ戦略)
|
||||
|
||||
### 相談2: 多段 PHI の循環検出
|
||||
|
||||
**質問**:
|
||||
- 循環 PHI は実際に発生するか?
|
||||
- 発生する場合、どう処理すべきか?(エラー or Unknown)
|
||||
- visited セットの最適なデータ構造
|
||||
|
||||
### 相談3: await 型推論の長期戦略
|
||||
|
||||
**質問**:
|
||||
- Phase 67+ async/await システムの型推論設計
|
||||
- Safepoint/Checkpoint 命令の型情報統合方法
|
||||
- 現在の暫定対応が将来の実装を妨げないか
|
||||
|
||||
## まとめ
|
||||
|
||||
Phase 84-2 の CopyTypePropagator により 12件 → 9件に削減成功。
|
||||
残り 9件は以下の 3パターンに分類:
|
||||
|
||||
- **GroupA**: Loop 制御フロー PHI(7件)→ Edge Copy 追跡で解決可能
|
||||
- **GroupB**: 多段 PHI(2件)→ 再帰的型推論で解決可能
|
||||
- **GroupC**: await 特殊(1件)→ 暫定対応で解決可能
|
||||
|
||||
Phase 84-3/4/5 の実装により、**Case D を完全解決** できる見込み。
|
||||
390
docs/development/current/main/phase84-2-failure-patterns.md
Normal file
390
docs/development/current/main/phase84-2-failure-patterns.md
Normal file
@ -0,0 +1,390 @@
|
||||
# Phase 84-2: Case D 失敗パターン詳細
|
||||
|
||||
## GroupA: Loop 制御フロー PHI(7件)
|
||||
|
||||
### パターン A-1: continue + break
|
||||
|
||||
**テスト**: `loop_with_continue_and_break_edge_copy_merge`
|
||||
**ValueId**: 56
|
||||
|
||||
**コード構造**:
|
||||
```hako
|
||||
i = 0
|
||||
sum = 0
|
||||
loop(i < 5) {
|
||||
i = i + 1
|
||||
if (i == 3) { break } // ← break 経路
|
||||
if (i % 2 == 0) { continue } // ← continue 経路
|
||||
sum = sum + i // ← normal 経路
|
||||
}
|
||||
return sum // ← ValueId(56) の型が未解決
|
||||
```
|
||||
|
||||
**MIR 構造(推測)**:
|
||||
```
|
||||
Block_LoopHeader:
|
||||
%sum_phi = PHI [%sum_init, %sum_continue, %sum_normal]
|
||||
%i_phi = PHI [%i_init, %i_continue, %i_normal]
|
||||
...
|
||||
|
||||
Block_Break:
|
||||
%sum_break = Copy %sum_phi ← value_types に型登録済み
|
||||
Jump after_loop
|
||||
|
||||
Block_Continue:
|
||||
%sum_continue = Copy %sum_phi ← value_types に型登録済み
|
||||
Jump loop_header
|
||||
|
||||
Block_Normal:
|
||||
%sum_normal = BinOp Add %sum_phi %i_phi
|
||||
Jump loop_header
|
||||
|
||||
Block_AfterLoop:
|
||||
%56 = PHI [%sum_break] ← incoming の型が未登録!
|
||||
Return %56
|
||||
```
|
||||
|
||||
**問題の本質**:
|
||||
- PHI(56) の incoming 値は `%sum_break`
|
||||
- `%sum_break` は Copy の dst で、value_types に未登録
|
||||
- Copy の src `%sum_phi` は型登録済みだが、GenericTypeResolver は追跡しない
|
||||
|
||||
**解決策**:
|
||||
```rust
|
||||
// GenericTypeResolver::resolve_from_phi_with_copy_trace()
|
||||
for (_, incoming_val) in phi_inputs {
|
||||
// Copy を遡る
|
||||
if let Some(src) = find_copy_src(function, incoming_val) {
|
||||
if let Some(ty) = types.get(&src) {
|
||||
return Some(ty.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### パターン A-2: 多段 continue/break
|
||||
|
||||
**テスト**: `nested_loop_with_multi_continue_break_edge_copy_merge`
|
||||
**ValueId**: 135
|
||||
|
||||
**コード構造**:
|
||||
```hako
|
||||
i = 0
|
||||
sum = 0
|
||||
loop(i < 10) {
|
||||
i = i + 1
|
||||
if (i == 2 || i == 4) { continue } // ← continue 経路1
|
||||
if (i == 7) {
|
||||
if (1 == 1) { break } // ← break 経路(ネスト)
|
||||
}
|
||||
if ((i % 3) == 0) { continue } // ← continue 経路2
|
||||
sum = sum + i // ← normal 経路
|
||||
}
|
||||
return sum // ← ValueId(135)
|
||||
```
|
||||
|
||||
**特徴**:
|
||||
- 複数の continue 経路
|
||||
- ネストした if 内の break
|
||||
- PHI の incoming 値が多い(4-5個)
|
||||
|
||||
### パターン A-3: Loop + 多段 if
|
||||
|
||||
**テスト**: `loop_inner_if_multilevel_edge_copy`
|
||||
**ValueId**: 74
|
||||
|
||||
**コード構造**:
|
||||
```hako
|
||||
j = 0
|
||||
acc = 0
|
||||
loop(j < 6) {
|
||||
j = j + 1
|
||||
if (j < 3) {
|
||||
if (j % 2 == 0) { continue } // ← 2段 if + continue
|
||||
acc = acc + 10
|
||||
} else {
|
||||
if (j == 5) { break } // ← 2段 if + break
|
||||
acc = acc + 1
|
||||
}
|
||||
}
|
||||
return acc // ← ValueId(74)
|
||||
```
|
||||
|
||||
**特徴**:
|
||||
- then/else の両方に制御フロー
|
||||
- 多段ネスト if
|
||||
- 変数更新が複数経路に分散
|
||||
|
||||
### パターン A-4: Loop + early return
|
||||
|
||||
**テスト**: `loop_break_and_early_return_edge_copy`
|
||||
**ValueId**: 40
|
||||
|
||||
**コード構造**:
|
||||
```hako
|
||||
i = 0
|
||||
acc = 0
|
||||
loop(i < 6) {
|
||||
i = i + 1
|
||||
if (i == 5) { break } // ← break 経路
|
||||
if (i == 3) { return acc } // ← early return 経路
|
||||
acc = acc + i
|
||||
}
|
||||
return acc // ← ValueId(40)
|
||||
```
|
||||
|
||||
**特徴**:
|
||||
- break と early return の混在
|
||||
- 関数終了が複数経路
|
||||
- return 型推論が複雑
|
||||
|
||||
### パターン A-5: 単純 if-break
|
||||
|
||||
**テスト**: `vm_exec_break_inside_if`
|
||||
**ValueId**: 27
|
||||
|
||||
**コード構造**:
|
||||
```hako
|
||||
local i = 0
|
||||
loop(i < 10) {
|
||||
if (i == 3) { break } // ← if 内 break
|
||||
i = i + 1
|
||||
}
|
||||
return i // ← ValueId(27)
|
||||
```
|
||||
|
||||
**特徴**:
|
||||
- 最もシンプルな if-break パターン
|
||||
- これが解決できればベースケース成功
|
||||
|
||||
### パターン A-6: 3段ネスト if
|
||||
|
||||
**テスト**: `loop_if_three_level_merge_edge_copy`
|
||||
**ValueId**: 75
|
||||
|
||||
**コード構造**:
|
||||
```hako
|
||||
x = 0
|
||||
i = 0
|
||||
loop(i < 7) {
|
||||
i = i + 1
|
||||
if (i % 2 == 0) {
|
||||
if (i == 4) { continue } // ← 3段目 continue
|
||||
x = x + 2
|
||||
} else {
|
||||
if (i == 5) { break } // ← 3段目 break
|
||||
x = x + 1
|
||||
}
|
||||
}
|
||||
return x // ← ValueId(75)
|
||||
```
|
||||
|
||||
**特徴**:
|
||||
- 3段ネスト制御フロー
|
||||
- then/else の両方に制御フロー
|
||||
- 変数更新の分岐が複雑
|
||||
|
||||
## GroupB: 多段 PHI 型推論(2件)
|
||||
|
||||
### パターン B-1: static box + 複数 return
|
||||
|
||||
**テスト**: `mir_stage1_cli_emit_program_min_*`
|
||||
**ValueId**: 7
|
||||
|
||||
**コード構造**:
|
||||
```hako
|
||||
static box Stage1Cli {
|
||||
emit_program_json(source) {
|
||||
if source == null || source == "" { return null } // ← return 経路1
|
||||
return "{prog:" + source + "}" // ← return 経路2
|
||||
}
|
||||
|
||||
stage1_main(args) {
|
||||
if args == null { args = new ArrayBox() }
|
||||
local src = env.get("STAGE1_SOURCE")
|
||||
if src == null || src == "" { return 96 } // ← return 経路3
|
||||
|
||||
local prog = me.emit_program_json(src)
|
||||
if prog == null { return 96 } // ← return 経路4
|
||||
print(prog)
|
||||
return 0 // ← return 経路5
|
||||
}
|
||||
}
|
||||
|
||||
static box Main {
|
||||
main(args) {
|
||||
env.set("STAGE1_SOURCE", "apps/tests/stage1_using_minimal.hako")
|
||||
return Stage1Cli.stage1_main(args) // ← ValueId(7)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**MIR 構造(推測)**:
|
||||
```
|
||||
Function: Stage1Cli.emit_program_json
|
||||
Block1:
|
||||
%1 = PHI [null, string_concat_result]
|
||||
Return %1
|
||||
|
||||
Function: Stage1Cli.stage1_main
|
||||
Block1:
|
||||
%2 = Call Stage1Cli.emit_program_json
|
||||
Block2:
|
||||
%3 = PHI [%2, const_96, const_0]
|
||||
Return %3
|
||||
|
||||
Function: Main.main
|
||||
Block1:
|
||||
%4 = Call Stage1Cli.stage1_main
|
||||
Block2:
|
||||
%7 = PHI [%4] ← %4 の型が未解決(多段 PHI)
|
||||
Return %7
|
||||
```
|
||||
|
||||
**問題の本質**:
|
||||
- PHI(7) の incoming 値は PHI(3) の結果
|
||||
- PHI(3) の incoming 値は PHI(1) の結果
|
||||
- **3段 PHI チェーン** が発生
|
||||
|
||||
**解決策**:
|
||||
```rust
|
||||
// GenericTypeResolver::resolve_from_phi_recursive()
|
||||
pub fn resolve_from_phi_recursive(
|
||||
function: &MirFunction,
|
||||
ret_val: ValueId,
|
||||
types: &BTreeMap<ValueId, MirType>,
|
||||
visited: &mut HashSet<ValueId>,
|
||||
) -> Option<MirType> {
|
||||
if visited.contains(&ret_val) {
|
||||
return None; // 循環検出
|
||||
}
|
||||
visited.insert(ret_val);
|
||||
|
||||
// PHI の incoming 値を再帰的に解決
|
||||
for (_, incoming_val) in phi_inputs {
|
||||
if let Some(ty) = resolve_from_phi_recursive(
|
||||
function, *incoming_val, types, visited
|
||||
) {
|
||||
return Some(ty);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
```
|
||||
|
||||
## GroupC: await 特殊パターン(1件)
|
||||
|
||||
### パターン C-1: await 式
|
||||
|
||||
**テスト**: `test_lowering_await_expression`
|
||||
**ValueId**: 2
|
||||
|
||||
**コード構造**:
|
||||
```rust
|
||||
// Rust AST 生成
|
||||
let ast = ASTNode::AwaitExpression {
|
||||
expression: Box::new(ASTNode::Literal {
|
||||
value: LiteralValue::Integer(1),
|
||||
span: crate::ast::Span::unknown(),
|
||||
}),
|
||||
span: crate::ast::Span::unknown(),
|
||||
};
|
||||
```
|
||||
|
||||
**MIR 構造(推測)**:
|
||||
```
|
||||
Block1:
|
||||
%1 = Const Integer(1)
|
||||
%2 = Await %1 ← await 命令の戻り値
|
||||
Return %2
|
||||
```
|
||||
|
||||
**問題の本質**:
|
||||
- await 式の型推論が未実装
|
||||
- 非同期システム(Safepoint/Checkpoint)が Phase 67+ 実装予定
|
||||
- 現在は MIR13 migration pending
|
||||
|
||||
**暫定対応**:
|
||||
```rust
|
||||
// lifecycle.rs に特殊ケース追加
|
||||
if is_await_expression {
|
||||
// await の戻り値型は Unknown で許容
|
||||
return MirType::Unknown;
|
||||
}
|
||||
```
|
||||
|
||||
**長期対応(Phase 67+)**:
|
||||
- async/await システム完全実装
|
||||
- type_hint による await 型推論
|
||||
- Safepoint/Checkpoint 命令統合
|
||||
|
||||
## 解決優先度
|
||||
|
||||
### 優先度1: GroupA(7件)
|
||||
|
||||
**理由**:
|
||||
- 最も頻出するパターン
|
||||
- Loop 制御フローは実用コードで必須
|
||||
- Edge Copy 追跡で一気に解決可能
|
||||
|
||||
**期待効果**: 9件 → 2件(78%削減)
|
||||
|
||||
### 優先度2: GroupB(2件)
|
||||
|
||||
**理由**:
|
||||
- static box は Stage1Cli で使用中
|
||||
- 多段メソッド呼び出しも実用的
|
||||
- 再帰的 PHI 推論で解決可能
|
||||
|
||||
**期待効果**: 2件 → 1件(50%削減)
|
||||
|
||||
### 優先度3: GroupC(1件)
|
||||
|
||||
**理由**:
|
||||
- await は実験的機能
|
||||
- 本格実装は Phase 67+ 予定
|
||||
- 暫定対応で十分
|
||||
|
||||
**期待効果**: 1件 → 0件(100%削減)
|
||||
|
||||
## 実装チェックリスト
|
||||
|
||||
### Phase 84-3: Edge Copy 追跡
|
||||
|
||||
- [ ] `GenericTypeResolver::resolve_from_phi_with_copy_trace()` 実装
|
||||
- [ ] `find_copy_src()` ヘルパー関数実装
|
||||
- [ ] `trace_copy_chain()` ヘルパー関数実装
|
||||
- [ ] lifecycle.rs 統合
|
||||
- [ ] テスト実行: GroupA の 7件を確認
|
||||
|
||||
### Phase 84-4: 多段 PHI 推論
|
||||
|
||||
- [ ] `GenericTypeResolver::resolve_from_phi_recursive()` 実装
|
||||
- [ ] 循環検出ロジック実装
|
||||
- [ ] lifecycle.rs 統合
|
||||
- [ ] テスト実行: GroupB の 2件を確認
|
||||
|
||||
### Phase 84-5: await 暫定対応
|
||||
|
||||
- [ ] lifecycle.rs に await 特殊ケース追加
|
||||
- [ ] テスト実行: GroupC の 1件を確認
|
||||
|
||||
## 完了確認
|
||||
|
||||
```bash
|
||||
# Phase 84-3 完了
|
||||
NYASH_PHI_FALLBACK_DISABLED=1 cargo test --release --lib 2>&1 | grep "Case D" | wc -l
|
||||
# 期待: 2
|
||||
|
||||
# Phase 84-4 完了
|
||||
NYASH_PHI_FALLBACK_DISABLED=1 cargo test --release --lib 2>&1 | grep "Case D" | wc -l
|
||||
# 期待: 1
|
||||
|
||||
# Phase 84-5 完了
|
||||
NYASH_PHI_FALLBACK_DISABLED=1 cargo test --release --lib 2>&1 | grep "Case D"
|
||||
# 期待: 出力なし(0件)
|
||||
|
||||
# 最終確認
|
||||
cargo test --release --lib
|
||||
# 期待: test result: ok
|
||||
```
|
||||
211
docs/development/current/main/phase84-2-summary.md
Normal file
211
docs/development/current/main/phase84-2-summary.md
Normal file
@ -0,0 +1,211 @@
|
||||
# Phase 84-2: CopyTypePropagator 実装完了サマリー
|
||||
|
||||
## 成果
|
||||
|
||||
### 削減結果
|
||||
|
||||
```
|
||||
Before Phase 84-2: 12件の Case D 失敗
|
||||
After Phase 84-2: 9件の Case D 失敗
|
||||
|
||||
削減数: 3件 (25%削減)
|
||||
```
|
||||
|
||||
### 実装内容
|
||||
|
||||
**新規作成ファイル**:
|
||||
- `src/mir/phi_core/copy_type_propagator.rs` (125行)
|
||||
|
||||
**主要機能**:
|
||||
```rust
|
||||
pub struct CopyTypePropagator;
|
||||
|
||||
impl CopyTypePropagator {
|
||||
pub fn propagate(
|
||||
function: &MirFunction,
|
||||
types: &mut BTreeMap<ValueId, MirType>,
|
||||
) {
|
||||
// Copy 命令を走査して型を伝播
|
||||
for inst in all_copy_instructions(function) {
|
||||
if let Some(src_type) = types.get(&src) {
|
||||
types.insert(dst, src_type.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**統合箇所**:
|
||||
- `src/mir/builder/lifecycle.rs:371` - infer_type_from_phi() の直前に呼び出し
|
||||
|
||||
## 残り 9件の分類
|
||||
|
||||
### GroupA: Loop 制御フロー PHI(7件)
|
||||
|
||||
**パターン**: Loop + continue/break による Edge Copy 合流
|
||||
|
||||
**典型的なコード**:
|
||||
```hako
|
||||
i = 0
|
||||
sum = 0
|
||||
loop(i < 5) {
|
||||
i = i + 1
|
||||
if (i == 3) { break } // → edge copy
|
||||
if (i % 2 == 0) { continue } // → edge copy
|
||||
sum = sum + i
|
||||
}
|
||||
return sum // ← PHI の型が未解決
|
||||
```
|
||||
|
||||
**問題**: PHI の incoming 値が Edge Copy の dst で、src の型を遡れない
|
||||
|
||||
**テスト一覧**:
|
||||
1. `loop_with_continue_and_break_edge_copy_merge` - ValueId(56)
|
||||
2. `nested_loop_with_multi_continue_break_edge_copy_merge` - ValueId(135)
|
||||
3. `loop_inner_if_multilevel_edge_copy` - ValueId(74)
|
||||
4. `loop_break_and_early_return_edge_copy` - ValueId(40)
|
||||
5. `vm_exec_break_inside_if` - ValueId(27)
|
||||
6. `loop_if_three_level_merge_edge_copy` - ValueId(75)
|
||||
7. (GroupA 合計 7件)
|
||||
|
||||
### GroupB: 多段 PHI 型推論(2件)
|
||||
|
||||
**パターン**: 複数の PHI 命令が連鎖
|
||||
|
||||
**典型的なコード**:
|
||||
```hako
|
||||
static box Stage1Cli {
|
||||
stage1_main(args) {
|
||||
if cond1 { return 96 }
|
||||
if cond2 { return 96 }
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
static box Main {
|
||||
main(args) {
|
||||
return Stage1Cli.stage1_main(args) // ← 多段 PHI
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**問題**: PHI の incoming 値が別の PHI で、再帰的に解決できない
|
||||
|
||||
**テスト一覧**:
|
||||
1. `mir_stage1_cli_emit_program_min_exec_hits_type_error` - ValueId(7)
|
||||
2. `mir_stage1_cli_emit_program_min_compiles_and_verifies` - ValueId(7)
|
||||
|
||||
### GroupC: await 特殊パターン(1件)
|
||||
|
||||
**パターン**: await 式の MIR lowering
|
||||
|
||||
**コード**:
|
||||
```rust
|
||||
let ast = ASTNode::AwaitExpression {
|
||||
expression: Box::new(ASTNode::Literal {
|
||||
value: LiteralValue::Integer(1),
|
||||
...
|
||||
}),
|
||||
...
|
||||
};
|
||||
```
|
||||
|
||||
**問題**: await の型推論が未実装(非同期システム未完成)
|
||||
|
||||
**テスト**:
|
||||
1. `test_lowering_await_expression` - ValueId(2)
|
||||
|
||||
## Phase 84-3 実装推奨
|
||||
|
||||
### 目標: GroupA の 7件を解決
|
||||
|
||||
**新機能**: Edge Copy 追跡 PHI 型推論
|
||||
|
||||
**実装方針**:
|
||||
```rust
|
||||
// GenericTypeResolver に追加
|
||||
pub fn resolve_from_phi_with_copy_trace(
|
||||
function: &MirFunction,
|
||||
ret_val: ValueId,
|
||||
types: &BTreeMap<ValueId, MirType>,
|
||||
) -> Option<MirType> {
|
||||
// PHI の incoming 値から Copy を遡る
|
||||
for (_, incoming_val) in phi_inputs {
|
||||
// 1. 直接型取得を試みる
|
||||
if let Some(ty) = types.get(incoming_val) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 2. Copy 命令を遡る
|
||||
if let Some(src) = find_copy_src(function, incoming_val) {
|
||||
if let Some(ty) = types.get(&src) {
|
||||
// src の型を使用
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 多段 Copy を再帰的に追跡
|
||||
if let Some(ty) = trace_copy_chain(function, incoming_val, types) {
|
||||
// チェーンを遡った型を使用
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**期待効果**:
|
||||
- 9件 → 2件に削減(GroupB + GroupC のみ残存)
|
||||
- Loop 制御フローの型推論が完全動作
|
||||
|
||||
### 実装ファイル
|
||||
|
||||
- `src/mir/join_ir/lowering/generic_type_resolver.rs` - 新関数追加
|
||||
- `src/mir/builder/lifecycle.rs` - 新関数呼び出し統合
|
||||
|
||||
### テスト検証
|
||||
|
||||
```bash
|
||||
# Phase 84-3 完了確認
|
||||
NYASH_PHI_FALLBACK_DISABLED=1 cargo test --release --lib 2>&1 | grep "Case D" | wc -l
|
||||
# 期待: 2 (GroupB のみ)
|
||||
```
|
||||
|
||||
## Phase 84-4/5 展望
|
||||
|
||||
### Phase 84-4: 多段 PHI 型推論
|
||||
|
||||
**目標**: GroupB の 2件を解決
|
||||
|
||||
**実装**: `resolve_from_phi_recursive()` で PHI チェーンを再帰的に追跡
|
||||
|
||||
### Phase 84-5: await 暫定対応
|
||||
|
||||
**目標**: GroupC の 1件を解決
|
||||
|
||||
**実装**: lifecycle.rs に await 特殊ケース追加(暫定)
|
||||
|
||||
## 完了条件
|
||||
|
||||
```bash
|
||||
# 全 Case D 解決
|
||||
NYASH_PHI_FALLBACK_DISABLED=1 cargo test --release --lib 2>&1 | grep "Case D"
|
||||
# 期待: 出力なし(0件)
|
||||
|
||||
# 最終確認
|
||||
cargo test --release --lib
|
||||
# 期待: test result: ok
|
||||
```
|
||||
|
||||
## タイムライン
|
||||
|
||||
- **Phase 84-2**: 完了 ✅ (12件 → 9件)
|
||||
- **Phase 84-3**: 推定 1-2日 (9件 → 2件)
|
||||
- **Phase 84-4**: 推定 1-2日 (2件 → 1件)
|
||||
- **Phase 84-5**: 推定 30分 (1件 → 0件)
|
||||
|
||||
**合計**: 2-4日で Case D 完全解決見込み
|
||||
|
||||
## 参考資料
|
||||
|
||||
- [Phase 84-2 詳細調査](./phase84-2-case-d-investigation.md)
|
||||
- [CopyTypePropagator 実装](../../../src/mir/phi_core/copy_type_propagator.rs)
|
||||
- [GenericTypeResolver](../../../src/mir/join_ir/lowering/generic_type_resolver.rs)
|
||||
- [lifecycle.rs 統合箇所](../../../src/mir/builder/lifecycle.rs:371)
|
||||
120
docs/development/current/main/phase84-2-test-list.md
Normal file
120
docs/development/current/main/phase84-2-test-list.md
Normal file
@ -0,0 +1,120 @@
|
||||
# Phase 84-2: Case D 残り 9件クイックリファレンス
|
||||
|
||||
## 一覧表
|
||||
|
||||
| # | Group | テスト名 | ValueId | ファイル | 行番号 |
|
||||
|---|-------|---------|---------|---------|-------|
|
||||
| 1 | C | `test_lowering_await_expression` | 2 | `src/mir/mod.rs` | 363 |
|
||||
| 2 | A | `loop_with_continue_and_break_edge_copy_merge` | 56 | `src/tests/loop_continue_break_no_phi_tests.rs` | 21 |
|
||||
| 3 | A | `nested_loop_with_multi_continue_break_edge_copy_merge` | 135 | `src/tests/loop_nested_no_phi_tests.rs` | 21 |
|
||||
| 4 | A | `loop_inner_if_multilevel_edge_copy` | 74 | `src/tests/loop_nested_no_phi_tests.rs` | 224 |
|
||||
| 5 | A | `loop_break_and_early_return_edge_copy` | 40 | `src/tests/loop_return_no_phi_tests.rs` | 22 |
|
||||
| 6 | A | `vm_exec_break_inside_if` | 27 | `src/tests/mir_ctrlflow_break_continue.rs` | 47 |
|
||||
| 7 | A | `loop_if_three_level_merge_edge_copy` | 75 | `src/tests/loop_return_no_phi_tests.rs` | 194 |
|
||||
| 8 | B | `mir_stage1_cli_emit_program_min_exec_hits_type_error` | 7 | `src/tests/mir_stage1_cli_emit_program_min.rs` | 97 |
|
||||
| 9 | B | `mir_stage1_cli_emit_program_min_compiles_and_verifies` | 7 | `src/tests/mir_stage1_cli_emit_program_min.rs` | 71 |
|
||||
|
||||
## グループ詳細
|
||||
|
||||
### GroupA: Loop 制御フロー PHI(7件)
|
||||
|
||||
**共通パターン**: Loop + continue/break
|
||||
|
||||
**テスト実行**:
|
||||
```bash
|
||||
# 個別テスト
|
||||
cargo test --release --lib loop_with_continue_and_break_edge_copy_merge
|
||||
|
||||
# GroupA 全体
|
||||
cargo test --release --lib loop_continue_break
|
||||
cargo test --release --lib loop_nested
|
||||
cargo test --release --lib loop_return
|
||||
cargo test --release --lib vm_exec_break
|
||||
```
|
||||
|
||||
**期待される解決策**: Edge Copy 追跡 PHI 型推論
|
||||
|
||||
### GroupB: 多段 PHI 型推論(2件)
|
||||
|
||||
**共通パターン**: static box + 複数 return 経路
|
||||
|
||||
**テスト実行**:
|
||||
```bash
|
||||
# GroupB 全体
|
||||
cargo test --release --lib mir_stage1_cli_emit_program_min
|
||||
```
|
||||
|
||||
**期待される解決策**: 再帰的 PHI 型推論
|
||||
|
||||
### GroupC: await 特殊パターン(1件)
|
||||
|
||||
**パターン**: await 式の MIR lowering
|
||||
|
||||
**テスト実行**:
|
||||
```bash
|
||||
cargo test --release --lib test_lowering_await_expression
|
||||
```
|
||||
|
||||
**期待される解決策**: await 特殊ケース処理(暫定)
|
||||
|
||||
## 実行コマンド集
|
||||
|
||||
### 全 Case D 確認
|
||||
|
||||
```bash
|
||||
NYASH_PHI_FALLBACK_DISABLED=1 cargo test --release --lib 2>&1 | grep -B5 "Case D"
|
||||
```
|
||||
|
||||
### ValueId 一覧取得
|
||||
|
||||
```bash
|
||||
NYASH_PHI_FALLBACK_DISABLED=1 cargo test --release --lib 2>&1 | grep "ValueId:" | sort | uniq
|
||||
```
|
||||
|
||||
### グループ別実行
|
||||
|
||||
```bash
|
||||
# GroupA のみ
|
||||
cargo test --release --lib loop_ mir_ctrlflow_break
|
||||
|
||||
# GroupB のみ
|
||||
cargo test --release --lib mir_stage1_cli
|
||||
|
||||
# GroupC のみ
|
||||
cargo test --release --lib test_lowering_await
|
||||
```
|
||||
|
||||
## デバッグ用環境変数
|
||||
|
||||
```bash
|
||||
# MIR ダンプ
|
||||
NYASH_DUMP_MIR=1 cargo test --release --lib <test_name>
|
||||
|
||||
# 詳細ログ
|
||||
RUST_LOG=debug cargo test --release --lib <test_name>
|
||||
|
||||
# バックトレース
|
||||
RUST_BACKTRACE=1 cargo test --release --lib <test_name>
|
||||
```
|
||||
|
||||
## 次のステップ
|
||||
|
||||
1. **Phase 84-3**: GroupA の 7件を解決
|
||||
- `GenericTypeResolver::resolve_from_phi_with_copy_trace()` 実装
|
||||
- Edge Copy 追跡ロジック追加
|
||||
- 期待: 9件 → 2件
|
||||
|
||||
2. **Phase 84-4**: GroupB の 2件を解決
|
||||
- `GenericTypeResolver::resolve_from_phi_recursive()` 実装
|
||||
- 再帰的 PHI 型推論
|
||||
- 期待: 2件 → 1件
|
||||
|
||||
3. **Phase 84-5**: GroupC の 1件を解決
|
||||
- await 特殊ケース追加
|
||||
- 期待: 1件 → 0件
|
||||
|
||||
## 参考資料
|
||||
|
||||
- [詳細調査](./phase84-2-case-d-investigation.md)
|
||||
- [サマリー](./phase84-2-summary.md)
|
||||
- [CopyTypePropagator 実装](../../../src/mir/phi_core/copy_type_propagator.rs)
|
||||
@ -2,10 +2,14 @@
|
||||
|
||||
## 概要
|
||||
|
||||
Phase 83 で Case D が 20件 → **24件** に増加(調査時点)。
|
||||
本レポートでは全 24 件の Case D 失敗を詳細に分析し、不足している型推論パターンを特定する。
|
||||
Phase 83 で Case D が 20 件 → **15 件** に減少(MethodReturnHintBox 実装)。
|
||||
その後 Phase 84-1(Const 命令型アノテーション追加)で **12 件**、Phase 84-2(CopyTypePropagator 導入)で **9 件** まで削減された。
|
||||
|
||||
**重要な発見**: 主要な原因は **Const命令の型アノテーション欠如** である。
|
||||
本レポート自体は「24 件あった調査時点」の分析ログとして残しつつ、
|
||||
現在は Const 欠如グループと単純な Copy チェーンは解消され、残りは主に PHI を含む複雑なパターンであることが判明している。
|
||||
|
||||
**重要な発見(当時)**: 主要な原因は **Const命令の型アノテーション欠如** である。
|
||||
**補足(現在)**: Const 命令については 40dfbc68 で修正済み、Copy 伝播については CopyTypePropagator(Phase 84-2)で整理済み。
|
||||
|
||||
---
|
||||
|
||||
@ -15,7 +19,7 @@ Phase 83 で Case D が 20件 → **24件** に増加(調査時点)。
|
||||
NYASH_PHI_FALLBACK_DISABLED=1 cargo test --release --lib 2>&1
|
||||
```
|
||||
|
||||
**テスト結果**: 471 passed; **52 failed** (うち Case D は24件)
|
||||
**テスト結果(当時)**: 471 passed; **52 failed** (うち Case D は24件)
|
||||
|
||||
---
|
||||
|
||||
|
||||
237
docs/development/current/main/phase84-case-d-index.md
Normal file
237
docs/development/current/main/phase84-case-d-index.md
Normal file
@ -0,0 +1,237 @@
|
||||
# Phase 84: Case D 完全解決ロードマップ
|
||||
|
||||
## 現在の状況
|
||||
|
||||
```
|
||||
Phase 84-2 完了: 12件 → 9件(25%削減)
|
||||
残り: 9件
|
||||
|
||||
内訳:
|
||||
- GroupA (Loop 制御フロー): 7件
|
||||
- GroupB (多段 PHI): 2件
|
||||
- GroupC (await 特殊): 1件
|
||||
```
|
||||
|
||||
## ドキュメント一覧
|
||||
|
||||
### 📊 サマリー
|
||||
|
||||
- **[Phase 84-2 サマリー](./phase84-2-summary.md)** - 実装完了報告と次のステップ
|
||||
- **[Phase 84-2 テスト一覧](./phase84-2-test-list.md)** - クイックリファレンス表
|
||||
|
||||
### 📖 詳細分析
|
||||
|
||||
- **[Phase 84-2 詳細調査](./phase84-2-case-d-investigation.md)** - 9件の分類と解決策提案
|
||||
- **[Phase 84-2 失敗パターン](./phase84-2-failure-patterns.md)** - 各パターンのコード例と MIR 構造
|
||||
|
||||
### 🔧 実装資料
|
||||
|
||||
- **[CopyTypePropagator 実装](../../../src/mir/phi_core/copy_type_propagator.rs)** - Phase 84-2 で実装
|
||||
- **[GenericTypeResolver](../../../src/mir/join_ir/lowering/generic_type_resolver.rs)** - Phase 84-3/4 で拡張予定
|
||||
- **[lifecycle.rs](../../../src/mir/builder/lifecycle.rs)** - 型推論統合箇所
|
||||
|
||||
## クイックリンク
|
||||
|
||||
### 🎯 次のタスク
|
||||
|
||||
**Phase 84-3: Edge Copy 追跡 PHI 型推論**
|
||||
- 目標: GroupA の 7件を解決
|
||||
- 期待: 9件 → 2件(78%削減)
|
||||
- 期間: 1-2日
|
||||
|
||||
**実装内容**:
|
||||
```rust
|
||||
// GenericTypeResolver に追加
|
||||
pub fn resolve_from_phi_with_copy_trace(
|
||||
function: &MirFunction,
|
||||
ret_val: ValueId,
|
||||
types: &BTreeMap<ValueId, MirType>,
|
||||
) -> Option<MirType> {
|
||||
// PHI の incoming 値から Copy を遡る
|
||||
for (_, incoming_val) in phi_inputs {
|
||||
if let Some(src) = find_copy_src(function, incoming_val) {
|
||||
if let Some(ty) = types.get(&src) {
|
||||
return Some(ty.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
```
|
||||
|
||||
### 🧪 テスト実行
|
||||
|
||||
```bash
|
||||
# 全 Case D 確認
|
||||
NYASH_PHI_FALLBACK_DISABLED=1 cargo test --release --lib 2>&1 | grep "Case D"
|
||||
|
||||
# GroupA のみ
|
||||
cargo test --release --lib loop_continue_break
|
||||
cargo test --release --lib loop_nested
|
||||
cargo test --release --lib loop_return
|
||||
cargo test --release --lib vm_exec_break
|
||||
|
||||
# GroupB のみ
|
||||
cargo test --release --lib mir_stage1_cli
|
||||
|
||||
# GroupC のみ
|
||||
cargo test --release --lib test_lowering_await
|
||||
```
|
||||
|
||||
## 完了条件
|
||||
|
||||
### Phase 84-3 完了
|
||||
|
||||
```bash
|
||||
NYASH_PHI_FALLBACK_DISABLED=1 cargo test --release --lib 2>&1 | grep "Case D" | wc -l
|
||||
# 期待: 2 (GroupB のみ残存)
|
||||
```
|
||||
|
||||
### Phase 84-4 完了
|
||||
|
||||
```bash
|
||||
NYASH_PHI_FALLBACK_DISABLED=1 cargo test --release --lib 2>&1 | grep "Case D" | wc -l
|
||||
# 期待: 1 (GroupC のみ残存)
|
||||
```
|
||||
|
||||
### Phase 84-5 完了
|
||||
|
||||
```bash
|
||||
NYASH_PHI_FALLBACK_DISABLED=1 cargo test --release --lib 2>&1 | grep "Case D"
|
||||
# 期待: 出力なし(0件)
|
||||
|
||||
cargo test --release --lib
|
||||
# 期待: test result: ok
|
||||
```
|
||||
|
||||
## タイムライン
|
||||
|
||||
| Phase | 目標 | 期間 | 削減数 | 残存数 |
|
||||
|-------|-----|-----|-------|-------|
|
||||
| 84-1 | PHI Fallback 無効化テスト | 完了 | - | 12件 |
|
||||
| 84-2 | CopyTypePropagator 実装 | 完了 ✅ | 3件 | 9件 |
|
||||
| 84-3 | Edge Copy 追跡 PHI 型推論 | 1-2日 | 7件 | 2件 |
|
||||
| 84-4 | 多段 PHI 型推論 | 1-2日 | 2件 | 1件 |
|
||||
| 84-5 | await 暫定対応 | 30分 | 1件 | 0件 |
|
||||
|
||||
**合計**: 2-4日で Case D 完全解決見込み
|
||||
|
||||
## グループ別詳細
|
||||
|
||||
### GroupA: Loop 制御フロー PHI(7件)
|
||||
|
||||
**パターン**: Loop + continue/break による Edge Copy 合流
|
||||
|
||||
**テスト一覧**:
|
||||
1. `loop_with_continue_and_break_edge_copy_merge` (ValueId 56)
|
||||
2. `nested_loop_with_multi_continue_break_edge_copy_merge` (ValueId 135)
|
||||
3. `loop_inner_if_multilevel_edge_copy` (ValueId 74)
|
||||
4. `loop_break_and_early_return_edge_copy` (ValueId 40)
|
||||
5. `vm_exec_break_inside_if` (ValueId 27)
|
||||
6. `loop_if_three_level_merge_edge_copy` (ValueId 75)
|
||||
7. (7件合計)
|
||||
|
||||
**解決策**: Edge Copy 追跡 PHI 型推論(Phase 84-3)
|
||||
|
||||
**詳細**: [失敗パターン - GroupA](./phase84-2-failure-patterns.md#groupa-loop-制御フロー-phi7件)
|
||||
|
||||
### GroupB: 多段 PHI 型推論(2件)
|
||||
|
||||
**パターン**: 複数の PHI 命令が連鎖
|
||||
|
||||
**テスト一覧**:
|
||||
1. `mir_stage1_cli_emit_program_min_exec_hits_type_error` (ValueId 7)
|
||||
2. `mir_stage1_cli_emit_program_min_compiles_and_verifies` (ValueId 7)
|
||||
|
||||
**解決策**: 再帰的 PHI 型推論(Phase 84-4)
|
||||
|
||||
**詳細**: [失敗パターン - GroupB](./phase84-2-failure-patterns.md#groupb-多段-phi-型推論2件)
|
||||
|
||||
### GroupC: await 特殊パターン(1件)
|
||||
|
||||
**パターン**: await 式の MIR lowering
|
||||
|
||||
**テスト**:
|
||||
1. `test_lowering_await_expression` (ValueId 2)
|
||||
|
||||
**解決策**: await 特殊ケース処理(Phase 84-5)
|
||||
|
||||
**詳細**: [失敗パターン - GroupC](./phase84-2-failure-patterns.md#groupc-await-特殊パターン1件)
|
||||
|
||||
## ChatGPT Pro 設計相談ポイント
|
||||
|
||||
### 相談1: Edge Copy 追跡の最適化
|
||||
|
||||
- Copy チェーンの追跡深度は 10 で十分か?
|
||||
- 循環 Copy 検出は必要か?
|
||||
- パフォーマンス最適化(キャッシュ戦略)
|
||||
|
||||
### 相談2: 多段 PHI の循環検出
|
||||
|
||||
- 循環 PHI は実際に発生するか?
|
||||
- 発生する場合の処理方法(エラー or Unknown)
|
||||
- visited セットの最適なデータ構造
|
||||
|
||||
### 相談3: await 型推論の長期戦略
|
||||
|
||||
- Phase 67+ async/await システムの型推論設計
|
||||
- Safepoint/Checkpoint 命令の型情報統合方法
|
||||
- 現在の暫定対応が将来の実装を妨げないか
|
||||
|
||||
## 実装チェックリスト
|
||||
|
||||
### Phase 84-3: Edge Copy 追跡
|
||||
|
||||
- [ ] `GenericTypeResolver::resolve_from_phi_with_copy_trace()` 実装
|
||||
- [ ] `find_copy_src()` ヘルパー関数実装
|
||||
- [ ] `trace_copy_chain()` ヘルパー関数実装
|
||||
- [ ] lifecycle.rs 統合(371行目付近)
|
||||
- [ ] テスト実行: GroupA の 7件を確認
|
||||
- [ ] ドキュメント更新
|
||||
|
||||
### Phase 84-4: 多段 PHI 推論
|
||||
|
||||
- [ ] `GenericTypeResolver::resolve_from_phi_recursive()` 実装
|
||||
- [ ] 循環検出ロジック実装(HashSet<ValueId>)
|
||||
- [ ] lifecycle.rs 統合
|
||||
- [ ] テスト実行: GroupB の 2件を確認
|
||||
- [ ] ドキュメント更新
|
||||
|
||||
### Phase 84-5: await 暫定対応
|
||||
|
||||
- [ ] lifecycle.rs に await 特殊ケース追加
|
||||
- [ ] テスト実行: GroupC の 1件を確認
|
||||
- [ ] ドキュメント更新
|
||||
- [ ] Phase 67+ 長期計画メモ作成
|
||||
|
||||
## 関連リソース
|
||||
|
||||
### 過去の分析
|
||||
|
||||
- [Phase 84-1 Case D 分析](./phase84-case-d-detailed-analysis.md) - 最初の 12件分析
|
||||
|
||||
### 実装ファイル
|
||||
|
||||
- `src/mir/phi_core/copy_type_propagator.rs` - Phase 84-2 実装
|
||||
- `src/mir/join_ir/lowering/generic_type_resolver.rs` - 拡張予定
|
||||
- `src/mir/builder/lifecycle.rs` - 型推論統合箇所(371行目)
|
||||
|
||||
### テストファイル
|
||||
|
||||
- `src/tests/loop_continue_break_no_phi_tests.rs` - GroupA-1
|
||||
- `src/tests/loop_nested_no_phi_tests.rs` - GroupA-2,3
|
||||
- `src/tests/loop_return_no_phi_tests.rs` - GroupA-4,6
|
||||
- `src/tests/mir_ctrlflow_break_continue.rs` - GroupA-5
|
||||
- `src/tests/mir_stage1_cli_emit_program_min.rs` - GroupB
|
||||
- `src/mir/mod.rs:363` - GroupC
|
||||
|
||||
## まとめ
|
||||
|
||||
Phase 84-2 の CopyTypePropagator により 12件 → 9件に削減成功。
|
||||
残り 9件は 3つのパターンに分類され、各々に明確な解決策が提案済み。
|
||||
|
||||
Phase 84-3/4/5 の実装により、**Case D を完全解決** できる見込み。
|
||||
|
||||
---
|
||||
|
||||
**次のアクション**: Phase 84-3 の Edge Copy 追跡 PHI 型推論を実装
|
||||
@ -2,11 +2,16 @@
|
||||
|
||||
## TL;DR
|
||||
|
||||
**現状**: 24件の Case D 失敗(52失敗中)
|
||||
**現状**: 9 件の Case D 失敗(Phase 83 + Phase 84-1 + Phase 84-2 実装後)
|
||||
|
||||
**主要原因**: **Const命令の型アノテーション欠如** (58-67%)
|
||||
**主要原因**: PHI 経由の複雑な edge パターン(await/try-catch、多段 PHI チェーンなど)
|
||||
|
||||
**解決策**: `constant.rs` の 5 関数に 5 行追加 → 14-16 件修正(1-2時間で完了)
|
||||
**対応状況**:
|
||||
- Phase 83: MethodReturnHintBox(P3-D)実装で 20 件 → 15 件
|
||||
- Phase 84-1: Const 命令型アノテーション追加で 15 件 → 12 件
|
||||
- Phase 84-2: CopyTypePropagator 導入で 12 件 → 9 件
|
||||
|
||||
**残タスク**: PHI 推論強化(Phase 84-3、PhiTypeResolver)と if_phi フォールバック縮退
|
||||
|
||||
---
|
||||
|
||||
@ -62,30 +67,40 @@ pub fn emit_integer(b: &mut MirBuilder, val: i64) -> ValueId {
|
||||
|
||||
## 実装計画
|
||||
|
||||
### Phase 84-1: Const命令型アノテーション(最優先)
|
||||
### Phase 84-1: Const命令型アノテーション(完了)
|
||||
|
||||
**Status**: ✅ 実装完了(40dfbc68)
|
||||
|
||||
**ファイル**: `src/mir/builder/emission/constant.rs`
|
||||
|
||||
**変更箇所**: 5 関数 × 1 行 = **5 行追加**
|
||||
|
||||
**期待効果**: Case D が 24件 → 8-10件(58-67%削減)
|
||||
**効果**: Case D が 15 件 → 12 件(Const 欠如グループは解消)
|
||||
|
||||
**所要時間**: 1-2 時間(テスト含む)
|
||||
|
||||
**リスク**: 極めて低い(String は既に実装済み)
|
||||
|
||||
### Phase 84-2: Copy命令型伝播(次点)
|
||||
### Phase 84-2: Copy命令型伝播(完了)
|
||||
|
||||
**Status**: ✅ 実装完了(CopyTypePropagator 導入)
|
||||
|
||||
**ファイル**:
|
||||
- `src/mir/builder/ssa/local.rs`
|
||||
- `src/mir/phi_core/loop_phi.rs`
|
||||
- `src/mir/phi_core/if_phi.rs`
|
||||
- `src/mir/phi_core/copy_type_propagator.rs`(新規箱)
|
||||
- `src/mir/phi_core/mod.rs`
|
||||
- `src/mir/builder/lifecycle.rs`
|
||||
|
||||
**期待効果**: Case D が 8-10件 → 2-4件(75-80%削減)
|
||||
**内容**:
|
||||
- `CopyTypePropagator` が MIR 関数内の `Copy { dst, src }` を固定点ループで走査し、
|
||||
`value_types[src]` の型を `value_types[dst]` に伝播(Unknown のみ上書き)。
|
||||
- `finalize_module` 内で return 型推論の前に実行。
|
||||
|
||||
**所要時間**: 1-2 日
|
||||
**効果**:
|
||||
- ベースラインテスト: 489 passed, 34 failed → 494 passed, 33 failed(+5/-1)。
|
||||
- Case D: 12 件 → 9 件(約 25% 削減)。
|
||||
|
||||
**リスク**: 中(既存ロジックとの整合性確認)
|
||||
**箱理論チェック**:
|
||||
- 単一責務(Copy の型伝播のみ)、副作用は `value_types` 更新に限定、PHI/JoinIR には非依存。
|
||||
|
||||
### Phase 84-3: PHI型推論強化(長期)
|
||||
|
||||
@ -99,31 +114,28 @@ pub fn emit_integer(b: &mut MirBuilder, val: i64) -> ValueId {
|
||||
|
||||
## 推奨アクション
|
||||
|
||||
1. **今すぐ Phase 84-1 を実装する**
|
||||
- 最小限の変更で最大の効果
|
||||
- リスクも極めて低い
|
||||
- 1-2 時間で完了
|
||||
1. **Phase 84-1 は完了済み**
|
||||
- Const 命令の型アノテーション欠如グループは解消済み。
|
||||
|
||||
2. **Phase 84-1 の効果を確認後、Phase 84-2 を検討**
|
||||
- 残存ケースのパターンを分析
|
||||
- 必要な箇所にのみ型伝播を追加
|
||||
2. **Phase 84-2 も完了済み**
|
||||
- Copy チェーンだけで説明できる Case D は削減済みで、残りは PHI 主体の複雑ケースに集中。
|
||||
|
||||
3. **Phase 84-3 は本当に必要か検証**
|
||||
- Await/Try-Catch の型推論を別途対応
|
||||
- 汎用的な多段 PHI チェーンは後回し
|
||||
3. **Phase 84-3 は「PHI 強化」を必要最小限で検討**
|
||||
- Await/Try-Catch や多段 PHI チェーンなど、本当に必要なパターンだけを PhiTypeResolver で扱う。
|
||||
|
||||
---
|
||||
|
||||
## 期待される最終結果
|
||||
|
||||
| Phase | Case D 件数 | 修正率 | 所要時間 |
|
||||
|-------|------------|--------|---------|
|
||||
| 現在 | 24 件 | 0% | - |
|
||||
| Phase 84-1 後 | 8-10 件 | 58-67% | 1-2 時間 |
|
||||
| Phase 84-2 後 | 2-4 件 | 92-96% | 1-2 日 |
|
||||
| Phase 84-3 後 | 0-2 件 | 92-100% | 要検討 |
|
||||
| Phase | Case D 件数 | 修正率 | 備考 |
|
||||
|-------|------------|--------|-----|
|
||||
| Phase 82 終了時 | 20 件 | - | lifecycle 修正後 |
|
||||
| Phase 83 後 | 15 件 | 25% | MethodReturnHintBox(P3-D) |
|
||||
| Phase 84-1 後 | 12 件 | 40% | Const 型アノテーション |
|
||||
| Phase 84-2 後 | 9 件 | 55% | CopyTypePropagator |
|
||||
| Phase 84-3 後(目標) | 0-2 件 | 80-100% | PhiTypeResolver(必要最小限) |
|
||||
|
||||
**最終目標**: テスト成功率 90% → **99-100%**
|
||||
**最終目標**: Case D を 0-2 件まで縮小し、`infer_type_from_phi*` を本線から外せる状態にする。
|
||||
|
||||
---
|
||||
|
||||
|
||||
@ -43,6 +43,8 @@ use crate::mir::join_ir::lowering::type_hint_policy::TypeHintPolicy;
|
||||
use crate::mir::join_ir::lowering::generic_type_resolver::GenericTypeResolver;
|
||||
// Phase 83: P3-D 既知メソッド戻り値型推論箱
|
||||
use crate::mir::join_ir::lowering::method_return_hint::MethodReturnHintBox;
|
||||
// Phase 84-2: Copy命令型伝播箱(ChatGPT Pro設計)
|
||||
use crate::mir::phi_core::copy_type_propagator::CopyTypePropagator;
|
||||
|
||||
// Phase 82: dev ガード用ヘルパー - Case 分類ロジック統一化
|
||||
//
|
||||
@ -303,6 +305,12 @@ impl super::MirBuilder {
|
||||
let mut module = self.current_module.take().unwrap();
|
||||
let mut function = self.current_function.take().unwrap();
|
||||
function.metadata.value_types = self.value_types.clone();
|
||||
// Phase 84-2: Copy命令型伝播(return型推論の前に実行)
|
||||
//
|
||||
// Loop exit や If merge の edge copy で発生する型欠如を解消する。
|
||||
// Copy チェーン: v1 → v2 → v3 で v1 の型が既知なら v2, v3 にも伝播。
|
||||
CopyTypePropagator::propagate(&function, &mut self.value_types);
|
||||
|
||||
// Phase 82-5: lifecycle.rs バグ修正 - terminator の Return のみをチェック
|
||||
// 問題: instructions を先に走査すると、中間値(const void 等)を誤って推論対象にしてしまう
|
||||
// 解決: terminator の Return のみをチェックし、実際の戻り値を正しく推論する
|
||||
|
||||
215
src/mir/phi_core/copy_type_propagator.rs
Normal file
215
src/mir/phi_core/copy_type_propagator.rs
Normal file
@ -0,0 +1,215 @@
|
||||
//! Phase 84-2: CopyTypePropagator — Copy命令型伝播箱(ChatGPT Pro設計)
|
||||
//!
|
||||
//! # 責務
|
||||
//!
|
||||
//! Copy命令の型伝播のみを担当する専用箱。
|
||||
//! 固定点ループで Copy チェーン全体に型を伝播させる。
|
||||
//!
|
||||
//! # 設計原則(箱理論)
|
||||
//!
|
||||
//! - **単一責務**: Copy命令の型伝播のみ
|
||||
//! - **固定点ループ**: 変化がなくなるまで反復
|
||||
//! - **副作用限定**: value_types のみ更新
|
||||
//!
|
||||
//! # アルゴリズム
|
||||
//!
|
||||
//! 1. 関数内の全 Copy 命令を走査
|
||||
//! 2. src の型が既知 & dst の型が未知 → dst に型を伝播
|
||||
//! 3. 変化がなくなるまで繰り返す(固定点)
|
||||
//!
|
||||
//! # 使用例
|
||||
//!
|
||||
//! ```ignore
|
||||
//! // lifecycle.rs から呼び出し
|
||||
//! CopyTypePropagator::propagate(&function, &mut value_types);
|
||||
//! ```
|
||||
|
||||
use crate::mir::{MirFunction, MirInstruction, MirType, ValueId};
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
/// Phase 84-2: Copy命令型伝播箱
|
||||
///
|
||||
/// Copy チェーン: v1 → v2 → v3 で v1 の型が既知なら v2, v3 にも伝播。
|
||||
/// Loop exit や If merge の edge copy で発生する型欠如を解消する。
|
||||
pub struct CopyTypePropagator;
|
||||
|
||||
impl CopyTypePropagator {
|
||||
/// Copy命令の型を固定点ループで伝播
|
||||
///
|
||||
/// # 引数
|
||||
///
|
||||
/// - `function`: MIR 関数
|
||||
/// - `value_types`: 型マップ(更新される)
|
||||
///
|
||||
/// # 戻り値
|
||||
///
|
||||
/// 伝播された型の数
|
||||
pub fn propagate(function: &MirFunction, value_types: &mut BTreeMap<ValueId, MirType>) -> usize {
|
||||
let mut total_propagated = 0usize;
|
||||
|
||||
// 固定点ループ: 変化がなくなるまで反復
|
||||
loop {
|
||||
let propagated = Self::propagate_single_pass(function, value_types);
|
||||
if propagated == 0 {
|
||||
break;
|
||||
}
|
||||
total_propagated += propagated;
|
||||
|
||||
// 無限ループ防止(理論上は不要だが安全策)
|
||||
if total_propagated > 10000 {
|
||||
if std::env::var("NYASH_COPY_PROP_DEBUG").is_ok() {
|
||||
eprintln!("[copy_prop] warning: exceeded 10000 propagations, stopping");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if std::env::var("NYASH_COPY_PROP_DEBUG").is_ok() && total_propagated > 0 {
|
||||
eprintln!(
|
||||
"[copy_prop] {} total types propagated for function {}",
|
||||
total_propagated, function.signature.name
|
||||
);
|
||||
}
|
||||
|
||||
total_propagated
|
||||
}
|
||||
|
||||
/// 1パスの型伝播(内部用)
|
||||
fn propagate_single_pass(
|
||||
function: &MirFunction,
|
||||
value_types: &mut BTreeMap<ValueId, MirType>,
|
||||
) -> usize {
|
||||
let mut propagated = 0usize;
|
||||
|
||||
for (_bid, bb) in function.blocks.iter() {
|
||||
for inst in bb.instructions.iter() {
|
||||
if let MirInstruction::Copy { dst, src } = inst {
|
||||
// src の型が既知 & dst の型が未知 → 伝播
|
||||
if !value_types.contains_key(dst) {
|
||||
if let Some(src_type) = value_types.get(src).cloned() {
|
||||
value_types.insert(*dst, src_type.clone());
|
||||
propagated += 1;
|
||||
|
||||
if std::env::var("NYASH_COPY_PROP_TRACE").is_ok() {
|
||||
eprintln!(
|
||||
"[copy_prop] {:?} <- {:?} : {:?}",
|
||||
dst, src, src_type
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
propagated
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::mir::{BasicBlock, BasicBlockId, MirFunction, FunctionSignature, EffectMask};
|
||||
|
||||
fn make_test_function() -> MirFunction {
|
||||
let sig = FunctionSignature {
|
||||
name: "test".to_string(),
|
||||
params: vec![],
|
||||
return_type: MirType::Void,
|
||||
effects: EffectMask::PURE,
|
||||
};
|
||||
MirFunction::new(sig, BasicBlockId::new(0))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_single_copy_propagation() {
|
||||
let mut f = make_test_function();
|
||||
let mut value_types = BTreeMap::new();
|
||||
|
||||
// Setup: v1 has type Integer, Copy v2 <- v1
|
||||
value_types.insert(ValueId(1), MirType::Integer);
|
||||
|
||||
let mut bb = BasicBlock::new(BasicBlockId::new(0));
|
||||
bb.instructions.push(MirInstruction::Copy {
|
||||
dst: ValueId(2),
|
||||
src: ValueId(1),
|
||||
});
|
||||
f.blocks.insert(BasicBlockId::new(0), bb);
|
||||
|
||||
// Propagate
|
||||
let count = CopyTypePropagator::propagate(&f, &mut value_types);
|
||||
|
||||
assert_eq!(count, 1);
|
||||
assert_eq!(value_types.get(&ValueId(2)), Some(&MirType::Integer));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_chain_copy_propagation() {
|
||||
let mut f = make_test_function();
|
||||
let mut value_types = BTreeMap::new();
|
||||
|
||||
// Setup: v1 -> v2 -> v3 chain
|
||||
value_types.insert(ValueId(1), MirType::String);
|
||||
|
||||
let mut bb = BasicBlock::new(BasicBlockId::new(0));
|
||||
bb.instructions.push(MirInstruction::Copy {
|
||||
dst: ValueId(2),
|
||||
src: ValueId(1),
|
||||
});
|
||||
bb.instructions.push(MirInstruction::Copy {
|
||||
dst: ValueId(3),
|
||||
src: ValueId(2),
|
||||
});
|
||||
f.blocks.insert(BasicBlockId::new(0), bb);
|
||||
|
||||
// Propagate (needs 2 iterations for chain)
|
||||
let count = CopyTypePropagator::propagate(&f, &mut value_types);
|
||||
|
||||
assert_eq!(count, 2);
|
||||
assert_eq!(value_types.get(&ValueId(2)), Some(&MirType::String));
|
||||
assert_eq!(value_types.get(&ValueId(3)), Some(&MirType::String));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_no_propagation_when_dst_has_type() {
|
||||
let mut f = make_test_function();
|
||||
let mut value_types = BTreeMap::new();
|
||||
|
||||
// Setup: both v1 and v2 already have types
|
||||
value_types.insert(ValueId(1), MirType::Integer);
|
||||
value_types.insert(ValueId(2), MirType::Bool); // already typed
|
||||
|
||||
let mut bb = BasicBlock::new(BasicBlockId::new(0));
|
||||
bb.instructions.push(MirInstruction::Copy {
|
||||
dst: ValueId(2),
|
||||
src: ValueId(1),
|
||||
});
|
||||
f.blocks.insert(BasicBlockId::new(0), bb);
|
||||
|
||||
// Propagate - should not overwrite existing type
|
||||
let count = CopyTypePropagator::propagate(&f, &mut value_types);
|
||||
|
||||
assert_eq!(count, 0);
|
||||
assert_eq!(value_types.get(&ValueId(2)), Some(&MirType::Bool));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_no_propagation_when_src_unknown() {
|
||||
let mut f = make_test_function();
|
||||
let mut value_types = BTreeMap::new();
|
||||
|
||||
// Setup: v1 has no type, Copy v2 <- v1
|
||||
let mut bb = BasicBlock::new(BasicBlockId::new(0));
|
||||
bb.instructions.push(MirInstruction::Copy {
|
||||
dst: ValueId(2),
|
||||
src: ValueId(1),
|
||||
});
|
||||
f.blocks.insert(BasicBlockId::new(0), bb);
|
||||
|
||||
// Propagate - nothing to propagate
|
||||
let count = CopyTypePropagator::propagate(&f, &mut value_types);
|
||||
|
||||
assert_eq!(count, 0);
|
||||
assert_eq!(value_types.get(&ValueId(2)), None);
|
||||
}
|
||||
}
|
||||
@ -29,6 +29,9 @@ pub mod loopform_builder;
|
||||
// Phase 26-E: PHI SSOT Unification - PhiBuilderBox
|
||||
pub mod phi_builder_box;
|
||||
|
||||
// Phase 84-2: Copy命令型伝播箱(ChatGPT Pro設計)
|
||||
pub mod copy_type_propagator;
|
||||
|
||||
// Phase 35-5: if_body_local_merge 削除(PhiBuilderBoxに吸収済み)
|
||||
// Phase 35-5: phi_invariants 削除(JoinIR Verifierに移譲済み)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user