Files
hakorune/docs/development/current/main/phase131-11-case-c-summary.md
nyash-codex 7dfd6ff1d9 feat(llvm): Phase 131-11-H/12 - ループキャリアPHI型修正 & vmap snapshot SSOT
## Phase 131-11-H: ループキャリアPHI型修正
- PHI生成時に初期値(entry block)の型のみ使用
- backedge の値を型推論に使わない(循環依存回避)
- NYASH_CARRIER_PHI_DEBUG=1 でトレース

## Phase 131-12-P0: def_blocks 登録 & STRICT エラー化
- safe_vmap_write() で PHI 上書き保護
- resolver miss を STRICT でエラー化(フォールバック 0 禁止)
- def_blocks 自動登録

## Phase 131-12-P1: vmap_cur スナップショット実装
- DeferredTerminator 構造体(block, term_ops, vmap_snapshot)
- Pass A で vmap_cur をスナップショット
- Pass C でスナップショット復元(try-finally)
- STRICT モード assert

## 結果
-  MIR PHI型: Integer(正しい)
-  VM: Result: 3
-  vmap snapshot 機構: 動作確認
- ⚠️ LLVM: Result: 0(別のバグ、次Phase で調査)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 21:28:41 +09:00

323 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Phase 131-11: Case C 本命タスク - 調査完了レポート
**Date**: 2025-12-14
**Status**: Active - Pattern detection landed; follow-ups tracked
---
## 🎯 Task Summary
**Goal**: Make `loop(true) { ... break ... continue }` compile and run in JoinIR
**Test File**: `apps/tests/llvm_stage3_loop_only.hako`
## 状態アップデートPhase 131-11 AC / H
- Phase 131-11 AC: `loop(true)` + break/continue を専用パターン(`pattern5_infinite_early_exit.rs`)へルーティングできる状態まで到達(検出/shape guard
- Phase 131-11 H: ループキャリアPHIの型が循環で壊れる問題に対して、PHI作成時に entry(init) 側の型のみを seed する修正が入った。
- 参考(原因レポート): `docs/development/current/main/phase-131-11-g-phi-type-bug-report.md`
- PHI/型デバッグ: `docs/reference/environment-variables.md``NYASH_PHI_TYPE_DEBUG` / `NYASH_PHI_META_DEBUG`
現状メモ:
- VM では期待値に一致するが、LLVM では結果が一致しないケースが残っている(別トピックとして棚卸し/切り分けが必要)。
---
## 🔍 Root Cause (完全解明済み)
### 問題の核心
**Case C fails because**:
1. **Pattern Gap**: `loop(true)` (infinite loop) is NOT recognized by any of Patterns 1-4
2. **Loop Variable Extraction Fails**: `extract_loop_variable_from_condition()` expects binary comparison (`i < 3`), not boolean literal (`true`)
3. **Classification Priority Bug**: `has_continue = true` routes to Pattern 4, but Pattern 4 expects a loop variable
### Failure Flow (5 Steps)
```
1. LoopPatternContext::new()
└─ has_continue=true, has_break=true (✅ detected correctly)
2. classify(features)
└─ Returns Pattern4Continue (❌ WRONG - should be Pattern2 or new Pattern5)
3. Pattern4::can_lower()
└─ Tries extract_loop_variable_from_condition(BoolLiteral(true))
4. extract_loop_variable_from_condition()
└─ ❌ Error: "Unsupported loop condition pattern"
└─ Expected: BinaryOp comparison (i < 3)
└─ Actual: BoolLiteral(true)
5. Pattern falls through
└─ No pattern matches → freeze() error
```
### 現在のパターン対応表
| Pattern | Condition Type | Break | Continue | Supported? |
|---------|---------------|-------|----------|------------|
| Pattern 1 | Comparison (`i < 3`) | ❌ | ❌ | ✅ |
| Pattern 2 | Comparison (`i < 3`) | ✅ | ❌ | ✅ |
| Pattern 3 | Comparison (`i < 3`) | ❌ | ❌ | ✅ |
| Pattern 4 | Comparison (`i < 3`) | ❌ | ✅ | ✅ |
| **Case C** | **Boolean (`true`)** | ✅ | ✅ | ❌ **GAP!** |
---
## 💡 Recommended Solution: Dedicated “InfiniteEarlyExit” pattern (recommended)
**Approach**: Add `is_infinite_loop` feature + fix classification, then add a dedicated JoinIR loop pattern module for `loop(true)` with early-exit.
### Why this approach?
1. **Correctness-first**: `has_break && has_continue` must not route to Pattern 4 (Pattern 4 assumes a loop variable in the condition).
2. **No naming collision**: Existing “Trim/P5” already exists; avoid calling this “Pattern 5”.
3. **Minimal + Fail-Fast**: Support exactly the Case C skeleton first, reject everything else.
4. **Keeps Pattern2 invariants**: Pattern2 is “break but no continue”; extending it to include continue blurs its contract.
### Implementation Strategy (3 Phases)
#### Phase 131-11-A: Feature Detection (30 min)
**Add `is_infinite_loop` field to LoopFeatures**
```rust
// src/mir/loop_pattern_detection/mod.rs
pub struct LoopFeatures {
pub has_break: bool,
pub has_continue: bool,
pub has_if: bool,
pub has_if_else_phi: bool,
pub carrier_count: usize,
pub break_count: usize,
pub continue_count: usize,
+ pub is_infinite_loop: bool, // NEW: true for loop(true)
pub update_summary: Option<LoopUpdateSummary>,
}
```
**Update extract_features to detect loop(true)**
```rust
// src/mir/builder/control_flow/joinir/patterns/ast_feature_extractor.rs
pub(crate) fn extract_features(
+ condition: &ASTNode, // NEW: need condition for infinite loop detection
body: &[ASTNode],
has_continue: bool,
has_break: bool
) -> LoopFeatures {
+ let is_infinite_loop = matches!(condition, ASTNode::BoolLiteral { value: true, .. });
// ... rest
}
```
**Update callers**
```rust
// src/mir/builder/control_flow/joinir/patterns/router.rs (LoopPatternContext::new)
- let features = ast_features::extract_features(body, has_continue, has_break);
+ let features = ast_features::extract_features(condition, body, has_continue, has_break);
```
#### Phase 131-11-B: Classification Fix (15 min)
**Fix classify() so break+continue does not misroute to Pattern 4**
```rust
// src/mir/loop_pattern_detection/mod.rs
pub fn classify(features: &LoopFeatures) -> LoopPatternKind {
+ // NEW: Case C core: infinite loop + break + continue → dedicated pattern kind
+ if features.is_infinite_loop && features.has_break && features.has_continue {
+ return LoopPatternKind::InfiniteEarlyExit;
+ }
// Pattern 4: Continue (existing)
if features.has_continue && !features.has_break {
return LoopPatternKind::Pattern4Continue;
}
// ... rest unchanged
}
```
#### Phase 131-11-C: InfiniteEarlyExit lowering (2-3 hours)
**Add a dedicated pattern module and keep Pattern2 untouched**
```rust
// src/mir/builder/control_flow/joinir/patterns/pattern_infinite_early_exit.rs
pub fn can_lower(ctx: &LoopPatternContext) -> bool {
matches!(ctx.pattern_kind, LoopPatternKind::InfiniteEarlyExit)
}
pub fn lower(builder: &mut MirBuilder, ctx: &LoopPatternContext) -> Result<Option<ValueId>, String> {
// Shape guard (Fail-Fast):
// - condition must be `true` literal
// - exactly one break site and one continue site
// - no nested loop / nested break/continue
// Lowering outline:
// - header: unconditional enter step
// - step: body core → break-check → continue (tailcall to step) / exit
unimplemented!()
}
```
---
## 📋 Modified Files Summary
**Total**: 56 files modified (+1 new pattern module)
1. **`src/mir/loop_pattern_detection/mod.rs`**
- Add `is_infinite_loop: bool` field to `LoopFeatures` struct
- Add `LoopPatternKind::InfiniteEarlyExit`
- Update `classify()` (infinite+break+continue must not route to Pattern4)
2. **`src/mir/builder/control_flow/joinir/patterns/ast_feature_extractor.rs`**
- Update `extract_features()` signature (add `condition: &ASTNode` param)
- Detect `loop(true)` in condition
3. **`src/mir/builder/control_flow/joinir/patterns/router.rs`**
- Pass condition into `extract_features()`
- Ensure `LOOP_PATTERNS` table routes `InfiniteEarlyExit`
4. **`src/mir/builder/control_flow/joinir/patterns/mod.rs`**
- `pub(in crate::mir::builder) mod pattern_infinite_early_exit;` (new module export)
5. **`src/mir/builder/control_flow/joinir/patterns/pattern_infinite_early_exit.rs`** (NEW)
- Shape guard + lowering implementation for Case C
---
## 🧪 Test Strategy
### Unit Tests
**File**: `src/mir/loop_pattern_detection/mod.rs` (tests module)
```rust
#[test]
fn test_classify_infinite_loop_with_break() {
let features = LoopFeatures {
has_break: true,
has_continue: false,
is_infinite_loop: true,
// ... other fields
};
assert_eq!(classify(&features), LoopPatternKind::Pattern2Break);
}
#[test]
fn test_classify_infinite_loop_with_continue_unsupported() {
let features = LoopFeatures {
has_break: false,
has_continue: true,
is_infinite_loop: true,
// ... other fields
};
assert_eq!(classify(&features), LoopPatternKind::Unknown);
}
```
### Integration Tests
**Case C Minimal** (`/tmp/case_c_minimal.hako`):
```nyash
static box Main {
main() {
local i = 0
loop (true) {
i = i + 1
if i == 3 { break }
}
print(i)
return 0
}
}
```
Expected: Prints `3`
**Case C Full** (`apps/tests/llvm_stage3_loop_only.hako`):
```nyash
loop (true) {
counter = counter + 1
if counter == 3 { break }
continue
}
```
Expected: MIR compile error (Fail-Fast - not supported yet)
### End-to-End Test
```bash
# VM test
./target/release/hakorune /tmp/case_c_minimal.hako
# Expected output: 3
# LLVM test (after Phase 131-11 complete)
tools/build_llvm.sh /tmp/case_c_minimal.hako -o /tmp/case_c_exe
/tmp/case_c_exe
# Expected output: 3
echo $?
# Expected exit code: 0
```
---
## ⏱️ Timeline Estimate
**Phase 131-11-A**: 30 minutes (Feature Detection)
**Phase 131-11-B**: 15 minutes (Classification Fix)
**Phase 131-11-C**: 2-3 hours (Pattern 2 Extension)
**Total**: 3-4 hours to complete Phase 131-11
---
## ✅ Success Criteria
**Phase 131-11 Complete** when:
1. ✅ Case C (minimal) compiles to MIR successfully
2. ✅ Case C (minimal) passes VM execution (prints `3`)
3. ✅ Case C (minimal) passes LLVM AOT (EMIT + LINK + RUN)
4. ✅ Case C (with continue) fails with clear error message (Fail-Fast)
5. ✅ No regression in Cases A, B, B2 (all still pass)
6. ✅ Unit tests for classification pass
---
## 📚 References
**Detailed Analysis**: [case-c-infinite-loop-analysis.md](./case-c-infinite-loop-analysis.md) (13KB, complete investigation)
**SSOT**: [phase131-3-llvm-lowering-inventory.md](./phase131-3-llvm-lowering-inventory.md) (updated with root cause)
**Related Files**:
- Pattern Detection: `src/mir/loop_pattern_detection/mod.rs`
- Feature Extraction: `src/mir/builder/control_flow/joinir/patterns/ast_feature_extractor.rs`
- Pattern Router: `src/mir/builder/control_flow/joinir/patterns/router.rs`
- Pattern 2 Lowering: `src/mir/builder/control_flow/joinir/patterns/pattern2_with_break.rs`
---
## 🚦 Next Steps
**For ChatGPT** (Implementation):
1. Start with Phase 131-11-A (Feature Detection) - 30 min
2. Proceed to Phase 131-11-B (Classification Fix) - 15 min
3. Implement Phase 131-11-C (Pattern 2 Extension) - 2-3 hours
4. Run unit tests + integration tests
5. Verify end-to-end LLVM AOT path
**For Claude** (Review):
- Review implementation for Box Theory alignment (Fail-Fast, modular boundaries)
- Verify no regression in existing patterns
- Check for code duplication opportunities (Pattern 2 finite vs infinite)
---
**Last Updated**: 2025-12-14
**Phase**: 131-11 (Case C本命タスク)
**Status**: 🎯 Ready for Implementation