2025-08-26 04:34:14 +09:00
|
|
|
use super::*;
|
|
|
|
|
use crate::box_trait::SharedNyashBox;
|
|
|
|
|
|
|
|
|
|
impl NyashInterpreter {
|
|
|
|
|
/// コンストラクタを実行 - Constructor execution
|
|
|
|
|
pub(super) fn execute_constructor(
|
|
|
|
|
&mut self,
|
|
|
|
|
instance: &SharedNyashBox,
|
|
|
|
|
constructor: &ASTNode,
|
|
|
|
|
arguments: &[ASTNode],
|
2025-09-17 07:43:07 +09:00
|
|
|
box_decl: &BoxDeclaration,
|
2025-08-26 04:34:14 +09:00
|
|
|
) -> Result<(), RuntimeError> {
|
2025-09-17 07:43:07 +09:00
|
|
|
if let ASTNode::FunctionDeclaration {
|
|
|
|
|
name: _,
|
|
|
|
|
params,
|
|
|
|
|
body,
|
|
|
|
|
..
|
|
|
|
|
} = constructor
|
|
|
|
|
{
|
2025-08-26 04:34:14 +09:00
|
|
|
let mut arg_values = Vec::new();
|
2025-09-17 07:43:07 +09:00
|
|
|
for arg in arguments {
|
|
|
|
|
arg_values.push(self.execute_expression(arg)?);
|
|
|
|
|
}
|
2025-08-26 04:34:14 +09:00
|
|
|
if params.len() != arg_values.len() {
|
|
|
|
|
return Err(RuntimeError::InvalidOperation {
|
2025-09-17 07:43:07 +09:00
|
|
|
message: format!(
|
|
|
|
|
"Constructor expects {} arguments, got {}",
|
|
|
|
|
params.len(),
|
|
|
|
|
arg_values.len()
|
|
|
|
|
),
|
2025-08-26 04:34:14 +09:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
let saved_locals = self.save_local_vars();
|
|
|
|
|
self.local_vars.clear();
|
|
|
|
|
for (param, value) in params.iter().zip(arg_values.iter()) {
|
|
|
|
|
self.declare_local_variable(param, value.clone_or_share());
|
|
|
|
|
}
|
|
|
|
|
self.declare_local_variable("me", instance.clone_or_share());
|
|
|
|
|
let old_context = self.current_constructor_context.clone();
|
|
|
|
|
self.current_constructor_context = Some(ConstructorContext {
|
|
|
|
|
class_name: box_decl.name.clone(),
|
|
|
|
|
parent_class: box_decl.extends.first().cloned(),
|
|
|
|
|
});
|
|
|
|
|
let mut result = Ok(());
|
|
|
|
|
for statement in body.iter() {
|
2025-09-17 07:43:07 +09:00
|
|
|
if let Err(e) = self.execute_statement(statement) {
|
|
|
|
|
result = Err(e);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2025-08-26 04:34:14 +09:00
|
|
|
}
|
|
|
|
|
self.restore_local_vars(saved_locals);
|
|
|
|
|
self.current_constructor_context = old_context;
|
|
|
|
|
result
|
|
|
|
|
} else {
|
2025-09-17 07:43:07 +09:00
|
|
|
Err(RuntimeError::InvalidOperation {
|
|
|
|
|
message: "Invalid constructor node".to_string(),
|
|
|
|
|
})
|
2025-08-26 04:34:14 +09:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// 親コンストラクタを実行 - Parent constructor execution
|
2025-09-17 07:43:07 +09:00
|
|
|
pub(crate) fn execute_parent_constructor(
|
|
|
|
|
&mut self,
|
|
|
|
|
parent_class: &str,
|
|
|
|
|
arguments: &[ASTNode],
|
|
|
|
|
) -> Result<Box<dyn NyashBox>, RuntimeError> {
|
2025-08-26 04:34:14 +09:00
|
|
|
let parent_decl = {
|
|
|
|
|
let box_decls = self.shared.box_declarations.read().unwrap();
|
2025-09-17 07:43:07 +09:00
|
|
|
box_decls
|
|
|
|
|
.get(parent_class)
|
|
|
|
|
.ok_or(RuntimeError::UndefinedClass {
|
|
|
|
|
name: parent_class.to_string(),
|
|
|
|
|
})?
|
2025-08-26 04:34:14 +09:00
|
|
|
.clone()
|
|
|
|
|
};
|
|
|
|
|
let birth_key = format!("birth/{}", arguments.len());
|
|
|
|
|
if let Some(parent_constructor) = parent_decl.constructors.get(&birth_key) {
|
2025-09-17 07:43:07 +09:00
|
|
|
let this_instance =
|
|
|
|
|
self.resolve_variable("me")
|
|
|
|
|
.map_err(|_| RuntimeError::InvalidOperation {
|
|
|
|
|
message: "'this' not available in parent constructor call".to_string(),
|
|
|
|
|
})?;
|
2025-08-26 04:34:14 +09:00
|
|
|
self.execute_constructor(&this_instance, parent_constructor, arguments, &parent_decl)?;
|
|
|
|
|
Ok(Box::new(VoidBox::new()))
|
|
|
|
|
} else {
|
|
|
|
|
Err(RuntimeError::InvalidOperation {
|
2025-09-17 07:43:07 +09:00
|
|
|
message: format!(
|
|
|
|
|
"No constructor found for parent class {} with {} arguments",
|
|
|
|
|
parent_class,
|
|
|
|
|
arguments.len()
|
|
|
|
|
),
|
2025-08-26 04:34:14 +09:00
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|