docs(joinir): phase80 plan finalize + fix p3 cond_env mut (dev-only)

Phase 80 後処理:
- phase80-bindingid-p3p4-plan.md: Status を Completed に更新、Task 80-B/C/D チェックマーク追加
- pattern3_with_if_phi.rs: cond_env を mut に修正 + #[allow(unused_mut)] 追加(将来の登録処理に備える)

Phase 80 完全完了(commit 84129a7e): Pattern2/3/4 全て BindingId 配線完了
Next: Phase 81 - Pattern2 ExitLine contract stabilization
This commit is contained in:
nyash-codex
2025-12-13 18:14:37 +09:00
parent 84129a7ed4
commit d150cecc36
2 changed files with 40 additions and 68 deletions

View File

@ -1,15 +1,15 @@
# Phase 80: BindingId P3/P4 Expansion Plan
**Status**: Ready for Task 80-B (Pattern3 Wiring)
**Status**: Completed (commit `84129a7e`)
**Created**: 2025-12-13
**Progress**:
- ✅ Task 80-0: Current Status Verification (complete)
- ✅ Task 80-A: SSOT Design Doc (complete)
- Task 80-B: Pattern3 BindingId Wiring (next)
- Task 80-C: Pattern4 BindingId Wiring
- Task 80-D: E2E Tests
- Task 80-B: Pattern3 BindingId Wiring (dev-only)
- Task 80-C: Pattern4 BindingId Wiring (dev-only)
- Task 80-D: E2E Tests (P3/P4, dev-only)
---
@ -57,7 +57,7 @@ tools/smokes/v2/run.sh --profile quick --filter "json_pp_vm"
## Decision: Defer Pattern2 E2EDigitPos/Trimuntil ExitLine contract is stabilized
Phase 80 の主目的は Pattern3/4 の BindingId 配線なので、Pattern2 の E2E は Phase 80-D に回し、
Phase 80 の主目的は Pattern3/4 の BindingId 配線なので、Pattern2 の E2E は Phase 81+ に回し、
さらに “promoted carriersDigitPos/Trimを含む Pattern2 の ExitLine 接続” が安定してから固定する。
## Task 80-0: Summary
@ -74,7 +74,7 @@ Phase 80 の主目的は Pattern3/4 の BindingId 配線なので、Pattern2 の
**Classification**:
- **Phase 80 blockers**: NONE
- **Phase 80 out-of-scope**:
- Pattern2DigitPos/Trimpromoted carriers の ExitLine 契約安定化Phase 80-D と合わせて着手
- Pattern2DigitPos/Trimpromoted carriers の ExitLine 契約安定化Phase 81+
- json_lint_vm smoke test failure (pre-existing Pattern2 verifier issue)
**Decision**: ✅ **Proceed to Task 80-A**
@ -130,11 +130,11 @@ Phase 80 の主目的は Pattern3/4 の BindingId 配線なので、Pattern2 の
**Key function**: `lower_pattern3_if_sum()`
**ConditionEnv creation**: Line ~195 (passed to `lower_if_sum_pattern()`)
**ConditionEnv creation**: `ConditionEnvBuilder` 生成直後(`lower_if_sum_pattern()` に渡す前)
**BindingId registration points**:
1. **Loop var registration** (lines ~116-128, Pattern2 reference):
1. **Loop var registration**dev-only:
```rust
#[cfg(feature = "normalized_dev")]
if let Some(loop_var_bid) = builder.binding_map.get(&loop_var_name).copied() {
@ -144,28 +144,25 @@ Phase 80 の主目的は Pattern3/4 の BindingId 配線なので、Pattern2 の
}
```
2. **Carrier BindingId registration** (via CarrierVar.binding_id):
2. **Condition bindings registration**dev-only:
```rust
#[cfg(feature = "normalized_dev")]
for carrier in &carrier_info.carriers {
if let Some(bid) = carrier.binding_id {
match carrier.role {
CarrierRole::ConditionOnly => {
cond_env.register_condition_binding(bid, carrier.join_id);
}
_ => {
cond_env.register_carrier_binding(bid, carrier.join_id)?;
}
}
eprintln!("[phase80/p3] Registered carrier '{}' BindingId({}) -> ValueId({})",
carrier.name, bid.0, carrier.join_id.0);
for binding in &inline_boundary.condition_bindings {
if let Some(bid) = builder.binding_map.get(&binding.name).copied() {
cond_env.register_condition_binding(bid, binding.join_value);
eprintln!(
"[phase80/p3] Registered condition binding '{}' BindingId({}) -> ValueId({})",
binding.name, bid.0, binding.join_value.0
);
}
}
```
**Timing**: AFTER ValueId allocation, BEFORE condition lowering
**Timing**: BEFORE condition lowering
**Data source**: `CarrierVar.binding_id` (populated by CarrierBindingAssigner in Phase 78)
**Note (重要)**:
- Pattern3/4 は lowering の後段ExitMeta / merge 側)で carrier join_id が確定するため、Phase 80 では **carriers の BindingId 登録はしない**。
- ここでの目的は「条件 loweringlookup_with_binding」の経路を先に BindingId 化して、shadowing の破綻を防ぐこと。
---
@ -175,35 +172,19 @@ Phase 80 の主目的は Pattern3/4 の BindingId 配線なので、Pattern2 の
**Key function**: `cf_loop_pattern4_with_continue()`
**ConditionEnv creation**: Within `lower_loop_with_continue_minimal()` (lines ~341-350)
**ConditionEnv creation**: `lower_loop_with_continue_minimal()`
**BindingId registration points**:
1. **Loop var registration** (same pattern as P3):
```rust
#[cfg(feature = "normalized_dev")]
if let Some(loop_var_bid) = builder.binding_map.get(&loop_var_name).copied() {
cond_env.register_loop_var_binding(loop_var_bid, loop_var_join_id);
eprintln!("[phase80/p4] Registered loop var '{}' BindingId({}) -> ValueId({})",
loop_var_name, loop_var_bid.0, loop_var_join_id.0);
}
```
1. **Caller side**dev-only: `binding_map` を lowerer に渡す
2. **Carrier BindingId registration** (via CarrierVar.binding_id from Pattern4CarrierAnalyzer):
```rust
#[cfg(feature = "normalized_dev")]
for carrier in &carrier_info.carriers {
if let Some(bid) = carrier.binding_id {
cond_env.register_carrier_binding(bid, carrier.join_id)?;
eprintln!("[phase80/p4] Registered carrier '{}' BindingId({}) -> ValueId({})",
carrier.name, bid.0, carrier.join_id.0);
}
}
```
2. **Lowerer side**dev-only: join_id が確定したタイミングで
- loop var / condition bindings / carriers を BindingId 登録する
- ログは `[phase80/p4]` タグで可視化する
**Special note**: Trim patterns (skip_whitespace) use promoted carriers, BindingId comes from `promoted_bindings` map via CarrierBindingAssigner
**Timing**: AFTER ValueId allocation, BEFORE continue condition lowering
**Timing**: ValueId allocation の直後(condition lowering の前)
---
@ -228,29 +209,19 @@ Phase 80 の主目的は Pattern3/4 の BindingId 配線なので、Pattern2 の
### Implementation Order
1. ✅ Task 80-A: Design doc (this section)
2. Task 80-B: Pattern3 wiring
- Modify `pattern3_with_if_phi.rs`
- Add BindingId registration for loop var + carriers
- Add `[phase80/p3]` debug logs
3. ⏳ Task 80-C: Pattern4 wiring
- Modify `pattern4_with_continue.rs`
- Add BindingId registration for loop var + carriers
- Add `[phase80/p4]` debug logs
4. ⏳ Task 80-D: E2E tests
- Add 2 tests to `tests/normalized_joinir_min.rs`
- Verify BindingId hit, NO fallback
- 972/972 lib tests PASS (970 + 2 new)
2. Task 80-B: Pattern3 wiringloop var + condition bindings
3. ✅ Task 80-C: Pattern4 wiringlowerer 側で登録)
4. ✅ Task 80-D: E2E testsP3 1本 / P4 1本, `tests/normalized_joinir_min.rs`
---
### Success Metrics
- [ ] P3 BindingId registration operational (debug logs show hits)
- [ ] P4 BindingId registration operational (debug logs show hits)
- [ ] Fallback detection working (tests can detect fallback)
- [ ] 972/972 lib tests PASS (970 existing + 2 new E2E)
- [ ] Smoke tests stable (no new failures)
- [ ] All code dev-only (`#[cfg(feature = "normalized_dev")]`)
- [x] P3: 条件 lowering が BindingId 経路で解決できるE2Eテストで固定
- [x] P4: 条件 lowering が BindingId 経路で解決できるE2Eテストで固定
- [x] Fallback 検知(`[binding_pilot/fallback]` をテストで検知できる)
- [x] `cargo test --release --lib` が PASSproduction 影響なし)
- [x] 追加コードは dev-only`normalized_dev`)に閉じている
---
@ -273,12 +244,12 @@ Phase 80 の主目的は Pattern3/4 の BindingId 配線なので、Pattern2 の
## Implementation Tasks (pending Task 80-0 completion)
1. Pattern3 (if-sum) BindingId 登録配線
2. Pattern4 (continue) BindingId 登録配線
3. E2E tests (P3 1本 / P4 1本)
1. Pattern3 (if-sum) BindingId 登録配線
2. Pattern4 (continue) BindingId 登録配線
3. E2E tests (P3 1本 / P4 1本)
## Success Metrics
- P3/P4 代表ケースで lookup_with_binding() 経路がヒット(ログ or テスト)
- Fallback 検知可能(既存 `[binding_pilot/fallback]` タグ活用)
- 970/970 lib tests PASS (+ new tests)
- `cargo test --release --lib` PASS退行なし

View File

@ -119,7 +119,8 @@ impl MirBuilder {
let loop_var_name = ctx.loop_var_name.clone();
let loop_var_id = ctx.loop_var_id;
let (cond_env, condition_bindings, _loop_var_join_id) =
#[allow(unused_mut)]
let (mut cond_env, condition_bindings, _loop_var_join_id) =
ConditionEnvBuilder::build_for_break_condition_v2(
condition,
&loop_var_name,