Files
hakorune/docs/development/roadmap/phases/phase-21.7-normalization/README.md
nyash-codex a13f14cea0 feat(mir): Phase 21.7 Step 1-2 - NamingBox decode & Hotfix 7修正
## 実装内容

### Step 1: NamingBox decode関数追加 (naming.rs)
-  `decode_static_method(func_name) -> Option<(box, method, arity)>`
-  `is_static_method_name(func_name) -> bool`
- 対称性: encode ⇔ decode のペア実装で一貫性確保

### Step 2: unified_emitter Hotfix 7修正 (Lines 267-304)
-  StaticCompiler box kind判定追加
-  static box method は receiver 追加をスキップ
-  instance method(RuntimeData/UserDefined)のみ receiver 追加
-  トレース: NYASH_STATIC_METHOD_TRACE=1 でログ出力

## 判定ロジック
```rust
if box_kind == CalleeBoxKind::StaticCompiler {
    // "BoxName.method/arity" 形式か確認
    let func_name = format!("{}.{}/{}", box_name, method, args.len());
    if is_static_method_name(&func_name) {
        // static box method → receiver 追加しない
    }
}
```

## 検証
 Stage-1 テスト: RC=0 (apps/tests/stage1_skip_ws_repro.hako)
 ビルド成功(0 error)

## 次のステップ
- Step 3: methodization実装 (HAKO_MIR_BUILDER_METHODIZE=1)

Co-Authored-By: ChatGPT5 <chatgpt@openai.com>
2025-11-21 23:52:10 +09:00

4.3 KiB
Raw Blame History

Phase 21.7 — Normalization & Unification (Methodize Static Boxes)

Goal

  • Unify user-defined function calls onto a single, consistent representation.
  • Move from ad-hoc Global("Box.method") calls toward Method calls with an explicit (singleton) receiver when appropriate.
  • Keep defaults stable; introduce dev toggles and canaries; then promote to default after green.

Scope

  • Parser/StageB: keep emitting Program(JSON v0). No schema changes required for MVP.
  • MirBuilder: add methodization (dev toggle) that:
    • Emits method functions as-is (defs) and/or provides a mapping to Method calls
    • Rewrites Global("Box.method") to Method {receiver=static singleton, box_name, method}
    • Preserves arity and naming as Box.method/N
  • VM: handle Method calls uniformly (receiver resolved via ensure_static_box_instance for static boxes).
  • LLVM: rely on mir_call(Method) lowering (already supported) and provide the static receiver where needed.

Toggles

  • HAKO_MIR_BUILDER_METHODIZE=1 — enable methodization (rewrite Global→Method with static singleton receiver)
  • HAKO_STAGEB_FUNC_SCAN=1 — StageB defs scan (already available)
  • HAKO_MIR_BUILDER_FUNCS=1 — defs→MIR 関数化(既存)
  • HAKO_MIR_BUILDER_CALL_RESOLVE=1 — Global 名解決(既存)

Design Rules

  • Naming: canonical "Box.method/N". Arity N must equal params.len (or callsite args len if defs unknown).
  • Receiver: for static boxes, provide implicit singleton receiver. For instance boxes, preserve existing Method path.
  • Effects: preserve EffectMask semantics; do not broaden side effects.
  • FailFast: when rewrite is ambiguous (multiple candidates), keep original form and WARN under dev toggle; never change defaults silently.

Acceptance

  • Canaries:
    • call (global style) passes when methodization ON (rc unchanged)
    • Existing return/binop/loop/call (global) canaries remain green when OFF
    • A dedicated methodization canary asserts presence of callee.type=="Method" in MIR(JSON v1) or correct v0 lowering

Rollout Plan

  1. Ship behind HAKO_MIR_BUILDER_METHODIZE=1 with canaries
  2. Validate on representative apps (selfhostfirst path)
  3. Promote to default ON only after green for a cycle; keep rollback instructions

Rollback

  • Disable HAKO_MIR_BUILDER_METHODIZE. Revert to Global("Box.method") resolution path (current 21.6 behavior).

Current notes (Phase 25.x bring-up)

  • NamingBox / static 名 SSOT

    • src/mir/naming.rs に NamingBox を実装済み。Main.main / main._nop などの揺れを "Main.main/0" 形式に正規化する経路は Rust VM/LLVM/JSON bridge から既に利用中。
    • VM 側は normalize_static_global_name を通して static box 名を一元化するよう更新済み。
  • 既知のギャップ

    • static box 内のローカル呼び出し(例: Main.mainme._nop())が Global 呼び出しのまま落ちるケースを確認済み。NamingBox で mainMain 正規化は済んでいるが、「Method 化receiver 付与」が未完了。
    • MeCallPolicy / method_call_handlers 周りで、static box method に対しても一律で receivermeを先頭に追加してしまうパスがあり、arity 不一致や miss-call の温床になり得る。
  • このフェーズでやること(具体タスク)

    1. src/mir/builder/method_call_handlers.rs / MeCallPolicy で「static box method かどうか」を判定し、static のときは receiver を追加しないargs はそのまま Global 互換で流す)ガードを入れる。
    2. methodization ロジックHAKO_MIR_BUILDER_METHODIZE=1 有効時で、static box 呼びを ensure_static_box_instance(Box) 経由の Method 呼び出しに寄せる:
      • Global("Main._nop/0") → Method{ receiver = ensure_static_box_instance("Main"), box="Main", method="_nop", arity=0 }。
    3. 最小テストを追加:
      • .hako 側 minimal: static box Main { static method _nop() { return 0 } } を呼ぶケース。
      • Rust 側: mir_stage1_static_main_nop_resolves_and_execsで、MIR verify + VM 実行が methodization ON/OFF の両方で安定することを確認。
    4. docs: 本ファイルに「static box 正規化の完了条件」と「NamingBox / ensure_static_box_instance / MeCallPolicy の責務分担」を 1 ページにまとめ、Phase 21.7 の完了ラインを明文化する。