diff --git a/docs/development/current/main/10-Now.md b/docs/development/current/main/10-Now.md index 5f56b6a4..75a698ef 100644 --- a/docs/development/current/main/10-Now.md +++ b/docs/development/current/main/10-Now.md @@ -35,12 +35,13 @@ - Unit tests: 1155/1155 PASS - 入口: `docs/development/current/main/phases/phase-129/README.md` -## Next: Phase 131(if-only Normalized loop lowering 準備) +## Next: Phase 131(loop(true) break-once Normalized support) -**Phase 131: if-only Normalized "Loop Lowering Foundation"(dev-only)** -- 目的: Loop capability を Normalized shadow に追加し、最小ループ(`loop(true) { break }`)を通す -- 入口: (未作成) +**Phase 131 P0: loop(true) break-once Normalized support(dev-only)** +- 目的: Loop capability を Normalized shadow に追加し、最小ループ(`loop(true) { * ; break }`)を通す +- 入口: `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 完了 ✅ diff --git a/docs/development/current/main/phases/phase-131/README.md b/docs/development/current/main/phases/phase-131/README.md new file mode 100644 index 00000000..31236d19 --- /dev/null +++ b/docs/development/current/main/phases/phase-131/README.md @@ -0,0 +1,233 @@ +# Phase 131: loop(true) break-once Normalized Support (P0) + +Status: IN PROGRESS +Scope: loop(true) break-once Normalized(StepTree → Normalized shadow pipeline) +Related: +- Entry: `docs/development/current/main/10-Now.md` +- Phase 130 (if-only post_k): `docs/development/current/main/phases/phase-130/README.md` +- ControlTree SSOT: `docs/development/current/main/design/control-tree.md` + +## Goal + +Add minimal loop support to Normalized shadow path: + +- Enable `loop(true) { * ; break }` (one-time execution loop) +- Keep **PHI禁止**: merge via env + continuations only +- Keep **dev-only** and **既定挙動不変**: unmatched shapes fall back (strict can Fail-Fast for fixtures) + +## Non-Goals + +- No general loop conditions (only `true` literal for now) +- No continue support (only break at end of body) +- No nested loops/ifs inside loop body (Phase 130 assigns only) +- No post-loop statements beyond simple return + +## Accepted Forms + +### ✅ Supported (P0) + +```nyash +// Form 1: loop(true) with break at end +local x +x = 0 +loop(true) { + x = 1 + break +} +return x // or print(x) +``` + +### ❌ Not Supported (Out of Scope) + +```nyash +// Continue (not break) +loop(true) { x = 1; continue } + +// Nested control flow +loop(true) { if (y == 1) { x = 2 }; break } + +// Multiple breaks / conditional break +loop(true) { if (cond) { break }; x = 1; break } + +// General loop conditions +loop(x < 10) { x = x + 1; break } + +// Complex post-loop computation +loop(true) { x = 1; break } +y = x + 2 +return y +``` + +## SSOT Contracts + +### EnvLayout (Phase 126) + +Same as Phase 130: +- `writes`: Variables assigned in the fragment +- `inputs`: Variables read from outer scope +- `env_fields()`: `writes ++ inputs` (SSOT for parameter order) + +### Loop Structure Contract + +For `loop(true) { body ; break }`: + +1. **Condition**: Must be Bool literal `true` (cond_ast check) +2. **Body**: Must be a Block ending with Break statement +3. **No exits**: No return/continue in body (only break at end) +4. **Assignments**: Body contains only Assign(int literal/var/add) and LocalDecl + +### Generated JoinModule Structure + +``` +main(env) → TailCall(loop_step, env) + +loop_step(env) → + if true { TailCall(loop_body, env) } + else { TailCall(k_exit, env) } + +loop_body(env) → + + TailCall(k_exit, env) + +k_exit(env) → + Ret(env[x]) // or TailCall(post_k, env) if post exists +``` + +**Key Invariants**: +- No PHI instructions (all merging via env parameters) +- All continuations take full env as parameters +- Condition `true` is lowered as constant true comparison + +## VM + LLVM Parity + +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) + +## Work Items (P0) + +### Step 0: Documentation + +- ✅ Create `docs/development/current/main/phases/phase-131/README.md` +- ✅ Update `docs/development/current/main/10-Now.md` Next section + +### Step 1: Fixtures + Smokes + +- New fixture: `apps/tests/phase131_loop_true_break_once_min.hako` + - Expected output: `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` + +### Step 2: Implementation + +- New file: `src/mir/control_tree/normalized_shadow/loop_true_break_once.rs` + - Box: `LoopTrueBreakOnceBuilderBox` + - Accept: `loop(true) { body ; break }` only + - Reject (Ok(None)): Non-matching patterns + - Generate: main → loop_step → loop_body → k_exit (no PHI) +- Integration: Add to `src/mir/control_tree/normalized_shadow/builder.rs` orchestrator + +### Step 3: Verification + +```bash +cargo test --lib + +# Phase 131 smokes +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 + +# Regressions (minimum 2) +bash tools/smokes/v2/profiles/integration/apps/phase130_if_only_post_if_add_vm.sh +bash tools/smokes/v2/profiles/integration/apps/phase97_next_non_ws_llvm_exe.sh +``` + +### Step 4: Commits + +1. `test(joinir): Phase 131 loop(true) break-once fixture + VM/LLVM smokes` +2. `feat(control_tree): Phase 131 normalized loop(true) break-once builder (dev-only)` +3. `docs: Phase 131 P0 DONE` + +## Implementation Notes + +### Fail-Fast vs Ok(None) + +- **Out of scope patterns**: Return `Ok(None)` (not an error, just unsupported) +- **Contract violations in supported patterns**: Fail-Fast with `freeze_with_hint` +- **Internal errors**: Return `Err(...)` + +### Reusing Phase 130 Infrastructure + +- `LegacyLowerer::lower_assign_stmt`: Reuse for body assignments +- `EnvLayout`: Same SSOT for env parameter management +- `alloc_value_id`, `build_env_map`, `collect_env_args`: Same helper patterns + +### Loop Detection + +Check StepNode structure: +```rust +match &step_tree.root { + StepNode::Loop { cond_ast, body, .. } => { + // Check cond_ast is Bool(true) + // Check body is Block ending with Break + // Check no return/continue in body + } + StepNode::Block(nodes) => { + // Check if loop is embedded in block with pre/post statements + } + _ => Ok(None) +} +``` + +## Current Status + +Phase 131 P0 - Structure Implementation (2025-12-18) + +### ✅ Completed + +- **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 + +**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. + +**Error Seen**: +``` +[ERROR] Loop lowering failed: JoinIR does not support this pattern +``` + +**Root Cause**: The `try_cf_loop_joinir` routing in `cf_loop` attempts existing patterns before Normalized shadow can intercept. + +**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. + +### Verification + +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 + +### Next Steps (Follow-Up Phase) + +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 + +### 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)