170 lines
4.9 KiB
Markdown
170 lines
4.9 KiB
Markdown
|
|
# 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)
|
||
|
|
```rust
|
||
|
|
// 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)
|
||
|
|
```rust
|
||
|
|
match current_joinir_mode() {
|
||
|
|
JoinIrMode::NormalizedDev => { /* dev path */ }
|
||
|
|
JoinIrMode::StructuredOnly => { /* default path */ }
|
||
|
|
JoinIrMode::NormalizedCanonical => { /* future canonical */ }
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## JoinIrMode Enum
|
||
|
|
|
||
|
|
```rust
|
||
|
|
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)
|
||
|
|
|
||
|
|
```rust
|
||
|
|
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)
|
||
|
|
|
||
|
|
```rust
|
||
|
|
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)
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Related Documentation
|
||
|
|
|
||
|
|
- **JoinIR Architecture**: [joinir-architecture-overview.md](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`
|