feat(joinir): Phase 46 - P2-Mid canonical Normalized promotion
Promote P2-Mid patterns (_atoi real, _parse_number real) to canonical
Normalized→MIR(direct) route, completing P2 line transition.
Canonical set expansion (Phase 41 → Phase 46):
- P2-Core: Pattern2Mini, skip_ws mini/real, atoi mini
- P2-Mid: atoi real, parse_number real (NEW)
All JsonParser P2 loops (_skip_whitespace, _atoi, _parse_number) now
canonical Normalized - Structured→MIR is legacy/comparison-only.
Key changes:
- shape_guard.rs: Expanded is_canonical_shape() (+2 patterns)
- JsonparserAtoiReal
- JsonparserParseNumberReal
- Made NormalizedDevShape enum public
- bridge.rs: Updated canonical routing comments (Phase 41 → 46)
- normalized.rs: Made shape_guard module public
- normalized_joinir_min.rs: Added Phase 46 canonical verification test
- phase46-norm-canon-p2-mid.md: Complete design documentation
Out of scope (deferred):
- P3/P4 Normalized support → NORM-P3/NORM-P4 phases
- Selfhost complex loops → separate phases
Benefits:
- Clear P2 boundary: All JsonParser P2 = Normalized canonical
- Infrastructure validation: Phase 43/245B proven production-ready
- Simplified mental model: P2 = Normalized-first, P3/P4 = future
Tests: 937/937 PASS (lib), 20/20 PASS (normalized_dev feature)
Phase 46 test: test_phase46_canonical_set_includes_p2_mid ✅
This commit is contained in:
@ -81,6 +81,12 @@
|
||||
- JsonParser `_atoi` 本体の Program(JSON) フィクスチャを normalized_dev に追加し、Structured→Normalized→MIR(direct) と Structured→MIR の VM 出力を比較するテストで一致を固定(符号あり/なしの簡易パス対応。canonical 切替は後続フェーズ)。
|
||||
- Phase 43-C(dev-only):
|
||||
- JsonParser `_parse_number` 本体の Program(JSON) フィクスチャを normalized_dev に追加し、Structured→Normalized→MIR(direct) と Structured→MIR の VM 出力を比較するテストで一致を固定(num_str は現状仕様のまま据え置き、P2-Mid の足慣らし)。
|
||||
- **Phase 46-NORM-CANON-P2-MID(実装済み✅ 2025-12-12)**:
|
||||
- P2-Mid パターン(_atoi real, _parse_number real)を canonical Normalized に昇格。
|
||||
- Canonical set 拡張: P2-Core(mini + skip_ws + atoi mini)+ P2-Mid(atoi real + parse_number real)。
|
||||
- JsonParser P2 ライン(_skip_whitespace/_atoi/_parse_number)全て canonical Normalized 化完了。
|
||||
- P3/P4 Normalized 対応は NORM-P3/NORM-P4 フェーズで実施(今回スコープ外)。
|
||||
- 937/937 tests PASS。
|
||||
- **Phase 45-NORM-MODE(実装済み✅ 2025-12-12)**:
|
||||
- JoinIR モード一本化: バラバラだったフラグ/feature を `JoinIrMode` enum に集約(StructuredOnly / NormalizedDev / NormalizedCanonical)。
|
||||
- `current_joinir_mode()` でモード取得、bridge/runner で `normalized_dev_enabled()` → mode pattern matching に移行。
|
||||
|
||||
@ -1106,6 +1106,28 @@ Normalized JoinIR では、制御構造を次の 3 要素だけで表現する
|
||||
これにより、現在 JoinIR 層で苦労している「PHI 配線」「exit_bindings/jump_args 整合性」「評価順のねじれ」は、
|
||||
Normalized JoinIR 側では「Env フィールドの更新順」と「どの継続を呼ぶか」に還元される想定だよ。
|
||||
|
||||
#### 3.2.1 P1〜P4 と Normalized ループ形
|
||||
|
||||
Normalized JoinIR のゴールは、「P1〜P4 すべてのループを同じループ骨格(`loop_step(env, k_exit)` + 継続)で表現する」ことだよ:
|
||||
|
||||
- P1 Simple:
|
||||
- `loop_step(env, k_exit)` だけを持つ最小形(break/continue なし)。
|
||||
- 条件が false になったら `k_exit(env)` に TailCall、true なら body を 1 ステップ進めて再び `loop_step` を呼ぶ。
|
||||
- P2 Break:
|
||||
- P1 の形に「body 後の break 判定」と `k_exit(env)` への分岐が加わったもの。
|
||||
- break/continue/return 自体はすべて継続呼び出し(`TailCallKont` / `TailCallFn`)として表現され、型レベルでは P1 の上位互換。
|
||||
- P3 If‑PHI:
|
||||
- ループ本体に `if_branch(env, k_then, k_else)` + join 継続を挟んだ形として表現し、PHI は「Env のフィールド更新順+ join 継続」で表す。
|
||||
- P4 Continue:
|
||||
- `continue` は「更新後に `loop_step(env', k_exit)` へ TailCall」するだけの構造として扱い、break/return と同じく継続レベルで閉じる。
|
||||
|
||||
設計としては **Normalized IR の型と不変条件は P1〜P4 で共通**で、違いは Structured 層からどのように `loop_step` / 継続を合成するか(`LoopCpsSynthesizer` 側の分岐)だけに閉じ込める前提だよ。
|
||||
|
||||
- Phase 26‑H / 28–43 では、まず P1/P2(特に JsonParser の P2-Core/P2-Mid)だけを Normalized に載せて設計を固定した。
|
||||
- P3/P4 の Normalized 対応は今後のフェーズ(NORM‑P3 / NORM‑P4 ライン)で、上の骨格に揃える形で段階的に進める。
|
||||
|
||||
この方針により、「先に P1/P2 だけ Normalized を実装しても、後から P3/P4 を同じ器に寄せられる」ことを文書上で保証しておく。
|
||||
|
||||
### 3.3 Normalized JoinIR 導入のメリットと初期コスト
|
||||
|
||||
Normalized JoinIR を 1 段挟むと、開発の手触りがどう変わるかをここでまとめておくよ。
|
||||
@ -1315,3 +1337,24 @@ Normalized JoinIR を 1 段挟むと、開発の手触りがどう変わるか
|
||||
- ✅ **Canonical-first routing**: P2-Core canonical shapes は mode 無視で常に Normalized→MIR(direct)
|
||||
- ✅ **Mode-based 分岐統一**: bridge/runner の pattern matching で一貫した挙動
|
||||
- ✅ **既存挙動完全保持**: 937/937 tests PASS
|
||||
|
||||
### 3.23 Phase 46-NORM-CANON-P2-MID – Normalized Canonical P2-Mid 昇格 ✅ COMPLETE (2025-12-12)
|
||||
|
||||
**設計詳細**: [phase46-norm-canon-p2-mid.md](./phase46-norm-canon-p2-mid.md)
|
||||
|
||||
P2-Mid パターン(_atoi real, _parse_number real)を canonical Normalized→MIR(direct) ルートに昇格。
|
||||
|
||||
**Canonical set 拡張(Phase 46)**:
|
||||
- P2-Core: Pattern2Mini, skip_ws mini/real, atoi mini
|
||||
- **P2-Mid: atoi real, parse_number real** (NEW)
|
||||
|
||||
JsonParser _skip_whitespace / _atoi / _parse_number が**すべて canonical Normalized** に。Structured→MIR は P2 ラインにおいてレガシー/比較用途のみ。
|
||||
|
||||
**スコープ外**: P3/P4 Normalized 対応(NORM-P3/NORM-P4 フェーズで実施)。
|
||||
|
||||
**変更ファイル**:
|
||||
- `shape_guard.rs`: `is_canonical_shape()` 拡張(+2 パターン)
|
||||
- `bridge.rs`: コメント更新(Phase 41 → Phase 46)
|
||||
- `normalized_joinir_min.rs`: canonical set 検証テスト追加
|
||||
|
||||
**テスト**: 937/937 PASS
|
||||
|
||||
103
docs/development/current/main/phase46-norm-canon-p2-mid.md
Normal file
103
docs/development/current/main/phase46-norm-canon-p2-mid.md
Normal file
@ -0,0 +1,103 @@
|
||||
# Phase 46: Normalized Canonical P2-Mid Promotion
|
||||
|
||||
**Status**: Implemented ✅ (2025-12-12)
|
||||
**Test Coverage**: 937/937 PASS
|
||||
|
||||
## Goal
|
||||
|
||||
Promote P2-Mid patterns (_atoi real, _parse_number real) to canonical Normalized→MIR(direct) route, alongside existing P2-Core patterns.
|
||||
|
||||
## Scope
|
||||
|
||||
**In Scope (P2 patterns)**:
|
||||
- JsonparserAtoiReal → canonical Normalized
|
||||
- JsonparserParseNumberReal → canonical Normalized
|
||||
|
||||
**Out of Scope (deferred to future phases)**:
|
||||
- Pattern3 (if-sum) → NORM-P3
|
||||
- Pattern4 (continue) → NORM-P4
|
||||
- Selfhost complex loops → separate phases
|
||||
|
||||
## Rationale
|
||||
|
||||
With Phase 43/245B infrastructure complete, JsonParser P2-Mid loops (_atoi, _parse_number) are production-ready for canonical Normalized route:
|
||||
|
||||
1. **Proven infrastructure**: DigitPos dual-value, NumberAccumulation, StepSchedule all working
|
||||
2. **Real-world validation**: JsonParser _atoi/_parse_number tests passing (937/937)
|
||||
3. **Clear boundary**: P2 vs P3/P4 separation simplifies rollout
|
||||
|
||||
After Phase 46, P2 line becomes "Normalized-first" - Structured→MIR is legacy/comparison only.
|
||||
|
||||
## Implementation Checklist
|
||||
|
||||
### 1. Expand Canonical Set (shape_guard.rs)
|
||||
|
||||
✅ Update `is_canonical_shape()` to include:
|
||||
- JsonparserAtoiReal
|
||||
- JsonparserParseNumberReal
|
||||
|
||||
✅ Update doc comments:
|
||||
- "Phase 41 canonical set" → "Phase 46 canonical set: P2-Core + P2-Mid"
|
||||
|
||||
### 2. Verify Bridge Routing (bridge.rs)
|
||||
|
||||
✅ Confirm `canonical_shapes()` routing unchanged (already calls `is_canonical_shape()`)
|
||||
|
||||
✅ Update comments:
|
||||
- "Phase 41: P2-Core only" → "Phase 46: P2-Core + P2-Mid (_atoi/_parse_number real)"
|
||||
|
||||
### 3. Add/Update Tests
|
||||
|
||||
✅ Verify existing tests cover canonical routing:
|
||||
- `normalized_pattern2_jsonparser_atoi_real_vm_bridge_direct_matches_structured`
|
||||
- `normalized_pattern2_jsonparser_parse_number_real_vm_bridge_direct_matches_structured`
|
||||
|
||||
✅ Add new unit test (normalized_dev feature only):
|
||||
- Verify canonical_shapes includes _atoi real / _parse_number real
|
||||
- Verify bridge always routes to Normalized→MIR(direct)
|
||||
|
||||
### 4. Update Documentation
|
||||
|
||||
✅ Add Phase 46 section to `joinir-architecture-overview.md`:
|
||||
- "JsonParser _skip_whitespace / _atoi / _parse_number now canonical Normalized"
|
||||
- Link to P3/P4 future work (NORM-P3/NORM-P4)
|
||||
|
||||
✅ Add Phase 46 entry to `CURRENT_TASK.md`:
|
||||
- Scope: P2-Core/P2-Mid canonical (P3/P4 out of scope)
|
||||
- Done condition: shape_guard + bridge + tests + docs
|
||||
|
||||
## Canonical Set Evolution
|
||||
|
||||
| Phase | Canonical Patterns | Description |
|
||||
|-------|-------------------|-------------|
|
||||
| Phase 41 | P2-Core: Pattern2Mini, skip_ws mini/real, atoi mini | Initial canonical set |
|
||||
| **Phase 46** | **+ P2-Mid: atoi real, parse_number real** | **JsonParser production patterns** |
|
||||
| Future | P3/P4, Selfhost loops | Deferred to NORM-P3/NORM-P4 |
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
**Existing coverage** (no new tests required):
|
||||
- `normalized_joinir_min.rs` already tests _atoi real / _parse_number real
|
||||
- VM output comparison verified (Normalized vs Structured)
|
||||
|
||||
**New unit test** (shape + bridge integration):
|
||||
- Verify `canonical_shapes()` includes P2-Mid
|
||||
- Feature-gated: `#[cfg(feature = "normalized_dev")]`
|
||||
|
||||
## Benefits
|
||||
|
||||
1. **Clear P2 boundary**: All JsonParser P2 loops now Normalized-first
|
||||
2. **Simplified mental model**: P2 = Normalized canonical, P3/P4 = future work
|
||||
3. **Production-ready**: _atoi/_parse_number real validated through Phase 246-EX/247-EX
|
||||
|
||||
## Next Steps (Out of Scope)
|
||||
|
||||
- **NORM-P3**: Pattern3 (if-sum) Normalized support
|
||||
- **NORM-P4**: Pattern4 (continue) Normalized support
|
||||
- **Selfhost**: Complex loops from selfhost compiler
|
||||
|
||||
## References
|
||||
|
||||
- **Completion Summary**: [PHASE_43_245B_NORMALIZED_COMPLETION.md](./PHASE_43_245B_NORMALIZED_COMPLETION.md)
|
||||
- **Phase 44 Capabilities**: [phase44-shape-capabilities-design.md](./phase44-shape-capabilities-design.md)
|
||||
- **Phase 45 Mode**: [phase45-norm-mode-design.md](./phase45-norm-mode-design.md)
|
||||
@ -19,7 +19,7 @@ pub mod fixtures;
|
||||
#[cfg(feature = "normalized_dev")]
|
||||
pub mod dev_env;
|
||||
#[cfg(feature = "normalized_dev")]
|
||||
pub(crate) mod shape_guard;
|
||||
pub mod shape_guard;
|
||||
#[cfg(feature = "normalized_dev")]
|
||||
use crate::mir::join_ir::normalized::shape_guard::NormalizedDevShape;
|
||||
|
||||
|
||||
@ -19,7 +19,7 @@ pub enum ShapeCapabilityKind {
|
||||
/// P2 Mid: _parse_number real (p + num_str + result)
|
||||
P2MidParseNumber,
|
||||
|
||||
/// Future: Other P2 patterns
|
||||
// Future: Other P2 patterns
|
||||
// P2MidAtOfLoop,
|
||||
// P2HeavyString,
|
||||
}
|
||||
@ -42,7 +42,7 @@ impl ShapeCapability {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub(crate) enum NormalizedDevShape {
|
||||
pub enum NormalizedDevShape {
|
||||
Pattern1Mini,
|
||||
Pattern2Mini,
|
||||
JsonparserSkipWsMini,
|
||||
@ -109,15 +109,25 @@ pub fn capability_for_shape(shape: &NormalizedDevShape) -> ShapeCapability {
|
||||
ShapeCapability::new(kind)
|
||||
}
|
||||
|
||||
/// Phase 44: Check if shape is canonical P2-Core (shape-level check)
|
||||
/// Phase 46: Canonical shapes that ALWAYS use Normalized→MIR(direct)
|
||||
/// regardless of feature flags or mode.
|
||||
///
|
||||
/// Phase 41 canonical set (exact): Pattern2Mini, skip_ws (mini/real), atoi mini.
|
||||
/// Excludes: Pattern1Mini, atoi real, parse_number real.
|
||||
/// Canonical set (Phase 46):
|
||||
/// - P2-Core: Pattern2Mini, JsonparserSkipWsMini, JsonparserSkipWsReal, JsonparserAtoiMini
|
||||
/// - P2-Mid: JsonparserAtoiReal, JsonparserParseNumberReal
|
||||
///
|
||||
/// P3/P4 patterns are NOT canonical (deferred to NORM-P3/NORM-P4 phases).
|
||||
pub fn is_canonical_shape(shape: &NormalizedDevShape) -> bool {
|
||||
use NormalizedDevShape::*;
|
||||
matches!(
|
||||
shape,
|
||||
Pattern2Mini | JsonparserSkipWsMini | JsonparserSkipWsReal | JsonparserAtoiMini
|
||||
Pattern2Mini
|
||||
| JsonparserSkipWsMini
|
||||
| JsonparserSkipWsReal
|
||||
| JsonparserAtoiMini
|
||||
// Phase 46: Add P2-Mid patterns
|
||||
| JsonparserAtoiReal
|
||||
| JsonparserParseNumberReal
|
||||
)
|
||||
}
|
||||
|
||||
@ -137,8 +147,13 @@ pub fn is_supported_by_normalized(cap: &ShapeCapability) -> bool {
|
||||
}
|
||||
|
||||
/// canonical(常時 Normalized 経路を通す)対象。
|
||||
/// Phase 41: P2 コアセット(P2 mini + JP skip_ws mini/real + JP atoi mini)。
|
||||
/// Phase 44: Capability-based filtering (backward compatible)。
|
||||
/// Phase 46: Extract canonical shapes from JoinModule.
|
||||
///
|
||||
/// Canonical set (P2-Core + P2-Mid):
|
||||
/// - Pattern2Mini, skip_ws mini/real, atoi mini/real, parse_number real
|
||||
///
|
||||
/// These shapes ALWAYS use Normalized→MIR(direct) regardless of mode.
|
||||
/// P3/P4 patterns are NOT canonical (future NORM-P3/NORM-P4 phases).
|
||||
pub(crate) fn canonical_shapes(module: &JoinModule) -> Vec<NormalizedDevShape> {
|
||||
let shapes: Vec<_> = detect_shapes(module)
|
||||
.into_iter()
|
||||
|
||||
@ -176,7 +176,9 @@ pub(crate) fn bridge_joinir_to_mir_with_meta(
|
||||
{
|
||||
let mode = current_joinir_mode();
|
||||
|
||||
// Phase 41: canonical shapes は mode が何であろうと常に Normalized → MIR を通す。
|
||||
// Phase 46: Canonical P2-Core + P2-Mid shapes always use Normalized→MIR(direct)
|
||||
// Canonical set: Pattern2Mini, skip_ws mini/real, atoi mini/real, parse_number real
|
||||
// P3/P4 patterns are NOT canonical (deferred to NORM-P3/NORM-P4)
|
||||
let canonical_shapes = shape_guard::canonical_shapes(module);
|
||||
if !canonical_shapes.is_empty() {
|
||||
match try_normalized_direct_bridge(module, meta, &canonical_shapes, false, false)? {
|
||||
|
||||
@ -507,3 +507,23 @@ fn normalized_pattern2_jsonparser_atoi_real_vm_bridge_direct_matches_structured(
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "normalized_dev")]
|
||||
#[test]
|
||||
fn test_phase46_canonical_set_includes_p2_mid() {
|
||||
use nyash_rust::mir::join_ir::normalized::shape_guard::{
|
||||
is_canonical_shape, NormalizedDevShape,
|
||||
};
|
||||
|
||||
// Phase 46: Verify P2-Mid patterns are canonical
|
||||
assert!(is_canonical_shape(&NormalizedDevShape::JsonparserAtoiReal));
|
||||
assert!(is_canonical_shape(
|
||||
&NormalizedDevShape::JsonparserParseNumberReal
|
||||
));
|
||||
|
||||
// Verify P2-Core patterns still canonical
|
||||
assert!(is_canonical_shape(&NormalizedDevShape::Pattern2Mini));
|
||||
assert!(is_canonical_shape(&NormalizedDevShape::JsonparserSkipWsMini));
|
||||
assert!(is_canonical_shape(&NormalizedDevShape::JsonparserSkipWsReal));
|
||||
assert!(is_canonical_shape(&NormalizedDevShape::JsonparserAtoiMini));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user