Files
hakorune/src/mir/builder/method_call_handlers.rs
nyash-codex dd65cf7e4c builder+vm: unify method calls via emit_unified_call; add RouterPolicy trace; finalize LocalSSA/BlockSchedule guards; docs + selfhost quickstart
- 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).
2025-09-28 20:38:09 +09:00

111 lines
3.6 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//! 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)
}
}