diff --git a/src/runner/selfhost.rs b/src/runner/selfhost.rs index 135364b1..031b9570 100644 --- a/src/runner/selfhost.rs +++ b/src/runner/selfhost.rs @@ -315,11 +315,16 @@ impl NyashRunner { } } crate::runner::child_env::pre_run_reset_oob_if_strict(); + crate::runner::child_env::pre_run_reset_oob_if_strict(); self.execute_mir_module(&module); if crate::config::env::oob_strict_fail() && crate::runtime::observe::oob_seen() { eprintln!("[selfhost][oob-strict] Out-of-bounds observed → exit(1)"); std::process::exit(1); } + if crate::config::env::oob_strict_fail() && crate::runtime::observe::oob_seen() { + eprintln!("[selfhost][oob-strict] Out-of-bounds observed → exit(1)"); + std::process::exit(1); + } return true; } else { return false; @@ -406,7 +411,12 @@ impl NyashRunner { std::process::exit(code); } } + crate::runner::child_env::pre_run_reset_oob_if_strict(); self.execute_mir_module(&module); + if crate::config::env::oob_strict_fail() && crate::runtime::observe::oob_seen() { + eprintln!("[selfhost][oob-strict] Out-of-bounds observed → exit(1)"); + std::process::exit(1); + } true } Err(e) => { diff --git a/tools/smokes/v2/lib/stageb_helpers.sh b/tools/smokes/v2/lib/stageb_helpers.sh new file mode 100644 index 00000000..3704e364 --- /dev/null +++ b/tools/smokes/v2/lib/stageb_helpers.sh @@ -0,0 +1,25 @@ +#!/bin/bash +# stageb_helpers.sh — Helpers to compile Hako(Stage‑B) source to MIR(JSON v0) + +stageb_compile_to_json() { + # Args: HAKO_CODE + local code="$1" + local hako_tmp="/tmp/hako_stageb_$$.hako" + local json_out="/tmp/hako_stageb_$$.mir.json" + printf "%s\n" "$code" > "$hako_tmp" + local raw="/tmp/hako_stageb_raw_$$.txt" + NYASH_PARSER_ALLOW_SEMICOLON=1 HAKO_ALLOW_USING_FILE=1 NYASH_ALLOW_USING_FILE=1 \ + HAKO_PARSER_STAGE3=1 NYASH_PARSER_STAGE3=1 \ + NYASH_VARMAP_GUARD_STRICT=0 NYASH_BLOCK_SCHEDULE_VERIFY=0 \ + NYASH_QUIET=1 HAKO_QUIET=1 NYASH_CLI_VERBOSE=0 \ + "$NYASH_BIN" --backend vm \ + "$NYASH_ROOT/lang/src/compiler/entry/compiler_stageb.hako" -- --source "$(cat "$hako_tmp")" > "$raw" 2>&1 || true + awk '/"version":0/ && /"kind":"Program"/ {print; exit}' "$raw" > "$json_out" + rm -f "$raw" "$hako_tmp" + echo "$json_out" +} + +stageb_json_nonempty() { + local path="$1" + [ -s "$path" ] +} diff --git a/tools/smokes/v2/profiles/quick/core/stageb/stageb_array_vm.sh b/tools/smokes/v2/profiles/quick/core/stageb/stageb_array_vm.sh new file mode 100644 index 00000000..b13858e0 --- /dev/null +++ b/tools/smokes/v2/profiles/quick/core/stageb/stageb_array_vm.sh @@ -0,0 +1,27 @@ +#!/bin/bash +# stageb_array_vm.sh — Stage‑B: array length → rc=3 + +set -euo pipefail +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then + ROOT="$ROOT_GIT" +else + ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)" +fi +source "$ROOT/tools/smokes/v2/lib/test_runner.sh" +source "$ROOT/tools/smokes/v2/lib/stageb_helpers.sh" +require_env || exit 2 + +code='box Main { static method main() { local a=[1,2,3]; return a.length(); } }' +json=$(stageb_compile_to_json "$code") +if ! stageb_json_nonempty "$json"; then + echo "[WARN] Stage‑B emit empty; skipping" >&2 + rm -f "$json" + exit 0 +fi +set +e +"$NYASH_BIN" --json-file "$json" >/dev/null 2>&1 +rc=$? +set -e +rm -f "$json" +if [ $rc -eq 3 ]; then echo "[PASS] stageb_array_vm"; exit 0; else echo "[FAIL] stageb_array_vm rc=$rc" >&2; exit 1; fi diff --git a/tools/smokes/v2/profiles/quick/core/stageb/stageb_binop_vm.sh b/tools/smokes/v2/profiles/quick/core/stageb/stageb_binop_vm.sh new file mode 100644 index 00000000..a1a76781 --- /dev/null +++ b/tools/smokes/v2/profiles/quick/core/stageb/stageb_binop_vm.sh @@ -0,0 +1,27 @@ +#!/bin/bash +# stageb_binop_vm.sh — Stage‑B: binop positive (return 1+2 → rc=3) + +set -euo pipefail +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then + ROOT="$ROOT_GIT" +else + ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)" +fi +source "$ROOT/tools/smokes/v2/lib/test_runner.sh" +source "$ROOT/tools/smokes/v2/lib/stageb_helpers.sh" +require_env || exit 2 + +code='box Main { static method main() { return 1+2 } }' +json=$(stageb_compile_to_json "$code") +if ! stageb_json_nonempty "$json"; then + echo "[WARN] Stage‑B emit empty; skipping" >&2 + rm -f "$json" + exit 0 +fi +set +e +"$NYASH_BIN" --json-file "$json" >/dev/null 2>&1 +rc=$? +set -e +rm -f "$json" +if [ $rc -eq 3 ]; then echo "[PASS] stageb_binop_vm"; exit 0; else echo "[FAIL] stageb_binop_vm rc=$rc" >&2; exit 1; fi diff --git a/tools/smokes/v2/profiles/quick/core/stageb/stageb_if_vm.sh b/tools/smokes/v2/profiles/quick/core/stageb/stageb_if_vm.sh new file mode 100644 index 00000000..528e0a1c --- /dev/null +++ b/tools/smokes/v2/profiles/quick/core/stageb/stageb_if_vm.sh @@ -0,0 +1,27 @@ +#!/bin/bash +# stageb_if_vm.sh — Stage‑B: if(5>4){return 1}else{return 0} → rc=1 + +set -euo pipefail +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then + ROOT="$ROOT_GIT" +else + ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)" +fi +source "$ROOT/tools/smokes/v2/lib/test_runner.sh" +source "$ROOT/tools/smokes/v2/lib/stageb_helpers.sh" +require_env || exit 2 + +code='box Main { static method main() { if(5>4){ return 1 } else { return 0 } } }' +json=$(stageb_compile_to_json "$code") +if ! stageb_json_nonempty "$json"; then + echo "[WARN] Stage‑B emit empty; skipping" >&2 + rm -f "$json" + exit 0 +fi +set +e +"$NYASH_BIN" --json-file "$json" >/dev/null 2>&1 +rc=$? +set -e +rm -f "$json" +if [ $rc -eq 1 ]; then echo "[PASS] stageb_if_vm"; exit 0; else echo "[FAIL] stageb_if_vm rc=$rc" >&2; exit 1; fi diff --git a/tools/smokes/v2/profiles/quick/core/stageb/stageb_loop_vm.sh b/tools/smokes/v2/profiles/quick/core/stageb/stageb_loop_vm.sh new file mode 100644 index 00000000..58b10f77 --- /dev/null +++ b/tools/smokes/v2/profiles/quick/core/stageb/stageb_loop_vm.sh @@ -0,0 +1,27 @@ +#!/bin/bash +# stageb_loop_vm.sh — Stage‑B: sum 1..3 → rc=6 + +set -euo pipefail +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then + ROOT="$ROOT_GIT" +else + ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)" +fi +source "$ROOT/tools/smokes/v2/lib/test_runner.sh" +source "$ROOT/tools/smokes/v2/lib/stageb_helpers.sh" +require_env || exit 2 + +code='box Main { static method main() { local i=1; local s=0; loop(i<=3){ s=s+i; i=i+1; } return s; } }' +json=$(stageb_compile_to_json "$code") +if ! stageb_json_nonempty "$json"; then + echo "[WARN] Stage‑B emit empty; skipping" >&2 + rm -f "$json" + exit 0 +fi +set +e +"$NYASH_BIN" --json-file "$json" >/dev/null 2>&1 +rc=$? +set -e +rm -f "$json" +if [ $rc -eq 6 ]; then echo "[PASS] stageb_loop_vm"; exit 0; else echo "[FAIL] stageb_loop_vm rc=$rc" >&2; exit 1; fi diff --git a/tools/smokes/v2/profiles/quick/core/stageb/stageb_map_vm.sh b/tools/smokes/v2/profiles/quick/core/stageb/stageb_map_vm.sh new file mode 100644 index 00000000..d6b9115e --- /dev/null +++ b/tools/smokes/v2/profiles/quick/core/stageb/stageb_map_vm.sh @@ -0,0 +1,27 @@ +#!/bin/bash +# stageb_map_vm.sh — Stage‑B: map size → rc=1 + +set -euo pipefail +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then + ROOT="$ROOT_GIT" +else + ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)" +fi +source "$ROOT/tools/smokes/v2/lib/test_runner.sh" +source "$ROOT/tools/smokes/v2/lib/stageb_helpers.sh" +require_env || exit 2 + +code='box Main { static method main() { local m=new MapBox(); m.set("a",1); return m.size(); } }' +json=$(stageb_compile_to_json "$code") +if ! stageb_json_nonempty "$json"; then + echo "[WARN] Stage‑B emit empty; skipping" >&2 + rm -f "$json" + exit 0 +fi +set +e +"$NYASH_BIN" --json-file "$json" >/dev/null 2>&1 +rc=$? +set -e +rm -f "$json" +if [ $rc -eq 1 ]; then echo "[PASS] stageb_map_vm"; exit 0; else echo "[FAIL] stageb_map_vm rc=$rc" >&2; exit 1; fi diff --git a/tools/smokes/v2/profiles/quick/core/stageb/stageb_print_vm.sh b/tools/smokes/v2/profiles/quick/core/stageb/stageb_print_vm.sh new file mode 100644 index 00000000..c67879ef --- /dev/null +++ b/tools/smokes/v2/profiles/quick/core/stageb/stageb_print_vm.sh @@ -0,0 +1,37 @@ +#!/bin/bash +# stageb_print_vm.sh — Stage‑B: print positive case (emit→Gate‑C direct) + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then + ROOT="$ROOT_GIT" +else + ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)" +fi +source "$ROOT/tools/smokes/v2/lib/test_runner.sh" +source "$ROOT/tools/smokes/v2/lib/stageb_helpers.sh" +require_env || exit 2 + +code='box Main { static method main() { print(3); return 0; } }' +json=$(stageb_compile_to_json "$code") || { echo "[WARN] Stage‑B emit failed; skipping" >&2; exit 0; } +if ! stageb_json_nonempty "$json"; then + echo "[WARN] Stage‑B emit empty; skipping" >&2 + rm -f "$json" + exit 0 +fi +set +e +output=$("$NYASH_BIN" --json-file "$json") +rc=$? +set -e +rm -f "$json" + +if [ "$output" = "3" ] && [ $rc -eq 0 ]; then + echo "[PASS] stageb_print_vm" + exit 0 +else + echo "[FAIL] stageb_print_vm (rc=$rc)" >&2 + echo "--- output ---" >&2 + echo "$output" >&2 + exit 1 +fi diff --git a/tools/smokes/v2/profiles/quick/core/stageb/stageb_string_vm.sh b/tools/smokes/v2/profiles/quick/core/stageb/stageb_string_vm.sh new file mode 100644 index 00000000..2e5a42de --- /dev/null +++ b/tools/smokes/v2/profiles/quick/core/stageb/stageb_string_vm.sh @@ -0,0 +1,27 @@ +#!/bin/bash +# stageb_string_vm.sh — Stage‑B: string length → rc=2 + +set -euo pipefail +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then + ROOT="$ROOT_GIT" +else + ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)" +fi +source "$ROOT/tools/smokes/v2/lib/test_runner.sh" +source "$ROOT/tools/smokes/v2/lib/stageb_helpers.sh" +require_env || exit 2 + +code='box Main { static method main() { local s="ab"; return s.length(); } }' +json=$(stageb_compile_to_json "$code") +if ! stageb_json_nonempty "$json"; then + echo "[WARN] Stage‑B emit empty; skipping" >&2 + rm -f "$json" + exit 0 +fi +set +e +"$NYASH_BIN" --json-file "$json" >/dev/null 2>&1 +rc=$? +set -e +rm -f "$json" +if [ $rc -eq 2 ]; then echo "[PASS] stageb_string_vm"; exit 0; else echo "[FAIL] stageb_string_vm rc=$rc" >&2; exit 1; fi