diff --git a/lang/src/compiler/entry/bundle_resolver.hako b/lang/src/compiler/entry/bundle_resolver.hako index b5bfd27b..c5570c30 100644 --- a/lang/src/compiler/entry/bundle_resolver.hako +++ b/lang/src/compiler/entry/bundle_resolver.hako @@ -7,6 +7,62 @@ static box BundleResolver { // - --require-mod Name must appear in named bundles ([bundle/missing] Name) // - Merge order: bundle-src* → bundle-mod* (in given order) resolve(bundle_srcs, bundle_names, bundle_mod_srcs, require_mods) { + // Alias table via env: HAKO_BUNDLE_ALIAS_TABLE / NYASH_BUNDLE_ALIAS_TABLE + // Format: entries separated by '|||', each entry as 'Name:code' + local table = env.get("HAKO_BUNDLE_ALIAS_TABLE") + if table == null || table == "" { table = env.get("NYASH_BUNDLE_ALIAS_TABLE") } + if table != null && table != "" { + local i = 0 + loop(i < table.length()) { + // find next delimiter or end + local j = table.indexOf("|||", i) + local seg = "" + if j >= 0 { seg = table.substring(i, j) } else { seg = table.substring(i, table.length()) } + if seg != "" { + local pos = -1 + local k = 0 + loop(k < seg.length()) { if seg.substring(k,k+1) == ":" { pos = k break } k = k + 1 } + if pos >= 0 { + local name = seg.substring(0, pos) + local code = seg.substring(pos+1, seg.length()) + if name != "" && code != "" { + if bundle_names == null { bundle_names = new ArrayBox() } + if bundle_mod_srcs == null { bundle_mod_srcs = new ArrayBox() } + bundle_names.push(name) + bundle_mod_srcs.push(code) + } + } + } + if j < 0 { break } + i = j + 3 + } + } + // Env alias injection (TTL, dev-only): HAKO_BUNDLE_ALIAS_ / NYASH_BUNDLE_ALIAS_ + // If a required module is not provided via --bundle-mod, but an env alias + // supplies its code, synthesize a named bundle entry before checks/merge. + if require_mods != null { + local i0 = 0; local rn0 = require_mods.length() + loop(i0 < rn0) { + local need = "" + require_mods.get(i0) + local present = 0 + if bundle_names != null { + local j0 = 0; local bn0 = bundle_names.length() + loop(j0 < bn0) { if ("" + bundle_names.get(j0)) == need { present = 1 break } j0 = j0 + 1 } + } + if present == 0 { + local alias_key = "HAKO_BUNDLE_ALIAS_" + need + local code = env.get(alias_key) + if code == null || code == "" { code = env.get("NYASH_BUNDLE_ALIAS_" + need) } + if code != null && code != "" { + if bundle_names == null { bundle_names = new ArrayBox() } + if bundle_mod_srcs == null { bundle_mod_srcs = new ArrayBox() } + bundle_names.push(need) + bundle_mod_srcs.push("" + code) + } + } + i0 = i0 + 1 + } + } // Fail on duplicate names if bundle_names != null && bundle_names.length() > 1 { local i = 0; local n = bundle_names.length() @@ -50,4 +106,3 @@ static box BundleResolver { return merged } } - diff --git a/lang/src/compiler/entry/compiler_stageb.hako b/lang/src/compiler/entry/compiler_stageb.hako index 8ec9753e..009905f6 100644 --- a/lang/src/compiler/entry/compiler_stageb.hako +++ b/lang/src/compiler/entry/compiler_stageb.hako @@ -1,6 +1,7 @@ // Stage-B compiler entry — ParserBox → FlowEntry emit-only using sh_core as StringHelpers // Required: ParserStringUtilsBox depends on this (using chain unresolved) +include "lang/src/compiler/entry/bundle_resolver.hako" using lang.compiler.parser.box as ParserBox // Note: Runner resolves entry as Main.main by default. @@ -148,25 +149,7 @@ static box Main { i = i + 1 } } - // Fail‑Fast: required modules must be provided via --bundle-mod - if require_mods.length() > 0 { - local idx = 0 - local rn = require_mods.length() - loop(idx < rn) { - local need = "" + require_mods.get(idx) - local found = 0 - { - local j = 0 - local bn = bundle_names.length() - loop(j < bn) { if ("" + bundle_names.get(j)) == need { found = 1 break } j = j + 1 } - } - if found == 0 { - print("[bundle/missing] " + need) - return 1 - } - idx = idx + 1 - } - } + // Required modules are validated in BundleResolver.resolve (includes env alias injection) // 4.6) Fail‑Fast on duplicate named bundles to avoid ambiguity // Policy: duplicate module names are not allowed. Emit a stable diagnostic tag and exit. @@ -188,7 +171,6 @@ static box Main { } if bundles.length() > 0 || bundle_srcs.length() > 0 { - include "lang/src/compiler/entry/bundle_resolver.hako" local merged_prefix = BundleResolver.resolve(bundles, bundle_names, bundle_srcs, require_mods) if merged_prefix == null { return 1 } body_src = merged_prefix + body_src diff --git a/lang/src/vm/README.md b/lang/src/vm/README.md index 9923b962..64bfd94c 100644 --- a/lang/src/vm/README.md +++ b/lang/src/vm/README.md @@ -45,6 +45,19 @@ Exit Code Policy - Gate‑C(Core): numeric return is mapped to process exit code。タグ付きの失敗時は安定メッセージを出し、可能な限り非0で終了。 - VM backend(Rust Interpreter): 戻り値は標準出力に出す。プロセスの終了コードは戻り値と一致しない場合があるため、スモークは安定タグや標準出力の数値で検証する(rcは参考)。 - 推奨: CIやスクリプトでは Gate‑C(Core) を優先し rc を厳密化。開発時の対話検証は VM ルートで標準出力を検証。 + +Tag→RC(Core Direct) +- Core Direct(`HAKO_CORE_DIRECT=1`)では、数値行が見つからない場合は rc≠0 を返す(Fail‑Fast)。 +- 代表タグ(例) + - `[core/string/bounds]` → rc=1 + - `[core/array/oob_set]` → rc=1 + - `[core/mir_call/method_unsupported]` → rc=1 + +Core Direct Toggle +- `HAKO_CORE_DIRECT=1`(互換: `NYASH_CORE_DIRECT`)で、Gate‑C(Core) の JSON 実行を "Core Dispatcher 直行" 子経路に切り替える。 + - 形: 一時Hakoスクリプトに `include "lang/src/vm/core/dispatcher.hako"` を埋め込み、`NyVmDispatcher.run(json)` を実行。 + - rc: 最後の数値行を rc にマップ。数値がない場合(タグ等)は rc≠0 とする(Fail‑Fast)。 + - 用途: Core の診断タグや rc を CI で直接検証したい時に使用。 - Runner Core toggle: `HAKO_NYVM_CORE=1` (or `NYASH_NYVM_CORE=1`) selects the Core bridge for the nyvm wrapper path. - Gate‑C Core route: set `NYASH_GATE_C_CORE=1` (or `HAKO_GATE_C_CORE=1`) to diff --git a/lang/src/vm/core/ops/mir_call.hako b/lang/src/vm/core/ops/mir_call.hako index fdd2c193..b682d3be 100644 --- a/lang/src/vm/core/ops/mir_call.hako +++ b/lang/src/vm/core/ops/mir_call.hako @@ -401,7 +401,7 @@ static box NyVmOpMirCall { if method == "keys" { local dst = me._read_dst(inst_json, "map keys") if dst == null { return -1 } - // Build keys by scanning mem for receiver-specific entry slots + // Build keys by scanning mem for receiver-specific entry slots (non-null values only) local keys_arr = new ArrayBox() local prefix = me._map_entry_slot(recv_id, "") // Iterate memory keys (MapBox.keys()) @@ -416,8 +416,11 @@ static box NyVmOpMirCall { if k.substring(0, prefix.length()) == prefix { ok = 1 } } if ok == 1 { - local tail = k.substring(prefix.length(), k.length()) - keys_arr.push(tail) + local v = mem.get(k) + if v != null { + local tail = k.substring(prefix.length(), k.length()) + keys_arr.push(tail) + } } i = i + 1 } @@ -473,7 +476,20 @@ static box NyVmOpMirCall { return 0 } if method == "clear" { - // clear(): set length to 0; entries are logically cleared(TTL: metadata‑only) + // clear(): set length to 0 and remove all entries for this map from mem + local prefix = me._map_entry_slot(recv_id, "") + local all_keys = mem.keys() + local i = 0 + local n = all_keys.length() + loop(i < n) { + local k = "" + all_keys.get(i) + local ok = 0 + if k.length() >= prefix.length() { + if k.substring(0, prefix.length()) == prefix { ok = 1 } + } + if ok == 1 { mem.set(k, null) } + i = i + 1 + } me._map_len_set(state, recv_id, 0) local dst_opt2 = me._read_optional_vid_field(inst_json, "dst") if dst_opt2 != null { NyVmState.set_reg(state, dst_opt2, void) } diff --git a/src/runner/core_executor.rs b/src/runner/core_executor.rs index 53f4b105..6901d006 100644 --- a/src/runner/core_executor.rs +++ b/src/runner/core_executor.rs @@ -119,5 +119,5 @@ fn try_run_core_direct(json: &str) -> Option { break; } } - rc + if let Some(code) = rc { Some(code) } else { Some(1) } } diff --git a/tools/smokes/v2/lib/stageb_helpers.sh b/tools/smokes/v2/lib/stageb_helpers.sh index 21290d34..8cc8889b 100644 --- a/tools/smokes/v2/lib/stageb_helpers.sh +++ b/tools/smokes/v2/lib/stageb_helpers.sh @@ -93,6 +93,42 @@ stageb_compile_to_json_with_bundles() { return 1 } +stageb_compile_to_json_with_require() { + # Args: MAIN_CODE REQUIRES_CSV (e.g., "U1,U2") + local code="$1"; shift || true + local requires_csv="$1"; shift || true + 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" + local extra_args=() + IFS=',' read -r -a REQS <<< "$requires_csv" + for r in "${REQS[@]}"; do + [ -n "$r" ] && extra_args+=("--require-mod" "$r") + done + ( + export NYASH_PARSER_ALLOW_SEMICOLON=1 + export NYASH_ALLOW_USING_FILE=0 + export HAKO_ALLOW_USING_FILE=0 + export NYASH_USING_AST=1 + export HAKO_PARSER_STAGE3=1 + export NYASH_PARSER_STAGE3=1 + export NYASH_VARMAP_GUARD_STRICT=0 + export NYASH_BLOCK_SCHEDULE_VERIFY=0 + NYASH_QUIET=0 HAKO_QUIET=0 NYASH_CLI_VERBOSE=0 \ + "$NYASH_BIN" --backend vm \ + "$NYASH_ROOT/lang/src/compiler/entry/compiler_stageb.hako" -- \ + "${extra_args[@]}" --source "$(cat "$hako_tmp")" + ) > "$raw" 2>&1 || true + if awk '(/"version":0/ && /"kind":"Program"/) {print; found=1; exit} END{exit(found?0:1)}' "$raw" > "$json_out"; then + rm -f "$raw" "$hako_tmp" + echo "$json_out" + return 0 + fi + rm -f "$raw" "$hako_tmp" "$json_out" + return 1 +} + stageb_json_nonempty() { local path="$1" [ -s "$path" ] diff --git a/tools/smokes/v2/profiles/quick/core/core_direct_string_bounds_rc_vm.sh b/tools/smokes/v2/profiles/quick/core/core_direct_string_bounds_rc_vm.sh new file mode 100644 index 00000000..6dcfe1e6 --- /dev/null +++ b/tools/smokes/v2/profiles/quick/core/core_direct_string_bounds_rc_vm.sh @@ -0,0 +1,31 @@ +#!/bin/bash +# core_direct_string_bounds_rc_vm.sh — Core direct path: substring bounds → non‑zero rc + +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='static box Main { method main(args) { local s="abc"; local t=s.substring(-1,1); return 0 } }' +json=$(stageb_compile_to_json "$code") || { echo "[FAIL] core_direct_string_bounds_rc_vm (emit failed)" >&2; exit 1; } + +set +e +NYASH_GATE_C_CORE=1 HAKO_GATE_C_CORE=1 HAKO_CORE_DIRECT=1 \ + NYASH_QUIET=1 HAKO_QUIET=1 NYASH_CLI_VERBOSE=0 NYASH_NYRT_SILENT_RESULT=1 \ + "$NYASH_BIN" --json-file "$json" >/dev/null 2>&1 +rc=$? +set -e +rm -f "$json" + +if [ "$rc" -ne 0 ]; then + echo "[PASS] core_direct_string_bounds_rc_vm" +else + echo "[FAIL] core_direct_string_bounds_rc_vm (rc=$rc)" >&2; exit 1 +fi + diff --git a/tools/smokes/v2/profiles/quick/core/core_direct_string_charat_bounds_rc_vm.sh b/tools/smokes/v2/profiles/quick/core/core_direct_string_charat_bounds_rc_vm.sh new file mode 100644 index 00000000..8eee7f32 --- /dev/null +++ b/tools/smokes/v2/profiles/quick/core/core_direct_string_charat_bounds_rc_vm.sh @@ -0,0 +1,31 @@ +#!/bin/bash +# core_direct_string_charat_bounds_rc_vm.sh — Core Direct: charAt bounds → non‑zero rc + +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='static box Main { method main(args) { local s="abc"; local c=s.charAt(5); return 0 } }' +json=$(stageb_compile_to_json "$code") || { echo "[FAIL] core_direct_string_charat_bounds_rc_vm (emit failed)" >&2; exit 1; } + +set +e +NYASH_GATE_C_CORE=1 HAKO_GATE_C_CORE=1 HAKO_CORE_DIRECT=1 \ + NYASH_QUIET=1 HAKO_QUIET=1 NYASH_CLI_VERBOSE=0 NYASH_NYRT_SILENT_RESULT=1 \ + "$NYASH_BIN" --json-file "$json" >/dev/null 2>&1 +rc=$? +set -e +rm -f "$json" + +if [ "$rc" -ne 0 ]; then + echo "[PASS] core_direct_string_charat_bounds_rc_vm" +else + echo "[FAIL] core_direct_string_charat_bounds_rc_vm (rc=$rc)" >&2; exit 1 +fi + diff --git a/tools/smokes/v2/profiles/quick/core/core_direct_string_replace_ok_vm.sh b/tools/smokes/v2/profiles/quick/core/core_direct_string_replace_ok_vm.sh new file mode 100644 index 00000000..ca92cbd7 --- /dev/null +++ b/tools/smokes/v2/profiles/quick/core/core_direct_string_replace_ok_vm.sh @@ -0,0 +1,27 @@ +#!/bin/bash +# core_direct_string_replace_ok_vm.sh — Core Direct: replace first occurrence + +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='static box Main { method main(args) { local s="a-b-c"; local t=s.replace("-","+"); print(t); return 0 } }' +json=$(stageb_compile_to_json "$code") || { echo "[FAIL] core_direct_string_replace_ok_vm (emit failed)" >&2; exit 1; } + +out=$(NYASH_GATE_C_CORE=1 HAKO_GATE_C_CORE=1 HAKO_CORE_DIRECT=1 \ + NYASH_QUIET=0 HAKO_QUIET=0 NYASH_CLI_VERBOSE=0 \ + "$NYASH_BIN" --json-file "$json" 2>&1) +rm -f "$json" +if echo "$out" | tail -n1 | grep -qx "a+b-c"; then + echo "[PASS] core_direct_string_replace_ok_vm" +else + echo "[FAIL] core_direct_string_replace_ok_vm" >&2; echo "$out" >&2; exit 1 +fi + diff --git a/tools/smokes/v2/profiles/quick/core/core_direct_string_substring_ok_vm.sh b/tools/smokes/v2/profiles/quick/core/core_direct_string_substring_ok_vm.sh new file mode 100644 index 00000000..57d26392 --- /dev/null +++ b/tools/smokes/v2/profiles/quick/core/core_direct_string_substring_ok_vm.sh @@ -0,0 +1,27 @@ +#!/bin/bash +# core_direct_string_substring_ok_vm.sh — Core Direct: substring positive + +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='static box Main { method main(args) { local s="abcdef"; local t=s.substring(2,5); print(t); return 0 } }' +json=$(stageb_compile_to_json "$code") || { echo "[FAIL] core_direct_string_substring_ok_vm (emit failed)" >&2; exit 1; } + +out=$(NYASH_GATE_C_CORE=1 HAKO_GATE_C_CORE=1 HAKO_CORE_DIRECT=1 \ + NYASH_QUIET=0 HAKO_QUIET=0 NYASH_CLI_VERBOSE=0 \ + "$NYASH_BIN" --json-file "$json" 2>&1) +rm -f "$json" +if echo "$out" | tail -n1 | grep -qx "cde"; then + echo "[PASS] core_direct_string_substring_ok_vm" +else + echo "[FAIL] core_direct_string_substring_ok_vm" >&2; echo "$out" >&2; exit 1 +fi + diff --git a/tools/smokes/v2/profiles/quick/core/map/map_clear_reset_vm.sh b/tools/smokes/v2/profiles/quick/core/map/map_clear_reset_vm.sh new file mode 100644 index 00000000..344cd38c --- /dev/null +++ b/tools/smokes/v2/profiles/quick/core/map/map_clear_reset_vm.sh @@ -0,0 +1,38 @@ +#!/bin/bash +# map_clear_reset_vm.sh — Map.clear resets size/has/keys + +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" +require_env || exit 2 + +code=$(cat <<'NY' +static box Main { + main() { + local m = new MapBox(); + m.set("a", 1); m.set("b", 2); + m.clear(); + print(m.size()); + print(m.has("a")); + local ks = m.keys(); + print(ks.size()); + return 0 + } +} +NY +) +out=$(run_nyash_vm -c "$code") +sz=$(echo "$out" | sed -n '1p') +has=$(echo "$out" | sed -n '2p') +ksz=$(echo "$out" | sed -n '3p') +if [ "$sz" = "0" ] && [ "$has" = "false" ] && [ "$ksz" = "0" ]; then + echo "[PASS] map_clear_reset_vm" +else + echo "[FAIL] map_clear_reset_vm" >&2; echo "$out" >&2; exit 1 +fi + diff --git a/tools/smokes/v2/profiles/quick/core/map/map_delete_has_size_vm.sh b/tools/smokes/v2/profiles/quick/core/map/map_delete_has_size_vm.sh new file mode 100644 index 00000000..814ed1c2 --- /dev/null +++ b/tools/smokes/v2/profiles/quick/core/map/map_delete_has_size_vm.sh @@ -0,0 +1,35 @@ +#!/bin/bash +# map_delete_has_size_vm.sh — Map.delete then has/size + +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" +require_env || exit 2 + +code=$(cat <<'NY' +static box Main { + main() { + local m = new MapBox(); + m.set("a", 1); m.set("b", 2); + m.delete("a"); + print(m.has("a")); + print(m.size()); + return 0 + } +} +NY +) +out=$(run_nyash_vm -c "$code") +first=$(echo "$out" | sed -n '1p') +second=$(echo "$out" | sed -n '2p') +if [ "$first" = "false" ] && [ "$second" = "1" ]; then + echo "[PASS] map_delete_has_size_vm" +else + echo "[FAIL] map_delete_has_size_vm" >&2; echo "$out" >&2; exit 1 +fi + diff --git a/tools/smokes/v2/profiles/quick/core/stageb/stageb_bundle_alias_env_ok_vm.sh b/tools/smokes/v2/profiles/quick/core/stageb/stageb_bundle_alias_env_ok_vm.sh new file mode 100644 index 00000000..33ac9f3a --- /dev/null +++ b/tools/smokes/v2/profiles/quick/core/stageb/stageb_bundle_alias_env_ok_vm.sh @@ -0,0 +1,27 @@ +#!/bin/bash +# stageb_bundle_alias_env_ok_vm.sh — Stage‑B: alias via env HAKO_BUNDLE_ALIAS_ + +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 + +main='static box Main { method main(args) { return 0 } }' +alias_code='static box UZ { method id(a){ return a } }' + +export HAKO_BUNDLE_ALIAS_UZ="$alias_code" +json=$(stageb_compile_to_json_with_require "$main" "UZ") || { echo "[FAIL] stageb_bundle_alias_env_ok_vm (emit failed)" >&2; exit 1; } +if [ -s "$json" ] && head -n1 "$json" | grep -q '"version":0' && head -n1 "$json" | grep -q '"kind":"Program"'; then + rm -f "$json"; echo "[PASS] stageb_bundle_alias_env_ok_vm"; exit 0 +else + echo "[FAIL] stageb_bundle_alias_env_ok_vm (missing header)" >&2 + test -f "$json" && head -n1 "$json" >&2 || true + rm -f "$json"; exit 1 +fi + diff --git a/tools/smokes/v2/profiles/quick/core/stageb/stageb_bundle_alias_table_ok_vm.sh b/tools/smokes/v2/profiles/quick/core/stageb/stageb_bundle_alias_table_ok_vm.sh new file mode 100644 index 00000000..76b64d76 --- /dev/null +++ b/tools/smokes/v2/profiles/quick/core/stageb/stageb_bundle_alias_table_ok_vm.sh @@ -0,0 +1,27 @@ +#!/bin/bash +# stageb_bundle_alias_table_ok_vm.sh — Stage‑B: alias table via env (multiple entries) + +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 + +main='static box Main { method main(args) { return 0 } }' +table='U1:static box U1 { method id(a){ return a } }|||U2:static box U2 { method id(a){ return a } }' + +export HAKO_BUNDLE_ALIAS_TABLE="$table" +json=$(stageb_compile_to_json_with_require "$main" "U1,U2") || { echo "[FAIL] stageb_bundle_alias_table_ok_vm (emit failed)" >&2; exit 1; } +if [ -s "$json" ] && head -n1 "$json" | grep -q '"version":0' && head -n1 "$json" | grep -q '"kind":"Program"'; then + rm -f "$json"; echo "[PASS] stageb_bundle_alias_table_ok_vm"; exit 0 +else + echo "[FAIL] stageb_bundle_alias_table_ok_vm (missing header)" >&2 + test -f "$json" && head -n1 "$json" >&2 || true + rm -f "$json"; exit 1 +fi +