Stage-B: add --v1-compat opt-in path and smoke

This commit is contained in:
nyash-codex
2025-11-01 03:56:25 +09:00
parent 1f415e733c
commit 4f4ee948e0
6 changed files with 92 additions and 6 deletions

View File

@ -39,7 +39,7 @@ Update — 2025-09-28 (json_query_vm PASS・最終ガード適用)
Update — 2025-10-31 (Phase 20.33 bring-up)
- Stage-A map literal parser hardened空白エスケープ; quick `index_operator_hako` expands coverage。
- Stage-B entry separated (`lang/src/compiler/entry/compiler_stageb.hako`); FlowEntry `emit_v0_from_ast_with_context` (using/extern) を既定採用。opt-in canariesbinop/if/index + nested/boundarygreen with `SMOKES_ENABLE_STAGEB=1`
- Stage-B entry separated (`lang/src/compiler/entry/compiler_stageb.hako`); FlowEntry `emit_v0_from_ast_with_context` (using/extern) を既定採用。`--v1-compat` で MirJsonV1Adapter 経路へ opt-in。opt-in canariesbinop/if/index + nested/boundary、v1
- `nyash.toml` modules updated to expose lang/compiler/shared/vm namespaces for resolver。
- quick profile: 72/72 PASSFileBox 未展開時は SKIP ハンドリング)。

View File

@ -4,6 +4,6 @@
- [x] `ParserBox.parse_program2` → AST JSON を取得Quiet: 1行。StageA map parser は空/空白/エスケープに対応。
- [x] FlowEntry.emit_v0_from_ast_with_contextusing/extern メタを統合)。
- [x] selfhost canaryreturn/binop/if/indexを StageB でも PASSoptin `SMOKES_ENABLE_STAGEB=1` で緑)。
- [ ] v1→v0 降格MirJsonV1Adapter経路を整備必要箇所のみ)。
- [x] v1→v0 降格MirJsonV1Adapter経路を整備`--v1-compat` / `selfhost_stageb_v1_compat_vm` opt-in)。
- [x] tools/smokes/v2/profiles/quick/core/selfhost_* を追加optin。配列ネスト/境界ケースを含む。
- [x] ドキュメント更新README/PLAN/CHECKLIST

View File

@ -9,7 +9,7 @@
1) 入口統合StageB ルートの optin 実装)
- `lang/src/compiler/entry/compiler_stageb.hako` を追加(既定: StageB emit 専用)。
- `ParserBox.parse_program2(src)``FlowEntryBox.emit_v0_from_ast_with_context(..., usings, modules?, externs)` → print 1 行 JSON。
- フラグ: `--prefer-cfg <N>` で pipeline 選好を切替。StageB は using あり / externs あり時の経路を統合済み
- フラグ: `--prefer-cfg <N>` で pipeline 選好を切替。`--v1-compat` で MirJsonV1Adapter 経路を opt-in
2) 代表構文の緑化
- binop/compare/if/index/new/boxcall/externcall を pipeline_v2 で受理できるよう確認。
- StageA canary と同等の selfhost canary を StageB でも PASS。

View File

@ -30,8 +30,10 @@
実装メモ
- StageB エントリを `lang/src/compiler/entry/compiler_stageb.hako` として分離。`FlowEntryBox.emit_v0_from_ast_with_context`using/extern メタを集約)を既定で使う。
- `--v1-compat` を指定すると `FlowEntryBox.emit_v1_compat_from_ast_with_meta` を経由MirJsonV1Adapter 降格)。
- StageA map parser を強化(空/空白/エスケープ対応)。対応済み canary: `index_operator_hako`
- StageB canary は `SMOKES_ENABLE_STAGEB=1` で有効化。binop/if/indexネスト・境界ケース込みを opt-in で検証可能。
- v1 互換 canary `selfhost_stageb_v1_compat_vm.sh``SMOKES_ENABLE_STAGEB_V1=1` で opt-in。
- Module 解決: `nyash.toml` に lang/compiler/shared/vm の論理名を追記し、using resolver から参照可能にした。
マイルストーン

View File

@ -28,7 +28,7 @@ static box StageBMain {
}
_collect_flags(args) {
local flags = { source: null, prefer_cfg: 1, stage3: 0 }
local flags = { source: null, prefer_cfg: 1, stage3: 0, v1_compat: 0 }
if args == null { return flags }
local i = 0
@ -44,6 +44,8 @@ static box StageBMain {
i = i + 1
} else if token == "--stage3" {
flags.stage3 = 1
} else if token == "--v1-compat" {
flags.v1_compat = 1
}
i = i + 1
}
@ -65,8 +67,14 @@ static box StageBMain {
local externs_json = p.get_externs_json()
local ast_json = p.parse_program2(src)
local prefer = flags.prefer_cfg
local jv0 = FlowEntryBox.emit_v0_from_ast_with_context(ast_json, prefer, usings_json, null, externs_json)
if jv0 == null {
local jv0 = null
if flags.v1_compat == 1 {
jv0 = FlowEntryBox.emit_v1_compat_from_ast_with_meta(ast_json, prefer, externs_json)
}
if jv0 == null || jv0 == "" {
jv0 = FlowEntryBox.emit_v0_from_ast_with_context(ast_json, prefer, usings_json, null, externs_json)
}
if jv0 == null || jv0 == "" {
jv0 = FlowEntryBox.emit_v0_from_ast(ast_json, prefer)
}
// Attach usings metadata when availableStage-B pipeline consumes via resolver

View File

@ -0,0 +1,76 @@
#!/bin/bash
# selfhost_stageb_v1_compat_vm.sh — Stage-B emit via MirJsonV1Adapter opt-in canary
set -uo 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
HAKO_BIN_DEFAULT="$ROOT/tools/bin/hako"
HAKO_BIN="${HAKO_BIN:-$HAKO_BIN_DEFAULT}"
warn() { echo -e "[WARN] $*" >&2; }
info() { echo -e "[INFO] $*" >&2; }
pass() { echo -e "[PASS] $*" >&2; }
fail() { echo -e "[FAIL] $*" >&2; return 1; }
skip() { echo -e "[SKIP] $*" >&2; exit 0; }
if [ "${SMOKES_ENABLE_STAGEB_V1:-0}" != "1" ]; then
skip "SMOKES_ENABLE_STAGEB_V1!=1; skipping Stage-B v1 compat canary"
fi
if [ ! -x "$HAKO_BIN" ]; then
warn "Hako binary not found: $HAKO_BIN (set HAKO_BIN to override)"
skip "hako binary missing"
fi
compile_stageb_v1() {
local code="$1"
local tmp_hako="/tmp/hako_stageb_v1_$$.hako"
local json_out="/tmp/hako_stageb_v1_$$.mir.json"
printf "%s\n" "$code" > "$tmp_hako"
local raw="/tmp/hako_stageb_v1_raw_$$.txt"
NYASH_PARSER_ALLOW_SEMICOLON=1 \
NYASH_SYNTAX_SUGAR_LEVEL=full \
NYASH_ENABLE_ARRAY_LITERAL=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_PHI_VERIFY=0 \
NYASH_QUIET=1 HAKO_QUIET=1 NYASH_CLI_VERBOSE=0 \
"$ROOT/target/release/nyash" --backend vm \
"$ROOT/lang/src/compiler/entry/compiler_stageb.hako" -- --v1-compat --source "$(cat "$tmp_hako")" > "$raw" 2>&1
awk '/"version":0/ && /"kind":"Program"/ {print; exit}' "$raw" > "$json_out"
rm -f "$raw" "$tmp_hako"
if [ ! -s "$json_out" ]; then
warn "Stage-B v1 compat compilation failed"
rm -f "$json_out"
return 1
fi
echo "$json_out"
return 0
}
run_gate_c() {
local json_path="$1"
NYASH_QUIET=1 HAKO_QUIET=1 NYASH_CLI_VERBOSE=0 NYASH_NYRT_SILENT_RESULT=1 \
out="$("$ROOT/target/release/nyash" --json-file "$json_path" 2>&1)"
printf '%s\n' "$out" | awk '/^(✅|ResultType|Result:)/{next} NF{last=$0} END{ if(last) print last }'
local rc=$?
rm -f "$json_path"
return $rc
}
info "Stage-B v1 compat: return literal"
json_path=$(compile_stageb_v1 'box Main { static method main() { return 42; } }') || skip "Stage-B v1 compat compilation not available"
out=$(run_gate_c "$json_path")
if [ "$out" = "42" ]; then
pass "stageb_v1_return"
else
printf 'Expected: 42\nActual: %s\n' "$out" >&2
fail "stageb_v1_return"
fi
exit 0