Phase 136 Documentation: - Created docs/development/current/main/phases/phase-136/README.md - Goal: loop(true) break-once with return literal (Integer) - Supported: return 7, loop + post + return literal - Implementation: lower_return_value_to_vid() method - Tests: 2 fixtures + 4 smokes - VM/LLVM EXE parity verification commands Phase 137 Documentation: - Created docs/development/current/main/phases/phase-137/README.md - Goal: loop(true) break-once with return add expression - Supported: return x+2, return 5+3, loop+post+return add - Implementation: Extended lower_return_value_to_vid() for BinaryOp Add - Return Value Lowering SSOT documented (lines 29-46) - Boxification trigger: when 2+ files need identical logic - Tests: 3 fixtures + 6 smokes - VM/LLVM EXE parity verification commands 10-Now.md Updates: - Added Phase 136 entry (return literal) - Added Phase 137 entry (return add expression) - Implementation details and test coverage - Links to phase READMEs 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
7.2 KiB
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
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)
// Form 1: return variable + integer literal
local x
x = 1
loop(true) {
break
}
return x + 2 // Expected: 3 (1 + 2)
// Form 2: return integer literal + integer literal
loop(true) {
break
}
return 5 + 3 // Expected: 8
// 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)
// 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
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:
//! ## 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
-
phase137_loop_true_break_once_return_add_min.hako
- Pattern:
x=1; loop(true){break}; return x+2 - Expected: exit code 3
- Pattern:
-
phase137_loop_true_break_once_return_add_const_min.hako
- Pattern:
loop(true){break}; return 5+3 - Expected: exit code 8
- Pattern:
-
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
- Pattern:
Smoke Tests
VM:
tools/smokes/v2/profiles/integration/apps/phase137_loop_true_break_once_return_add_vm.shtools/smokes/v2/profiles/integration/apps/phase137_loop_true_break_once_return_add_const_vm.shtools/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.shtools/smokes/v2/profiles/integration/apps/phase137_loop_true_break_once_return_add_const_llvm_exe.shtools/smokes/v2/profiles/integration/apps/phase137_loop_true_break_once_post_return_add_llvm_exe.sh
Verification
# 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) returnOk(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.