Files
hakorune/docs/development/roadmap/phases/phase-25.1c/README.md

88 lines
7.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Phase 25.1c — Env / Extern / BoxIntrospect Structural Cleanup
Status: planning構造整理フェーズ・挙動は変えない
## ゴール
- `env.*` / `hostbridge.*` / `env.box_introspect.*` の責務と経路を整理し、型システムまわりの「正しい入口」を 1 箇所に揃える。
- Box 型情報 API`env.box_introspect.kind` + `BoxTypeInspectorBox`)を **コア型システム**として扱えるようにするplugins の有無に依存しない)。
- i64 / MapBox / ArrayBox の unwrap ロジックを SSOT に寄せ、MirBuilder / JsonEmit / LoopOpts / BoxHelpers が同じ前提で動くようにする。
## スコープ(何をここで扱うか)
- 対象:
- Rust 側: `extern_registry.rs` / `handlers/externals.rs` / `handlers/extern_provider.rs` / `runtime/plugin_loader_v2/*`
- Hako 側: `BoxTypeInspectorBox` / `BoxHelpers` / `JsonEmitBox` / `MirSchemaBox` / `LoopOptsBox`
- ドキュメント: `docs/specs`env externs / box_introspect / numeric view の設計メモ)
- 非対象:
- 新しい言語機能や VM 命令の追加Phase 25 ポリシーに従い、仕様拡張はしない)。
- MirBuilder の意味論変更multicarrier や LoopForm の設計は Phase 25.1b の範囲に留める)。
## やりたい整理(タスクリスト)
1. **env.* extern の SSOT を決める**
- `env.get` / `env.mirbuilder.emit` / `env.codegen.emit_object` / `env.codegen.link_object` / `env.box_introspect.kind` を一覧化し、仕様引数・戻り値・MIR 形)を `docs/specs/env_externs.md`(仮)に明文化する。
- JSON v0 → MIR ブリッジ(`MapVars::resolve` / loweringで、上記が必ず `ExternCall("env.*", ..)` に落ちることを確認・修正する。
2. **hostbridge.extern_invoke を「互換レイヤ」に押し込める**
- 方針: 「`env.*` で表現できるものは ExternCall を正義とし、`hostbridge.extern_invoke` は互換用ラッパに限定する」。
- Hako 側: `hostbridge.extern_invoke("env.*", ..)` は内部で `env.*` を呼ぶだけにする(新規コードは直接 `env.*` を使う)。
- Rust 側: `"hostbridge.extern_invoke"` の実装は、`extern_provider_dispatch("env.*", ..)` に委譲する薄いブリッジに整理する。
3. **BoxIntrospect をコア型システムに昇格させる**
- `env.box_introspect.kind` の実装を plugin loader v2 直下ではなく、コア runtime例: `runtime/box_introspect.rs`)に寄せる。
- コア型MapBox / ArrayBox / StringBox / IntegerBox / BoolBox / NullBoxは runtime 側で `build_box_info` を定義し、plugin loader は「ユーザー Box の拡張」だけを担当する。
- `BoxTypeInspectorBox``env.box_introspect.kind(value)` を唯一の情報源として扱い、repr ベースの fallback は「plugins も env.* も使えないデバッグ環境のみ」で使うことをコメントで明示する。
4. **Numeric viewi64 unwrapの SSOT 化**
- Hako 側: `string_helpers` / `BoxHelpers` / `MirSchemaBox` / `JsonEmitBox` / `LoopOptsBox` に散っている i64 unwrap ロジックを、小さなユーティリティ(仮: `box_numeric_view.hako`)に寄せる。
- Rust 側: `NyashBox` から i64 を取り出す `as_i64` 的な関数を 1 箇所に置き、extern / BoxIntrospect 経路からはそれを使う。
5. **StageB Main を箱に分割して SSA/デバッグを軽くする**
- 現状の `compiler_stageb.hako: Main.main` は:
- CLI 引数パース (`--source` / `--bundle-*` / `--require-mod`)
- bundle/require 解決 (`BundleResolver`)
- body 抽出 (`body_src` の抽出ロジック)
- ParserBox 呼び出し (`parse_program2` → emit JSON)
- defs スキャン (`FuncScannerBox.scan_all_boxes`)
が 1 関数に詰め込まれており、MIR 上でも巨大な `Main.main` になっている。
- 25.1c ではこれを「箱理論」に沿って分割する:
- `StageBArgsBox`CLI 引数と bundle/require の扱いだけを担当)
- `StageBBodyExtractorBox``body_src` 抽出ロジックだけを担当)
- `StageBDriverBox`ParserBox/FuncScannerBox を呼んで Program(JSON v0) を emit
- Rust 側 MirBuilder には、この箱ごとの小さな関数をそのまま MIR に落とさせることで、`Main.main` の SSA/Loop の複雑さを減らし、今回のような ValueId 追跡をしやすくする。
- 併せて、現状 selfhost CLI サンプルで観測されている `Main.main` 内の `ParserBox.length()` 呼び出しに対する recv 未定義エラー(`Invalid value: use of undefined value ValueId(17)`を、StageB Main 分割LocalSSA/LoopBuilder 整理の一環として根本修正するMethodCall の recv にも SSA/verify を適用する)。
6. **LoopBuilder / pin スロットの型付け・箱化**
- いまの LoopBuilder は `__pin$*$@recv` のような文字列ベースの「内部変数名」を `variable_map` に直接突っ込んで、SSA/phi/pin を管理している。
- 25.1c では、Loop 状態を「箱」として切り出して型付けする:
- 例: `LoopStateBox`Rust 側構造体)に
- `recv_slots`Method receiver 用)
- `index_slots`(ループカウンタ用)
- `limit_slots`limit/上限 expr 用)
を明示的に持たせる。
- `LoopBuilder::emit_phi_at_block_start` / `update_variable` は、この LoopStateBox を通じてのみ pin/phi を操作し、「recv に Null/未定義が混ざらない」ことを構造レベルで保証する。
7. **ビルダー観測用の専用レイヤ(デバッグ箱)**
- すでに `NYASH_BUILDER_TRACE_RECV` / `NYASH_BUILDER_DEBUG` などで ad-hoc に eprintln を入れているが、出力箇所が複数ファイルに散っていて再利用しにくい。
- 25.1c ではこれを `builder.observe` 的なモジュール(箱)に集約する:
- 例: `observe::recv::log(fn, bb, name, src, dst)``observe::phi::log(fn, bb, dst, inputs)` など。
- ポリシー:
- すべて dev トグルNYASH_BUILDER_TRACE_*)越しに呼ぶ。
- 本番挙動は変えず、「どこをどうトレースできるか」を構造として明示する。
8. **StageB 向けの極小 MIR 再現ハーネス**
- `docs/private/roadmap/phases/phase-20.33/DEBUG.md` にあるような StageB 向けメモを踏まえ、StageB/MirBuilder 用の「極小 Hako → MIR テスト」を 1 つ用意する。
- 例:
- 100〜200 行程度の `.hako``lang/src/compiler/tests/stageb_min_sample.hako` のようなファイルに固定。
- Rust 側で MirBuilder に直接その AST を食わせて MIR を生成し、`NYASH_VM_VERIFY_MIR=1` で「Undefined value」が出ないことを確認するユニットスモークを足す構造バグ検知用
- これにより、StageB/LoopBuilder に関する修正が `.hako` 本番コード全体に依存せず、小さな再現ケースで検証できるようにする。
## 進め方メモ
- 先にドキュメントを書くenv extern / BoxIntrospect / numeric view の仕様を `docs/specs` 配下に整理)→ そのあとで Bridge / VM / Hako を小さく揃える。
- 既存フェーズとの関係:
- Phase 25.1b: selfhost builder / multicarrier / BoxTypeInspector 実装フェーズ(機能側)。
- Phase 25.1c: そのうち「env.* / hostbridge.* / BoxIntrospect」に加えて、StageB Main / LoopBuilder / builder 観測レイヤの構造と責務も整理するメタフェーズ(構造側)。
- 挙動を変えないことFailFast / default path は現状維持)を前提に、小さな差分で進める。