- Unify standard method calls to emit_unified_call; route via RouterPolicy and apply rewrite::{special,known} at a single entry.\n- Stabilize emit-time invariants: LocalSSA finalize + BlockSchedule PHI→Copy→Call ordering; metadata propagation on copies.\n- Known rewrite default ON (userbox only, strict guards) with opt-out flag NYASH_REWRITE_KNOWN_DEFAULT=0.\n- Expand TypeAnnotation whitelist (is_digit_char/is_hex_digit_char/is_alpha_char/Map.has).\n- Docs: unified-method-resolution design note; Quick Reference normalization note; selfhosting/quickstart.\n- Tools: add tools/selfhost_smoke.sh (dev-only).\n- Keep behavior unchanged for Unknown/core/user-instance via BoxCall fallback; all tests green (quick/integration).
111 lines
3.6 KiB
Rust
111 lines
3.6 KiB
Rust
//! Method call handlers for MIR builder
|
||
//!
|
||
//! This module contains specialized handlers for different types of method calls,
|
||
//! following the Single Responsibility Principle.
|
||
|
||
use crate::ast::ASTNode;
|
||
use crate::mir::builder::{MirBuilder, ValueId};
|
||
use crate::mir::builder::builder_calls::CallTarget;
|
||
use crate::mir::{MirInstruction, TypeOpKind, MirType};
|
||
|
||
impl MirBuilder {
|
||
/// Handle static method calls: BoxName.method(args)
|
||
pub(super) fn handle_static_method_call(
|
||
&mut self,
|
||
box_name: &str,
|
||
method: &str,
|
||
arguments: &[ASTNode],
|
||
) -> Result<ValueId, String> {
|
||
// Build argument values
|
||
let mut arg_values = Vec::new();
|
||
for arg in arguments {
|
||
arg_values.push(self.build_expression(arg.clone())?);
|
||
}
|
||
|
||
// Compose lowered function name: BoxName.method/N
|
||
let func_name = format!("{}.{}/{}", box_name, method, arg_values.len());
|
||
let dst = self.value_gen.next();
|
||
|
||
if std::env::var("NYASH_STATIC_CALL_TRACE").ok().as_deref() == Some("1") {
|
||
eprintln!("[builder] static-call {}", func_name);
|
||
}
|
||
|
||
// Use legacy global-call emission to avoid unified builtin/extern constraints
|
||
self.emit_legacy_call(Some(dst), CallTarget::Global(func_name), arg_values)?;
|
||
Ok(dst)
|
||
}
|
||
|
||
/// Handle TypeOp method calls: value.is("Type") and value.as("Type")
|
||
pub(super) fn handle_typeop_method(
|
||
&mut self,
|
||
object_value: ValueId,
|
||
method: &str,
|
||
type_name: &str,
|
||
) -> Result<ValueId, String> {
|
||
let mir_ty = Self::parse_type_name_to_mir(type_name);
|
||
let dst = self.value_gen.next();
|
||
let op = if method == "is" {
|
||
TypeOpKind::Check
|
||
} else {
|
||
TypeOpKind::Cast
|
||
};
|
||
|
||
self.emit_instruction(MirInstruction::TypeOp {
|
||
dst,
|
||
op,
|
||
value: object_value,
|
||
ty: mir_ty,
|
||
})?;
|
||
|
||
Ok(dst)
|
||
}
|
||
|
||
/// Check if this is a TypeOp method call
|
||
pub(super) fn is_typeop_method(method: &str, arguments: &[ASTNode]) -> Option<String> {
|
||
if (method == "is" || method == "as") && arguments.len() == 1 {
|
||
Self::extract_string_literal(&arguments[0])
|
||
} else {
|
||
None
|
||
}
|
||
}
|
||
|
||
/// Handle me.method() calls within static box context
|
||
pub(super) fn handle_me_method_call(
|
||
&mut self,
|
||
method: &str,
|
||
arguments: &[ASTNode],
|
||
) -> Result<Option<ValueId>, String> {
|
||
// Convert slice to Vec for compatibility
|
||
let args_vec = arguments.to_vec();
|
||
// Delegate to existing try_handle_me_direct_call
|
||
match self.try_handle_me_direct_call(method, &args_vec) {
|
||
Some(result) => result.map(Some),
|
||
None => Ok(None),
|
||
}
|
||
}
|
||
|
||
/// Handle standard Box/Plugin method calls (fallback)
|
||
pub(super) fn handle_standard_method_call(
|
||
&mut self,
|
||
object_value: ValueId,
|
||
method: String,
|
||
arguments: &[ASTNode],
|
||
) -> Result<ValueId, String> {
|
||
// Build argument values
|
||
let mut arg_values = Vec::new();
|
||
for arg in arguments {
|
||
arg_values.push(self.build_expression(arg.clone())?);
|
||
}
|
||
|
||
// Receiver class hintは emit_unified_call 側で起源/型から判断する(重複回避)
|
||
// 統一経路: emit_unified_call に委譲(RouterPolicy と rewrite::* で安定化)
|
||
let dst = self.value_gen.next();
|
||
self.emit_unified_call(
|
||
Some(dst),
|
||
CallTarget::Method { box_type: None, method, receiver: object_value },
|
||
arg_values,
|
||
)?;
|
||
Ok(dst)
|
||
}
|
||
}
|