feat(joinir): Phase 171 complete - Trim pattern LoopBodyLocal promotion

Phase 171-C-4/5 + impl-Trim: Full Trim pattern validation infrastructure

## CarrierInfo 統合 (C-4)
- CarrierInfo::merge_from(): Deduplicated carrier merging
- TrimPatternInfo::to_carrier_info(): Conversion helper
- Pattern2/4: Promoted carrier merge integration
- 7 unit tests for merge logic

## TrimLoopHelper 設計 (C-5)
- TrimLoopHelper struct: Trim-specific validation box
- carrier_type(), initial_value(), whitespace helpers
- CarrierInfo::trim_helper() accessor
- 5 unit tests

## Validation-Only Integration (impl-Trim)
- TrimLoopHelper::is_safe_trim(), is_trim_like(), has_valid_structure()
- Pattern2/4: Trim exception route with safety validation
- body_locals extraction from loop body AST
- LoopBodyCarrierPromoter: ASTNode::Local handler extension
- 4 unit tests for safety validation

## Architecture
- Box Theory: TrimLoopHelper is "validation only" (no JoinIR generation)
- Fail-Fast: Non-Trim LoopBodyLocal immediately rejected
- Whitelist approach: Only Trim pattern bypasses LoopBodyLocal restriction

Tests: 16 new unit tests, all passing
E2E: test_trim_main_pattern.hako validation successful

Next: Phase 172 - Actual JoinIR lowering for Trim pattern

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
nyash-codex
2025-12-08 02:41:53 +09:00
parent a1f3d913f9
commit 14c84fc583
9 changed files with 939 additions and 12 deletions

View File

@ -254,4 +254,171 @@ loop(start < end && is_whitespace) {
- `is_substring_method_call()`: Detects `substring()` method calls
- `extract_equality_literals()`: Extracts string literals from OR chains
- `TrimPatternInfo`: Captures pattern details for carrier promotion
- Phase 171-C-3: Integration with Pattern 2/4 routing
- Phase 171-C-3: Integration with Pattern 2/4 routing complete
- Phase 171-C-4: ✅ CarrierInfo integration complete (2025-12-07)
- `CarrierInfo::merge_from()`: Deduplicated carrier merging with deterministic sorting
- `TrimPatternInfo::to_carrier_info()`: Conversion to CarrierInfo with TrimLoopHelper
- Pattern 2/4 lowerers: Promoted carrier merging in `Promoted` branch
- 7 unit tests: Merge success/failure/duplication/determinism validation
- Phase 171-C-5: ✅ TrimLoopHelper design complete (2025-12-07)
- `TrimLoopHelper` struct: Encapsulates Trim pattern lowering logic
- `CarrierInfo::trim_helper()`: Accessor for pattern-specific helper
- Module export: `mod.rs` updated with `pub use TrimLoopHelper`
- 4 unit tests: Helper creation and accessor validation
---
## Phase 171-C-3/4/5: Responsibility Positions and Data Flow
### Responsibility Separation Principle
The promotion system follows Box Theory's single responsibility principle:
1. **router.rs**: Pattern table + `can_lower()`/`lower()` call abstraction (no Scope/condition logic)
2. **Pattern 2/4 lowerer**: Holds LoopScope / ConditionScope / CarrierInfo / Promoter
3. **LoopBodyCarrierPromoter**: LoopBodyLocal handling specialist box
4. **TrimLoopHelper**: Trim pattern-specific helper (future extensibility)
### Data Flow Diagram
```
LoopConditionScopeBox::analyze()
has_loop_body_local()?
↓ true
LoopBodyCarrierPromoter::try_promote()
↓ Promoted { trim_info }
TrimPatternInfo::to_carrier_info()
CarrierInfo::merge_from()
TrimLoopHelper (attached to CarrierInfo)
Pattern 2/4 lowerer (JoinIR generation)
```
### Implementation Locations
**Phase 171-C-4 Changes**:
- `src/mir/join_ir/lowering/carrier_info.rs`: Added `merge_from()`, `trim_helper()`, `trim_helper` field
- `src/mir/loop_pattern_detection/loop_body_carrier_promoter.rs`: Updated `to_carrier_info()` to attach TrimLoopHelper
- `src/mir/builder/control_flow/joinir/patterns/pattern2_with_break.rs`: Promoted branch now merges carriers
- `src/mir/builder/control_flow/joinir/patterns/pattern4_with_continue.rs`: Promoted branch now merges carriers
**Phase 171-C-5 Changes**:
- `src/mir/loop_pattern_detection/trim_loop_helper.rs`: NEW - TrimLoopHelper struct with 4 unit tests
- `src/mir/loop_pattern_detection/mod.rs`: Export TrimLoopHelper module
---
## Phase 171-impl-Trim: Trim 特例の実戦投入
**Date**: 2025-12-08
**Status**: ✅ Validation complete
**Purpose**: Safely integrate Trim pattern detection into JoinIR pipeline with validation-only implementation
### 設計原則
> **「LoopBodyLocal を全面解禁」ではなく、Trim パターンだけを箱経由でホワイトリストに載せる**
### 安全機構
1. `TrimLoopHelper::is_safe_trim()` - 構造的に安全か判定
2. `TrimLoopHelper::is_trim_like()` - Trim パターンに合致するか判定
3. `TrimLoopHelper::has_valid_structure()` - 構造チェック
### データフローTrim 特例)
```
LoopConditionScopeBox::analyze()
has_loop_body_local() == true
LoopBodyCarrierPromoter::try_promote()
↓ Promoted { trim_info }
TrimPatternInfo::to_carrier_info()
CarrierInfo::merge_from()
carrier_info.trim_helper()?.is_safe_trim()
↓ true
✅ Validation Success (TODO: JoinIR lowering in Phase 172)
```
### 実装状況
- [x] Phase 171-impl-Trim-1: 受け入れ条件を 1 箇所に ✅
- `TrimLoopHelper::is_safe_trim()` implemented
- `Pattern2/4` で Trim 特例ルート実装
- Fail-Fast on unsafe patterns
- [x] Phase 171-impl-Trim-2: TrimLoopHelper 判定メソッド ✅
- `is_trim_like()`, `has_valid_structure()` implemented
- 4+ ユニットテスト追加 (9 tests total, all passing)
- [x] Phase 171-impl-Trim-3: E2E テスト ✅
- `local_tests/test_trim_main_pattern.hako` validated
- 出力: `[pattern2/trim] Safe Trim pattern detected`
- 出力: `✅ Trim pattern validation successful!`
- Status: Validation-only (JoinIR lowering deferred to Phase 172)
- [x] Phase 171-impl-Trim-4: ドキュメント更新 ✅
- `phase171-pattern5-loop-inventory.md` updated
- `CURRENT_TASK.md` status tracking
### 実装詳細
**ファイル変更**:
1. `src/mir/loop_pattern_detection/trim_loop_helper.rs`
- `is_safe_trim()`, `is_trim_like()`, `has_valid_structure()` methods
- 4 new unit tests for safety validation
2. `src/mir/builder/control_flow/joinir/patterns/pattern2_with_break.rs`
- Trim exception route with safety check
- `body_locals` extraction from loop body AST
- Validation message for successful detection
3. `src/mir/builder/control_flow/joinir/patterns/pattern4_with_continue.rs`
- Same Trim exception logic as Pattern2
- `body_locals` extraction from normalized loop body
4. `src/mir/loop_pattern_detection/loop_body_carrier_promoter.rs`
- `ASTNode::Local { variables, initial_values, .. }` handler
- Support for `local ch = expr` pattern recognition
### テスト結果
**ユニットテスト**: ✅ 9/9 passing
- `test_is_safe_trim`
- `test_is_safe_trim_empty_carrier`
- `test_is_safe_trim_no_whitespace`
- `test_has_valid_structure`
- (+ 5 existing tests)
**E2E テスト**: ✅ Validation successful
```
[pattern2/check] Analyzing condition scope: 3 variables
[pattern2/check] 'ch': LoopBodyLocal
[pattern2/promoter] LoopBodyLocal 'ch' promoted to carrier 'is_ch_match'
[pattern2/trim] Safe Trim pattern detected, bypassing LoopBodyLocal restriction
[pattern2/trim] Carrier: 'is_ch_match', original var: 'ch', whitespace chars: ["\r", "\n", "\t", " "]
✅ Trim pattern validation successful! Carrier 'is_ch_match' ready for Phase 172 implementation.
(Pattern detection: PASS, Safety check: PASS, JoinIR lowering: TODO)
```
**ビルド結果**: ✅ Success
- `cargo build --release`: Success
- `cargo test --lib trim_loop_helper`: 9/9 passing
### 重要な発見
1. **AST構造の理解**: `local ch = expr``ASTNode::Local { variables, initial_values, .. }` として表現される
2. **body_locals 抽出**: Pattern2/4 で `LoopScopeShape.body_locals` を AST から抽出する必要があった
3. **段階的実装**: Validation-only approach で安全性を先に確立し、JoinIR lowering は Phase 172 に分離
### 次のステップ (Phase 172)
- [ ] Phase 172-1: Trim pattern JoinIR generation
- Carrier initialization code
- Carrier update logic (substring + OR chain → bool)
- Exit PHI mapping
- [ ] Phase 172-2: JsonParser loops への展開
- Similar pattern recognition
- Generalized carrier promotion