diff --git a/CURRENT_TASK.md b/CURRENT_TASK.md index 4a7cf2c1..05b3f7f4 100644 --- a/CURRENT_TASK.md +++ b/CURRENT_TASK.md @@ -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 canaries(binop/if/index + nested/boundary)green 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 canaries(binop/if/index + nested/boundary、v1)緑。 - `nyash.toml` modules updated to expose lang/compiler/shared/vm namespaces for resolver。 - quick profile: 72/72 PASS(FileBox 未展開時は SKIP ハンドリング)。 diff --git a/docs/private/roadmap/phases/phase-20.33/CHECKLIST.md b/docs/private/roadmap/phases/phase-20.33/CHECKLIST.md index 95190c1f..b3fb496d 100644 --- a/docs/private/roadmap/phases/phase-20.33/CHECKLIST.md +++ b/docs/private/roadmap/phases/phase-20.33/CHECKLIST.md @@ -4,6 +4,6 @@ - [x] `ParserBox.parse_program2` → AST JSON を取得(Quiet: 1行)。Stage‑A map parser は空/空白/エスケープに対応。 - [x] FlowEntry.emit_v0_from_ast_with_context(using/extern メタを統合)。 - [x] selfhost canary(return/binop/if/index)を Stage‑B でも PASS(opt‑in `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_* を追加(opt‑in)。配列ネスト/境界ケースを含む。 - [x] ドキュメント更新(README/PLAN/CHECKLIST)。 diff --git a/docs/private/roadmap/phases/phase-20.33/PLAN.md b/docs/private/roadmap/phases/phase-20.33/PLAN.md index 13c8d54b..3bbf5c0c 100644 --- a/docs/private/roadmap/phases/phase-20.33/PLAN.md +++ b/docs/private/roadmap/phases/phase-20.33/PLAN.md @@ -9,7 +9,7 @@ 1) 入口統合(Stage‑B ルートの opt‑in 実装) - `lang/src/compiler/entry/compiler_stageb.hako` を追加(既定: Stage‑B emit 専用)。 - `ParserBox.parse_program2(src)` → `FlowEntryBox.emit_v0_from_ast_with_context(..., usings, modules?, externs)` → print 1 行 JSON。 - - フラグ: `--prefer-cfg ` で pipeline 選好を切替。Stage‑B は using あり / externs あり時の経路を統合済み。 + - フラグ: `--prefer-cfg ` で pipeline 選好を切替。`--v1-compat` で MirJsonV1Adapter 経路を opt-in。 2) 代表構文の緑化 - binop/compare/if/index/new/boxcall/externcall を pipeline_v2 で受理できるよう確認。 - Stage‑A canary と同等の selfhost canary を Stage‑B でも PASS。 diff --git a/docs/private/roadmap/phases/phase-20.33/README.md b/docs/private/roadmap/phases/phase-20.33/README.md index de3d2cb6..b666f1e2 100644 --- a/docs/private/roadmap/phases/phase-20.33/README.md +++ b/docs/private/roadmap/phases/phase-20.33/README.md @@ -30,8 +30,10 @@ 実装メモ - Stage‑B エントリを `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 降格)。 - Stage‑A map parser を強化(空/空白/エスケープ対応)。対応済み canary: `index_operator_hako` - Stage‑B 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 から参照可能にした。 マイルストーン diff --git a/lang/src/compiler/entry/compiler_stageb.hako b/lang/src/compiler/entry/compiler_stageb.hako index b869cea4..0c7bbc62 100644 --- a/lang/src/compiler/entry/compiler_stageb.hako +++ b/lang/src/compiler/entry/compiler_stageb.hako @@ -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 available(Stage-B pipeline consumes via resolver) diff --git a/tools/smokes/v2/profiles/quick/core/selfhost_stageb_v1_compat_vm.sh b/tools/smokes/v2/profiles/quick/core/selfhost_stageb_v1_compat_vm.sh new file mode 100644 index 00000000..e6dfeb7b --- /dev/null +++ b/tools/smokes/v2/profiles/quick/core/selfhost_stageb_v1_compat_vm.sh @@ -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