Files
hakorune/docs/development/current/main/phase45-norm-mode-design.md
nyash-codex 879d3ee08e feat(joinir): Phase 45 - JoinIR mode unification
Unified JoinIR routing logic through centralized JoinIrMode enum:

Key changes:
- Added JoinIrMode enum (StructuredOnly / NormalizedDev / NormalizedCanonical)
- Added current_joinir_mode() for centralized mode determination
- Refactored normalized_dev_enabled() as thin wrapper over mode enum
- Updated bridge.rs: mode-based routing with canonical P2-Core special handling
- Updated runner.rs: mode pattern matching for dev roundtrip path

Files modified:
- joinir_dev.rs: JoinIrMode enum + current_joinir_mode() (+49 lines)
- bridge.rs: Replaced boolean checks with mode pattern matching (+29 lines)
- runner.rs: Mode-based routing logic (+9 lines)
- CURRENT_TASK.md: Phase 45 implementation summary

Documentation:
- phase45-norm-mode-design.md: Complete design spec and implementation guide

Behavior preservation:
- Canonical P2-Core shapes: always Normalized→MIR(direct) (mode-independent)
- NormalizedDev mode: Structured→Normalized→MIR for supported shapes
- StructuredOnly mode: Structured→MIR direct (default)

Tests: 937/937 PASS (no regression, pure refactor)

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-12 03:31:58 +09:00

4.9 KiB

Phase 45: JoinIR Mode Unification

Status: Implemented Date: 2025-12-12 Goal: Unify JoinIR routing logic through a single JoinIrMode enum


Overview

Phase 45 consolidates fragmented feature flags and environment variables into a unified JoinIrMode enum, making JoinIR routing decisions centralized and maintainable.

Before (Fragmented)

// Scattered checks across codebase
if normalized_dev_enabled() { /* ... */ }
if cfg!(feature = "normalized_dev") { /* ... */ }
if env::var("NYASH_JOINIR_NORMALIZED_DEV_RUN").is_ok() { /* ... */ }

After (Unified)

match current_joinir_mode() {
    JoinIrMode::NormalizedDev => { /* dev path */ }
    JoinIrMode::StructuredOnly => { /* default path */ }
    JoinIrMode::NormalizedCanonical => { /* future canonical */ }
}

JoinIrMode Enum

pub enum JoinIrMode {
    /// Default: Structured→MIR direct (no Normalized layer)
    StructuredOnly,

    /// Dev mode: Structured→Normalized→MIR(direct) for supported shapes
    /// Requires: --features normalized_dev + NYASH_JOINIR_NORMALIZED_DEV_RUN=1
    NormalizedDev,

    /// Future: All canonical shapes use Normalized→MIR(direct)
    /// Reserved for Phase 46+ canonical migration
    NormalizedCanonical,
}

Mode Determination Logic

┌─────────────────────────────────────────────────┐
│ current_joinir_mode()                           │
├─────────────────────────────────────────────────┤
│                                                 │
│  #[cfg(feature = "normalized_dev")]             │
│    ├─ NYASH_JOINIR_NORMALIZED_DEV_RUN=1         │
│    │   → NormalizedDev                          │
│    └─ else                                      │
│        → StructuredOnly                         │
│                                                 │
│  #[cfg(not(feature = "normalized_dev"))]        │
│    └─ StructuredOnly                            │
│                                                 │
└─────────────────────────────────────────────────┘

Routing Logic

Bridge (bridge.rs)

let mode = current_joinir_mode();
let shapes = shape_guard::classify(&module);

// 1. Canonical P2-Core: always Normalized→MIR(direct) (mode-independent)
if !canonical_shapes.is_empty() {
    return lower_via_normalized_direct(...);
}

// 2. Mode-based routing
match mode {
    JoinIrMode::NormalizedDev => {
        if !dev_shapes.is_empty() {
            return lower_via_normalized_dev(...);
        } else {
            return lower_structured(...);
        }
    }
    JoinIrMode::StructuredOnly | JoinIrMode::NormalizedCanonical => {
        return lower_structured(...);
    }
}

Canonical P2-Core shapes (Phase 41):

  • Pattern2Mini
  • JsonparserSkipWsMini/Real
  • JsonparserAtoiMini/Real
  • JsonparserParseNumberReal

Runner (join_ir_runner.rs)

match current_joinir_mode() {
    JoinIrMode::NormalizedDev => {
        // Dev roundtrip: Structured→Normalized→Structured
        run_joinir_function_normalized_dev(...)
    }
    _ => {
        // Structured-only path (default)
        run_joinir_function_structured(...)
    }
}

Implementation Summary

Files Modified

  1. src/config/env/joinir_dev.rs:

    • Added JoinIrMode enum (3 variants)
    • Added current_joinir_mode() function
    • Refactored normalized_dev_enabled() as thin wrapper
  2. src/mir/join_ir_vm_bridge/bridge.rs:

    • Replaced normalized_dev_enabled() with current_joinir_mode()
    • Updated routing logic to use pattern matching
    • Preserved canonical P2-Core special handling
  3. src/mir/join_ir_runner.rs:

    • Replaced boolean check with mode pattern matching
    • Updated comments to reference JoinIrMode::NormalizedDev

Tests

  • 937/937 tests pass (no regression)
  • Both configurations verified:
    • Default (without --features normalized_dev)
    • With --features normalized_dev

Future Work (Phase 46+)

NormalizedCanonical mode is reserved for future use when:

  • All Pattern1/Pattern2/Pattern3 shapes become canonical
  • Normalized→MIR(direct) becomes the default for all supported shapes
  • StructuredOnly mode becomes legacy/fallback only

Migration path:

Phase 45 (now):   StructuredOnly (default) + NormalizedDev (opt-in)
Phase 46+:        NormalizedCanonical (default) + StructuredOnly (legacy)

  • JoinIR Architecture: joinir-architecture-overview.md
  • Shape Guard: src/mir/join_ir/normalized/shape_guard.rs
  • Normalized Bridge: src/mir/join_ir_vm_bridge/normalized_bridge.rs