Files
hakorune/docs/development/current/main/phase43-norm-canon-p2-mid.md
nyash-codex ed8e2d3142 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>
2025-12-12 03:15:45 +09:00

149 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Status: Planned
Scope: Phase 43NORMCANONP2MID — JsonParser 本命 P2`_parse_number` / `_atoi` 本体 / `_atof_loop`)を Normalized 基準に寄せるための事前設計メモ。
Update (Phase 43-A): `_atoi` 本体を Program(JSON) フィクスチャ `jsonparser_atoi_real` で dev Normalized→MIR(direct) 経路に載せ、Structured 直経路との VM 出力一致を確認済み(符号あり/なしの簡易パスまで対応。canonical 化は後続で検討)。
Update (Phase 43-C): `_parse_number` 本体を Program(JSON) フィクスチャ `jsonparser_parse_number_real` で dev Normalized→MIR(direct) 経路に載せ、Structured 直経路との VM 出力一致を dev テストで固定num_str は現状仕様のまま据え置き)。
# Phase 43NORMCANONP2MID 設計メモJsonParser P2Mid 向け Normalized 拡張)
## 0. ゴールと前提
- ゴール
- JsonParser の本命 P2 ループP2Midを、既存の Normalized インフラの延長で扱えるようにするための設計方針を固める。
- 特に `_parse_number` / `_atoi` 本体 / `_atof_loop` について、
- どのキャリア・bodylocal を EnvLayout に載せるか
- どの JpInst / JpOp パターンが追加で必要か
- StepScheduleBox / DigitPos / NumberAccumulation との責務分担
を整理する。
- 前提
- P2CoreP2 ミニ + JP skip_ws mini/real + JP atoi miniは Phase 41 までで Normalized→MIR(direct) が canonical 済み。
- P2Mid は **JoinIR(Structured) までは載っているが Normalized は未対応** の状態Phase 245/246 系)。
- 本メモは「設計レベル」で止め、実装・テスト追加は後続フェーズ43 実装回)で扱う。
---
## 1. 対象ループと P2Mid クラスの整理
- 対象とする P2MidJsonParser 側)
- `_parse_number`(数値文字列の収集 + digit_pos break
- `_atoi` 本体(範囲チェック + digit_pos + NumberAccumulation
- `_atof_loop`(構造的には `_atoi` と同型の浮動小数点版)
- すべて Pattern2 Break で、既に JoinIR(Structured) には載っている:
- `_parse_number` → Phase 245EX で header / break / `p` 更新を Pattern2 に統合済み(`num_str` は当面対象外)。
- `_atoi` → Phase 246EX で DigitPos dual 値 + NumberAccumulation パターンとして JoinIR 経路に統合済み。
- `_atof_loop` → 設計上 `_atoi` と同型とみなし、P2Mid クラスに含める。
- P2Core との差分
- P2 ミニ / skip_ws / atoi ミニに比べて:
- Carrier の本数(`p` + `result` + 場合によっては `num_str`)が増える。
- bodylocal / Derived Carrier`digit_pos`, `is_digit_pos`, `digit_value` 等)の依存関係が複雑。
- 一部で文字列連結(`num_str = num_str + ch`)や Range チェック(`"0" <= ch <= "9"`)が入る。
---
## 2. Normalized IR に必要な拡張EnvLayout / JpInst / JpOp
### 2.1 EnvLayout / フィールド設計
- P2Mid で EnvLayout に載せる候補
- LoopState キャリア
- `_parse_number`: `p`(必須)、`num_str`Phase 43 では **オプション**、まず `p` 単独で正規化する案も許容)。
- `_atoi` 本体 / `_atof_loop`: `i`, `result`NumberAccumulation キャリア)。
- Condition 専用 / FromHost
- `len` / `s` / `digits` などの不変値は ParamRole::Condition として EnvLayout 側に持たない(現状どおり)。
- Derived LoopStateDigitPos 系)
- P2Core で既に導入済みの `digit_value` / `is_digit_pos` と同じ方針:
- EnvLayout に「FromHost ではない LoopState キャリア」として載せる。
- host_slot を持たず、ExitBinding には出さない(ループ内部完結キャリア)。
### 2.2 JpInst / JpOp 側の必要パターン
- 既存の Normalized が既に扱っているもの
- `Let { dst, op: Const / BinOp / Unary / Compare / BoxCall, args }`
- `If { cond, then_target, else_target, env }`
- `TailCallFn` / `TailCallKont`loop_step / k_exit のみ)
- P2Mid で追加検証・明文化が必要なパターン
- `_parse_number`
- `substring` / `indexOf` の BoxCall パターンP2Core でも使用済みだが、`num_str` 周辺の利用を含めてドキュメントで SSOT 化する)。
- 文字列連結 `num_str = num_str + ch`
- 当面は「扱わない」(`num_str` を Carrier から外す)案
- もしくは `BinOp(Add)` として Normalized→MIR 直ブリッジに追加する案
のどちらにするかを Phase 43 実装メモで最終決定する。
- `_atoi` 本体 / `_atof_loop`
- Range チェック `ch < "0" || ch > "9"`
- ExprLowerer / ConditionEnv 側で既に対応済みであれば、Normalized には Compare + BinOp(or) の形で入る。
- Normalized では追加の JpOp は不要Compare / BinOp を利用)。
- NumberAccumulation パターン:
- Structured 側では `UpdateRhs::NumberAccumulation` として扱っているので、
- Normalized → MIR 直ブリッジ側で「Mul + Add + digit_value」の形を既に対応済み。
- Phase 43 では `_atoi` 本体 / `_atof_loop` でも同じシーケンスになることを前提とし、JpInst 種別追加は行わない。
---
## 3. StepScheduleBox / DigitPos / NumberAccumulation の役割分担
### 3.1 StepScheduleBox評価順の適用範囲
- Phase 39 で導入した StepScheduleBoxPattern2 用は、P2Mid に対しても「どの StepKind をどの順番で評価するか」を決める SSOT として使う。
- `_parse_number` / `_atoi` 本体 / `_atof_loop` では、以下のようなフラグを想定:
- `has_digitpos_body_local`DigitPos 二重値を使うか)
- `has_number_accumulation`(結果キャリアに Mul+Add があるか)
- `has_bodylocal_break`break 条件が bodylocal に依存するか)
- StepScheduleBox は、これらのフラグだけを見て
- 標準 P2: `[HeaderCond, BreakCheck, BodyInit, Updates, Tail]`
- DigitPos / atoi 系: `[HeaderCond, BodyInit, BreakCheck, Updates, Tail]`
など、評価順のバリエーションを返す「薄い箱」のまま保つ。
- Pattern2 lowerer / Normalized 変換側は、この StepSchedule に従って
- header 条件
- bodylocal initDigitPos / Range check 等)
- break 条件
- carrier 更新NumberAccumulation / i++ 等)
を「並べるだけ」にし、条件式の詳細や bodylocal の構造には踏み込まない。
### 3.2 DigitPos / NumberAccumulation との接続
- DigitPos 系
- `digit_pos``is_digit_pos` / `digit_value` の二重値設計は、P2Core と同じく「LoopState キャリアFromHost なし)」として EnvLayout に載せる。
- ExitBinding には出さず、Normalized→MIR 直ブリッジでも Loop 内部だけで完結させる。
- Break 条件 `digit_pos < 0` は Phase 224 の DigitPosConditionNormalizerAST→`!is_digit_pos`を前提にし、Normalized 側は `!is_digit_pos` という bool 条件だけを受け取る。
- NumberAccumulation 系
- Structured 側の LoopUpdateAnalyzer / CarrierUpdateEmitter が `result = result * 10 + digit_value` パターンを `UpdateRhs::NumberAccumulation` として検出・JoinIR 生成済み。
- Normalized→MIR 直ブリッジは、P2Core と同じ Mul + Add シーケンスで MIR を吐く設計を維持し、P2Mid でも追加ロジックを増やさずに流用する。
---
## 4. Bridge / ShapeGuard / canonical 切り替え方針
- ShapeGuard 拡張
- 既存の P2Core 判定P2 ミニ / skip_ws mini/real / atoi miniに加えて、
- `_parse_number` 本体
- `_atoi` 本体
- `_atof_loop`
を P2Mid として検出できる Shape 種別を追加する(例: `ShapeKind::JsonparserParseNumber`, `ShapeKind::JsonparserAtoiCore`)。
- Phase 43 実装フェーズでは、まず P2Mid ループを **dev only** の Normalized 対象にするcanonical 切り替えは Phase 43 後半〜Phase 44 相当で検討)。
- Bridge 側の経路
- `bridge_joinir_to_mir` の入口で:
- P2Core: 既に canonical Normalized→MIR(direct)Phase 41 の状態を維持)。
- P2Mid: `normalized_dev_enabled()` が true のときに限り Structured→Normalized→MIR(direct) を試し、テストで Structured 直経路と比較。
- FailFast 方針
- P2Mid では「Normalized が未対応の領域」がまだ多いため、
- dev / debug ビルドでは invariant 破壊・未対応命令で panicNormalized 実装の穴を早期検出)。
- release / canonical OFF 時は Structured→MIR 直経路に落とすサイレントフォールバックではなく「Normalized をそもそも使わない」構成にする)。
---
## 5. テストと完了条件Phase 43 実装フェーズ向けメモ)
- テスト戦略(概要)
- `_parse_number`:
- 代表ケース("42", "7z" など)で
- Structured→MIR→VM
- Structured→Normalized→MIR(direct)→VM
の stdout / RC を比較する dev テストを追加。
- `num_str` をまだ Normalized キャリアに載せない場合でも、「p / break 条件 / DigitPos 周り」が齟齬なく動くことを確認する。
- `_atoi` 本体 / `_atof_loop`:
- 既存の `_atoi` mini dev fixture と同じ観点で、NumberAccumulation / DigitPos / Range check が Normalized 経路で再現できるかをチェック。
- Mini / 本体 / `_atof_loop` が同じ normalized helper / bridge ロジックを共有できることを確認する。
- 完了条件Phase 43 実装のためのチェックリスト)
- EnvLayout / JpInst / JpOp / StepScheduleBox / DigitPos / NumberAccumulation の役割分担が本メモの通りに整理されている。
- P2Mid`_parse_number` / `_atoi` 本体 / `_atof_loop`)に対して、どこまでを Phase 43 で扱い、どこから先を後続フェーズに回すかの線引きが明文化されている。
- `joinir-architecture-overview.md` の Phase 43 セクション3.20)と、この設計メモの内容が矛盾していない。