Files
hakorune/docs/development/current/main/phase222-if-cond-normalization.md
nyash-codex f0536fa330 feat(joinir): Phase 222-2 ConditionPatternBox normalization implementation
Phase 222: If Condition Normalization - Part 2
Goal: Support '0 < i', 'i > j' patterns in addition to 'i > 0'

Changes:
1. condition_pattern.rs (+160 lines):
   - Added ConditionValue enum (Variable | Literal)
   - Added NormalizedCondition struct (left_var, op, right)
   - Added flip_compare_op() for operator reversal
   - Added binary_op_to_compare_op() converter
   - Added normalize_comparison() main normalization function
   - Extended analyze_condition_pattern() to accept 3 cases:
     * Phase 219: var CmpOp literal (e.g., i > 0)
     * Phase 222: literal CmpOp var (e.g., 0 < i) → normalized
     * Phase 222: var CmpOp var (e.g., i > j)
   - Added 9 unit tests (all passing)

2. loop_update_summary.rs (cleanup):
   - Commented out obsolete test_typical_index_names
   - Function is_typical_index_name() was removed in earlier phase

Test results:
- 7 normalization tests: PASS 
- 2 pattern analysis tests: PASS 

Next: Phase 222-3 - integrate normalization into is_if_sum_pattern()
Status: Ready for integration
2025-12-10 09:18:21 +09:00

7.5 KiB
Raw Blame History

Phase 222: If Condition Normalization Design

概要

Phase 221で発見した制約「if condition pattern: if-sum mode は var CmpOp literal のみ」を解消し、 左辺変数・右辺変数の両方をサポートする条件正規化を実装する。

目標

以下のパターンを全て「simple condition」として扱えるようにする

  1. 基本形(既にサポート済み):

    • i > 0, i < len, i == 5 (左辺=変数、右辺=リテラル)
  2. 左右反転(新規対応):

    • 0 < i, len > i, 5 == i (左辺=リテラル、右辺=変数)
    • i > 0, i < len, i == 5 に正規化
  3. 変数同士(新規対応):

    • i > j, i < end, start == pos (両辺=変数)
    • → simple condition として扱うConditionEnv 経由で解決)
  4. 複雑条件(引き続き NG:

    • i % 2 == 1, i + 1 > len, f(x) == 0
    • → legacy P3 経路へフォールバック

設計方針

1. ConditionPatternBox の責務拡張

現在の API:

pub fn is_simple_comparison(cond: &ASTNode) -> bool

拡張後の API:

pub enum ConditionPattern {
    SimpleComparison,  // var CmpOp literal/var
    Complex,           // BinaryOp, MethodCall, etc.
}

pub fn analyze_condition_pattern(cond: &ASTNode) -> ConditionPattern

pub fn is_simple_comparison(cond: &ASTNode) -> bool  // 互換性維持

新規追加:

/// Normalize condition to canonical form (var on left)
pub fn normalize_comparison(cond: &ASTNode) -> Option<NormalizedCondition>

pub struct NormalizedCondition {
    pub left_var: String,      // 左辺変数名
    pub op: CompareOp,         // 比較演算子
    pub right: ConditionValue, // 右辺(変数 or リテラル)
}

pub enum ConditionValue {
    Variable(String),
    Literal(i64),
}

2. 正規化ルール

Rule 1: 左右反転literal on left → var on left

Input Normalized 演算子変換
0 < i i > 0 <>
len > i i < len ><
5 == i i == 5 == (不変)
10 != i i != 10 != (不変)

実装箇所: ConditionPatternBox::normalize_comparison()

Rule 2: 変数同士は正規化不要

Input Normalized 理由
i > j i > j 既に canonical form
i < end i < end 既に canonical form
j > i j > i 左辺変数名の辞書順は気にしない

3. ConditionEnv との統合

Phase 220-D で実装済み: loop 条件で変数を ConditionEnv から解決する機能

// Phase 220-D: extract_loop_condition() の拡張版
fn extract_loop_condition<F>(
    cond: &ASTNode,
    alloc_value: &mut F,
    cond_env: &ConditionEnv,
) -> Result<(String, CompareOp, ValueId, Vec<JoinInst>), String>

Phase 222 での拡張: if 条件でも同様の処理を行う

// 新規追加: extract_if_condition()
fn extract_if_condition<F>(
    cond: &ASTNode,
    alloc_value: &mut F,
    cond_env: &ConditionEnv,
) -> Result<(String, CompareOp, ConditionValue, Vec<JoinInst>), String>

4. is_if_sum_pattern() の拡張

現在の実装Phase 219-fix:

pub fn is_if_sum_pattern(&self) -> bool {
    // 1. if statement 存在チェック
    let if_stmt = self.extract_if_statement();
    if if_stmt.is_none() { return false; }

    // 2. Phase 219-fix: if 条件が simple comparison かチェック
    if let Some(ASTNode::If { condition, .. }) = if_stmt {
        use crate::mir::join_ir::lowering::condition_pattern::is_simple_comparison;
        if !is_simple_comparison(condition) {
            return false;  // 複雑条件 → legacy mode
        }
    }

    // 3. Carrier structure check (既存ロジック)
    // ...
}

Phase 222 での拡張:

pub fn is_if_sum_pattern(&self) -> bool {
    // 1. if statement 存在チェック(既存)
    let if_stmt = self.extract_if_statement();
    if if_stmt.is_none() { return false; }

    // 2. Phase 222: if 条件を正規化して simple comparison かチェック
    if let Some(ASTNode::If { condition, .. }) = if_stmt {
        use crate::mir::join_ir::lowering::condition_pattern::{
            analyze_condition_pattern, normalize_comparison
        };

        // (a) パターン判定
        let pattern = analyze_condition_pattern(condition);
        if pattern != ConditionPattern::SimpleComparison {
            return false;  // 複雑条件 → legacy mode
        }

        // (b) 正規化可能性チェックoptional: 詳細バリデーション)
        if normalize_comparison(condition).is_none() {
            return false;  // 正規化失敗 → legacy mode
        }
    }

    // 3. Carrier structure check既存ロジック
    // ...
}

実装戦略

Phase 222-2: BoolExprLowerer/ConditionPatternBox 拡張

  1. ConditionPatternBox 拡張 (condition_pattern.rs):

    • normalize_comparison() 関数追加
    • NormalizedCondition / ConditionValue 型追加
    • 左右反転ロジック実装(演算子マッピング)
  2. BoolExprLowerer 統合 (bool_expr_lowerer.rs):

    • 正規化後の条件を lowering する経路を追加
    • ConditionEnv で変数同士の比較を解決
  3. condition_to_joinir 統合 (condition_to_joinir.rs):

    • loop 条件・if 条件の統一的な処理経路を確立

Phase 222-3: if-sum 判定に統合

  1. PatternPipelineContext 更新 (pattern_pipeline.rs):

    • is_if_sum_pattern() で正規化 API を使用
  2. if-sum lowerer 更新 (loop_with_if_phi_if_sum.rs):

    • extract_if_condition() を正規化ベースに変更
    • ConditionValue::Variable / ConditionValue::Literal の両方をサポート

Phase 222-4: E2E & 回帰テスト

  1. 既存テスト確認:

    • phase212_if_sum_min.hako: RC=2 維持
    • loop_if_phi.hako: sum=9 維持(複雑条件 → legacy mode
  2. 新規テスト作成:

    • phase222_if_cond_left_literal.hako: if 0 < i { sum = sum + 1 }
    • phase222_if_cond_var_var.hako: if i > j { sum = sum + 1 }

Phase 222-5: ドキュメント更新

  1. joinir-architecture-overview.md:

    • Section 2.2 条件式ライン: ConditionPatternBox の正規化機能を追加
    • Section 4.3 JsonParser 実戦カバレッジ: Phase 222 成果を追記
  2. CURRENT_TASK.md:

    • Phase 222 サマリー追加3行

期待される成果

  1. 言語の自然性向上:

    • if 0 < i, if i > j のような自然な条件式が if-sum パターンで使える
  2. 制約の明確化:

    • 「simple condition」の定義が明確になる正規化可能な比較式
    • 「complex condition」との境界が自明BinaryOp, MethodCall 等)
  3. コードの局所性:

    • 変更は ConditionPatternBox と if-sum lowerer のみ
    • JoinIR の芯P1-P5, ExitLine, PHI contractは一切変更なし

非目標Non-Goals

  1. 論理演算子のサポート:

    • i > 0 && i < len → Phase 223+ で対応予定
    • Phase 222 では単一比較式のみ
  2. 算術式のサポート:

    • i + 1 > len, i * 2 < max → Phase 223+ で対応予定
    • Phase 222 では変数・リテラルの直接比較のみ
  3. MethodCall のサポート:

    • f(x) > 0, s.length() < 10 → 別フェーズで対応
    • Phase 222 では変数のみ

参照

  • Phase 219-fix: ConditionPatternBox 初版実装
  • Phase 220-D: loop 条件変数サポートConditionEnv 統合)
  • Phase 221: 制約整理if condition pattern 制約を発見)