test: Phase 114 if-only return+post parity (VM + LLVM EXE)
Phase 114 validates that if-only lowering correctly handles cases with: - Early return in the if-only branch - Post-if statements that execute on the else path - Different return values from each path Fixture: apps/tests/phase114_if_only_return_then_post_min.hako - Expected output: 7\n2 - f(1): condition true → early return 7 - f(0): condition false → x=1+1=2, return 2 Testing: - VM backend: phase114_if_only_return_then_post_vm.sh ✅ - LLVM EXE backend: phase114_if_only_return_then_post_llvm_exe.sh ✅ - Regression: Phase 103/113 maintained ✅ Implementation: No new code required - validates existing if-only exit line routing and post-if statement processing. Documentation: - docs/development/current/main/phases/phase-114/README.md - Updated: 10-Now.md, 01-JoinIR-Selfhost-INDEX.md 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
17
apps/tests/phase114_if_only_return_then_post_min.hako
Normal file
17
apps/tests/phase114_if_only_return_then_post_min.hako
Normal file
@ -0,0 +1,17 @@
|
||||
// Phase 114: if-only return+post parity
|
||||
// Tests: early return in if-only with post-if statements
|
||||
|
||||
static box Main {
|
||||
f(flag) {
|
||||
local x = 1
|
||||
if flag == 1 { return 7 }
|
||||
x = x + 1
|
||||
return x
|
||||
}
|
||||
|
||||
main() {
|
||||
print(f(1))
|
||||
print(f(0))
|
||||
return "OK"
|
||||
}
|
||||
}
|
||||
@ -64,17 +64,19 @@ JoinIR の箱構造と責務、ループ/if の lowering パターンを把握
|
||||
- `docs/development/current/main/phases/phase-103/README.md`
|
||||
15. Phase 113: if-only partial assign parity(片側代入の保持 merge)
|
||||
- `docs/development/current/main/phases/phase-113/README.md`
|
||||
16. Phase 104: loop(true) break-only digits(VM + LLVM EXE)
|
||||
16. Phase 114: if-only return+post parity(early return + post-if statements)
|
||||
- `docs/development/current/main/phases/phase-114/README.md`
|
||||
17. Phase 104: loop(true) break-only digits(VM + LLVM EXE)
|
||||
- `docs/development/current/main/phases/phase-104/README.md`
|
||||
17. Phase 107: json_cur find_balanced_* depth scan(VM + LLVM EXE)
|
||||
18. Phase 107: json_cur find_balanced_* depth scan(VM + LLVM EXE)
|
||||
- `docs/development/current/main/phases/phase-107/README.md`
|
||||
18. Phase 108: Pattern2 policy router SSOT(入口の薄さを固定)
|
||||
19. Phase 108: Pattern2 policy router SSOT(入口の薄さを固定)
|
||||
- `docs/development/current/main/phases/phase-108/README.md`
|
||||
19. Phase 109: error_tags hints SSOT(Fail-Fast + hint の語彙固定)
|
||||
20. Phase 109: error_tags hints SSOT(Fail-Fast + hint の語彙固定)
|
||||
- `docs/development/current/main/phases/phase-109/README.md`
|
||||
20. MIR Builder(Context 分割の入口)
|
||||
21. MIR Builder(Context 分割の入口)
|
||||
- `src/mir/builder/README.md`
|
||||
21. Scope/BindingId(shadowing・束縛同一性の段階移行)
|
||||
22. Scope/BindingId(shadowing・束縛同一性の段階移行)
|
||||
- `docs/development/current/main/phase73-scope-manager-design.md`
|
||||
- `docs/development/current/main/PHASE_74_SUMMARY.md`
|
||||
- `docs/development/current/main/PHASE_75_SUMMARY.md`
|
||||
|
||||
@ -1,5 +1,14 @@
|
||||
# Self Current Task — Now (main)
|
||||
|
||||
## 2025-12-18:Phase 114 完了 ✅
|
||||
|
||||
**Phase 114: if-only return+post parity**
|
||||
- if-only で early return + post-if statements パターンを VM/LLVM で固定
|
||||
- Fixture: phase114_if_only_return_then_post_min.hako (expected: 7, 2)
|
||||
- Smoke: VM + LLVM EXE parity 検証済み
|
||||
- 回帰: Phase 103/113 維持確認
|
||||
- 入口: `docs/development/current/main/phases/phase-114/README.md`
|
||||
|
||||
## 2025-12-18:Phase 113 完了 ✅
|
||||
|
||||
**Phase 113: if-only partial assign parity**
|
||||
|
||||
132
docs/development/current/main/phases/phase-114/README.md
Normal file
132
docs/development/current/main/phases/phase-114/README.md
Normal file
@ -0,0 +1,132 @@
|
||||
# Phase 114: if-only return+post parity
|
||||
|
||||
## Status: DONE
|
||||
|
||||
## Background
|
||||
|
||||
Phase 114 extends if-only JoinIR lowering to support cases where:
|
||||
- The if-only branch contains an early return
|
||||
- Post-if statements exist after the if block
|
||||
- The function eventually returns a value from the post-if path
|
||||
|
||||
This pattern is common in early-exit optimization code where certain conditions trigger an immediate return, while the normal flow continues with additional processing.
|
||||
|
||||
## Test Fixture
|
||||
|
||||
**File**: `apps/tests/phase114_if_only_return_then_post_min.hako`
|
||||
|
||||
```hako
|
||||
// Phase 114: if-only return+post parity
|
||||
// Tests: early return in if-only with post-if statements
|
||||
|
||||
static box Main {
|
||||
f(flag) {
|
||||
local x = 1
|
||||
if flag == 1 { return 7 }
|
||||
x = x + 1
|
||||
return x
|
||||
}
|
||||
|
||||
main() {
|
||||
print(f(1))
|
||||
print(f(0))
|
||||
return "OK"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Expected Output**:
|
||||
```
|
||||
7
|
||||
2
|
||||
```
|
||||
|
||||
**Logic**:
|
||||
- `f(1)`: condition true → early return 7
|
||||
- `f(0)`: condition false → x=1+1=2, return 2
|
||||
|
||||
## Implementation
|
||||
|
||||
This pattern was already supported by the existing JoinIR if-only lowering infrastructure:
|
||||
- If-select pattern recognition
|
||||
- Early return handling via exit line routing
|
||||
- Post-if statement processing in the else path
|
||||
|
||||
No new implementation was required - Phase 114 validates that this pattern works correctly in both VM and LLVM backends.
|
||||
|
||||
## Testing
|
||||
|
||||
### Smoke Tests
|
||||
|
||||
1. **VM Backend**: `tools/smokes/v2/profiles/integration/apps/phase114_if_only_return_then_post_vm.sh`
|
||||
```bash
|
||||
bash tools/smokes/v2/profiles/integration/apps/phase114_if_only_return_then_post_vm.sh
|
||||
```
|
||||
|
||||
2. **LLVM EXE Backend**: `tools/smokes/v2/profiles/integration/apps/phase114_if_only_return_then_post_llvm_exe.sh`
|
||||
```bash
|
||||
bash tools/smokes/v2/profiles/integration/apps/phase114_if_only_return_then_post_llvm_exe.sh
|
||||
```
|
||||
|
||||
Both tests run with:
|
||||
- `NYASH_DISABLE_PLUGINS=1` (core path only)
|
||||
- `HAKO_JOINIR_STRICT=1` (strict validation)
|
||||
|
||||
### Regression Tests
|
||||
|
||||
Verified backward compatibility with:
|
||||
- Phase 103: if-only early return (both branches return)
|
||||
- Phase 113: if-only partial assign (one branch assigns)
|
||||
|
||||
All regression tests pass without modifications.
|
||||
|
||||
## Verification Commands
|
||||
|
||||
```bash
|
||||
# Quick VM test
|
||||
bash tools/smokes/v2/profiles/integration/apps/phase114_if_only_return_then_post_vm.sh
|
||||
|
||||
# Full LLVM EXE test (requires plugins)
|
||||
bash tools/smokes/v2/profiles/integration/apps/phase114_if_only_return_then_post_llvm_exe.sh
|
||||
|
||||
# Regression verification
|
||||
bash tools/smokes/v2/profiles/integration/apps/phase103_if_only_early_return_vm.sh
|
||||
bash tools/smokes/v2/profiles/integration/apps/phase113_if_only_partial_assign_vm.sh
|
||||
bash tools/smokes/v2/profiles/integration/apps/phase113_if_only_partial_assign_llvm_exe.sh
|
||||
```
|
||||
|
||||
## Architecture Notes
|
||||
|
||||
### Pattern Coverage
|
||||
|
||||
Phase 114 completes the if-only pattern matrix:
|
||||
|
||||
| Pattern | Phase | Description |
|
||||
|---------|-------|-------------|
|
||||
| Both branches return early | Phase 103 | `if flag { return A } else { return B }` |
|
||||
| One branch assigns, else implicit | Phase 113 | `if flag { x = value }` (else preserves x) |
|
||||
| **One branch returns early, else continues** | **Phase 114** | `if flag { return A }; post-code; return B` |
|
||||
|
||||
### Box Theory Alignment
|
||||
|
||||
This implementation follows Box Theory modularization principles:
|
||||
- **Single responsibility**: If-only lowering handles one pattern variation
|
||||
- **Separation of concerns**: Exit line routing is independent from assignment merging
|
||||
- **Reusability**: Post-if statement processing reuses existing boundary SSA infrastructure
|
||||
- **Fail-Fast**: No fallback paths - pattern either matches or explicitly fails
|
||||
|
||||
### Exit Line Routing
|
||||
|
||||
The key to Phase 114 is proper exit line routing:
|
||||
1. **Early return**: Creates an exit line directly to function return
|
||||
2. **Post-if path**: Continues to post-if statements, then returns
|
||||
3. **No join point**: The two paths never merge (one exits early)
|
||||
|
||||
This is handled by the existing ExitLineReconnector Box.
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Phase 103: if-only early return](../phase-103/README.md)
|
||||
- [Phase 113: if-only partial assign](../phase-113/README.md)
|
||||
- [JoinIR Architecture Overview](../../joinir-architecture-overview.md)
|
||||
- [Exit Line Architecture](../../design/exit-line-architecture.md)
|
||||
@ -0,0 +1,38 @@
|
||||
#!/bin/bash
|
||||
# Phase 114: if-only return+post 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/phase114_if_only_return_then_post_plugin_build.log"
|
||||
llvm_exe_ensure_plugins_or_fail || exit 1
|
||||
|
||||
INPUT_HAKO="$NYASH_ROOT/apps/tests/phase114_if_only_return_then_post_min.hako"
|
||||
OUTPUT_EXE="$NYASH_ROOT/tmp/phase114_if_only_return_then_post_llvm_exe"
|
||||
|
||||
EXPECTED=$'7\n2'
|
||||
EXPECTED_LINES=2
|
||||
LLVM_BUILD_LOG="/tmp/phase114_if_only_return_then_post_build.log"
|
||||
if llvm_exe_build_and_run_numeric_smoke; then
|
||||
test_pass "phase114_if_only_return_then_post_llvm_exe: output matches expected (7\\n2)"
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
@ -0,0 +1,56 @@
|
||||
#!/bin/bash
|
||||
# Phase 114: if-only return+post parity (VM)
|
||||
#
|
||||
# Verifies that if-only with early return and post-if statements works correctly.
|
||||
|
||||
source "$(dirname "$0")/../../../lib/test_runner.sh"
|
||||
export SMOKES_USE_PYVM=0
|
||||
require_env || exit 2
|
||||
|
||||
PASS_COUNT=0
|
||||
FAIL_COUNT=0
|
||||
RUN_TIMEOUT_SECS=${RUN_TIMEOUT_SECS:-10}
|
||||
|
||||
INPUT="$NYASH_ROOT/apps/tests/phase114_if_only_return_then_post_min.hako"
|
||||
|
||||
echo "[INFO] Phase 114: if-only return+post parity (VM) - $INPUT"
|
||||
|
||||
set +e
|
||||
OUTPUT=$(timeout "$RUN_TIMEOUT_SECS" env \
|
||||
NYASH_DISABLE_PLUGINS=1 \
|
||||
HAKO_JOINIR_STRICT=1 \
|
||||
"$NYASH_BIN" --backend vm "$INPUT" 2>&1)
|
||||
EXIT_CODE=$?
|
||||
set -e
|
||||
|
||||
if [ "$EXIT_CODE" -eq 124 ]; then
|
||||
echo "[FAIL] hakorune timed out (>${RUN_TIMEOUT_SECS}s)"
|
||||
FAIL_COUNT=$((FAIL_COUNT + 1))
|
||||
elif [ "$EXIT_CODE" -eq 0 ]; then
|
||||
EXPECTED=$'7\n2'
|
||||
CLEAN=$(printf "%s\n" "$OUTPUT" | grep -E '^-?[0-9]+$' | head -n 2 | tr -d '\r')
|
||||
if [ "$CLEAN" = "$EXPECTED" ]; then
|
||||
echo "[PASS] Output verified: 7\\n2"
|
||||
PASS_COUNT=$((PASS_COUNT + 1))
|
||||
else
|
||||
echo "[FAIL] Unexpected output (expected: 7\\n2)"
|
||||
echo "[INFO] output (tail):"
|
||||
echo "$OUTPUT" | tail -n 50 || true
|
||||
FAIL_COUNT=$((FAIL_COUNT + 1))
|
||||
fi
|
||||
else
|
||||
echo "[FAIL] hakorune failed with exit code $EXIT_CODE"
|
||||
echo "[INFO] output (tail):"
|
||||
echo "$OUTPUT" | tail -n 50 || true
|
||||
FAIL_COUNT=$((FAIL_COUNT + 1))
|
||||
fi
|
||||
|
||||
echo "[INFO] PASS: $PASS_COUNT, FAIL: $FAIL_COUNT"
|
||||
|
||||
if [ "$FAIL_COUNT" -eq 0 ]; then
|
||||
test_pass "phase114_if_only_return_then_post_vm: All tests passed"
|
||||
exit 0
|
||||
else
|
||||
test_fail "phase114_if_only_return_then_post_vm: $FAIL_COUNT test(s) failed"
|
||||
exit 1
|
||||
fi
|
||||
Reference in New Issue
Block a user