feat(joinir): Phase 248 - Normalized JoinIR infrastructure

Major refactoring of JoinIR normalization pipeline:

Key changes:
- Structured→Normalized→MIR(direct) pipeline established
- ShapeGuard enhanced with Pattern2 loop validation
- dev_env.rs: New development fixtures and env control
- fixtures.rs: jsonparser_parse_number_real fixture
- normalized_bridge/direct.rs: Direct MIR generation from Normalized
- pattern2_step_schedule.rs: Extracted step scheduling logic

Files changed:
- normalized.rs: Enhanced NormalizedJoinModule with DevEnv support
- shape_guard.rs: Pattern2-specific validation (+300 lines)
- normalized_bridge.rs: Unified bridge with direct path
- loop_with_break_minimal.rs: Integrated step scheduling
- Deleted: step_schedule.rs (moved to pattern2_step_schedule.rs)

New files:
- param_guess.rs: Loop parameter inference
- pattern2_step_schedule.rs: Step scheduling for Pattern2
- phase43-norm-canon-p2-mid.md: Design doc

Tests: 937/937 PASS (+6 from baseline 931)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
nyash-codex
2025-12-12 03:15:45 +09:00
parent 59caf5864c
commit ed8e2d3142
32 changed files with 1559 additions and 421 deletions

View File

@ -987,7 +987,7 @@ JoinIR は Rust 側だけでなく、将来的に .hako selfhost コンパイラ
- [x] 退行なし: Phase 190-196 テスト全 PASS ✅
- 詳細: phase197-lightweight-loops-deployment.md
7. **JsonParser/selfhost 実戦 JoinIR 適用状況** (2025-12-09 更新)
7. **JsonParser/selfhost 実戦 JoinIR 適用状況** (2025-12-09 更新 → Phase 42 で棚卸し済み)
| Function | Pattern | Status | Note |
|----------|---------|--------|------|
@ -998,15 +998,15 @@ JoinIR は Rust 側だけでなく、将来的に .hako selfhost コンパイラ
| `phase195_sum_count` | P3 | ✅ JoinIR OK | Phase 196 検証済みmulti-carrier|
| `loop_if_phi` | P3 | ✅ JoinIR OK | Phase 196 検証済みsingle-carrier|
| `loop_min_while` | P1 | ✅ JoinIR OK | Phase 165 基本検証済み |
| `_parse_number` | P2 | ⚠️ Deferred | ConditionEnv 制約Phase 200+|
| `_atoi` | P2 | ⚠️ Deferred | ConditionEnv 制約Phase 200+|
| `_parse_number` | P2 | ✅ JoinIR OK | Phase 245B-IMPL: P2-Midnum_str LoopState キャリア)を Structured→Normalized(dev, direct) で固定 |
| `_atoi` | P2 | ✅ JoinIR OK | Phase 246-EX で NumberAccumulation パターンとして統合P2-Mid、Normalized: mini + real(dev, 符号対応) / canonical 準備中|
| `_parse_string` | P3 | ⚠️ Deferred | 複雑キャリアPhase 195+ 拡張後)|
| `_unescape_string` | P3 | ⚠️ Deferred | 複雑キャリアPhase 195+ 拡張後)|
| `_parse_array` | - | ⚠️ Deferred | 複数 MethodCallPhase 195+|
| `_parse_object` | - | ⚠️ Deferred | 複数 MethodCallPhase 195+|
**Coverage**: 7/13 ループ JoinIR 対応済み(54%
**Verification**: 4/7 ループ E2E PASS、3/7 structural/routing 確認済み
**Coverage**: 9/13 ループ JoinIR 対応済み(約 69%
**Verification**: 代表ループP1/P2 Core + Trim/P3については E2E テストで挙動確認済み。詳細なケースごとの状況は各 Phase ドキュメントPhase 197/245/246 など)を参照。
8. **JsonParser 残り複雑ループへの適用Phase 198+, 200+**
- Phase 200+: ConditionEnv 拡張 (function-scoped variables) → _parse_number, _atoi
@ -1247,3 +1247,61 @@ Normalized JoinIR を 1 段挟むと、開発の手触りがどう変わるか
- Normalized ブリッジを direct 実装と Structured 再構成の二段に分離し、shape_guard で direct 対象P1/P2 ミニ + JsonParser skip_ws/atoi ミニ)だけを Normalized→MIR 直接生成に切り替えた。
- direct 経路は `normalized_bridge::direct` に閉じ込め、非対応形状は `[joinir/normalized-bridge/fallback]` ログ付きで Structured 再構成経路に落とす構造に整理。dev テストでは direct 経路の VM 出力が従来経路と一致することを固定。
### 3.15 Phase 37-NORM-JP-REAL JsonParser `_skip_whitespace` 本体を dev Normalized で比較
- JsonParser 本体の `_skip_whitespace` ループを Program(JSON) フィクスチャ化し、`shape_guard` で real 版を検知して Structured→Normalized→MIR(direct) の dev 経路に通すように拡張。`extract_value` は `&&`/`||` を BinOp として受け付けるようにした。
- Break パターンのパラメータ推定を柔軟化loop_var/acc/n が無いケースでも loop_var を優先し、acc が無ければ同一キャリアとして扱うし、skip_ws real の構造で panic しないようにした。
- tests/normalized_joinir_min.rs に `_skip_whitespace` real フィクスチャの VM 比較テストを追加し、env ON 時は Structured→Normalized→MIR(direct) と Structured 直経路の stdout が一致することを固定env OFF は既存経路のまま)。
- normalized_dev 用フィクスチャは `docs/private/roadmap2/phases/normalized_dev/fixtures/` に配置し、Program(JSON) から `AstToJoinIrLowerer` で読み込む運用に統一した。
### 3.16 Phase 38-NORM-OBS Normalized dev ログ/FailFast の整備
- Normalized/JoinIR dev 経路のログカテゴリを `[joinir/normalized-bridge/*]` / `[joinir/normalized-dev/shape]` に統一し、`JOINIR_TEST_DEBUG` フラグ下のみ詳細を出すよう静音化。Verifier/FailFast メッセージも shape/役割付きに整理してデバッグ観測性を強化。
### 3.17 Phase 40-NORM-CANON-TESTS テスト側で Normalized を“当たり前”に通す
- `normalized_dev_enabled()` と env ガードを整理し、P1/P2 ミニ + JsonParser skip_ws/atoi ミニ/real の代表テストは「Normalized dev 経路が必ず通る」前提にする(壊れたら normalized_* スイートが赤になる)。
- 既存の Structured 直経路は比較用に維持しつつ、tests/normalized_joinir_min.rs 経路では Structured→Normalized→MIR(direct) が第一観測点になるように整備(本番 CLI は Structured→MIR のまま)。
### 3.18 Phase 41-NORM-CANON-P2-CORE Pattern2 コアケースの canonical Normalized 化
- Pattern2 のコアセットP2 ミニ + JsonParser skip_ws/atoi ミニ/realについて、JoinIR→MIR Bridge の既定を Normalized→MIR に寄せ、Structured→MIR は比較テスト用/フォールバック用の位置づけにするFailFast ポリシーは維持)。
- `shape_guard` で「Normalized 対応と宣言した P2 コアループ」は常に Normalized 経路を通すようにし、Normalized 側の invariant 破損は dev では panic、本番では明示エラーで早期検出する設計に寄せる。
### 3.19 Phase 42-NORM-P2-INVENTORY P2 コア/ミドル/ヘビーの棚卸し
- JsonParser / selfhost で **現役の P2 ループ** を洗い出し、次の 3 クラスに整理した:
- **P2-Core**(すでに Normalized canonical なもの)
- test fixture 系: `loop_min_while` P2 ミニ, Phase 34 break fixture (`i/acc/n`)
- JsonParser 系: `_skip_whitespace` mini/real, `_atoi` mini
- これらは Phase 3641 で **Structured→Normalized→MIR(direct)** が canonical になっており、`bridge_joinir_to_mir` でも優先的に Normalized 経路が選ばれる。
- **P2-Mid**(次に Normalized を当てる候補)
- JsonParser: `_parse_number`, `_atoi` 本体, `_atof_loop`
- いずれも Pattern2 Break で JoinIR(Structured) には載っておりPhase 245/246 系、Normalized への写像は今後の拡張対象として扱う。
- **P2-Heavy**(複数 MethodCall / 複雑キャリアを持つもの)
- JsonParser: `_parse_string`, `_parse_array`, `_parse_object`, `_unescape_string`
- P2/P3/P4 が混在し、複雑なキャリアや MethodCall 多数のため、Phase 43 以降の後続フェーズで設計する。
- P2-Core については Phase 41 で canonical Normalized 化が完了しており、Structured→MIR は比較テスト用 / フォールバック用の経路として扱う。
- P2-Mid のうち、Phase 43 ではまず `_parse_number` を第 1 候補、`_atoi` 本体を第 2 候補として扱い、Normalized→MIR(direct) に必要な追加インフラEnvLayout 拡張 / JpInst パターン拡張)を段階的に入れていく前提を整理した。
### 3.20 Phase 43-NORM-CANON-P2-MID JsonParser 本命 P2_parse_number/_atoiへの適用
- JsonParser `_parse_number` / `_atoi` 本体の Pattern2 ループを、既存インフラDigitPos dual 値, LoopLocalZero, StepScheduleBox, ExprLowerer/MethodCall, Normalized ブリッジ)上で Structured→Normalized→MIR(direct) に載せる。
- dev で Structured 直経路との VM 実行結果一致を固定した上で、段階的に「この関数だけ Normalized canonical」とみなすプロファイル/フラグを導入し、最終的に JsonParser P2 の canonical route を Normalized 側に寄せるための足場にする。
- Phase 43-Adev 専用): `_atoi` 本体を Program(JSON) フィクスチャ `jsonparser_atoi_real` で Structured→Normalized→MIR(direct) に通し、Structured 直経路との VM 出力一致を比較テストで固定(符号あり/なしの簡易パスまで対応。canonical 化は後続フェーズで検討)。
- Phase 43-Cdev 専用): `_parse_number` 本体を Program(JSON) フィクスチャ `jsonparser_parse_number_real` で Structured→Normalized→MIR(direct) に通し、`num_str = num_str + ch` の LoopState キャリアを含めた状態で Structured 直経路との VM 出力一致を比較テストで固定。
### 3.21 Phase 44-SHAPE-CAP shape_guard の能力ベース化(計画)
- 現状の shape_guard は `JsonparserSkipWsMini/Real`, `JsonparserAtoiMini/Real` など「関数名ベースの個別 shape」が増えつつあるため、将来的には:
- 「P2 / LoopParam1 / Carrier≤N / MethodCall パターン = このセット」のような **能力ベースの ShapeCapability テーブル** に寄せる。
- JsonParser/selfhost の各ループは「どの capability を満たしているか」を参照するだけにし、関数名ベタ書き依存を減らす。
- この Phase では docs 上で API/テーブル設計を固め、コード側では shape_guard の内部表現を Capability 中心に書き換える前段として扱う。
### 3.22 Phase 45-NORM-MODE JoinIR モードの一本化(計画)
- 現状は `normalized_dev_enabled()`, `NYASH_JOINIR_NORMALIZED_DEV_RUN`, `JOINIR_TEST_DEBUG` など複数の env/feature でモードを切り替えているため、将来的には:
- `JoinIrMode = { StructuredOnly, NormalizedDev, NormalizedCanonical }` のような enum を導入し、
- env/feature はこのモードの初期値を決めるだけに寄せる(コード側の `if`/分岐を減らす)。
- この Phase では JoinIR パイプラインの「モード遷移図」と `JoinIrMode` API を docs で設計し、後続フェーズで実装に反映する計画を置いておく。