Files
hakorune/docs/private/roadmap/phases/phase-20.33

Phase 20.33 — Hakorune コンパイラ完成StageB 本線)

目的

  • Hakorune 製コンパイラを「実用レベル」へ引き上げるStageB
  • Rust ラインの意味論を変えず、Ny→JSON v0必要に応じて v1→v0を安定出力。
  • 既存 Runner/VM/LLVMllvmlite, ny-llvmcと確実に連携する。

非目標(本フェーズ外)

  • 大規模最適化MIR 前処理/LLVM最適化/ベンチ高速化)は Phase20.31 継続タスク。
  • Runner の全面移行Phase20.32 にて段階導入)。

設計原則

  • BoxFirst / FailFast / 仕様不変Rust ラインの意味論は維持)。
  • 既定 OFF の新トグル。既定挙動は CI/quick 緑のまま。
  • JSON v0 は 1 行出力Quiet

スコープStageB

  • ParserBoxStage2/3→ pipeline_v2 → FlowEntryemit-only
  • 対応ノード(優先度順)
    • 必須: const/binop/compare/if/branch/jump/ret/new/boxcall/externcall
    • 実用: load/store/phi/copy/unary/typeop
    • 先送り: lambda/async/match形状のみ or SKIP
  • v1 互換: MirCallv1→ MirJsonV1Adapter で v0 に降格(当面の橋渡し)

受け入れ基準

  • JSON v0 canaryHako: return/binop/if/indexarray/map/whitespace緑。
  • RunnerGateCで v0 を読み VM 実行 → Rust ラインと同じ出力。
  • ny-llvmcllvmliteで v0→EXE 生成が最小ケースで PASS。
  • 既定 OFF のため quick/integration は回帰なし。

実装メモ

  • StageB エントリを lang/src/compiler/entry/compiler_stageb.hako として分離。FlowEntryBox.emit_v0_from_ast_with_contextusing/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.shSMOKES_ENABLE_STAGEB_V1=1 で opt-in。
  • GateC(Core) wrapper トグル: HAKO_NYVM_CORE=1alias NYASH_NYVM_CORE)で canonicalize→NyVmDispatcher 経路を準備(現状は JSON 正規化のみ、NyVmDispatcher 実行は今後のタスク)。
  • Module 解決: nyash.toml に lang/compiler/shared/vm の論理名を追記し、using resolver から参照可能にした。

マイルストーン

  1. 入口統一
    • Main.main → ParserBox.parse → pipeline_v2 → FlowEntry.emit_v0 で 1 行 JSON 出力。
    • NYASH_JSON_ONLY=1 下で静音保証。
  2. 代表構文の対応
    • binop/compare/if/index/new/boxcall/externcall を優先実装。
    • 既存 StageA の canarybinop/if/indexを StageB でも緑化。
  3. v1→v0 アダプタ
    • pipeline_v2 が v1MirCallを出す経路を活かし、Adapter で v0 へ降格。
  4. スモーク整備
    • tools/smokes/v2/profiles/quick/core/selfhost_* を追加optin
  5. ドキュメント
    • 本 README / PLAN / CHECKLIST を維持更新。

リスクと対策

  • 仕様すり替え禁止: Runner/VM/LLVM の意味論差が出たら FailFast。
  • ノイズ: NYASH_QUIET=1 HAKO_QUIET=1 NYASH_CLI_VERBOSE=0 をデフォルトで injectemit 経路)。

参考

  • lang/src/compiler/pipeline_v2/*
  • lang/src/compiler/entry/compiler.hako入口
  • lang/src/shared/json/mir_v1_adapter.hako
  • src/runner/json_v0_bridge/*Rust 側 v0 ブリッジ)

不足機能(現状のギャップ)

  • GateC(Core) v1 経路は実装済みMIR Interpreter 直行)

    • 現状: HAKO_NYVM_CORE=1 時に v1(JSON) を json_v1_bridgeMirModule へ変換し、MIR Interpreter で実行const/binop/compare/branch/jump/phi 対応)。
    • NyVmDispatcher 直行は別タスクとして扱う既定OFF・将来対応
  • 静的Boxの Singletonself規約の明文化と整備

    • 背景: 静的Boxのメソッドは「先頭に selfSingletonを持つ」前提。MIR/Verifier もこの arity を期待する。
    • 現状: 一部の LLVM 命令Box相当例: LLVMPhiInstructionBox.lower_phi 等)が self 非対応の設計で呼び出されるケースがあり、Verifier が「Singleton+引数…」の期待と不一致になる。
    • 対応: 本フェーズで「メソッド定義側を self 先頭に揃える」ことを原則とし、互換が必要な経路には HAKO_BRIDGE_INJECT_SINGLETON=1opt-inで受理・補完する。
    • FailFast: 期待 arity と不一致の呼び出しは静かなフォールバックを行わず、安定化メッセージで失敗させる。
  • v1→v0 ダウングレードRunner 側)が未実装(任意)

    • 代表命令const/binop/compare/ret/branch/jump/phiの最小降格を HAKO_NYVM_V1_DOWNCONVERT=1 で optin。
    • 未対応命令は FailFast。Core 直行が有効な場合は直行を優先。
  • Bridge 正規化トグルの中身が未実装

    • HAKO_BRIDGE_INJECT_SINGLETON / HAKO_BRIDGE_EARLY_PHI_MATERIALIZE は env のみ存在。実際の補完・整列は未実装。
    • 仕様確定後に JSON 編集(受信モジュール内の命令配列へ最小差分)を実装する。

Bridge 正規化 仕様(案/このフェーズで凍結)

  • 目的: GateC(Wrapper) 経路で v1 形状の JSON を安全に Core/VM で実行可能な形に最小正規化する。
  • トグル既定OFF・FailFast優先
    • HAKO_BRIDGE_INJECT_SINGLETONalias NYASH_BRIDGE_INJECT_SINGLETON
      • 対象: ModuleFunction/Method で receiver が明示されない「静的呼び出し風」の形。
      • 変換(最小):
        • 形状: ModuleFunction { name: "ArrayBox.len" , args:[X] }Method { receiver:X, method:"size" }
        • 形状: ModuleFunction { name: "MapBox.len" , args:[X] }Method { receiver:X, method:"len" }
        • 形状: ModuleFunction { name: "LLVMPhiInstructionBox.lower_phi", args:[dst,incoming] }Method { receiver:Singleton(LLVMPhiInstructionBox), method:"lower_phi", args:[dst,incoming] }将来の静的Box命令群に一般化
        • 前提: args が 1 要素の数値レジスタID。それ以外は変換せず Fail。
        • 変換は命令 JSON の当該オブジェクトのみを書き換え、周囲の命令順や値定義順には触れない。
        • 未対応: push/pop/get/set の ModuleFunction 形(将来拡張)。
    • HAKO_BRIDGE_EARLY_PHI_MATERIALIZEalias NYASH_BRIDGE_EARLY_PHI_MATERIALIZE
      • 対象: ブロック内で φ 命令が先頭以外に出現する形、または φ と非φ が交差している形。
      • 変換(最小):
        • 同一ブロック内で φ 命令列を先頭に移動(相対順は保持)。
        • 非φ 命令列は元順序を保持するusebeforedef を避けるための再順序付けは行わない)。
        • 追加のコピー挿入edge copy 合成)は行わない。必要なら Fail。
      • 失敗時: 安定化したエラーメッセージで FailFast静かなフォールバック禁止

注: 上記はいずれも「既定OFF」。Runner での v1 受理は 1) 直行NyVmDispatcher/Core 2) 最小ダウングレードv1→v0, 任意の順で選好し、Bridge 正規化は Wrapper 経路の補助として段階導入する。

  • GateCfile/pipe× Plugins ON/OFF の対称性検証が未整備

    • 数値出力とプロセス終了コードの一致rc=出力数値)の保証スモークを追加する。
  • StageA map リテラルの堅牢化の残り

    • エスケープや Unicode、空マップ {}、不正形(診断)などの追加ケースを補強する。
  • スモーク実行権限の不足

    • 一部 tools/smokes/v2/profiles/quick/core/*.sh が実行不可のまま。chmod +x を反映する。
  • 参照の古い表記が残存

    • hako.toml のコメントや docs に apps/selfhost-compiler の表記が散見。lang/src/compiler/* 基準に置換(履歴の文脈が必要な箇所は注記)。
  • ランナー子環境ヘルパーの集約が未完

    • selfhost 子プロセス向け ENV セットの重複を helper に寄せるタスクが残り。
  • Extern SSOTVM/AOT 共有ローダ)が未導入(最小)

    • VM/AOT 双方で参照する単一起点を用意既定OFF、optin

このフェーズの次アクション(短期)

  • GateC 実行切替v1直行/トグル配下)と対称性スモークの追加。
  • Bridge トグルの実装方針を SPEC 化Singleton 注入ルール / φ 整列の期待形)。
  • スモークの権限整備と StageA/StageB の追加境界ケース投入。

現状ステータス20251101 更新)

  • GateC v1 経路:
    • Runner 側で HAKO_NYVM_CORE=1 / NYASH_NYVM_CORE=1 を検知すると、v1(JSON) を Rust の json_v1_bridgeMirModule に変換し、MIR Interpreter で直接実行する経路が完成const/binop/compare/branch/jump/phi 対応)。
    • 子プロセス経路は撤退(call 依存なし)。
  • v1→v0 ダウングレード:
    • HAKO_NYVM_V1_DOWNCONVERT=1alias NYASH_NYVM_V1_DOWNCONVERTで同じコンバータを使用し、v1 JSON を MIR Interpreter へ降格FailFast
  • Bridge トグル:
    • INJECT_SINGLETON/EARLY_PHI_MATERIALIZE を実装既定OFF。Array/Map len 変換と φ 先頭化のみ対応済み。未対応は Fail。
  • スモーク:
    • GateC v1 parityfile/pipe × plugins ON/OFFの optin スモーク(SMOKES_ENABLE_GATE_C_V1=1)。
    • StageA map 境界(エスケープ/Unicode/空)スモーク追加(診断含め PASS

直近のフォロー

  • 変換器は最小命令セットのみ対応mir_call/extern 等は Fail。対応範囲を広げる場合は json_v1_bridge に実装を追加。