## 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>
198 lines
6.4 KiB
Rust
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(())
|
|
} |