From 99e1d24eaf752a801ea67f14457f4ba2c6de9a08 Mon Sep 17 00:00:00 2001 From: nyash-codex Date: Wed, 17 Dec 2025 17:41:07 +0900 Subject: [PATCH] test: Phase 103 if-only merge fixture + VM/LLVM smokes --- apps/tests/phase103_if_only_merge_min.hako | 23 ++++ .../apps/phase103_if_only_llvm_exe.sh | 120 ++++++++++++++++++ .../integration/apps/phase103_if_only_vm.sh | 57 +++++++++ 3 files changed, 200 insertions(+) create mode 100644 apps/tests/phase103_if_only_merge_min.hako create mode 100644 tools/smokes/v2/profiles/integration/apps/phase103_if_only_llvm_exe.sh create mode 100644 tools/smokes/v2/profiles/integration/apps/phase103_if_only_vm.sh diff --git a/apps/tests/phase103_if_only_merge_min.hako b/apps/tests/phase103_if_only_merge_min.hako new file mode 100644 index 00000000..2e9aa7b0 --- /dev/null +++ b/apps/tests/phase103_if_only_merge_min.hako @@ -0,0 +1,23 @@ +// Phase 103: if-only merge regression fixture +// Goal: require merge (PHI-equivalent) in an if-only program (no loops), +// and include one nested if to ensure nested merge stability. + +box Main { + main() { + local x = 0 + + if "x" == "x" { + if "y" == "z" { + x = 1 + } else { + x = 2 + } + } else { + x = 3 + } + + print(x) + return "OK" + } +} + diff --git a/tools/smokes/v2/profiles/integration/apps/phase103_if_only_llvm_exe.sh b/tools/smokes/v2/profiles/integration/apps/phase103_if_only_llvm_exe.sh new file mode 100644 index 00000000..803b5a4f --- /dev/null +++ b/tools/smokes/v2/profiles/integration/apps/phase103_if_only_llvm_exe.sh @@ -0,0 +1,120 @@ +#!/bin/bash +# Phase 103: if-only merge regression (LLVM EXE parity) + +source "$(dirname "$0")/../../../lib/test_runner.sh" +export SMOKES_USE_PYVM=0 +require_env || exit 2 + +# LLVM availability checks (graceful SKIP) +if ! command -v llvm-config-18 &> /dev/null; then + test_skip "llvm-config-18 not found"; exit 0 +fi + +if ! "$NYASH_BIN" --help 2>&1 | grep -q "llvm"; then + test_skip "hakorune --backend llvm not available"; exit 0 +fi + +if ! python3 -c "import llvmlite" 2>/dev/null; then + test_skip "Python llvmlite not found"; exit 0 +fi + +# 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" + +check_plugins() { + python3 - "$FILEBOX_SO" "$MAPBOX_SO" "$STRINGBOX_SO" "$CONSOLEBOX_SO" "$INTEGERBOX_SO" <<'PY' +import ctypes +import os +import sys +names = ["FileBox", "MapBox", "StringBox", "ConsoleBox", "IntegerBox"] +paths = sys.argv[1:] +failures = [] +for name, path in zip(names, paths): + if not os.path.isfile(path): + failures.append(f"[plugin/missing] {name}: {path}") + continue + try: + ctypes.CDLL(path) + except Exception as e: # noqa: BLE001 + failures.append(f"[plugin/dlopen] {name}: {path} ({e})") +if failures: + print("\n".join(failures)) + sys.exit(1) +print("OK") +PY +} + +echo "[INFO] Checking plugin artifacts (FileBox/MapBox/StringBox/ConsoleBox/IntegerBox)" +if ! CHECK_OUTPUT=$(check_plugins 2>&1); then + echo "$CHECK_OUTPUT" + echo "[INFO] Missing/broken plugin detected, running build-all (core plugins)" + BUILD_LOG="/tmp/phase103_if_only_plugin_build.log" + if ! bash "$NYASH_ROOT/tools/plugins/build-all.sh" \ + nyash-filebox-plugin nyash-map-plugin nyash-string-plugin nyash-console-plugin nyash-integer-plugin \ + >"$BUILD_LOG" 2>&1; then + echo "[FAIL] tools/plugins/build-all.sh failed for core plugins" + tail -n 80 "$BUILD_LOG" + exit 1 + fi + if ! CHECK_OUTPUT=$(check_plugins 2>&1); then + echo "$CHECK_OUTPUT" + echo "[FAIL] Plugin artifacts still missing or unloadable after build-all" + tail -n 80 "$BUILD_LOG" + exit 1 + fi +fi + +mkdir -p "$NYASH_ROOT/tmp" + +INPUT_HAKO="$NYASH_ROOT/apps/tests/phase103_if_only_merge_min.hako" +OUTPUT_EXE="$NYASH_ROOT/tmp/phase103_if_only_llvm_exe" + +echo "[INFO] Building: $INPUT_HAKO → $OUTPUT_EXE" + +BUILD_LOG="/tmp/phase103_if_only_build.log" +if ! env NYASH_DISABLE_PLUGINS=0 "$NYASH_ROOT/tools/build_llvm.sh" "$INPUT_HAKO" -o "$OUTPUT_EXE" 2>&1 | tee "$BUILD_LOG"; then + echo "[FAIL] build_llvm.sh failed" + tail -n 80 "$BUILD_LOG" + exit 1 +fi + +if [ ! -x "$OUTPUT_EXE" ]; then + echo "[FAIL] Executable not created or not executable: $OUTPUT_EXE" + ls -la "$OUTPUT_EXE" 2>/dev/null || echo "File does not exist" + exit 1 +fi + +echo "[INFO] Executing: $OUTPUT_EXE" + +set +e +OUTPUT=$(timeout "${RUN_TIMEOUT_SECS:-10}" env NYASH_DISABLE_PLUGINS=0 "$OUTPUT_EXE" 2>&1) +EXIT_CODE=$? +set -e + +if [ "$EXIT_CODE" -ne 0 ]; then + echo "[FAIL] Execution failed with exit code $EXIT_CODE" + echo "$OUTPUT" | tail -n 80 + exit 1 +fi + +CLEAN=$(printf "%s\n" "$OUTPUT" | grep -v '^\[' | grep -E '^-?[0-9]+$' | head -n 1 | tr -d '\r') +EXPECTED="2" + +echo "[INFO] CLEAN output:" +echo "$CLEAN" + +if [ "$CLEAN" = "$EXPECTED" ]; then + test_pass "phase103_if_only_llvm_exe: output matches expected (2)" +else + echo "[FAIL] Output mismatch" + echo "[INFO] Raw output (tail):" + echo "$OUTPUT" | tail -n 80 + echo "[INFO] Expected:" + printf "%s\n" "$EXPECTED" + exit 1 +fi + diff --git a/tools/smokes/v2/profiles/integration/apps/phase103_if_only_vm.sh b/tools/smokes/v2/profiles/integration/apps/phase103_if_only_vm.sh new file mode 100644 index 00000000..20b1a2f9 --- /dev/null +++ b/tools/smokes/v2/profiles/integration/apps/phase103_if_only_vm.sh @@ -0,0 +1,57 @@ +#!/bin/bash +# Phase 103: if-only merge regression (VM) +# +# Verifies that if-only lowering (nested if + merge) is stable in VM backend. + +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/phase103_if_only_merge_min.hako" + +echo "[INFO] Phase 103: if-only merge regression (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="2" + CLEAN=$(printf "%s\n" "$OUTPUT" | grep -E '^-?[0-9]+$' | head -n 1 | tr -d '\r') + if [ "$CLEAN" = "$EXPECTED" ]; then + echo "[PASS] Output verified: 2" + PASS_COUNT=$((PASS_COUNT + 1)) + else + echo "[FAIL] Unexpected output (expected: 2)" + 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 "phase103_if_only_vm: All tests passed" + exit 0 +else + test_fail "phase103_if_only_vm: $FAIL_COUNT test(s) failed" + exit 1 +fi +