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:
15
apps/tests/phase217_methodize_test.hako
Normal file
15
apps/tests/phase217_methodize_test.hako
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user