Files
hakorune/docs/development/current/main/phases/phase-137/README.md

240 lines
7.2 KiB
Markdown
Raw Normal View History

# Phase 137: loop(true) break-once with return add expression
**Date**: 2025-12-18
**Status**: DONE ✅
**Scope**: return add expression (x + 2) support in Normalized shadow (dev-only)
---
## Goal
feat(mir): Phase 137-5 - Decision Policy SSOT化完了 ## 目的 Canonicalizer の RoutingDecision.chosen を「lowerer 選択の最終結果」にする (構造クラス名ではなく ExitContract ベースの決定) ## 実装内容 ### 1. Canonicalizer の決定ロジック修正 - `src/mir/loop_canonicalizer/mod.rs` - `skip_whitespace` パターン認識で ExitContract (has_break=true) を考慮 - Pattern3IfPhi → Pattern2Break に修正(構造は似ているが break あり) - 単体テスト更新(Pattern2Break 期待に変更) ### 2. Parity 検証テスト修正 - `src/mir/builder/control_flow/joinir/routing.rs` - `test_parity_check_mismatch_detected` → `test_parity_check_skip_whitespace_match` - Canonicalizer と Router の一致を検証(ミスマッチ検出からマッチ検証へ) - Phase 137-5 の SSOT 原則を反映 ### 3. ドキュメント更新 - `docs/development/current/main/design/loop-canonicalizer.md` - Phase 137-5: Decision Policy SSOT セクション追加 - ExitContract 優先の原則を明記 - skip_whitespace の例を追加 - `docs/development/current/main/phases/phase-137/README.md` - Phase 4 完了マーク追加 - Phase 5 完了セクション追加(実装・検証・効果) ## 検証結果 - ✅ 単体テスト: `cargo test --release --lib loop_canonicalizer::tests` (11/11 passed) - ✅ Parity テスト: `cargo test --release --lib 'routing::tests::test_parity'` (2/2 passed) - ✅ Strict モード: `HAKO_JOINIR_STRICT=1` で skip_whitespace parity OK ## 効果 - Router と Canonicalizer の pattern 選択が一致 - ExitContract が pattern 決定の SSOT として明確化 - 構造的特徴(if-else 等)は notes に記録(将来拡張に備える) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-16 06:17:03 +09:00
Extend Phase 136 return literal to support minimal add expressions:
- Enable `return x + 2` (variable + integer literal)
- Enable `return 5 + 3` (integer literal + integer literal)
- Keep **PHI禁止**: merge via env + continuations only
- Keep **dev-only** and **既定挙動不変**: unmatched shapes fall back
## Supported Forms
### ✅ Supported (Phase 137 P0)
```nyash
// Form 1: return variable + integer literal
local x
x = 1
loop(true) {
break
}
return x + 2 // Expected: 3 (1 + 2)
```
```nyash
// Form 2: return integer literal + integer literal
loop(true) {
break
}
return 5 + 3 // Expected: 8
```
```nyash
// Form 3: loop + post assigns + return add
local x
x = 0
loop(true) {
x = 1
break
}
x = x + 10
return x + 2 // Expected: 13 (0 → 1 → 11 → 13)
```
### ❌ Not Supported (Out of Scope)
```nyash
// Variable + variable (Phase 138+)
return x + y
// Other operators (Phase 138+)
return x - 2
return x * 2
// Nested expressions
return (x + 2) + 3
// Function calls
return f()
```
## Implementation
### Core Changes
**File**: `src/mir/control_tree/normalized_shadow/loop_true_break_once.rs`
**Method**: `lower_return_value_to_vid()` (行 638-743, BinaryOp Add at 行 673)
**Added Pattern**: BinaryOp Add
```rust
ASTNode::BinaryOp { operator, left, right, .. } => {
// Phase 137 contract: Add only
if !matches!(operator, BinaryOperator::Add) {
return Ok(None); // out of scope
}
// Lower LHS (Variable or Integer literal)
let lhs_vid = match left.0.as_ref() {
ASTNode::Variable { name, .. } => {
match env.get(name).copied() {
Some(vid) => vid,
None => return Ok(None), // out of scope
}
}
ASTNode::Literal { value: LiteralValue::Integer(i), .. } => {
// Generate Const for LHS
let vid = ValueId(*next_value_id);
*next_value_id += 1;
body.push(JoinInst::Compute(MirLikeInst::Const {
dst: vid,
value: ConstValue::Integer(*i),
}));
vid
}
_ => return Ok(None),
};
// Lower RHS (Integer literal only)
let rhs_vid = match right.0.as_ref() {
ASTNode::Literal { value: LiteralValue::Integer(i), .. } => {
let vid = ValueId(*next_value_id);
*next_value_id += 1;
body.push(JoinInst::Compute(MirLikeInst::Const {
dst: vid,
value: ConstValue::Integer(*i),
}));
vid
}
_ => return Ok(None), // e.g., return x + y
};
// Generate BinOp Add
let result_vid = ValueId(*next_value_id);
*next_value_id += 1;
body.push(JoinInst::Compute(MirLikeInst::BinOp {
dst: result_vid,
op: BinOpKind::Add,
lhs: lhs_vid,
rhs: rhs_vid,
}));
Ok(Some(result_vid))
}
```
### Return Value Lowering SSOT
**Location**: `src/mir/control_tree/normalized_shadow/loop_true_break_once.rs` (行 29-43)
**SSOT Documentation**:
```rust
//! ## Return Value Lowering SSOT (Phase 137+)
//!
//! - Function: `lower_return_value_to_vid()`
//! - Responsibility: Lower return values (variable, literal, expr) to ValueId
//! - Supported patterns:
//! - Variable: env lookup
//! - Integer literal: Const generation
//! - Add expr (Phase 137): x + 2 → BinOp(Add, env[x], Const(2))
//! - Fallback: Out-of-scope patterns return `Ok(None)` for legacy routing
//!
//! ### Boxification Trigger
//!
//! If 2+ files need identical return lowering logic, promote to:
//! - `normalized_shadow/common/return_value_lowerer_box.rs`
//! - Single responsibility: return value → ValueId conversion
```
### Fixtures
1. **phase137_loop_true_break_once_return_add_min.hako**
- Pattern: `x=1; loop(true){break}; return x+2`
- Expected: exit code 3
2. **phase137_loop_true_break_once_return_add_const_min.hako**
- Pattern: `loop(true){break}; return 5+3`
- Expected: exit code 8
3. **phase137_loop_true_break_once_post_return_add_min.hako**
- Pattern: `x=0; loop(true){x=1;break}; x=x+10; return x+2`
- Expected: exit code 13
### Smoke Tests
**VM**:
- `tools/smokes/v2/profiles/integration/apps/phase137_loop_true_break_once_return_add_vm.sh`
- `tools/smokes/v2/profiles/integration/apps/phase137_loop_true_break_once_return_add_const_vm.sh`
- `tools/smokes/v2/profiles/integration/apps/phase137_loop_true_break_once_post_return_add_vm.sh`
**LLVM EXE**:
- `tools/smokes/v2/profiles/integration/apps/phase137_loop_true_break_once_return_add_llvm_exe.sh`
- `tools/smokes/v2/profiles/integration/apps/phase137_loop_true_break_once_return_add_const_llvm_exe.sh`
- `tools/smokes/v2/profiles/integration/apps/phase137_loop_true_break_once_post_return_add_llvm_exe.sh`
## Verification
```bash
# Build
cargo build --release -p nyash-rust --features llvm
# Phase 137 smokes (6 tests)
bash tools/smokes/v2/profiles/integration/apps/phase137_loop_true_break_once_return_add_vm.sh
bash tools/smokes/v2/profiles/integration/apps/phase137_loop_true_break_once_return_add_const_vm.sh
bash tools/smokes/v2/profiles/integration/apps/phase137_loop_true_break_once_post_return_add_vm.sh
bash tools/smokes/v2/profiles/integration/apps/phase137_loop_true_break_once_return_add_llvm_exe.sh
bash tools/smokes/v2/profiles/integration/apps/phase137_loop_true_break_once_return_add_const_llvm_exe.sh
bash tools/smokes/v2/profiles/integration/apps/phase137_loop_true_break_once_post_return_add_llvm_exe.sh
# Regressions
bash tools/smokes/v2/profiles/integration/apps/phase97_next_non_ws_llvm_exe.sh
bash tools/smokes/v2/profiles/integration/apps/phase97_json_loader_escape_llvm_exe.sh
bash tools/smokes/v2/profiles/integration/apps/phase131_loop_true_break_once_vm.sh
bash tools/smokes/v2/profiles/integration/apps/phase135_loop_true_break_once_post_empty_return_vm.sh
bash tools/smokes/v2/profiles/integration/apps/phase136_loop_true_break_once_return_literal_vm.sh
```
## Acceptance Criteria
- ✅ Phase 137 VM: 3/3 PASS
- ✅ Phase 137 LLVM EXE: 3/3 PASS
- ✅ Phase 97 regression: 2/2 PASS
- ✅ Phase 131/135/136 regression: 3/3 PASS
- ✅ Dev toggle OFF → no impact (Ok(None) fallback)
## Key Design Points
### Ok(None) for Fallback
- Unsupported patterns (e.g., `return x + y`, `return x - 2`) return `Ok(None)`
- Fallback to existing JoinIR routing
- No hard errors for out-of-scope patterns
### BinOp Generation Pattern
- LHS: Variable (env lookup) or Integer literal (Const generation)
- RHS: Integer literal only (Const generation)
- Result: `BinOp(Add, lhs_vid, rhs_vid)`
### Phase 137 P0 Scope Decision
- **Approach A (adopted)**: Direct extension in `loop_true_break_once.rs`
- **Reasoning**: Small change scope, no boxification needed yet
- **Boxification Trigger**: When 2+ files need identical return lowering logic
### post_if_post_k.rs Not Modified
- Different responsibility (if-with-post normalization)
- Unification planned for Phase 138-139 when needed
## Current Status
Phase 137 - DONE ✅ (2025-12-18)
VM/LLVM EXE parity achieved (exit codes 3, 8, 13).
Return Value Lowering SSOT documented in `loop_true_break_once.rs`.