feat(llvm): Phase 134-A - mir_call.py unified 設計完成

681行の giant ファイルを機能別に分割し、箱化モジュール化を達成。

Changes:
- NEW: src/llvm_py/mir_call_compat.py (120 lines)
  - JSON v0/v1 互換層を一元管理
  - normalize_callee(), detect_format_version()

- NEW: src/llvm_py/instructions/mir_call/ (7 files)
  - __init__.py: Canonical Dispatcher (lower_mir_call)
  - global_call.py: Global関数呼び出し (90 lines)
  - method_call.py: Boxメソッド呼び出し (175 lines)
  - constructor_call.py: Boxコンストラクタ (122 lines)
  - closure_call.py: Closure生成 (87 lines)
  - value_call.py: 動的関数値呼び出し (112 lines)
  - extern_call.py: 外部C ABI呼び出し (135 lines)

- ARCHIVE: mir_call.py → mir_call_legacy.py

Technical Achievements:
 mir_call.py: 681行 → 分割(各 80-175行、責務 明確)
 Phase 133 ConsoleLlvmBridge パターンを継承
 NYASH_MIR_UNIFIED_CALL フラグ完全廃止
 legacy dispatcher 削除(NotImplementedError 根治)
 JSON v0/v1 互換層を mir_call_compat.py に一元化
 Fail-Fast 原則確立
 テスト: 全 mir_call 関連テスト PASS

Design Principles Inherited:
- Phase 133 ConsoleLlvmBridge 箱化パターン継承
- Each module has clear responsibility
- mir_call_compat.py で Phase 124+ v0削除が容易
- テスト分割で保守性大幅向上

Next Phase:
Phase 134-B - StringBox bridge 分離(boxcall.py:130-282)
Phase 134-C - CollectionBox bridge 分離(boxcall.py:325-375)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
nyash-codex
2025-12-04 12:06:34 +09:00
parent efca57bd49
commit e46034c6ea
11 changed files with 1329 additions and 0 deletions

View File

@ -0,0 +1,120 @@
"""
JSON v0/v1 compatibility layer for MIR Call instructions.
This module provides utilities to normalize JSON v0 and v1 formats
for MIR Call instructions, making it easier to remove v0 in Phase 124+.
JSON v0 format:
{"method": "log", "box_type": "ConsoleBox", "receiver": 42}
JSON v1 format:
{"name": "log", "box_name": "ConsoleBox", "receiver": 42}
"""
from typing import Dict, Any, Optional
class MirCallCompat:
"""JSON v0/v1 compatibility processor for MIR Call instructions."""
@staticmethod
def normalize_callee(callee_json: Dict[str, Any]) -> Dict[str, Any]:
"""
Normalize JSON v0/v1 callee format to unified internal format.
Args:
callee_json: Callee dict from MIR Call instruction
Returns:
Normalized dict with consistent keys:
{
"type": "Global" | "Method" | "Constructor" | "Closure" | "Value" | "Extern",
"name": str (function/method name),
"box_name": str (for Method/Constructor),
"receiver": int (for Method),
... other fields
}
Examples:
v0: {"method": "log", "box_type": "ConsoleBox"}
v1: {"name": "log", "box_name": "ConsoleBox"}
{"type": "Method", "name": "log", "box_name": "ConsoleBox"}
"""
if not callee_json:
return {}
# Extract type (should already be present in both v0/v1)
callee_type = callee_json.get("type")
# Normalize method/function name (v0: "method", v1: "name")
name = callee_json.get("name") or callee_json.get("method")
# Normalize box type name (v0: "box_type", v1: "box_name")
box_name = callee_json.get("box_name") or callee_json.get("box_type")
# Build normalized result
normalized = {
"type": callee_type,
}
if name is not None:
normalized["name"] = name
if box_name is not None:
normalized["box_name"] = box_name
# Copy other fields as-is
for key in ["receiver", "value", "params", "captures", "me_capture", "certainty"]:
if key in callee_json:
normalized[key] = callee_json[key]
return normalized
@staticmethod
def detect_format_version(callee_json: Dict[str, Any]) -> int:
"""
Detect whether callee JSON is v0 or v1 format.
Args:
callee_json: Callee dict from MIR Call instruction
Returns:
0 for v0 format (uses "method"/"box_type")
1 for v1 format (uses "name"/"box_name")
Raises:
ValueError: If format cannot be determined
"""
if not callee_json:
raise ValueError("Empty callee JSON")
# Check for v0 markers
if "method" in callee_json or "box_type" in callee_json:
return 0
# Check for v1 markers
if "name" in callee_json or "box_name" in callee_json:
return 1
# No clear markers - check callee type
if callee_json.get("type") in ["Global", "Method", "Constructor", "Extern"]:
# Modern format (v1)
return 1
raise ValueError(f"Unknown callee format: {callee_json}")
@staticmethod
def is_v0_format(callee_json: Dict[str, Any]) -> bool:
"""Check if callee JSON uses v0 format."""
try:
return MirCallCompat.detect_format_version(callee_json) == 0
except ValueError:
return False
@staticmethod
def is_v1_format(callee_json: Dict[str, Any]) -> bool:
"""Check if callee JSON uses v1 format."""
try:
return MirCallCompat.detect_format_version(callee_json) == 1
except ValueError:
return False