Phase 118: Loop + If-Only Merge Parity (VM + LLVM EXE)
目的
Phase 117で if-only nested-if + call merge が固まったので、Phase 118では "loop + if-only + merge" を固定する。loop側のPHI生成と if-only条件付き更新を組み合わせたパターンを確立し、VM + LLVM EXE の両方で動作保証する。
背景
- Phase 117: if-only nested-if + call merge parity 確立(
phase117_if_only_nested_if_call_merge_min.hako) - Phase 118: loop + if-only merge の組み合わせテスト
- ループ内で if-only により条件付き変数更新
- Pattern3 (if-sum) の活用(既存実装を利用)
- ループ継続条件での PHI 生成
- Exit での merge 処理
テストケース
Fixture
ファイル: apps/tests/phase118_loop_nested_if_merge_min.hako
// Phase 118: loop + if-only merge parity test
// Expected output: 2 (numeric line)
// Calculation: i=0: x=0 (skip), i=1: x=0+1→1, i=2: x=1+1→2
static box Main {
main() {
local i = 0
local x = 0
loop(i < 3) {
if i > 0 {
x = x + 1
}
i = i + 1
}
print(x)
return "OK"
}
}
期待出力: 2(数値1行)
計算ロジック:
i=0:i > 0は false、x は 0 のまま(skip)i=1:i > 0は true、x = 0 + 1 → 1(if ブランチ)i=2:i > 0は true、x = 1 + 1 → 2(if ブランチ)- ループ終了後に
xの値2を出力
Pattern3 活用: このパターンは Pattern3 (if-sum) で既に対応済み。if-only で条件付き加算を行うパターンとして、既存実装を活用。
スモークテスト
VM Smoke Test
ファイル: tools/smokes/v2/profiles/integration/apps/phase118_loop_nested_if_merge_vm.sh
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/../../../lib/output_validator.sh"
FIXTURE="apps/tests/phase118_loop_nested_if_merge_min.hako"
echo "[phase118_loop_nested_if_merge_vm] Testing loop + if-else merge parity (VM)..."
# VM execution with STRICT mode
OUTPUT=$(NYASH_DISABLE_PLUGINS=1 HAKO_JOINIR_STRICT=1 ./target/release/hakorune --backend vm "$FIXTURE" 2>&1) || {
echo "❌ VM execution failed"
echo "$OUTPUT"
exit 1
}
# Validate: expect 1 line with value 2
validate_numeric_output 1 "2" "$OUTPUT"
echo "✅ [phase118_loop_nested_if_merge_vm] PASS"
実行条件:
NYASH_DISABLE_PLUGINS=1: プラグイン無効(core経路のみ)HAKO_JOINIR_STRICT=1: JoinIR STRICT モード有効--backend vm: Rust VM バックエンド
検証: validate_numeric_output 1 "2" "$OUTPUT"(1行、値2)
LLVM EXE Smoke Test
ファイル: tools/smokes/v2/profiles/integration/apps/phase118_loop_nested_if_merge_llvm_exe.sh
#!/bin/bash
# Phase 118: loop + if-else merge parity (LLVM EXE)
source "$(dirname "$0")/../../../lib/test_runner.sh"
source "$(dirname "$0")/../../../lib/llvm_exe_runner.sh"
export SMOKES_USE_PYVM=0
require_env || exit 2
llvm_exe_preflight_or_skip || exit 0
# Phase 97/98/100 SSOT: plugin dlopen check → build only if needed → dlopen recheck.
FILEBOX_SO="$NYASH_ROOT/plugins/nyash-filebox-plugin/libnyash_filebox_plugin.so"
MAPBOX_SO="$NYASH_ROOT/plugins/nyash-map-plugin/libnyash_map_plugin.so"
STRINGBOX_SO="$NYASH_ROOT/plugins/nyash-string-plugin/libnyash_string_plugin.so"
CONSOLEBOX_SO="$NYASH_ROOT/plugins/nyash-console-plugin/libnyash_console_plugin.so"
INTEGERBOX_SO="$NYASH_ROOT/plugins/nyash-integer-plugin/libnyash_integer_plugin.so"
LLVM_REQUIRED_PLUGINS=(
"FileBox|$FILEBOX_SO|nyash-filebox-plugin"
"MapBox|$MAPBOX_SO|nyash-map-plugin"
"StringBox|$STRINGBOX_SO|nyash-string-plugin"
"ConsoleBox|$CONSOLEBOX_SO|nyash-console-plugin"
"IntegerBox|$INTEGERBOX_SO|nyash-integer-plugin"
)
LLVM_PLUGIN_BUILD_LOG="/tmp/phase118_loop_nested_if_merge_plugin_build.log"
llvm_exe_ensure_plugins_or_fail || exit 1
INPUT_HAKO="$NYASH_ROOT/apps/tests/phase118_loop_nested_if_merge_min.hako"
OUTPUT_EXE="$NYASH_ROOT/tmp/phase118_loop_nested_if_merge_llvm_exe"
EXPECTED='2'
EXPECTED_LINES=1
LLVM_BUILD_LOG="/tmp/phase118_loop_nested_if_merge_build.log"
if llvm_exe_build_and_run_numeric_smoke; then
test_pass "phase118_loop_nested_if_merge_llvm_exe: output matches expected (2)"
else
exit 1
fi
必要プラグイン: FileBox, MapBox, StringBox, ConsoleBox, IntegerBox(Phase 117と同じセット)
検証: llvm_exe_build_and_run_numeric_smoke(EXPECTED='2', EXPECTED_LINES=1)
検証コマンド
VM Smoke Test
bash tools/smokes/v2/profiles/integration/apps/phase118_loop_nested_if_merge_vm.sh
LLVM EXE Smoke Test
bash tools/smokes/v2/profiles/integration/apps/phase118_loop_nested_if_merge_llvm_exe.sh
回帰テスト(Phase 117)
bash tools/smokes/v2/profiles/integration/apps/phase117_if_only_nested_if_call_merge_llvm_exe.sh
成果物
- Fixture:
apps/tests/phase118_loop_nested_if_merge_min.hako - VM Smoke:
tools/smokes/v2/profiles/integration/apps/phase118_loop_nested_if_merge_vm.sh - LLVM EXE Smoke:
tools/smokes/v2/profiles/integration/apps/phase118_loop_nested_if_merge_llvm_exe.sh - ドキュメント:
docs/development/current/main/phases/phase-118/README.md(本ファイル)
追加(Phase 118 follow-up):Pattern3 carrier PHI contract 固定
Pattern3(if-sum)の exit carrier PHI が欠けると、後段で Carrier '<name>' not found in carrier_phis が発生する。
このフェーズでは fixture + VM/LLVM EXE smoke で再現と回帰固定を行い、さらに Fail-Fast の契約チェックを追加した。
Fixture
apps/tests/phase118_pattern3_if_sum_min.hako(期待:12)
Smoke
- VM:
tools/smokes/v2/profiles/integration/apps/phase118_pattern3_if_sum_vm.sh - LLVM EXE:
tools/smokes/v2/profiles/integration/apps/phase118_pattern3_if_sum_llvm_exe.sh
契約(SSOT)
exit_bindingsに含まれるLoopStatecarrier は、必ず exit PHI(exit_carrier_phis)を持つこと。- 違反時は
[joinir/phase118/exit_phi/missing_carrier_phi] ... Hint: ...で Fail-Fast。
Phase 118 完了条件
- ✅ VM Smoke Test PASS
- ✅ LLVM EXE Smoke Test PASS
- ✅ Phase 117 回帰テスト PASS
- ✅ ドキュメント更新(10-Now.md, 01-JoinIR-Selfhost-INDEX.md)
次のステップ
Phase 119以降で更に複雑なループ + 制御フロー構造のテストケースを追加予定。