2025-08-09 15:14:44 +09:00
|
|
|
|
/*!
|
|
|
|
|
|
* Nyash Instance System - Box Instance Implementation
|
|
|
|
|
|
*
|
|
|
|
|
|
* BoxインスタンスとClassBoxの実装
|
|
|
|
|
|
* Everything is Box哲学に基づくオブジェクト指向システム
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
2025-08-11 12:09:14 +09:00
|
|
|
|
use crate::box_trait::{NyashBox, StringBox, BoolBox, VoidBox, BoxCore, BoxBase};
|
2025-08-09 15:14:44 +09:00
|
|
|
|
use crate::ast::ASTNode;
|
|
|
|
|
|
use std::collections::HashMap;
|
|
|
|
|
|
use std::fmt::{Debug, Display};
|
|
|
|
|
|
use std::any::Any;
|
|
|
|
|
|
use std::sync::{Arc, Mutex};
|
|
|
|
|
|
|
|
|
|
|
|
/// Boxインスタンス - フィールドとメソッドを持つオブジェクト
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
|
|
pub struct InstanceBox {
|
|
|
|
|
|
/// クラス名
|
|
|
|
|
|
pub class_name: String,
|
|
|
|
|
|
|
|
|
|
|
|
/// フィールド値
|
|
|
|
|
|
pub fields: Arc<Mutex<HashMap<String, Box<dyn NyashBox>>>>,
|
|
|
|
|
|
|
|
|
|
|
|
/// メソッド定義(ClassBoxから共有)
|
|
|
|
|
|
pub methods: Arc<HashMap<String, ASTNode>>,
|
|
|
|
|
|
|
2025-08-11 12:09:14 +09:00
|
|
|
|
/// Box基底
|
|
|
|
|
|
base: BoxBase,
|
2025-08-09 15:14:44 +09:00
|
|
|
|
|
|
|
|
|
|
/// 解放済みフラグ
|
|
|
|
|
|
finalized: Arc<Mutex<bool>>,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl InstanceBox {
|
|
|
|
|
|
pub fn new(class_name: String, fields: Vec<String>, methods: HashMap<String, ASTNode>) -> Self {
|
|
|
|
|
|
// フィールドをVoidBoxで初期化
|
|
|
|
|
|
let mut field_map = HashMap::new();
|
|
|
|
|
|
for field in fields {
|
|
|
|
|
|
field_map.insert(field, Box::new(VoidBox::new()) as Box<dyn NyashBox>);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Self {
|
|
|
|
|
|
class_name,
|
|
|
|
|
|
fields: Arc::new(Mutex::new(field_map)),
|
|
|
|
|
|
methods: Arc::new(methods),
|
2025-08-11 12:09:14 +09:00
|
|
|
|
base: BoxBase::new(),
|
2025-08-09 15:14:44 +09:00
|
|
|
|
finalized: Arc::new(Mutex::new(false)),
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// フィールドの値を取得
|
|
|
|
|
|
pub fn get_field(&self, field_name: &str) -> Option<Box<dyn NyashBox>> {
|
|
|
|
|
|
self.fields.lock().unwrap().get(field_name).map(|v| v.clone_box())
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// フィールドに値を設定
|
|
|
|
|
|
pub fn set_field(&self, field_name: &str, value: Box<dyn NyashBox>) -> Result<(), String> {
|
|
|
|
|
|
let mut fields = self.fields.lock().unwrap();
|
|
|
|
|
|
if fields.contains_key(field_name) {
|
|
|
|
|
|
fields.insert(field_name.to_string(), value);
|
|
|
|
|
|
Ok(())
|
|
|
|
|
|
} else {
|
|
|
|
|
|
Err(format!("Field '{}' does not exist in {}", field_name, self.class_name))
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// 🌍 GlobalBox用:フィールドを動的に追加・設定
|
|
|
|
|
|
pub fn set_field_dynamic(&mut self, field_name: String, value: Box<dyn NyashBox>) {
|
|
|
|
|
|
let mut fields = self.fields.lock().unwrap();
|
|
|
|
|
|
fields.insert(field_name, value);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// メソッド定義を取得
|
|
|
|
|
|
pub fn get_method(&self, method_name: &str) -> Option<&ASTNode> {
|
|
|
|
|
|
self.methods.get(method_name)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// メソッドが存在するかチェック
|
|
|
|
|
|
pub fn has_method(&self, method_name: &str) -> bool {
|
|
|
|
|
|
self.methods.contains_key(method_name)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-11 07:55:41 +09:00
|
|
|
|
/// 🌍 GlobalBox用:メソッドを動的に追加 - 🔥 暗黙オーバーライド禁止による安全実装
|
|
|
|
|
|
pub fn add_method(&mut self, method_name: String, method_ast: ASTNode) -> Result<(), String> {
|
2025-08-09 15:14:44 +09:00
|
|
|
|
// Arc<T>は不変なので、新しいHashMapを作成してArcで包む
|
|
|
|
|
|
let mut new_methods = (*self.methods).clone();
|
2025-08-11 07:55:41 +09:00
|
|
|
|
|
|
|
|
|
|
// 🚨 暗黙オーバーライド禁止:既存メソッドの検査
|
|
|
|
|
|
if let Some(existing_method) = new_methods.get(&method_name) {
|
|
|
|
|
|
// 新しいメソッドのoverride状態を確認
|
|
|
|
|
|
let is_override = match &method_ast {
|
|
|
|
|
|
crate::ast::ASTNode::FunctionDeclaration { is_override, .. } => *is_override,
|
|
|
|
|
|
_ => false, // FunctionDeclaration以外はオーバーライドなし
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
if !is_override {
|
|
|
|
|
|
// 🔥 明示的オーバーライド革命:overrideキーワードなしの重複を禁止
|
|
|
|
|
|
return Err(format!(
|
|
|
|
|
|
"🚨 EXPLICIT OVERRIDE REQUIRED: Method '{}' already exists.\n\
|
|
|
|
|
|
💡 To replace the existing method, use 'override {}(...) {{ ... }}'.\n\
|
|
|
|
|
|
🌟 This is Nyash's explicit delegation philosophy - no hidden overrides!",
|
|
|
|
|
|
method_name, method_name
|
|
|
|
|
|
));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// override宣言があれば、明示的な置換として許可
|
|
|
|
|
|
eprintln!("🔥 EXPLICIT OVERRIDE: Method '{}' replaced with override declaration", method_name);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-09 15:14:44 +09:00
|
|
|
|
new_methods.insert(method_name, method_ast);
|
|
|
|
|
|
self.methods = Arc::new(new_methods);
|
2025-08-11 07:55:41 +09:00
|
|
|
|
Ok(())
|
2025-08-09 15:14:44 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// fini()メソッド - インスタンスの解放
|
|
|
|
|
|
pub fn fini(&self) -> Result<(), String> {
|
|
|
|
|
|
let mut finalized = self.finalized.lock().unwrap();
|
|
|
|
|
|
if *finalized {
|
|
|
|
|
|
// 既に解放済みなら何もしない
|
|
|
|
|
|
return Ok(());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
*finalized = true;
|
|
|
|
|
|
|
|
|
|
|
|
// フィールドをクリア
|
|
|
|
|
|
let mut fields = self.fields.lock().unwrap();
|
|
|
|
|
|
fields.clear();
|
|
|
|
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// 解放済みかチェック
|
|
|
|
|
|
pub fn is_finalized(&self) -> bool {
|
|
|
|
|
|
*self.finalized.lock().unwrap()
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl NyashBox for InstanceBox {
|
|
|
|
|
|
fn to_string_box(&self) -> StringBox {
|
2025-08-11 15:01:11 +09:00
|
|
|
|
StringBox::new(format!("<{} instance #{}>", self.class_name, self.base.id))
|
2025-08-09 15:14:44 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn equals(&self, other: &dyn NyashBox) -> BoolBox {
|
|
|
|
|
|
if let Some(other_instance) = other.as_any().downcast_ref::<InstanceBox>() {
|
|
|
|
|
|
// 同じインスタンスIDなら等しい
|
2025-08-11 15:01:11 +09:00
|
|
|
|
BoolBox::new(self.base.id == other_instance.base.id)
|
2025-08-09 15:14:44 +09:00
|
|
|
|
} else {
|
|
|
|
|
|
BoolBox::new(false)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn type_name(&self) -> &'static str {
|
|
|
|
|
|
"InstanceBox"
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn clone_box(&self) -> Box<dyn NyashBox> {
|
|
|
|
|
|
// インスタンスは同じフィールドを共有
|
|
|
|
|
|
Box::new(self.clone())
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-08-11 12:09:14 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl BoxCore for InstanceBox {
|
2025-08-09 15:14:44 +09:00
|
|
|
|
fn box_id(&self) -> u64 {
|
2025-08-11 15:01:11 +09:00
|
|
|
|
self.base.id
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn parent_type_id(&self) -> Option<std::any::TypeId> {
|
|
|
|
|
|
self.base.parent_type_id
|
2025-08-11 12:09:14 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn fmt_box(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
2025-08-11 15:01:11 +09:00
|
|
|
|
write!(f, "<{} instance #{}>", self.class_name, self.base.id)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn as_any(&self) -> &dyn Any {
|
|
|
|
|
|
self
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn as_any_mut(&mut self) -> &mut dyn Any {
|
|
|
|
|
|
self
|
2025-08-09 15:14:44 +09:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl Display for InstanceBox {
|
|
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
2025-08-11 12:09:14 +09:00
|
|
|
|
self.fmt_box(f)
|
2025-08-09 15:14:44 +09:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ===== Tests =====
|
|
|
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
|
mod tests {
|
|
|
|
|
|
use super::*;
|
|
|
|
|
|
use crate::box_trait::IntegerBox;
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
|
fn test_instance_creation() {
|
|
|
|
|
|
let fields = vec!["x".to_string(), "y".to_string()];
|
|
|
|
|
|
let methods = HashMap::new();
|
|
|
|
|
|
let instance = InstanceBox::new("Point".to_string(), fields, methods);
|
|
|
|
|
|
|
|
|
|
|
|
assert_eq!(instance.class_name, "Point");
|
|
|
|
|
|
assert!(instance.get_field("x").is_some());
|
|
|
|
|
|
assert!(instance.get_field("y").is_some());
|
|
|
|
|
|
assert!(instance.get_field("z").is_none());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
|
fn test_field_access() {
|
|
|
|
|
|
let fields = vec!["value".to_string()];
|
|
|
|
|
|
let methods = HashMap::new();
|
|
|
|
|
|
let instance = InstanceBox::new("TestBox".to_string(), fields, methods);
|
|
|
|
|
|
|
|
|
|
|
|
// フィールドに値を設定
|
|
|
|
|
|
let int_value = Box::new(IntegerBox::new(42)) as Box<dyn NyashBox>;
|
|
|
|
|
|
instance.set_field("value", int_value).unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
// フィールドの値を取得
|
|
|
|
|
|
let retrieved = instance.get_field("value").unwrap();
|
|
|
|
|
|
let int_box = retrieved.as_any().downcast_ref::<IntegerBox>().unwrap();
|
|
|
|
|
|
assert_eq!(int_box.value, 42);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
|
fn test_instance_equality() {
|
|
|
|
|
|
let instance1 = InstanceBox::new("Test".to_string(), vec![], HashMap::new());
|
|
|
|
|
|
let instance2 = InstanceBox::new("Test".to_string(), vec![], HashMap::new());
|
|
|
|
|
|
|
|
|
|
|
|
// 異なるインスタンスは等しくない
|
|
|
|
|
|
assert!(!instance1.equals(&instance2).value);
|
|
|
|
|
|
|
|
|
|
|
|
// 同じインスタンスは等しい
|
|
|
|
|
|
assert!(instance1.equals(&instance1).value);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|