From 84ded8ca6cced478ae6e359dfa87fdaab3d62f09 Mon Sep 17 00:00:00 2001 From: nyash-codex Date: Tue, 16 Dec 2025 04:37:47 +0900 Subject: [PATCH] docs: add loop canonicalizer SSOT + MirBuilder entrypoint --- AGENTS.md | 4 + CURRENT_TASK.md | 43 +++------- .../current/main/01-JoinIR-Selfhost-INDEX.md | 16 ++-- docs/development/current/main/10-Now.md | 4 +- .../development/current/main/design/README.md | 4 + .../current/main/design/joinir-design-map.md | 1 + .../current/main/design/loop-canonicalizer.md | 81 +++++++++++++++++++ .../development/current/main/phases/README.md | 2 +- .../current/main/phases/phase-136/README.md | 32 +++++--- src/mir/builder/README.md | 47 +++++++++++ 10 files changed, 180 insertions(+), 54 deletions(-) create mode 100644 docs/development/current/main/design/loop-canonicalizer.md create mode 100644 src/mir/builder/README.md diff --git a/AGENTS.md b/AGENTS.md index 5ade0f31..3cfa4b6e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -221,6 +221,10 @@ fn check_layer_boundary() { `docs/development/current/` は文書が増えやすいので、**入口/設計図/Phaseログ/調査ログを混ぜない**運用を必須にするよ。 - SSOT: `docs/development/current/main/DOCS_LAYOUT.md` +- よく参照する入口(例): + - JoinIR の地図(navigation SSOT): `docs/development/current/main/design/joinir-design-map.md` + - Loop Canonicalizer(設計 SSOT): `docs/development/current/main/design/loop-canonicalizer.md` + - MIR Builder(Context 分割の入口): `src/mir/builder/README.md` - 追加ルール(最小): - 新しい Phase 文書は `docs/development/current/main/phases/` 配下に置く(`main/` 直下に増やさない) - 長期参照の設計図は `docs/development/current/main/design/` に置く diff --git a/CURRENT_TASK.md b/CURRENT_TASK.md index 9590aa2c..a47d26d2 100644 --- a/CURRENT_TASK.md +++ b/CURRENT_TASK.md @@ -27,7 +27,7 @@ - **Phase 133 完了**: Promoted carrier の `join_id` 解決(Trim)を SSOT に寄せて根治(smoke は compile-only)。 - **Phase 134 完了**: Plugin loader best-effort loading(決定的順序 + failure 集約 + 継続)を導入。 - **Phase 135 完了**: ConditionLoweringBox allocator SSOT(P0: 根治修正 + P1: contract_checks Fail-Fast 強化)。 -- **Phase 136 完了**: ValueId allocator SSOT 徹底(関数内経路から `value_gen.next()` 掃討完了)。 +- **Phase 136 完了**: MirBuilder Context SSOT 化(+ ValueId allocator 掃討)。 - **Phase 88 完了**: continue + 可変ステップ(i=i+const 差分)を dev-only fixture で固定、StepCalculator Box 抽出。 - **Phase 89 完了**: P0(ContinueReturn detector)+ P1(lowering 実装)完了。 - **Phase 90 完了**: ParseStringComposite + `Null` literal + ContinueReturn(同一値の複数 return-if)を dev-only fixture で固定。 @@ -52,49 +52,23 @@ ## 次の指示書(優先順位) -### P0: Phase 135 検証(Trim fixture の `--verify` を緑に固定) - -目的: -- `apps/tests/phase133_json_skip_whitespace_min.hako` で発生していた MIR SSA 破綻(ValueId 重複)を後戻りしない形で固定する。 - -やること: -1. `./target/release/hakorune --verify apps/tests/phase133_json_skip_whitespace_min.hako` が PASS することを確認 -2. 必要なら integration smoke を追加(quick は増やさない) -3. Phase 文書を更新: `docs/development/current/main/phases/phase-135/README.md` - -受け入れ基準: -- `--verify` が PASS -- 既存の Phase 132/133/134 の integration smoke が退行しない - -### P1: Docs 整備(数の増殖を止める) - -**目的**: SSOT への集約と導線整備(Phase 86–90 の情報が散らばらない状態にする) - -やること: -1. Phase 86–90 の要約を 1 ファイルに集約(SSOT) - - `docs/development/current/main/phase86-90-loop-frontends-summary.md` -2. INDEX から要約へ導線を追加(迷子対策) - - `docs/development/current/main/01-JoinIR-Selfhost-INDEX.md` -3. `10-Now.md` / `CURRENT_TASK.md` の断定・重複を “要約へのリンク” に寄せる - -**受け入れ基準**: -- 読み始め導線が `01-JoinIR-Selfhost-INDEX.md` から辿れる -- `10-Now.md` と `CURRENT_TASK.md` は “最新の入口” として機能する(詳細は要約へ) - -### P1: Loop Canonicalizer の設計(設計待ち - 外部検討中) +### P0: Loop Canonicalizer の設計(設計待ち - 外部検討中) **状態**: 🔶 設計中(ChatGPT Pro と詰めている) **目的**: ループ形状の組み合わせ爆発を抑えるための "前処理パス" を設計し、SSOT を定める -**次に触るSSO**: +SSOT: +- `docs/development/current/main/design/loop-canonicalizer.md` + +**次に触るSSOT**: - Loop系の設計: `docs/development/current/main/joinir-architecture-overview.md` 注意: - 実装は急がず、設計(SSOT)を先に固める - 既定挙動は変えない(dev-only で段階投入する) -### P2: JoinIR / Selfhost depth-2 の前進(実装可能 - Phase 91 候補) +### P1: JoinIR / Selfhost depth-2 の前進(実装可能 - Phase 91 候補) **状態**: ✅ 実装可能 @@ -114,7 +88,7 @@ 受け入れ基準: - 代表ケースが 1 コマンドで再現可能(CI は増やさない、quick を重くしない)。 -### P3: Ownership/Relay runtime 対応の再開(Phase 92 候補) +### P2: Ownership/Relay runtime 対応の再開(Phase 92 候補) 目的: - multihop/merge relay を “runtime でも” 受理できるところまで契約を伸ばす(Fail-Fast の段階解除)。 @@ -125,6 +99,7 @@ ### Done: Phase 86–90(Loop frontends) - まとめ(SSOT): `docs/development/current/main/phase86-90-loop-frontends-summary.md` +- MirBuilder の入口(Context 分割): `src/mir/builder/README.md` + `docs/development/current/main/01-JoinIR-Selfhost-INDEX.md` --- diff --git a/docs/development/current/main/01-JoinIR-Selfhost-INDEX.md b/docs/development/current/main/01-JoinIR-Selfhost-INDEX.md index 557d66cc..8526a992 100644 --- a/docs/development/current/main/01-JoinIR-Selfhost-INDEX.md +++ b/docs/development/current/main/01-JoinIR-Selfhost-INDEX.md @@ -40,7 +40,11 @@ JoinIR の箱構造と責務、ループ/if の lowering パターンを把握 - `docs/development/current/main/joinir-boundary-builder-pattern.md` 4. JoinIR 設計地図(現役の地図) - `docs/development/current/main/design/joinir-design-map.md` -5. Scope/BindingId(shadowing・束縛同一性の段階移行) +5. Loop Canonicalizer(設計 SSOT) + - `docs/development/current/main/design/loop-canonicalizer.md` +6. MIR Builder(Context 分割の入口) + - `src/mir/builder/README.md` +7. Scope/BindingId(shadowing・束縛同一性の段階移行) - `docs/development/current/main/phase73-scope-manager-design.md` - `docs/development/current/main/PHASE_74_SUMMARY.md` - `docs/development/current/main/PHASE_75_SUMMARY.md` @@ -48,16 +52,16 @@ JoinIR の箱構造と責務、ループ/if の lowering パターンを把握 - `docs/development/current/main/phase78-bindingid-promoted-carriers.md` - `docs/development/current/main/phase80-bindingid-p3p4-plan.md`(P3/P4 への配線計画) - `docs/development/current/main/phase81-pattern2-exitline-contract.md`(promoted carriers の ExitLine 契約検証) -6. Boxification feedback(Phase 78–85 の振り返りと Phase 86 推奨) +8. Boxification feedback(Phase 78–85 の振り返りと Phase 86 推奨) - `docs/development/current/main/phase78-85-boxification-feedback.md` -7. Phase 86: Carrier Init Builder + Error Tags ✅ +9. Phase 86: Carrier Init Builder + Error Tags ✅ - **Status**: COMPLETE (2025-12-13) - **Modules**: - `src/mir/builder/control_flow/joinir/merge/carrier_init_builder.rs` (+8 tests) - `src/mir/join_ir/lowering/error_tags.rs` (+5 tests) - **Achievements**: SSOT 確立(CarrierInit → ValueId 生成統一、エラータグ中央化、DebugOutputBox 完全移行) - **Impact**: 987/987 tests PASS, +13 unit tests, Single Responsibility validated -8. Phase 87: LLVM Exe Line SSOT ✅ +10. Phase 87: LLVM Exe Line SSOT ✅ - **Status**: COMPLETE (2025-12-13) - **SSOT**: `tools/build_llvm.sh` - Single pipeline for .hako → executable - **Deliverables**: @@ -66,11 +70,11 @@ JoinIR の箱構造と責務、ループ/if の lowering パターンを把握 - Integration smoke: `tools/smokes/v2/profiles/integration/apps/phase87_llvm_exe_min.sh` (SKIP if no LLVM) - **Policy**: No script duplication, integration smoke only (not quick), graceful SKIP - **Impact**: Standard procedure established, prerequisites documented -9. 代表的な Phase 文書(現役ラインとの接点だけ絞ったもの) +11. 代表的な Phase 文書(現役ラインとの接点だけ絞ったもの) - `docs/development/current/main/phase33-16-INDEX.md` - `docs/development/current/main/phase33-17-joinir-modularization-analysis.md` - `docs/development/current/main/phase183-selfhost-depth2-joinir-status.md` -10. Phase 86–90(Loop frontends)の要約(1枚) +12. Phase 86–90(Loop frontends)の要約(1枚) - `docs/development/current/main/phase86-90-loop-frontends-summary.md` Phase 文書は歴史や検証ログも含むので、「JoinIR の現役設計を確認した上で、必要なときだけ掘る」という前提で読んでね。 diff --git a/docs/development/current/main/10-Now.md b/docs/development/current/main/10-Now.md index 008717ba..eaa52fd1 100644 --- a/docs/development/current/main/10-Now.md +++ b/docs/development/current/main/10-Now.md @@ -18,12 +18,14 @@ **追加(Phase 132-P3): Exit PHI collision の早期検出(debug-only)** - `verify_exit_phi_no_collision()` を `contract_checks.rs` に追加し、ValueId 衝突を JoinIR merge の段階で Fail-Fast する -## 2025‑12‑15:Phase 133–135(短報) +## 2025‑12‑15:Phase 133–136(短報) - Phase 133: promoted carrier(Trim)の `join_id` 解決を SSOT に寄せて修正(smoke は compile-only)。 - Phase 134: plugin loader best-effort loading を導入(決定的順序 + failure 集約 + 継続)。 - Phase 135: ConditionLoweringBox が allocator SSOT を無視して ValueId 衝突を起こす問題を根治。 - 詳細: `docs/development/current/main/phases/phase-135/README.md` +- Phase 136: MirBuilder の Context 分割を完了し、状態の SSOT を Context に一本化。 + - 詳細: `docs/development/current/main/phases/phase-136/README.md` ## 2025‑12‑14:現状サマリ diff --git a/docs/development/current/main/design/README.md b/docs/development/current/main/design/README.md index 61a4f82f..f0444e2b 100644 --- a/docs/development/current/main/design/README.md +++ b/docs/development/current/main/design/README.md @@ -5,3 +5,7 @@ - 原則: “Phaseの作業ログ/完了報告” は `../phases/` に置く。 - 原則: “不具合調査ログ” は `../investigations/` に置く。 +## 現役の設計図(入口) + +- JoinIR の地図(navigation SSOT): `docs/development/current/main/design/joinir-design-map.md` +- Loop Canonicalizer(設計 SSOT): `docs/development/current/main/design/loop-canonicalizer.md` diff --git a/docs/development/current/main/design/joinir-design-map.md b/docs/development/current/main/design/joinir-design-map.md index 546c8428..9b4f27b1 100644 --- a/docs/development/current/main/design/joinir-design-map.md +++ b/docs/development/current/main/design/joinir-design-map.md @@ -6,6 +6,7 @@ Related: - SSOT: [`docs/development/current/main/joinir-architecture-overview.md`](../joinir-architecture-overview.md) - SSOT: [`docs/development/current/main/loop_pattern_space.md`](../loop_pattern_space.md) - SSOT: [`docs/development/current/main/joinir-boundary-builder-pattern.md`](../joinir-boundary-builder-pattern.md) +- SSOT: [`docs/development/current/main/design/loop-canonicalizer.md`](./loop-canonicalizer.md) このドキュメントは Phase ログではなく、「JoinIR を触る人が迷子にならず、どこを直すべきかが一発で分かる」ための設計図(地図)です。 詳細な経緯・作業ログは `docs/development/current/main/phases/` と `docs/development/current/main/investigations/` に分離します。 diff --git a/docs/development/current/main/design/loop-canonicalizer.md b/docs/development/current/main/design/loop-canonicalizer.md new file mode 100644 index 00000000..2026e762 --- /dev/null +++ b/docs/development/current/main/design/loop-canonicalizer.md @@ -0,0 +1,81 @@ +# 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` + - `HeaderCond`(あれば) + - `BodyInit`(body-local 初期化を分離するなら) + - `BreakCheck` / `ContinueCheck`(あれば) + - `Updates`(carrier 更新規則) + - `Tail`(継続呼び出し/次ステップ) +- `carriers: Vec`(loop var を含む。役割/更新規則/境界通過の契約) +- `exits: ExitContract`(break/continue/return の有無と payload) +- `captured: Vec`(外側変数の取り込み) +- `derived: Vec`(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 は重くしない) + diff --git a/docs/development/current/main/phases/README.md b/docs/development/current/main/phases/README.md index a07eb480..ae30d512 100644 --- a/docs/development/current/main/phases/README.md +++ b/docs/development/current/main/phases/README.md @@ -8,7 +8,7 @@ - **Phase 133**: Promoted carrier join_id(Trim)修正 - **Phase 134**: Plugin loader best-effort loading - **Phase 135**: ConditionLoweringBox allocator SSOT(ValueId 衝突の根治) -- **Phase 136**: ValueId allocator SSOT 徹底(残存 value_gen.next() 掃討) +- **Phase 136**: MirBuilder Context SSOT 化(+ ValueId allocator 掃討) ## Phase フォルダ構成(推奨) diff --git a/docs/development/current/main/phases/phase-136/README.md b/docs/development/current/main/phases/phase-136/README.md index 99618fcd..1ab12d68 100644 --- a/docs/development/current/main/phases/phase-136/README.md +++ b/docs/development/current/main/phases/phase-136/README.md @@ -1,19 +1,27 @@ -# Phase 136: ValueId allocator SSOT 徹底(残存 value_gen.next() 掃討) +# Phase 136: MirBuilder Context SSOT 化(+ ValueId allocator 掃討) ## Status -- 状態: ✅ P0 完了 -- スコープ: 関数内 ValueId 発行を `MirBuilder::next_value_id()` に一本化し、予約PHI/引数/ローカルとの衝突余地を消す +- 状態: ✅ Done +- スコープ: + - MirBuilder の状態を Context(箱)へ分割し、状態の SSOT を Context に一本化する + - 併せて、関数内 ValueId 発行を `MirBuilder::next_value_id()` に一本化し、予約PHI/引数/ローカルとの衝突余地を消す ## Problem -Phase 135 で契約(allocator SSOT)は固まったが、一部のコードで `builder.value_gen.next()` を直接使用していた。 -これは関数内で走る場合、予約PHI dst や関数引数との ValueId 衝突を引き起こす可能性がある。 +MirBuilder が肥大化し、以下が同時に起きやすい状態だった: +- 状態の置き場所が分散し、変更者が「何を触っているか」を追いづらい +- ValueId の発行が局所的に `value_gen.next()` へ逃げると、関数内で衝突しうる(Phase 135 の契約を破りやすい) ## Fix -### SSOT 化対象 -1. **`src/mir/builder.rs:new_typed_value()`** - 型付きValueId発行API - - Before: `let id = self.value_gen.next();` - - After: `let id = self.next_value_id();` (関数コンテキストを尊重) +### 1) Context 分割(状態の SSOT を一本化) +- Type/Core/Scope/Binding/Variable/Metadata/Compilation の 7 Context へ分割し、二重管理(sync helpers)を撤去。 +- 入口: + - `src/mir/builder/context.rs` + - `src/mir/builder/*_context.rs` + - 読む入口: `src/mir/builder/README.md` + +### 2) ValueId allocator の SSOT 徹底(関数内経路の掃討) +- 例: `src/mir/builder.rs:new_typed_value()` は `self.next_value_id()` を唯一入口に統一。 2. **テストコード内の `value_gen.next()`** - 関数スコープをシミュレート - `test_shadowing_binding_restore`: 関数スコープシミュレーションで `next_value_id()` を使用 @@ -27,10 +35,10 @@ Phase 135 で契約(allocator SSOT)は固まったが、一部のコード - `src/mir/utils/phi_helpers.rs:insert_phi_unified()` - 69行目 ## Acceptance -- ✅ `rg -n "value_gen\.next\(" src/mir` で関数内経路から消える -- ✅ `cargo test --release --lib` - 997 passed +- ✅ `rg -n "value_gen\.next\(" src/mir` で関数内経路から消える(module context の意図的フォールバックを除く) +- ✅ `cargo test --release --lib` が退行しない - ✅ `phase135_trim_mir_verify.sh` - PASS - ✅ `phase132_exit_phi_parity.sh` - 3/3 PASS ## Remaining Tasks(残課題) -なし。全ての関数内経路から `value_gen.next()` を排除完了。Module context のフォールバックは意図的に残す。 +なし。状態は Context に一本化され、関数内経路から `value_gen.next()` を排除完了。Module context のフォールバックは意図的に残す。 diff --git a/src/mir/builder/README.md b/src/mir/builder/README.md new file mode 100644 index 00000000..2e72441e --- /dev/null +++ b/src/mir/builder/README.md @@ -0,0 +1,47 @@ +# MIR Builder (`src/mir/builder/`) + +このディレクトリは Rust 側の MIR 生成(AST → MIR)を担う。 +JoinIR の merge もここ(`control_flow/joinir/merge/`)が入口。 + +## 原則(SSOT / Box-First) + +- **状態は Context が SSOT**: `MirBuilder` の状態は Context(箱)に分割され、二重管理をしない。 +- **ValueId 発行は SSOT**: 関数内の ValueId は `MirBuilder::next_value_id()` を唯一入口にする。 +- **境界は Fail-Fast**: JoinIR merge は `contract_checks.rs` で契約違反を早期検出する(debug-only)。 + +## Context 構成(責務マップ) + +- `core_context.rs` + - ID 生成器(ValueId/BlockId/BindingId 等)と最小の共通コア状態。 +- `type_context.rs` + - ValueId → 型/種別/起源(NewBox 由来など)の追跡。 +- `scope_context.rs` + - lexical scope / loop/if/try のスタックと、`current_function` / `current_block` の実行文脈。 +- `binding_context.rs` + - 変数名 ↔ BindingId の対応(shadowing の復元を含む)。 +- `variable_context.rs` + - 変数解決(variable_map 等)。 +- `metadata_context.rs` + - span/source_hint/region(観測)などのメタ情報。 +- `compilation_context.rs` + - コンパイル全体のレジストリ(Box/型レジストリ、reserved ids 等)。 +- `context.rs` + - 上記 Context を束ねる入れ物(`MirBuilder` はここを介して状態へアクセスする)。 + +## 主要エントリポイント + +- ValueId/BlockId + - `src/mir/builder/utils.rs`(`MirBuilder::next_value_id()` など) +- AST → MIR の基本道 + - `src/mir/builder/stmts.rs` + - `src/mir/builder/exprs.rs` +- JoinIR merge(契約検証を含む) + - `src/mir/builder/control_flow/joinir/merge/mod.rs` + - `src/mir/builder/control_flow/joinir/merge/contract_checks.rs` + +## 追加ルール(将来の変更者向け) + +- 新しい状態を追加する場合は、まず「どの Context の責務か」を決めてから追加する(`MirBuilder` 直下に増やさない)。 +- 変更後に最低限確認する: + - `tools/smokes/v2/profiles/integration/apps/phase135_trim_mir_verify.sh`(MIR verify の回帰防止) +