feat(joinir): Phase 185 Strict Mode Semantics Cleanup

Remove redundant strict checks from If lowering (3 → 1 check point):
- mod.rs: Remove 2 strict panic blocks from try_lower_if_to_joinir()
- mod.rs: Comment out unused strict_on variable
- Keep single strict check at caller level (if_form.rs)

This aligns If lowering architecture with Loop lowering:
- Lowerers are thin Result-returning boxes (no policy decisions)
- Strict mode check happens at router/caller level (single source of truth)
- Fail-Fast principle: panic at ONE location when strict=ON

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
nyash-codex
2025-12-04 22:27:12 +09:00
parent d9e91d4228
commit 6561832545
2 changed files with 60 additions and 16 deletions

View File

@ -1,5 +1,59 @@
# Current Task
## ✅ Phase 185: JoinIR Strict Mode Semantics Cleanup (Completed - 2025-12-04)
**Status**: ✅ **All Tasks Completed** → Clean Architecture Established
**Key Achievement**: Strict mode semantics unified between Loop/If lowering. If lowering now has SINGLE strict check point (like Loop), eliminating double/triple-invocation problem.
### Completed Tasks
**Task 1-2**: Strict flow inventory and design
- Created comprehensive flow inventory document
- Identified problem: If lowering had 3 strict check points vs Loop's 1
- Document: `docs/private/roadmap2/phases/phase-185-joinir-strict-mode/strict_flow_inventory.md`
**Task 3**: If lowering strict check consolidation
- **Removed 2 strict checks** from `try_lower_if_to_joinir()` (lines 296, 314)
- **Kept 1 strict check** at caller level in `if_form.rs` (line 311)
- Pattern now matches Loop lowering: Result-returning box + single check at router
**Task 4**: Representative strict tests verified
- Loop (reference): `loop_min_while.hako` ✅ Passes with NYASH_JOINIR_STRICT=1
- If Select: `joinir_if_select_simple.hako` ✅ Passes with NYASH_JOINIR_STRICT=1
- If Merge: `joinir_if_merge_simple.hako` ✅ Passes with NYASH_JOINIR_STRICT=1
- Fallback: All tests pass without strict mode (backward compatibility maintained)
**Task 5**: Documentation updated
- Phase 185 implementation complete
- Phase 184 Known Issues resolved (double-invocation problem fixed)
- CURRENT_TASK.md updated with completion status
### Implementation Summary
**Architecture Change**: Strict check consolidation
| Component | Before (Problem) | After (Fixed) |
|-----------|-----------------|---------------|
| **try_lower_if_to_joinir** | 2 panic points (lines 296, 314) | 0 panic points (thin Result box) |
| **if_form.rs caller** | 1 panic point (line 311) | 1 panic point (SINGLE source) |
| **Total** | **3 check points** ❌ | **1 check point** ✅ |
**Pattern Now Matches Loop Lowering**:
- Loop: `LoopToJoinLowerer::lower()` → Result → Single check in `join_ir_vm_bridge_dispatch`
- If: `try_lower_if_to_joinir()` → Option → Single check in `if_form.rs`
**Modified Files**:
- `src/mir/join_ir/lowering/mod.rs` (removed 2 strict checks, -8 lines)
- `src/mir/builder/if_form.rs` (kept 1 strict check at caller level, 0 changes)
**Semantic Guarantee**:
- strict=OFF: Lowering failure → fallback to traditional path (dev/test)
- strict=ON: Lowering failure → panic with clear message (production gate)
- Fail-Fast principle: ONE check point = ONE source of truth
---
## ✅ Phase 184: JoinIR If Lowering Mainline (Completed - 2025-12-04)
**Status**: ✅ **All Tasks Completed** → Phase 185+ Ready
@ -54,7 +108,7 @@
### Known Issues (Non-blocking)
1. **Double-invocation in strict mode**: NYASH_JOINIR_STRICT=1 can panic even when lowering succeeds (skeleton + lowering passes). Workaround: use NYASH_JOINIR_DEBUG=1 instead.
1. ~~**Double-invocation in strict mode**: NYASH_JOINIR_STRICT=1 can panic even when lowering succeeds (skeleton + lowering passes). Workaround: use NYASH_JOINIR_DEBUG=1 instead.~~**FIXED in Phase 185**
2. **Test output formatting**: Tests show "RC: 0" instead of expected print output (unrelated to If lowering infrastructure).
### Verification Commands

View File

@ -202,7 +202,8 @@ pub fn try_lower_if_to_joinir(
return None;
}
let core_on = crate::config::env::joinir_core_enabled();
let strict_on = crate::config::env::joinir_strict_enabled();
// Phase 185: strict check moved to caller (if_form.rs)
// let strict_on = crate::config::env::joinir_strict_enabled();
// Phase 33-9.1: Loop専任関数の除外Loop/If責務分離
// Loop lowering対象関数はIf loweringの対象外にすることで、
@ -248,7 +249,7 @@ pub fn try_lower_if_to_joinir(
return None;
}
}
let strict_allowed = strict_on && core_on && is_allowed;
// Phase 185: strict_allowed removed (strict check moved to caller: if_form.rs)
if debug_level >= 1 {
eprintln!(
@ -286,6 +287,8 @@ pub fn try_lower_if_to_joinir(
if_select::IfSelectLowerer::new(debug_level)
};
// Phase 185: Remove strict checks from lowerer (thin Result-returning box)
// Strict mode panic should happen at caller level (if_form.rs), not here
if !if_select_lowerer.can_lower_to_select(func, block_id) {
if debug_level >= 1 {
eprintln!(
@ -293,12 +296,6 @@ pub fn try_lower_if_to_joinir(
func.signature.name
);
}
if strict_allowed {
panic!(
"[joinir/if] strict mode: pattern not matched for {}",
func.signature.name
);
}
return None;
}
@ -311,13 +308,6 @@ pub fn try_lower_if_to_joinir(
);
}
if result.is_none() && strict_allowed {
panic!(
"[joinir/if] strict mode: lowering failed for {}",
func.signature.name
);
}
result
}