feat(mir): Phase 21.7 Step 3 - Methodization実装完了

🎯 Global("BoxName.method/arity") → Method{receiver=singleton} 変換

実装内容:
1. builder.rs: static_box_singletons フィールド追加
   - BoxName → ValueId マッピングでシングルトン管理
2. unified_emitter.rs: methodization ロジック実装
   - HAKO_MIR_BUILDER_METHODIZE=1 で有効化
   - decode_static_method() でstatic box method判定
   - singleton instance を NewBox で生成(キャッシュ済み)
   - Callee::Global → Callee::Method 変換

動作確認:
- デフォルト(OFF): call_global Calculator.add/2 (既存挙動維持)
- トグル(ON): new Calculator → call %singleton.add (methodization)
- RC=0 両モード動作確認済み

テスト:
- apps/tests/phase217_methodize_test.hako 追加
- [methodize] Global(...) → Method{...} トレース出力

環境変数:
- HAKO_MIR_BUILDER_METHODIZE=1: methodization 有効化
- NYASH_METHODIZE_TRACE=1: 変換ログ出力

Phase 21.7 Step 3 完了!🎊
次: ドキュメント更新
This commit is contained in:
nyash-codex
2025-11-22 00:00:51 +09:00
parent a13f14cea0
commit b5cd05c27a
3 changed files with 73 additions and 0 deletions

View File

@ -0,0 +1,15 @@
// Phase 21.7: Methodization test
// Tests Global("BoxName.method/arity") → Method{receiver=singleton} conversion
static box Calculator {
add(a, b) {
return a + b
}
main() {
// This will be called as Global("Calculator.add/2") by default
// With HAKO_MIR_BUILDER_METHODIZE=1, it becomes Method{Calculator.add, recv=singleton}
print("Result: " + ("" + Calculator.add(10, 20)))
return 0
}
}

View File

@ -221,6 +221,12 @@ pub struct MirBuilder {
/// - Some(true): App mode (static box Main.main is entry) /// - Some(true): App mode (static box Main.main is entry)
/// - Some(false): Script/Test mode (top-level Program runs sequentially) /// - Some(false): Script/Test mode (top-level Program runs sequentially)
pub(super) root_is_app_mode: Option<bool>, pub(super) root_is_app_mode: Option<bool>,
/// 🎯 Phase 21.7: Static box singleton instances for methodization
/// Maps BoxName → ValueId of singleton instance (created on demand)
/// Used when HAKO_MIR_BUILDER_METHODIZE=1 to convert Global("BoxName.method/arity")
/// to Method{receiver=singleton} calls
pub(super) static_box_singletons: HashMap<String, ValueId>,
} }
impl MirBuilder { impl MirBuilder {
@ -282,6 +288,7 @@ impl MirBuilder {
in_unified_boxcall_fallback: false, in_unified_boxcall_fallback: false,
recursion_depth: 0, recursion_depth: 0,
root_is_app_mode: None, root_is_app_mode: None,
static_box_singletons: HashMap::new(), // Phase 21.7: methodization support
} }
} }

View File

@ -173,6 +173,57 @@ impl UnifiedCallEmitterBox {
} }
}; };
// 🎯 Phase 21.7: Methodization (HAKO_MIR_BUILDER_METHODIZE=1)
// Convert Global("BoxName.method/arity") → Method{receiver=static singleton}
if std::env::var("HAKO_MIR_BUILDER_METHODIZE").ok().as_deref() == Some("1") {
if let Callee::Global(ref name) = callee {
let name_clone = name.clone(); // Clone to avoid borrow checker issues
// Try to decode as static box method
if let Some((box_name, method, arity)) = crate::mir::naming::decode_static_method(&name_clone) {
// Check if arity matches provided args
if arity == args.len() {
// Get or create static box singleton instance
let singleton = if let Some(&existing) = builder.static_box_singletons.get(box_name) {
existing
} else {
// Create new singleton instance
let singleton_id = builder.next_value_id();
builder.emit_instruction(MirInstruction::NewBox {
dst: singleton_id,
box_type: box_name.to_string(),
args: Vec::new(), // Static box singleton, no constructor args
})?;
// Register type information
builder.value_types.insert(
singleton_id,
crate::mir::MirType::Box(box_name.to_string()),
);
builder.value_origin_newbox.insert(singleton_id, box_name.to_string());
// Cache for future use
builder.static_box_singletons.insert(box_name.to_string(), singleton_id);
singleton_id
};
// Convert to Method call
callee = Callee::Method {
box_name: box_name.to_string(),
method: method.to_string(),
receiver: Some(singleton),
certainty: crate::mir::definitions::call_unified::TypeCertainty::Known,
box_kind: crate::mir::definitions::call_unified::CalleeBoxKind::StaticCompiler,
};
if std::env::var("NYASH_METHODIZE_TRACE").ok().as_deref() == Some("1") {
eprintln!(
"[methodize] Global({}) → Method{{{}.{}, recv=%{}}}",
name_clone, box_name, method, singleton.0
);
}
}
}
}
}
// Structural guard FIRST: prevent static compiler boxes from being called with runtime receivers // Structural guard FIRST: prevent static compiler boxes from being called with runtime receivers
// 箱理論: CalleeGuardBox による構造的分離 // 箱理論: CalleeGuardBox による構造的分離
// (Guard may convert Method → Global, so we check BEFORE materializing receiver) // (Guard may convert Method → Global, so we check BEFORE materializing receiver)