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
7.5 KiB
7.5 KiB
Phase 222: If Condition Normalization Design
概要
Phase 221で発見した制約「if condition pattern: if-sum mode は var CmpOp literal のみ」を解消し、
左辺変数・右辺変数の両方をサポートする条件正規化を実装する。
目標
以下のパターンを全て「simple condition」として扱えるようにする:
-
基本形(既にサポート済み):
i > 0,i < len,i == 5(左辺=変数、右辺=リテラル)
-
左右反転(新規対応):
0 < i,len > i,5 == i(左辺=リテラル、右辺=変数)- →
i > 0,i < len,i == 5に正規化
-
変数同士(新規対応):
i > j,i < end,start == pos(両辺=変数)- → simple condition として扱う(ConditionEnv 経由で解決)
-
複雑条件(引き続き 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 拡張
-
ConditionPatternBox 拡張 (
condition_pattern.rs):normalize_comparison()関数追加NormalizedCondition/ConditionValue型追加- 左右反転ロジック実装(演算子マッピング)
-
BoolExprLowerer 統合 (
bool_expr_lowerer.rs):- 正規化後の条件を lowering する経路を追加
- ConditionEnv で変数同士の比較を解決
-
condition_to_joinir 統合 (
condition_to_joinir.rs):- loop 条件・if 条件の統一的な処理経路を確立
Phase 222-3: if-sum 判定に統合
-
PatternPipelineContext 更新 (
pattern_pipeline.rs):is_if_sum_pattern()で正規化 API を使用
-
if-sum lowerer 更新 (
loop_with_if_phi_if_sum.rs):extract_if_condition()を正規化ベースに変更- ConditionValue::Variable / ConditionValue::Literal の両方をサポート
Phase 222-4: E2E & 回帰テスト
-
既存テスト確認:
- phase212_if_sum_min.hako: RC=2 維持
- loop_if_phi.hako: sum=9 維持(複雑条件 → legacy mode)
-
新規テスト作成:
- phase222_if_cond_left_literal.hako:
if 0 < i { sum = sum + 1 } - phase222_if_cond_var_var.hako:
if i > j { sum = sum + 1 }
- phase222_if_cond_left_literal.hako:
Phase 222-5: ドキュメント更新
-
joinir-architecture-overview.md:
- Section 2.2 条件式ライン: ConditionPatternBox の正規化機能を追加
- Section 4.3 JsonParser 実戦カバレッジ: Phase 222 成果を追記
-
CURRENT_TASK.md:
- Phase 222 サマリー追加(3行)
期待される成果
-
言語の自然性向上:
if 0 < i,if i > jのような自然な条件式が if-sum パターンで使える
-
制約の明確化:
- 「simple condition」の定義が明確になる(正規化可能な比較式)
- 「complex condition」との境界が自明(BinaryOp, MethodCall 等)
-
コードの局所性:
- 変更は ConditionPatternBox と if-sum lowerer のみ
- JoinIR の芯(P1-P5, ExitLine, PHI contract)は一切変更なし
非目標(Non-Goals)
-
論理演算子のサポート:
i > 0 && i < len→ Phase 223+ で対応予定- Phase 222 では単一比較式のみ
-
算術式のサポート:
i + 1 > len,i * 2 < max→ Phase 223+ で対応予定- Phase 222 では変数・リテラルの直接比較のみ
-
MethodCall のサポート:
f(x) > 0,s.length() < 10→ 別フェーズで対応- Phase 222 では変数のみ
参照
- Phase 219-fix: ConditionPatternBox 初版実装
- Phase 220-D: loop 条件変数サポート(ConditionEnv 統合)
- Phase 221: 制約整理(if condition pattern 制約を発見)