docs: Phase 131 P2 DirectValue exit reconnection complete
Update completion status for Phase 131 P2: - CURRENT_TASK.md: Note WSL restart resolved EXDEV issue - 10-Now.md: Add Phase 131 P2 completion entry - phase-131/README.md: Document P1.5 and P2 deliverables Phase 131 Status: DONE ✅ - loop(true) break-once executes correctly - Exit values propagate through DirectValue mode - VM + LLVM EXE parity verified 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@ -5,3 +5,59 @@ Scope: Repo root の旧リンク互換。現行の入口は `docs/development/cu
|
||||
|
||||
- Now: `docs/development/current/main/10-Now.md`
|
||||
- Backlog: `docs/development/current/main/30-Backlog.md`
|
||||
|
||||
---
|
||||
|
||||
## Handoff (was blocking; now unblocked)
|
||||
|
||||
### 状況
|
||||
|
||||
- JoinIR/Phase 131 系(Normalized shadow + DirectValue exit)が進行中だが、**LLVM EXE smoke が Rust のビルド段階でブロック**していた。
|
||||
- エラー: `Invalid cross-device link (os error 18)`(`cargo build` が `.rmeta/.rlib` を書き出すときに落ちる)
|
||||
- 2025-12-18: `wsl --shutdown` による WSL 再起動後、`cargo build`/LLVM build/該当 smokes が復活(下のコマンドは PASS)。
|
||||
|
||||
### 症状(再現コマンド)
|
||||
|
||||
- `cargo build -p nyash-rust`
|
||||
- `cargo build --release -p nyash-rust --features llvm`
|
||||
- LLVM EXE smokes(内部で release build するので同様に失敗)
|
||||
- `bash tools/smokes/v2/profiles/integration/apps/phase131_loop_true_break_once_llvm_exe.sh`
|
||||
- `bash tools/smokes/v2/profiles/integration/apps/phase97_next_non_ws_llvm_exe.sh`
|
||||
|
||||
### 影響しない(通るもの)
|
||||
|
||||
- `cargo test --lib` は PASS
|
||||
- VM smokes は PASS(例)
|
||||
- `bash tools/smokes/v2/profiles/integration/apps/phase131_loop_true_break_once_vm.sh`
|
||||
- `bash tools/smokes/v2/profiles/integration/apps/phase130_if_only_post_if_add_vm.sh`
|
||||
|
||||
### 根本原因メモ(環境)
|
||||
|
||||
- WSL2 上で、`O_TMPFILE` で作った一時ファイルを `/proc/self/fd/<n>` 経由で `link` すると **EXDEV が返る**挙動を確認。
|
||||
- Rustc/cargo が内部で類似の「tmpfile → persist(link/rename)」を使っている可能性が高い。
|
||||
- さらに、この環境では `~/.rustup/tmp` と `~/.cargo` が書き込み不可に見える(immutable/perm issue の疑い)。
|
||||
- DNS も一時的に死んでおり、`rustup toolchain install` 等の回避策が取れない状態だった(`Temporary failure in name resolution`)。
|
||||
|
||||
### 対処(ユーザー側での復旧手順)
|
||||
|
||||
1. WSL を完全再起動:
|
||||
- Windows 側で `wsl --shutdown` → その後 WSL を起動し直す
|
||||
2. 再起動後にビルドが復活しているか確認:
|
||||
- `cargo build -p nyash-rust`
|
||||
- `cargo build --release -p nyash-rust --features llvm`
|
||||
3. 復活したら、VM+LLVM EXE の最終確認(integration):
|
||||
- `bash tools/smokes/v2/profiles/integration/apps/phase131_loop_true_break_once_vm.sh`
|
||||
- `bash tools/smokes/v2/profiles/integration/apps/phase131_loop_true_break_once_llvm_exe.sh`
|
||||
- `bash tools/smokes/v2/profiles/integration/apps/phase97_next_non_ws_llvm_exe.sh`
|
||||
|
||||
### 補足(再発時のワークアラウンド)
|
||||
|
||||
- `tools/build_llvm.sh` は EXDEV を避けるため、`TMPDIR` を `target/...` 配下へ寄せる(同一 FS 内での artifact finalize を狙う)。
|
||||
|
||||
### 注意(作業ツリー)
|
||||
|
||||
- 現在 `git status` は clean ではない(Phase 131 関連の変更が多数 + 未tracked docs/ファイルあり)。
|
||||
- 未tracked: `docs/development/current/main/phases/phase-131/p1.5-implementation-guide.md`
|
||||
- 未tracked: `docs/development/current/main/phases/phase-131/p1.5-option-b-analysis.md`
|
||||
- 未tracked: `docs/development/current/main/phases/phase-131/p1.5-root-cause-summary.md`
|
||||
- 未tracked: `src/mir/control_tree/normalized_shadow/exit_reconnector.rs`
|
||||
|
||||
@ -35,13 +35,18 @@
|
||||
- Unit tests: 1155/1155 PASS
|
||||
- 入口: `docs/development/current/main/phases/phase-129/README.md`
|
||||
|
||||
## Next: Phase 131(loop(true) break-once Normalized support)
|
||||
## 2025-12-18:Phase 131 P2 完了 ✅
|
||||
|
||||
**Phase 131 P0: loop(true) break-once Normalized support(dev-only)**
|
||||
- 目的: Loop capability を Normalized shadow に追加し、最小ループ(`loop(true) { <assign>* ; break }`)を通す
|
||||
**Phase 131: loop(true) break-once Normalized(dev-only)**
|
||||
- 目的: Normalized shadow の最小ループを VM/LLVM EXE 両方で動かし、更新値が外に見えることまで固定
|
||||
- 仕様:
|
||||
- `loop(true) { x = 1; break }; return x` は exit code `1`
|
||||
- DirectValue mode(PHI-free)で exit 値を `variable_map` に再接続
|
||||
- 検証:
|
||||
- `bash tools/smokes/v2/profiles/integration/apps/phase131_loop_true_break_once_vm.sh`
|
||||
- `bash tools/smokes/v2/profiles/integration/apps/phase131_loop_true_break_once_llvm_exe.sh`
|
||||
- 環境: WSL の一時的な EXDEV(`Invalid cross-device link`)は `wsl --shutdown` 再起動で解消、上記 + `phase97_next_non_ws_llvm_exe.sh` まで PASS
|
||||
- 入口: `docs/development/current/main/phases/phase-131/README.md`
|
||||
- 受け入れ: Phase 131 VM + LLVM EXE smokes + Phase 130/129 回帰が green
|
||||
- Status: IN PROGRESS
|
||||
|
||||
## 2025-12-18:Phase 127 完了 ✅
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# Phase 131: loop(true) break-once Normalized Support (P0)
|
||||
# Phase 131: loop(true) break-once Normalized Support
|
||||
|
||||
Status: IN PROGRESS
|
||||
Status: DONE
|
||||
Scope: loop(true) break-once Normalized(StepTree → Normalized shadow pipeline)
|
||||
Related:
|
||||
- Entry: `docs/development/current/main/10-Now.md`
|
||||
@ -104,7 +104,12 @@ Both backends must produce identical results:
|
||||
- VM: Rust VM backend (`--backend vm`)
|
||||
- LLVM: LLVM EXE backend via llvm_exe_runner.sh
|
||||
|
||||
Expected output for fixture: `1` (single line, numeric)
|
||||
Expected contract for fixture: exit code `1` (return value)
|
||||
|
||||
## Environment Note (WSL)
|
||||
|
||||
- If `cargo build` fails with `Invalid cross-device link (os error 18)` on WSL, a full WSL restart (`wsl --shutdown`) has been sufficient to recover in practice.
|
||||
- `tools/build_llvm.sh` also forces `TMPDIR` under `target/` to reduce EXDEV risk during artifact finalization.
|
||||
|
||||
## Work Items (P0)
|
||||
|
||||
@ -116,7 +121,7 @@ Expected output for fixture: `1` (single line, numeric)
|
||||
### Step 1: Fixtures + Smokes
|
||||
|
||||
- New fixture: `apps/tests/phase131_loop_true_break_once_min.hako`
|
||||
- Expected output: `1`
|
||||
- Expected exit code: `1`
|
||||
- Form: x=0; loop(true) { x=1; break }; return x
|
||||
- VM smoke: `tools/smokes/v2/profiles/integration/apps/phase131_loop_true_break_once_vm.sh`
|
||||
- LLVM EXE smoke: `tools/smokes/v2/profiles/integration/apps/phase131_loop_true_break_once_llvm_exe.sh`
|
||||
@ -183,51 +188,65 @@ match &step_tree.root {
|
||||
|
||||
## Current Status
|
||||
|
||||
Phase 131 P0 - Structure Implementation (2025-12-18)
|
||||
Phase 131 P2 - Variable Propagation (2025-12-18)
|
||||
|
||||
### ✅ Completed
|
||||
### ✅ P0 Completed (Structure)
|
||||
|
||||
- **Fixtures**: `apps/tests/phase131_loop_true_break_once_min.hako` created
|
||||
- **Builder**: `src/mir/control_tree/normalized_shadow/loop_true_break_once.rs` (407 lines)
|
||||
- **Integration**: Wired into `builder.rs` orchestrator via `lower_with_loop_support()`
|
||||
- **Smoke Tests**: VM and LLVM EXE smoke scripts created
|
||||
- **Unit Tests**: All 1155 tests passing
|
||||
- **Structure**: Shadow JoinModule generation working correctly
|
||||
|
||||
### ⚠️ Execution Path Not Yet Wired
|
||||
### ✅ P1 Completed (Execution Path)
|
||||
|
||||
**Current Behavior**: Normalized shadow generates correct JoinModules but only for observation/verification (dev-only). Execution still routes through Pattern2/canonicalizer which rejects loop(true) break-once.
|
||||
- **Routing**: `try_cf_loop_joinir` now checks Normalized shadow before Pattern2 (`routing.rs`)
|
||||
- **Dev Gating**: Routes to Normalized when `NYASH_JOINIR_DEV=1`
|
||||
- **Merge Pipeline**: Uses existing `JoinIRConversionPipeline` (JoinModule → MirModule → merge)
|
||||
- **Execution**: Loop executes successfully without freeze (verified in trace output)
|
||||
- **Void Return**: Emits void constant when loop has no explicit return value
|
||||
|
||||
**Error Seen**:
|
||||
**Evidence of Success**:
|
||||
```
|
||||
[ERROR] Loop lowering failed: JoinIR does not support this pattern
|
||||
[joinir/meta] MirFunc 'main', 'loop_step', 'loop_body', 'k_exit' converted
|
||||
[cf_loop/joinir] Phase 189: Merge complete: 4 functions merged
|
||||
[trace:debug] build_block: Statement 4/4 ... (loop completed, execution continues)
|
||||
RC: 0 (program completes without freeze)
|
||||
```
|
||||
|
||||
**Root Cause**: The `try_cf_loop_joinir` routing in `cf_loop` attempts existing patterns before Normalized shadow can intercept.
|
||||
### ✅ P1.5 Completed (DirectValue Exit Reconnection)
|
||||
|
||||
**Why This Is OK for P0**: Phase 131 P0 scope is "structure implementation" - proving the Normalized lowering logic works. Execution wiring is follow-up work.
|
||||
**DirectValue mode**: Normalized shadow path does not build exit PHIs. Final env values are reconnected directly to host `variable_map`.
|
||||
|
||||
### Verification
|
||||
**Example**:
|
||||
```hako
|
||||
x = 0
|
||||
loop(true) { x = 1; break }
|
||||
return x // Returns 1 ✅
|
||||
```
|
||||
|
||||
The shadow builder generates correct structure (verified in dev mode):
|
||||
- main(env) → loop_step(env) → loop_body(env) → k_exit(env)
|
||||
- PHI-free: all state via env parameters
|
||||
- Continuation-passing style: TailCall for all transitions
|
||||
- Structural verification passing
|
||||
**Root Cause** (fixed): PHI-based exit merge assumptions did not match continuation-based Normalized control flow.
|
||||
|
||||
### Next Steps (Follow-Up Phase)
|
||||
**Fix**:
|
||||
- Introduce `ExitReconnectMode::DirectValue` and skip exit PHI generation in that mode.
|
||||
- Carry `remapped_exit_values` through the merge result and update host `variable_map` directly.
|
||||
|
||||
To make this executable:
|
||||
1. Modify `try_cf_loop_joinir` to check Normalized shadow before Pattern2 routing
|
||||
2. Add dev-mode gating: route loop(true) break-once to Normalized when `NYASH_JOINIR_DEV=1`
|
||||
3. Implement JoinModule → MIR merge for Normalized loop patterns
|
||||
4. Enable and verify VM/LLVM smoke tests
|
||||
### ✅ P2 Completed (k_exit contract alignment)
|
||||
|
||||
**Problem**: continuation entry-jumps / exit edges were inconsistent, so the updated env visible at `k_exit` could be lost.
|
||||
|
||||
**Fix**: normalize tail-call/exit edges so updated env reaches the exit reconnection point.
|
||||
|
||||
### Deliverables
|
||||
|
||||
Phase 131 P0 provides:
|
||||
- ✅ Complete loop(true) break-once Normalized lowering logic
|
||||
- ✅ PHI-free implementation (env + continuations)
|
||||
- ✅ Box-First modular design
|
||||
- ✅ Foundation for execution (structure verified)
|
||||
- 📋 Clear path to execution wiring (documented above)
|
||||
Phase 131 P2 provides:
|
||||
- ✅ Execution path fully wired (dev-only, `NYASH_JOINIR_DEV=1`)
|
||||
- ✅ Loop completes without freeze and returns the updated value
|
||||
- ✅ DirectValue mode skips exit PHIs (PHI-free)
|
||||
- ✅ Existing patterns unaffected (既定挙動不変)
|
||||
|
||||
### Design Notes (historical)
|
||||
|
||||
- `docs/development/current/main/phases/phase-131/p1.5-root-cause-summary.md`
|
||||
- `docs/development/current/main/phases/phase-131/p1.5-option-b-analysis.md`
|
||||
- `docs/development/current/main/phases/phase-131/p1.5-implementation-guide.md`
|
||||
|
||||
Reference in New Issue
Block a user