Phase 273 P0-P1: Two-layer plan architecture - DomainPlan: Pattern-specific knowledge (ScanWithInit) - CorePlan: Fixed vocabulary (Seq, Loop, If, Effect, Exit) - ValueId references only (String expressions forbidden) - Pipeline: Extractor→Normalizer→Verifier→Lowerer New plan/ module: - mod.rs: Type definitions, SSOT spec - normalizer.rs: DomainPlan→CorePlan + ID allocation - verifier.rs: V1-V6 invariant checks (fail-fast) - lowerer.rs: CorePlan→MIR (pattern-agnostic) LLVM fix (ChatGPT): - function_lower.py: Fix argument reference bug - Phase 258 index_of_string now PASS on LLVM backend 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
3.2 KiB
3.2 KiB
Phase 273 P0: Plan Extractor(pure)導入の最小収束(Claude Code 指示書)
Status: instructions / design-first
目的:
- pattern を “分岐ロジック” ではなく “Plan抽出プラグイン” に降格する。
- block/value/phi の生成責務を PlanLowerer に集約し、裾広がりを止める。
制約:
- Extractor は builder を触らない(
next_block_id/next_value_id/insert_phi/...禁止) - 新しい env var 禁止
- by-name hardcode 禁止(Box名/Pattern名の文字列分岐を増やさない)
- terminator SSOT は維持(
Frag → emit_frag())
参照:
- SSOT設計:
docs/development/current/main/design/edgecfg-fragments.md - 参照実装(既存): Phase 272/269 の Frag 経路
docs/development/current/main/phases/phase-272/README.mddocs/development/current/main/phases/phase-269/README.md
Step 1: Plan の固定語彙を作る(増殖しない型)
新規モジュール(例):
src/mir/builder/control_flow/plan/(またはsrc/mir/control_plan/)
最低限の語彙(案):
Plan::Seq(Vec<Plan>)Plan::Loop { params, body }Plan::If { cond, then_, else_ }Plan::Effect { ... }(副作用の順序だけ表す)Plan::Exit { kind, values }
重要:
- Plan は AST/expr を “参照” するだけ(必要なら node id / span を持つ)
- Plan は “CFGを作らない”
Step 2: Extractor を pure にする(pattern の責務縮退)
対象:
src/mir/builder/control_flow/joinir/patterns/*
方針:
- 既存の
extract_*_parts(...)のような抽出関数を “Plan を返す” 形に寄せる Ok(None)/Ok(Some(plan))/Err(...)を明確に使い分ける
Fail-fast:
- “一致した” のに必要条件が満たせない場合は
Err(close-but-unsupported を黙って通さない)
Step 3: PlanLowerer を作る(唯一の builder 触り役)
新規モジュール(例):
src/mir/builder/control_flow/plan/lowerer.rs
責務:
- block/value/phi を作るのはここだけ
- Frag を組み立てて
emit_frag()に渡す - 既存の emission(Phase 272 の
loop_scan_with_init/loop_split_scanなど)を呼ぶのは Lowerer 側に寄せる
Step 4: まず1つのパターンで PoC(最小差分)
推奨:
- Pattern6 または Pattern8 を 1つ選び、以下の順で移行:
- extractor は plan を返すだけにする
- lowerer が既存 emission を呼ぶ
- router は “plan を得たら lowerer へ” にする
Acceptance:
- 既存の fixture/smoke が変わらず PASS(既定挙動不変)
- Extractor が builder を触っていないこと(grep で確認)
Step 5: docs(SSOT)更新
更新対象:
docs/development/current/main/phases/phase-273/README.md
最低限:
- “Extractorはpure / Lowererだけが作る” を SSOT として明文化
- Plan語彙が固定であること(増殖しない理由)を短く書く
完了条件(P0)
- Plan の語彙が導入され、Extractor が pure になっている(最低1パターンでPoC)
- Lowerer が block/value/phi 生成の唯一の場所になっている
- terminator SSOT(emit_frag)が維持されている
- 既存スモークに退行がない