Files
hakorune/docs/development/current/main/phases/phase-29ai/P12-FACTS-PATTERN2-LOOPBODYLOCAL-PROMOTION-INSTRUCTIONS.md

4.6 KiB
Raw Blame History

Phase 29ai P12: Facts SSOTPattern2 LoopBodyLocal promotion

Date: 2025-12-29
Status: Ready for execution
Scope: Pattern2 の LoopBodyLocal promotionA-3 Trim / A-4 DigitPosを Facts として仕様化(仕様不変)
Goal: “promotion が必要な形” を Facts で 1 箇所に固定し、JoinIR/pattern 側に解析が散らないようにする

Background

Pattern2 には break 条件が loop-body で生成した一時値LoopBodyLocalに依存する形があり、ここが promotionhost binding / derived slot / trim 形状など) の主要露出点になっている。既存実装は JoinIR 側の箱群Pattern2 promotionで成立しているが、長期的には Facts→Plan→Emit の 1 本導線へ寄せたい。

P12 では “解析(何が LoopBodyLocal で、どの形か)” を Facts として SSOT 化し、Planner/Emitter が再解析・分岐増殖しない形にする。

Non-goalsこの P12 ではやらない)

  • 実際の promotion ロジックの差し替え(既定挙動の変更)
  • derived slot emitter / merge 側の契約変更
  • Pattern2 の全形対応real-world まで一気に拡張しない)
  • 新しい env var / debug トグル追加
  • by-name 分岐の追加(禁止)

Target FixturesSSOT

この 2 本を “promotion が必要な代表” として SSOT にする(既存のまま):

  • apps/tests/phase29ab_pattern2_loopbodylocal_min.hakoA-4 DigitPos
  • apps/tests/phase29ab_pattern2_loopbodylocal_seg_min.hakoA-3 Trim / seg

Deliverables

  1. Facts 型と抽出入口SSOT:
    • Pattern2LoopBodyLocalFacts(例: variant=TrimSeg|DigitPos + 関連 var 名 + 依存グラフの最小)
    • 抽出: try_extract_pattern2_loopbodylocal_facts(condition, body) -> Result<Option<_>, Freeze>
  2. Facts→Planner/Plan への橋渡しのための “最低限の情報” を明文化(どの情報が必須か)。
  3. unit testsAST を組んで Ok(Some) / Ok(None) の境界を固定)。
  4. 追跡 docsphase-29ai README / Now / Backlog更新。

Proposed Data Model最小

Pattern2LoopBodyLocalFacts は “promotion の判断に必要な最小セット” だけ持つ(推測は禁止。取れなければ Ok(None))。

例:

  • 共通:
    • loop_var: String
    • loopbodylocal_var: String(例: seg / digit_pos
    • break_uses_loopbodylocal: bool(必ず true で Some を返す)
    • shape: LoopBodyLocalShape(下の enum
  • LoopBodyLocalShapeP12は2つだけ
    • TrimSeg { s_var, i_var }seg = s.substring(i, i+1) + if seg == " " || seg == "\\t" { break }
    • DigitPos { digits_var, ch_var }digit_pos = digits.indexOf(ch) + if digit_pos < 0 { break }

Implementation StepsCritical Order

Step 1: Facts module を追加

  • 新規: src/mir/builder/control_flow/plan/facts/pattern2_loopbodylocal_facts.rs
  • 更新: src/mir/builder/control_flow/plan/facts/mod.rsmodule 登録)

Step 2: LoopFacts に “補助 facts” を接続(ただし既定挙動不変)

  • 更新: src/mir/builder/control_flow/plan/facts/loop_facts.rs
    • pattern2_loopbodylocal: Option<Pattern2LoopBodyLocalFacts> を追加(または pattern2_break 内へ nest
    • try_build_loop_facts()try_extract_pattern2_loopbodylocal_facts(condition, body) を呼ぶ

方針:

  • 抽出が曖昧なら Ok(None)Freeze は出さない)。
  • pattern2_breakNone のときは pattern2_loopbodylocalNone にする(矛盾を作らない)。

Step 3: unit tests で境界固定

  • src/mir/builder/control_flow/plan/facts/pattern2_loopbodylocal_facts.rs#[cfg(test)] を追加
  • 2 fixture 相当の AST を直接組んで Ok(Some(shape=...)) を固定
  • “似てるけど違う” 形(例: seg = substring(i,i+2) / break で seg を使ってない)を Ok(None) に固定

Step 4: docs / tracking 更新

  • docs/development/current/main/phases/phase-29ai/README.md
  • docs/development/current/main/10-Now.md
  • docs/development/current/main/30-Backlog.md

書くこと(最小):

  • P12 の scopeFacts のみ、仕様不変)
  • P13 候補(例: Facts→Planner で “promotion-required” を Plan に載せる)

Verification (SSOT)

  • cargo build --release
  • ./tools/smokes/v2/run.sh --profile quick
  • ./tools/smokes/v2/profiles/integration/joinir/phase29ae_regression_pack_vm.sh

NotesFail-Fast / Freeze

P12 は実行経路で Freeze を増やさない(曖昧なら Ok(None)。Fail-Fast/Freeze を導入するのは、P13 以降で “planner-first で確実に採用される範囲” が固まってからにする。