Phase 92 P2-2完了:ConditionalStepのcondition(ch == '\\'など)でbody-local変数をサポート ## 主要変更 ### 1. condition_lowerer.rs拡張 - `lower_condition_to_joinir`に`body_local_env`パラメータ追加 - 変数解決優先度:ConditionEnv → LoopBodyLocalEnv - すべての再帰ヘルパー(comparison, logical_and, logical_or, not, value_expression)対応 ### 2. conditional_step_emitter.rs修正 - `emit_conditional_step_update`に`body_local_env`パラメータ追加 - condition loweringにbody-local環境を渡す ### 3. loop_with_break_minimal.rs修正 - break condition loweringをbody-local init の**後**に移動(line 411) - header_break_lowering::lower_break_conditionにbody_local_env渡す - emit_conditional_step_updateにbody_local_env渡す(line 620) ### 4. header_break_lowering.rs修正 - `lower_break_condition`に`body_local_env`パラメータ追加 - scope_managerにbody-local環境を渡す ### 5. 全呼び出し箇所修正 - expr_lowerer.rs (2箇所) - method_call_lowerer.rs (2箇所) - loop_with_if_phi_if_sum.rs (3箇所) - loop_with_continue_minimal.rs (1箇所) - carrier_update_emitter.rs (1箇所・legacy) ## アーキテクチャ改善 ### Break Condition Lowering順序修正 旧: Header → **Break Cond** → Body-local Init 新: Header → **Body-local Init** → Break Cond 理由:break conditionが`ch == '\"'`のようにbody-local変数を参照する場合、body-local initが先に必要 ### 変数解決優先度(Phase 92 P2-2) 1. ConditionEnv(ループパラメータ、captured変数) 2. LoopBodyLocalEnv(body-local変数like `ch`) ## テスト ### ビルド ✅ cargo build --release成功(30 warnings、0 errors) ### E2E ⚠️ body-local promotion問題でブロック(Phase 92範囲外) - Pattern2はbody-local変数をcarrier promotionする必要あり - 既存パターン(A-3 Trim, A-4 DigitPos)に`ch = get_char(i)`が該当しない - **Phase 92 P2-2目標(condition loweringでbody-local変数サポート)は達成** ## 次タスク(Phase 92 P3以降) - body-local variable promotion拡張(Pattern2で`ch`のような変数を扱う) - P5b E2Eテスト完全動作確認 ## Phase 92 P2-2完了 ✅ Body-local変数のcondition lowering対応完了 ✅ ConditionalStepでbody-local変数参照可能 ✅ Break condition lowering順序修正
6.3 KiB
6.3 KiB
Phase 92 P0-2: Skeleton Integration to LoopPatternContext (Option A)
概要
ConditionalStep情報をPattern2 lowererに渡すため、LoopPatternContextにSkeletonフィールドを追加しました。
Update(Phase 92 P1)
Phase 92 P1 で境界を整理し、routing 層から skeleton を取り除いた。
本ドキュメントは「P0-2 で一度試した配線(Option A)」の記録として残し、現行の入口は docs/development/current/main/phases/phase-92/README.md を SSOT とする。
SSOT原則
中心的なルール: Canonicalizerが一度検出したConditionalStep情報を、lowering側で再検出しない。Skeleton経由でUpdate情報を渡す。
実装内容
1. router.rs - LoopPatternContextの拡張
追加フィールド:
/// Phase 92 P0-2: Optional LoopSkeleton from canonicalizer
/// This provides ConditionalStep information for Pattern2 lowering.
/// None if canonicalizer hasn't run yet (backward compatibility).
/// SSOT Principle: Avoid re-detecting ConditionalStep in lowering phase.
pub skeleton: Option<&'a LoopSkeleton>,
新規メソッド:
/// Phase 92 P0-2: Set skeleton (for canonicalizer integration)
pub(crate) fn with_skeleton(mut self, skeleton: &'a LoopSkeleton) -> Self {
self.skeleton = Some(skeleton);
self
}
変更内容:
skeleton: Noneをデフォルト値としてnew()に追加- 後方互換性を保つため、Optionalとして実装
2. parity_checker.rs - Skeletonの取得と返却
関数シグネチャ変更:
// Before:
pub(super) fn verify_router_parity(...) -> Result<(), String>
// After (Phase 92 P0-2):
pub(super) fn verify_router_parity(...)
-> (Result<(), String>, Option<LoopSkeleton>)
変更理由:
- 既に
canonicalize_loop_expr()を呼び出していた - Skeletonを破棄せず、呼び出し側に返すことで再利用可能に
- パリティチェックとSkeleton取得の2つの責務を同時に実行
3. routing.rs - Skeletonのコンテキストへの設定
実装パターン:
// Phase 92 P0-2: Get skeleton from canonicalizer for Option A
let skeleton_holder: Option<crate::mir::loop_canonicalizer::LoopSkeleton>;
if crate::config::env::joinir_dev_enabled() {
let (result, skeleton_opt) = self.verify_router_parity(condition, body, func_name, &ctx);
result?;
skeleton_holder = skeleton_opt;
if skeleton_holder.is_some() {
// Set skeleton reference in context (must use holder lifetime)
ctx.skeleton = skeleton_holder.as_ref();
}
} else {
skeleton_holder = None;
}
設計ポイント:
skeleton_holderでライフタイムを延長ctx.skeleton = skeleton_holder.as_ref()で参照を設定joinir_dev_enabled()時のみ有効(パフォーマンス考慮)
4. pattern2_with_break.rs - ConditionalStepの検出
can_lower()への追加:
// Phase 92 P0-2: Check skeleton for ConditionalStep support
if let Some(skeleton) = ctx.skeleton {
use crate::mir::loop_canonicalizer::UpdateKind;
// Count ConditionalStep carriers
let conditional_step_count = skeleton.carriers.iter()
.filter(|c| matches!(c.update_kind, UpdateKind::ConditionalStep { .. }))
.count();
if conditional_step_count > 0 {
if ctx.debug {
trace::trace().debug(
"pattern2/can_lower",
&format!(
"Phase 92 P0-2: Found {} ConditionalStep carriers in skeleton",
conditional_step_count
),
);
}
// Phase 92 P0-2: ConditionalStep support enabled
// Pattern2 can handle these via if-else JoinIR generation
// TODO: Implement actual lowering in cf_loop_pattern2_with_break_impl
}
}
実装戦略:
- まず検出ロジックのみ実装(TODOマーク付き)
- 実際のloweringは次のフェーズで実装
- デバッグトレース追加で動作確認可能
箱化モジュール化の原則
責任分離
| モジュール | 責任 |
|---|---|
| loop_canonicalizer | LoopSkeleton生成、ConditionalStep検出 |
| parity_checker | パリティ検証、Skeleton取得 |
| routing | Skeletonのコンテキスト設定 |
| pattern2_with_break | ConditionalStepのlowering(将来実装) |
Fail-Fast原則
- 未対応ケース: TODOコメントで明示
- エラーケース: 既存のエラーハンドリングを維持
- 検証: can_lower()で早期チェック
後方互換性
既存パターンへの影響
- Pattern 1-5:
ctx.skeletonはNoneのまま、既存動作に影響なし - Pattern 2: Skeletonがある場合のみ追加機能が有効化
- テスト: 全20テスト中18テスト成功(2テスト無視)
段階的導入
- Phase 92 P0-2 (このフェーズ): Skeleton配線のみ
- Phase 92 P1: ConditionalStep lowering実装
- Phase 92 P2: carrier_update_emitter統合
ビルド結果
cargo check --release
# ✅ 成功 (警告のみ、エラーなし)
cargo test --release --lib pattern2
# ✅ 18 passed; 0 failed; 2 ignored
次のステップ (Phase 92 P1)
ConditionalStep Lowering実装
-
carrier_update_emitter.rs:
UpdateKind::ConditionalStepのマッチング追加- if-else形式のJoinIR生成
-
loop_update_analyzer.rs:
- ConditionalStep用の処理追加(必要に応じて)
-
pattern2_with_break.rs:
- TODO実装
- Skeletonからのthen_delta/else_delta読み取り
- JoinIR if-else構造の生成
テストケース追加
test_escape_sequence_loop():i += 2vsi += 1test_conditional_delta_carriers(): 複数キャリア対応
ファイル一覧
実装で変更されたファイル:
/home/tomoaki/git/hakorune-selfhost/src/mir/builder/control_flow/joinir/patterns/router.rs/home/tomoaki/git/hakorune-selfhost/src/mir/builder/control_flow/joinir/parity_checker.rs/home/tomoaki/git/hakorune-selfhost/src/mir/builder/control_flow/joinir/routing.rs/home/tomoaki/git/hakorune-selfhost/src/mir/builder/control_flow/joinir/patterns/pattern2_with_break.rs
参照
- Skeleton定義:
/home/tomoaki/git/hakorune-selfhost/src/mir/loop_canonicalizer/skeleton_types.rs - UpdateKind Contract: skeleton_types.rs L63-109 (ConditionalStepのコメント)