82 lines
3.9 KiB
Markdown
82 lines
3.9 KiB
Markdown
|
|
# Loop Canonicalizer(設計 SSOT)
|
|||
|
|
|
|||
|
|
Status: Design (P0)
|
|||
|
|
Scope: ループ形の組み合わせ爆発を抑えるための “前処理” の設計(fixture/shape guard/fail-fast と整合)
|
|||
|
|
Related:
|
|||
|
|
- SSOT (契約/不変条件): `docs/development/current/main/joinir-architecture-overview.md`
|
|||
|
|
- SSOT (地図/入口): `docs/development/current/main/design/joinir-design-map.md`
|
|||
|
|
- SSOT (パターン空間): `docs/development/current/main/loop_pattern_space.md`
|
|||
|
|
|
|||
|
|
## 目的
|
|||
|
|
|
|||
|
|
- 実アプリ由来のループ形を、fixture + shape guard + Fail-Fast の段階投入で飲み込む方針を維持したまま、
|
|||
|
|
“パターン数を増やさない” 形でスケールさせる。
|
|||
|
|
- ループ lowerer が「検出 + 正規化 + merge 契約」を同時に背負って肥大化するのを防ぎ、責務を前処理に寄せる。
|
|||
|
|
|
|||
|
|
## 推奨配置(結論)
|
|||
|
|
|
|||
|
|
**おすすめ**: `AST → LoopSkeleton → JoinIR(Structured)` の前処理として Canonicalizer を置く。
|
|||
|
|
|
|||
|
|
- 「組み合わせ爆発」が Pattern 検出/shape guard の手前で起きるため、Normalized 変換だけでは吸収しきれない。
|
|||
|
|
- LoopSkeleton を SSOT にすると、lowerer は “骨格を吐く” だけの薄い箱になり、Fail-Fast の理由が明確になる。
|
|||
|
|
|
|||
|
|
代替案(参考):
|
|||
|
|
- `Structured JoinIR → Normalized JoinIR` を実質 Canonicalizer とみなす(既存延長)。
|
|||
|
|
ただし「検出/整理の肥大」は Structured 生成側に残りやすい。
|
|||
|
|
|
|||
|
|
## LoopSkeleton(SSOT になる出力)
|
|||
|
|
|
|||
|
|
Canonicalizer の出力は “ループの骨格” に限る。例示フィールド:
|
|||
|
|
|
|||
|
|
- `steps: Vec<Step>`
|
|||
|
|
- `HeaderCond`(あれば)
|
|||
|
|
- `BodyInit`(body-local 初期化を分離するなら)
|
|||
|
|
- `BreakCheck` / `ContinueCheck`(あれば)
|
|||
|
|
- `Updates`(carrier 更新規則)
|
|||
|
|
- `Tail`(継続呼び出し/次ステップ)
|
|||
|
|
- `carriers: Vec<CarrierSlot>`(loop var を含む。役割/更新規則/境界通過の契約)
|
|||
|
|
- `exits: ExitContract`(break/continue/return の有無と payload)
|
|||
|
|
- `captured: Vec<CapturedSlot>`(外側変数の取り込み)
|
|||
|
|
- `derived: Vec<DerivedSlot>`(digit_pos 等の派生値)
|
|||
|
|
|
|||
|
|
## Capability Guard(shape guard の上位化)
|
|||
|
|
|
|||
|
|
Skeleton を生成できても、lower/merge 契約が成立するとは限らない。
|
|||
|
|
そこで `SkeletonGuard` を “Capability の集合” として設計する。
|
|||
|
|
|
|||
|
|
例:
|
|||
|
|
- `RequiresConstStepIncrement`(i=i+const のみ)
|
|||
|
|
- `BreakOnlyOnce` / `ContinueOnlyInTail`
|
|||
|
|
- `NoSideEffectInHeader`(header に副作用がない)
|
|||
|
|
- `ExitBindingsComplete`(境界へ渡す値が過不足ない)
|
|||
|
|
|
|||
|
|
未達の場合は Fail-Fast(理由を `RoutingDecision` に載せる)。
|
|||
|
|
|
|||
|
|
## RoutingDecision(理由の SSOT)
|
|||
|
|
|
|||
|
|
Canonicalizer は “できない理由” を機械的に返す。
|
|||
|
|
|
|||
|
|
- `RoutingDecision { chosen, missing_caps, notes, error_tags }`
|
|||
|
|
- `missing_caps` は定型の語彙で出す(ログ/デバッグ/統計で集約可能にする)
|
|||
|
|
|
|||
|
|
## Corpus / Signature(拡張のための仕組み)
|
|||
|
|
|
|||
|
|
将来の規模増加に備え、ループ形の差分検知を Skeleton ベースで行えるようにする。
|
|||
|
|
|
|||
|
|
- `LoopSkeletonSignature = hash(steps + exit_contract + carrier_roles + required_caps)`
|
|||
|
|
- 既知集合との差分が出たら “fixture 化候補” として扱う(設計上の導線)。
|
|||
|
|
|
|||
|
|
## 実装の境界(非目標)
|
|||
|
|
|
|||
|
|
- 新しい言語仕様/ルール実装はしない(既存の意味論を保つ)。
|
|||
|
|
- 非 JoinIR への退避(prohibited fallback)は導入しない。
|
|||
|
|
- 既定挙動は変えない(必要なら dev-only で段階投入する)。
|
|||
|
|
|
|||
|
|
## 追加・変更チェックリスト
|
|||
|
|
|
|||
|
|
- [ ] 追加するループ形を最小 fixture に落とす(再現固定)
|
|||
|
|
- [ ] LoopSkeleton の差分(steps/exits/carriers)を明示する
|
|||
|
|
- [ ] 必要 Capability を列挙し、未達は Fail-Fast(理由が出る)
|
|||
|
|
- [ ] 既存 smoke/verify が退行しない(quick は重くしない)
|
|||
|
|
|