feat: MIR builder TypeOp lowering for is/as methods and isType/asType functions

- Add early TypeOp lowering in build_expression for method-style is()/as()
- Add early TypeOp lowering in build_expression for function-style isType()/asType()
- Add special handling in build_print_statement for print(isType/asType(...))
- Fix MIR optimizer borrow checker issues and remove obsolete BoxFieldLoad
- Extract string literal helper supports both direct literals and StringBox wrappers
- Note: isType call generation still has issues (undefined SSA value in print)

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Moe Charm
2025-08-24 00:05:12 +09:00
parent ee740be119
commit 3c3dc86be0
10 changed files with 584 additions and 33 deletions

View File

@ -12,6 +12,26 @@ 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 {
@ -94,4 +114,43 @@ impl NyashInterpreter {
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),
}
}
}