Files
hakorune/src/mir/builder/calls/call_unified.rs
Selfhosting Dev 2f306dd6a5 feat: 大規模リファクタリング - SRP原則に基づくモジュール分割
## MIR builder_calls.rs リファクタリング
- 879行 → 629行 (28%削減) + 7専門モジュール
- calls/ ディレクトリに機能別分割:
  - call_target.rs: CallTarget型定義
  - method_resolution.rs: メソッド解決ロジック
  - extern_calls.rs: 外部呼び出し処理
  - special_handlers.rs: 特殊ハンドラー
  - function_lowering.rs: 関数変換ユーティリティ
  - call_unified.rs: 統一Call実装
  - mod.rs: モジュール統合

## Parser statements.rs リファクタリング
- 723行 → 8専門モジュール
- statements/ ディレクトリに機能別分割:
  - control_flow.rs: if/loop/break/continue/return
  - declarations.rs: 宣言系ディスパッチャー
  - exceptions.rs: try/throw/catch/cleanup
  - helpers.rs: ヘルパー関数
  - io_async.rs: print/nowait
  - modules.rs: import/using/from
  - variables.rs: local/outbox/assignments
  - mod.rs: 統合モジュール

## 効果
 単一責任原則(SRP)の達成
 保守性・再利用性の向上
 ChatGPT5 Pro設計の型安全Call解決システム実装
 スモークテスト通過確認済み

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-25 09:01:55 +09:00

198 lines
6.4 KiB
Rust

/*!
* Unified Call System
*
* ChatGPT5 Pro A++ design for complete call unification
* Replaces 6 different call instructions with a single unified system
*/
use crate::mir::{Callee, Effect, EffectMask, ValueId};
use crate::mir::definitions::call_unified::{CallFlags, MirCall};
use super::call_target::CallTarget;
use super::method_resolution;
use super::extern_calls;
/// Check if unified call system is enabled
pub fn is_unified_call_enabled() -> bool {
std::env::var("NYASH_MIR_UNIFIED_CALL").unwrap_or_default() == "1"
}
/// Convert CallTarget to Callee
/// Main translation layer between builder and MIR representations
pub fn convert_target_to_callee(
target: CallTarget,
value_origin_newbox: &std::collections::HashMap<ValueId, String>,
value_types: &std::collections::HashMap<ValueId, crate::mir::MirType>,
) -> Result<Callee, String> {
match target {
CallTarget::Global(name) => {
// Check if it's a built-in function
if method_resolution::is_builtin_function(&name) {
Ok(Callee::Global(name))
} else if method_resolution::is_extern_function(&name) {
Ok(Callee::Extern(name))
} else {
Err(format!("Unknown global function: {}", name))
}
},
CallTarget::Method { box_type, method, receiver } => {
let inferred_box_type = box_type.unwrap_or_else(|| {
// Try to infer box type from value origin or type annotation
value_origin_newbox.get(&receiver)
.cloned()
.or_else(|| {
value_types.get(&receiver)
.and_then(|t| match t {
crate::mir::MirType::Box(box_name) => Some(box_name.clone()),
_ => None,
})
})
.unwrap_or_else(|| "UnknownBox".to_string())
});
Ok(Callee::Method {
box_name: inferred_box_type,
method,
receiver: Some(receiver),
})
},
CallTarget::Constructor(box_type) => {
Ok(Callee::Constructor { box_type })
},
CallTarget::Extern(name) => {
Ok(Callee::Extern(name))
},
CallTarget::Value(func_val) => {
Ok(Callee::Value(func_val))
},
CallTarget::Closure { params, captures, me_capture } => {
Ok(Callee::Closure { params, captures, me_capture })
},
}
}
/// Compute effects for a call based on its callee
pub fn compute_call_effects(callee: &Callee) -> EffectMask {
match callee {
Callee::Global(name) => {
match name.as_str() {
"print" | "error" => EffectMask::IO,
"panic" | "exit" => EffectMask::IO.add(Effect::Control),
"gc_collect" => EffectMask::IO.add(Effect::Alloc),
_ => EffectMask::IO,
}
},
Callee::Method { method, box_name, .. } => {
match method.as_str() {
"birth" => EffectMask::PURE.add(Effect::Alloc),
"get" | "length" | "size" => EffectMask::READ,
"set" | "push" | "pop" => EffectMask::READ.add(Effect::WriteHeap),
_ => {
// Check if it's a known pure method
if is_pure_method(box_name, method) {
EffectMask::PURE
} else {
EffectMask::READ
}
}
}
},
Callee::Constructor { .. } => EffectMask::PURE.add(Effect::Alloc),
Callee::Closure { .. } => EffectMask::PURE.add(Effect::Alloc),
Callee::Extern(name) => {
let (iface, method) = extern_calls::parse_extern_name(name);
extern_calls::compute_extern_effects(&iface, &method)
},
Callee::Value(_) => EffectMask::IO, // Conservative for dynamic calls
}
}
/// Check if a method is known to be pure (no side effects)
fn is_pure_method(box_name: &str, method: &str) -> bool {
match (box_name, method) {
("StringBox", m) => matches!(m, "upper" | "lower" | "trim" | "length"),
("IntegerBox", m) => matches!(m, "abs" | "toString"),
("FloatBox", m) => matches!(m, "round" | "floor" | "ceil"),
("BoolBox", "not") => true,
_ => false,
}
}
/// Create CallFlags based on callee type
pub fn create_call_flags(callee: &Callee) -> CallFlags {
if callee.is_constructor() {
CallFlags::constructor()
} else if matches!(callee, Callee::Closure { .. }) {
CallFlags::constructor() // Closures are also constructors
} else {
CallFlags::new()
}
}
/// Create a MirCall instruction from components
pub fn create_mir_call(
dst: Option<ValueId>,
callee: Callee,
args: Vec<ValueId>,
) -> MirCall {
let effects = compute_call_effects(&callee);
let flags = create_call_flags(&callee);
MirCall {
dst,
callee,
args,
flags,
effects,
}
}
/// Validate call arguments match expected signature
pub fn validate_call_args(
callee: &Callee,
args: &[ValueId],
) -> Result<(), String> {
match callee {
Callee::Global(name) => {
// Check known global functions
match name.as_str() {
"print" | "error" | "panic" => {
if args.is_empty() {
return Err(format!("{} requires at least one argument", name));
}
}
"exit" => {
if args.len() != 1 {
return Err("exit requires exactly one argument (exit code)".to_string());
}
}
_ => {} // Unknown functions pass through
}
},
Callee::Method { box_name, method, .. } => {
// Validate known methods
match (box_name.as_str(), method.as_str()) {
("ArrayBox", "get") | ("ArrayBox", "set") => {
if args.is_empty() {
return Err(format!("ArrayBox.{} requires an index", method));
}
}
_ => {} // Unknown methods pass through
}
},
_ => {} // Other callee types don't have validation yet
}
Ok(())
}