Files
hakorune/src/archive/interpreter_legacy/functions.rs

189 lines
7.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.

/*!
* Function Processing Module
*
* Extracted from core.rs - function call and definition handling
* Handles function declarations, calls, and function-related operations
* Core philosophy: "Everything is Box" with structured function processing
*/
use super::*;
impl NyashInterpreter {
/// 関数呼び出しを実行 - 🌍 革命的実装GlobalBoxのメソッド呼び出し
pub(super) fn execute_function_call(
&mut self,
name: &str,
arguments: &[ASTNode],
) -> Result<Box<dyn NyashBox>, RuntimeError> {
// Fallback: built-in type ops as global functions: isType(value, "Type"), asType(value, "Type")
if (name == "isType" || name == "asType") && arguments.len() == 2 {
// Evaluate args
let val = self.execute_expression(&arguments[0])?;
let ty_box = self.execute_expression(&arguments[1])?;
// Get type name string
let type_name = if let Some(s) = ty_box
.as_any()
.downcast_ref::<crate::box_trait::StringBox>()
{
s.value.clone()
} else {
return Err(RuntimeError::InvalidOperation {
message: "Type name must be a string".to_string(),
});
};
if name == "isType" {
let matched = Self::matches_type_name(&val, &type_name);
return Ok(Box::new(crate::box_trait::BoolBox::new(matched)));
} else {
// asType: minimal safe cast (int<->float), otherwise identity
return Self::cast_to_type(val, &type_name);
}
}
// コンストラクタ内での親コンストラクタ呼び出しチェック
if let Some(context) = self.current_constructor_context.clone() {
if let Some(parent_class) = context.parent_class {
if name == parent_class {
// 親コンストラクタ呼び出し
return self.execute_parent_constructor(&parent_class, arguments);
}
}
}
// 🌍 GlobalBoxのメソッドとして実行
let global_box = self.shared.global_box.lock().unwrap();
let method_ast = global_box
.get_method(name)
.ok_or(RuntimeError::UndefinedFunction {
name: name.to_string(),
})?
.clone();
drop(global_box);
// メソッド呼び出しとして実行GlobalBoxインスタンス上で
if let ASTNode::FunctionDeclaration { params, body, .. } = method_ast {
// 引数を評価
let mut arg_values = Vec::new();
for arg in arguments {
arg_values.push(self.execute_expression(arg)?);
}
// パラメータ数チェック
if arg_values.len() != params.len() {
return Err(RuntimeError::InvalidOperation {
message: format!(
"Function {} expects {} arguments, got {}",
name,
params.len(),
arg_values.len()
),
});
}
// 🌍 local変数スタックを保存・クリア関数呼び出し開始
let saved_locals = self.save_local_vars();
self.local_vars.clear();
// パラメータをlocal変数として設定
for (param, value) in params.iter().zip(arg_values.iter()) {
self.declare_local_variable(param, value.clone_or_share());
}
// 関数本体を実行TaskGroupスコープをプッシュ
crate::runtime::global_hooks::push_task_scope();
let mut result: Box<dyn NyashBox> = Box::new(VoidBox::new());
for statement in &body {
result = self.execute_statement(statement)?;
// return文チェック
if let super::ControlFlow::Return(return_val) = &self.control_flow {
if std::env::var("NYASH_INT_RET_TRACE").ok().as_deref() == Some("1") {
let ty = return_val.type_name();
let sv = return_val.to_string_box().value;
eprintln!("[INT-RET] epilogue capture: type={} value={}", ty, sv);
}
result = return_val.clone_box();
self.control_flow = super::ControlFlow::None;
break;
}
}
// 🌍 local変数スタックを復元関数呼び出し終了
crate::runtime::global_hooks::pop_task_scope();
self.restore_local_vars(saved_locals);
Ok(result)
} else {
Err(RuntimeError::InvalidOperation {
message: format!("Function '{}' is not a valid function declaration", name),
})
}
}
/// 関数宣言を登録 - 🌍 革命的実装GlobalBoxのメソッドとして登録
pub(super) fn register_function_declaration(
&mut self,
name: String,
params: Vec<String>,
body: Vec<ASTNode>,
) {
// 🌍 GlobalBoxのメソッドとして登録
let func_ast = ASTNode::FunctionDeclaration {
name: name.clone(),
params,
body,
is_static: false, // 通常の関数は静的でない
is_override: false, // 🔥 通常の関数はオーバーライドでない
span: crate::ast::Span::unknown(), // デフォルトspan
};
self.register_global_function(name, func_ast)
.unwrap_or_else(|err| {
eprintln!("Warning: Failed to register global function: {}", err);
});
}
/// Helper: match a NyashBox value against a simple type name
fn matches_type_name(val: &Box<dyn NyashBox>, type_name: &str) -> bool {
let tn = val.type_name();
match type_name {
"Integer" | "Int" | "I64" => tn == "IntegerBox",
"Float" | "F64" => tn == "FloatBox",
"Bool" | "Boolean" => tn == "BoolBox",
"String" => tn == "StringBox",
"Void" | "Unit" => tn == "VoidBox",
other => tn == other || tn == format!("{}Box", other),
}
}
/// Helper: cast box to a target type name (minimal support)
fn cast_to_type(
val: Box<dyn NyashBox>,
type_name: &str,
) -> Result<Box<dyn NyashBox>, RuntimeError> {
match type_name {
"Integer" | "Int" | "I64" => {
// Float -> Integer (truncate), Integer -> Integer, else error
if let Some(i) = val.as_any().downcast_ref::<crate::box_trait::IntegerBox>() {
Ok(Box::new(crate::box_trait::IntegerBox::new(i.value)))
} else if let Some(f) = val.as_any().downcast_ref::<crate::boxes::FloatBox>() {
Ok(Box::new(crate::box_trait::IntegerBox::new(f.value as i64)))
} else {
Ok(val) // identity fallback for now
}
}
"Float" | "F64" => {
if let Some(f) = val.as_any().downcast_ref::<crate::boxes::FloatBox>() {
Ok(Box::new(crate::boxes::FloatBox::new(f.value)))
} else if let Some(i) = val.as_any().downcast_ref::<crate::box_trait::IntegerBox>()
{
Ok(Box::new(crate::boxes::FloatBox::new(i.value as f64)))
} else {
Ok(val)
}
}
_ => Ok(val),
}
}
}