feat(joinir): Phase 171-C-2 Trim pattern detection in LoopBodyCarrierPromoter

Implements the Trim pattern detection logic for carrier promotion:

- find_definition_in_body(): Iterative AST traversal to locate variable definitions
- is_substring_method_call(): Detects substring() method calls
- extract_equality_literals(): Extracts string literals from OR chains (ch == " " || ch == "\t")
- TrimPatternInfo: Captures detected pattern details for carrier promotion

This enables Pattern 5 to detect trim-style loops:
```hako
loop(start < end) {
    local ch = s.substring(start, start+1)
    if ch == " " || ch == "\t" || ch == "\n" || ch == "\r" {
        start = start + 1
    } else {
        break
    }
}
```

Unit tests cover:
- Simple and nested definition detection
- substring method call detection
- Single and chained equality literal extraction
- Full Trim pattern detection with 2-4 whitespace characters

Next: Phase 171-C-3 integration with Pattern 2/4 routing

🤖 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-07 23:09:25 +09:00
parent 907a54b55c
commit 88400e7e22
11 changed files with 2334 additions and 4668 deletions

View File

@ -91,12 +91,50 @@ JoinIR ラインで守るべきルールを先に書いておくよ:
- `ConditionEnv` 経由で「変数名 → JoinIR ValueId」のみを見る。
- host 側の ValueId は `ConditionBinding { name, host_value, join_value }` として JoinInlineBoundary に記録する。
- **LoopConditionScopeBox設計中**
- 予定ファイル: `src/mir/loop_pattern_detection/loop_condition_scope.rs`
- **LoopConditionScopeBoxPhase 170-D 実装済み**
- ファイル: `src/mir/loop_pattern_detection/loop_condition_scope.rs`
- 責務:
- 条件式に登場する変数が、ループパラメータLoopParam/ループ外ローカルOuterLocal/ループ本体ローカルLoopBodyLocalのどれかを分類する。
- Pattern2/4 が「対応してよい条件のスコープ」を判定するための箱。
- ループ本体ローカルを条件に含む高度なパターンは、将来の Pattern5+ で扱う設計とし、現状は FailFast で明示的に弾く
- ループ本体ローカルを条件に含む高度なパターンは、**LoopBodyCarrierPromoterPhase 171** で carrier に昇格させる
- **Bug Fix2025-12-07**:
- 関数パラメータが LoopBodyLocal と誤分類される問題を修正。
- `condition_var_analyzer.rs``is_outer_scope_variable()` で、`variable_definitions` に含まれない変数を OuterLocal とする。
- これにより JsonParserBox などの関数パラメータを含むループが正しく動作。
- **LoopBodyCarrierPromoterPhase 171-C-1 実装中)**
- ファイル: `src/mir/loop_pattern_detection/loop_body_carrier_promoter.rs`
- 責務:
- LoopBodyLocal 変数を carrier に昇格させ、Pattern 2/4 で処理可能にする。
- 昇格成功 → Pattern 2/4 にルーティング(新しい carrier 情報付き)。
- 昇格失敗 → UnsupportedPatternFail-Fast
- **Pattern 2/4 + Pattern 5 の境界線**:
- **Pattern 2/4 の守備範囲**: LoopParam + OuterLocal のみ。LoopBodyLocal 条件は受け入れない。
- **Pattern 5 の守備範囲**: LoopBodyLocal を carrier に昇格。成功なら Pattern 2/4 へ委譲。
- **境界**: LoopConditionScopeBox が LoopBodyLocal 検出 → LoopBodyCarrierPromoter で昇格試行。
- **Design StrategyDesign D: Evaluated Bool Carrier**:
- `ch == " " || ...` のような条件を `is_whitespace` (bool carrier) に変換。
- 昇格例:
```hako
// Before (blocked)
loop(start < end) {
local ch = s.substring(start, start+1)
if ch == " " || ... { ... } else { break }
}
// After (Pattern2 compatible)
local is_whitespace = true
loop(start < end && is_whitespace) {
local ch = s.substring(start, start+1)
is_whitespace = (ch == " " || ...)
if is_whitespace { ... } else { break }
}
```
- **Current StatusPhase 171-C-1**:
- ✅ API 定義: `PromotionRequest` → `PromotionResult`
- ✅ Skeleton 実装: LoopBodyLocal 検出・定義探索
- ⏳ Promotion logic: Phase 171-C-2 で Trim パターンの実際の昇格ロジックを実装予定
- **詳細**: `docs/development/current/main/phase171-pattern5-loop-inventory.md`
### 2.3 キャリア / Exit / Boundary ライン