🔥 Phase 2 Complete: Comprehensive fini system with ChatGPT5 design

Co-authored-by: moe-charm <217100418+moe-charm@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2025-08-13 02:22:20 +00:00
parent 014fac2b9b
commit c6f76505b5
7 changed files with 387 additions and 8 deletions

View File

@ -34,14 +34,24 @@ pub struct InstanceBox {
/// 解放済みフラグ /// 解放済みフラグ
finalized: Arc<Mutex<bool>>, finalized: Arc<Mutex<bool>>,
/// 🔥 Phase 2: finiシステム完全実装 - ChatGPT5設計
/// init宣言順序決定的カスケード用
init_field_order: Vec<String>,
/// weak フィールド高速判定用
weak_fields_union: std::collections::HashSet<String>,
/// 解放中フラグ(再入防止)
in_finalization: Arc<Mutex<bool>>,
} }
impl InstanceBox { impl InstanceBox {
pub fn new(class_name: String, fields: Vec<String>, methods: HashMap<String, ASTNode>) -> Self { pub fn new(class_name: String, fields: Vec<String>, methods: HashMap<String, ASTNode>) -> Self {
// フィールドをVoidBoxで初期化 // フィールドをVoidBoxで初期化
let mut field_map = HashMap::new(); let mut field_map = HashMap::new();
for field in fields { for field in &fields {
field_map.insert(field, Box::new(VoidBox::new()) as Box<dyn NyashBox>); field_map.insert(field.clone(), Box::new(VoidBox::new()) as Box<dyn NyashBox>);
} }
Self { Self {
@ -51,6 +61,39 @@ impl InstanceBox {
methods: Arc::new(methods), methods: Arc::new(methods),
base: BoxBase::new(), base: BoxBase::new(),
finalized: Arc::new(Mutex::new(false)), finalized: Arc::new(Mutex::new(false)),
init_field_order: fields.clone(), // 🔥 Basic field order for backwards compatibility
weak_fields_union: std::collections::HashSet::new(), // 🔥 Empty for backwards compatibility
in_finalization: Arc::new(Mutex::new(false)), // 🔥 Initialize finalization guard
}
}
/// 🔥 Enhanced constructor with complete fini system support
pub fn new_with_box_info(
class_name: String,
fields: Vec<String>,
methods: HashMap<String, ASTNode>,
init_field_order: Vec<String>,
weak_fields: Vec<String>
) -> Self {
// フィールドをVoidBoxで初期化
let mut field_map = HashMap::new();
for field in &fields {
field_map.insert(field.clone(), Box::new(VoidBox::new()) as Box<dyn NyashBox>);
}
// Weak fields をHashSetに変換高速判定用
let weak_fields_union: std::collections::HashSet<String> = weak_fields.into_iter().collect();
Self {
class_name,
fields: Arc::new(Mutex::new(field_map)),
fields_ng: Arc::new(Mutex::new(HashMap::new())),
methods: Arc::new(methods),
base: BoxBase::new(),
finalized: Arc::new(Mutex::new(false)),
init_field_order, // 🔥 決定的カスケード順序
weak_fields_union, // 🔥 高速weak判定
in_finalization: Arc::new(Mutex::new(false)), // 🔥 再入防止
} }
} }
@ -290,19 +333,75 @@ impl InstanceBox {
Ok(()) Ok(())
} }
/// fini()メソッド - インスタンスの解放 /// 🔥 Enhanced fini()メソッド - ChatGPT5設計による完全実装
pub fn fini(&self) -> Result<(), String> { pub fn fini(&self) -> Result<(), String> {
// 1) finalized チェックidempotent
let mut finalized = self.finalized.lock().unwrap(); let mut finalized = self.finalized.lock().unwrap();
if *finalized { if *finalized {
// 既に解放済みなら何もしない // 既に解放済みなら何もしない
return Ok(()); return Ok(());
} }
*finalized = true; // 2) in_finalization = true再入防止
let mut in_finalization = self.in_finalization.lock().unwrap();
if *in_finalization {
return Err("Circular finalization detected - fini() called recursively".to_string());
}
*in_finalization = true;
// フィールドをクリア // 3) TODO: ユーザー定義fini()実行(インタープリター側で実装予定)
// このメソッドは低レベルなfini処理なので、高レベルなユーザー定義fini()は
// インタープリター側で先に呼び出される想定
// 4) 自動カスケード: init_field_order の強参照フィールドに child.fini()
self.cascade_finalize_fields()?;
// 5) 全フィールドクリア + finalized = true
let mut fields = self.fields.lock().unwrap(); let mut fields = self.fields.lock().unwrap();
fields.clear(); fields.clear();
let mut fields_ng = self.fields_ng.lock().unwrap();
fields_ng.clear();
*finalized = true;
*in_finalization = false; // 再入フラグをクリア
eprintln!("🔥 fini(): Instance {} (ID: {}) finalized", self.class_name, self.base.id);
Ok(())
}
/// 🔥 自動カスケード解放 - init宣言順でフィールドをfini
fn cascade_finalize_fields(&self) -> Result<(), String> {
let fields_ng = self.fields_ng.lock().unwrap();
// init_field_order の逆順でfiniを実行LIFO - Last In First Out
for field_name in self.init_field_order.iter().rev() {
// weak フィールドはスキップ
if self.weak_fields_union.contains(field_name) {
eprintln!("🔥 fini(): Skipping weak field '{}' (non-owning reference)", field_name);
continue;
}
// フィールドの値を取得してfini呼び出し
if let Some(field_value) = fields_ng.get(field_name) {
match field_value {
crate::value::NyashValue::Box(arc_box) => {
if let Ok(inner_box) = arc_box.try_lock() {
// InstanceBoxならfini()を呼び出し
if let Some(instance) = inner_box.as_any().downcast_ref::<InstanceBox>() {
eprintln!("🔥 fini(): Cascading finalization to field '{}'", field_name);
if let Err(e) = instance.fini() {
eprintln!("🔥 fini(): Warning - failed to finalize field '{}': {}", field_name, e);
// エラーは警告として記録するが、続行する
}
}
}
}
_ => {
// non-Box値はfini不要
}
}
}
}
Ok(()) Ok(())
} }
@ -311,6 +410,16 @@ impl InstanceBox {
pub fn is_finalized(&self) -> bool { pub fn is_finalized(&self) -> bool {
*self.finalized.lock().unwrap() *self.finalized.lock().unwrap()
} }
/// 🔥 解放中かチェック
pub fn is_in_finalization(&self) -> bool {
*self.in_finalization.lock().unwrap()
}
/// 🔥 指定フィールドがweakかチェック
pub fn is_weak_field(&self, field_name: &str) -> bool {
self.weak_fields_union.contains(field_name)
}
} }
impl NyashBox for InstanceBox { impl NyashBox for InstanceBox {

View File

@ -498,8 +498,37 @@ impl NyashInterpreter {
// InstanceBox method calls // InstanceBox method calls
if let Some(instance) = obj_value.as_any().downcast_ref::<InstanceBox>() { if let Some(instance) = obj_value.as_any().downcast_ref::<InstanceBox>() {
// 🔥 Usage prohibition guard - check if instance is finalized
if instance.is_finalized() {
return Err(RuntimeError::InvalidOperation {
message: "Instance was finalized; further use is prohibited".to_string(),
});
}
// fini()は特別処理 // fini()は特別処理
if method == "fini" { if method == "fini" {
// 🔥 weak-fini prohibition check - prevent fini() on weak fields
if let ASTNode::FieldAccess { object: field_object, field, .. } = object {
// Check if this is me.<field>.fini() pattern
if let ASTNode::Variable { name, .. } = field_object.as_ref() {
if name == "me" {
// Get current instance to check if field is weak
if let Ok(current_me) = self.resolve_variable("me") {
if let Some(current_instance) = current_me.as_any().downcast_ref::<InstanceBox>() {
if current_instance.is_weak_field(field) {
return Err(RuntimeError::InvalidOperation {
message: format!(
"Cannot finalize weak field '{}' (non-owning reference)",
field
),
});
}
}
}
}
}
}
// 既に解放済みの場合は何もしない二重fini()対策) // 既に解放済みの場合は何もしない二重fini()対策)
if instance.is_finalized() { if instance.is_finalized() {
return Ok(Box::new(VoidBox::new())); return Ok(Box::new(VoidBox::new()));
@ -625,6 +654,13 @@ impl NyashInterpreter {
// InstanceBoxにキャスト // InstanceBoxにキャスト
if let Some(instance) = obj_value.as_any().downcast_ref::<InstanceBox>() { if let Some(instance) = obj_value.as_any().downcast_ref::<InstanceBox>() {
// 🔥 Usage prohibition guard - check if instance is finalized
if instance.is_finalized() {
return Err(RuntimeError::InvalidOperation {
message: "Instance was finalized; further use is prohibited".to_string(),
});
}
// フィールドの値を取得 // フィールドの値を取得
let field_value = instance.get_field(field) let field_value = instance.get_field(field)
.ok_or(RuntimeError::InvalidOperation { .ok_or(RuntimeError::InvalidOperation {

View File

@ -650,11 +650,17 @@ impl NyashInterpreter {
// 継承チェーンを解決してフィールドとメソッドを収集init_fieldsも含む // 継承チェーンを解決してフィールドとメソッドを収集init_fieldsも含む
let (all_fields, all_methods) = self.resolve_inheritance(&final_box_decl)?; let (all_fields, all_methods) = self.resolve_inheritance(&final_box_decl)?;
// インスタンスを作成 // 🔥 フィールド順序と weak フィールドを準備finiシステム用
let instance = InstanceBox::new( let init_field_order = final_box_decl.init_fields.clone();
let weak_fields = final_box_decl.weak_fields.clone();
// インスタンスを作成Enhanced fini system対応
let instance = InstanceBox::new_with_box_info(
actual_class_name.clone(), actual_class_name.clone(),
all_fields, all_fields,
all_methods all_methods,
init_field_order,
weak_fields
); );
let instance_box = Box::new(instance) as Box<dyn NyashBox>; let instance_box = Box::new(instance) as Box<dyn NyashBox>;

View File

@ -275,6 +275,13 @@ impl NyashInterpreter {
let obj_value = self.execute_expression(object)?; let obj_value = self.execute_expression(object)?;
if let Some(instance) = obj_value.as_any().downcast_ref::<InstanceBox>() { if let Some(instance) = obj_value.as_any().downcast_ref::<InstanceBox>() {
// 🔥 Usage prohibition guard - check if instance is finalized
if instance.is_finalized() {
return Err(RuntimeError::InvalidOperation {
message: "Instance was finalized; further use is prohibited".to_string(),
});
}
// 🔗 Weak Reference Assignment Check // 🔗 Weak Reference Assignment Check
let box_decls = self.shared.box_declarations.read().unwrap(); let box_decls = self.shared.box_declarations.read().unwrap();
if let Some(box_decl) = box_decls.get(&instance.class_name) { if let Some(box_decl) = box_decls.get(&instance.class_name) {
@ -315,6 +322,13 @@ impl NyashInterpreter {
})?; })?;
if let Some(instance) = this_value.as_any().downcast_ref::<InstanceBox>() { if let Some(instance) = this_value.as_any().downcast_ref::<InstanceBox>() {
// 🔥 Usage prohibition guard - check if instance is finalized
if instance.is_finalized() {
return Err(RuntimeError::InvalidOperation {
message: "Instance was finalized; further use is prohibited".to_string(),
});
}
// 既存のthis.field値があればfini()を呼ぶ // 既存のthis.field値があればfini()を呼ぶ
if let Some(old_field_value) = instance.get_field(field) { if let Some(old_field_value) = instance.get_field(field) {
if let Some(old_instance) = old_field_value.as_any().downcast_ref::<InstanceBox>() { if let Some(old_instance) = old_field_value.as_any().downcast_ref::<InstanceBox>() {
@ -341,6 +355,13 @@ impl NyashInterpreter {
})?; })?;
if let Some(instance) = me_value.as_any().downcast_ref::<InstanceBox>() { if let Some(instance) = me_value.as_any().downcast_ref::<InstanceBox>() {
// 🔥 Usage prohibition guard - check if instance is finalized
if instance.is_finalized() {
return Err(RuntimeError::InvalidOperation {
message: "Instance was finalized; further use is prohibited".to_string(),
});
}
// 既存のme.field値があればfini()を呼ぶ // 既存のme.field値があればfini()を呼ぶ
if let Some(old_field_value) = instance.get_field(field) { if let Some(old_field_value) = instance.get_field(field) {
if let Some(old_instance) = old_field_value.as_any().downcast_ref::<InstanceBox>() { if let Some(old_instance) = old_field_value.as_any().downcast_ref::<InstanceBox>() {

119
test_fini_system.nyash Normal file
View File

@ -0,0 +1,119 @@
// 🔥 Comprehensive fini System Test - ChatGPT5 Design Validation
// Test Case 1: Basic finalization and usage prohibition
box SimpleResource {
init { name, value }
pack(resourceName) {
me.name = resourceName
me.value = 42
}
getValue() {
return me.value
}
fini() {
print("🔥 SimpleResource.fini(): Cleaning up " + me.name.toString())
}
}
// Test Case 2: Circular reference with weak fields
box Parent {
init { name, weak child }
pack(parentName) {
me.name = parentName
}
setChild(c) {
me.child = c
}
getName() {
return me.name
}
}
box Child {
init { id, parent }
pack(childId, p) {
me.id = childId
me.parent = p
}
// Test Case 3: weak-fini prohibition
fini() {
print("🔥 Child.fini(): Cleaning up child " + me.id.toString())
// me.parent.fini() // This should be caught and prevented
}
}
// Test Case 4: Deterministic cascade finalization
box Pipeline {
init { r1, r2, r3, weak monitor }
pack(name) {
me.r1 = new SimpleResource(name + "_r1")
me.r2 = new SimpleResource(name + "_r2")
me.r3 = new SimpleResource(name + "_r3")
}
setMonitor(m) {
me.monitor = m
}
// Custom fini with specific order control
fini() {
print("🔥 Pipeline.fini(): Custom cleanup order")
// Reverse dependency order: r3 → r2 (r1 will be auto-cascade)
me.r3.fini()
me.r2.fini()
// r1 should be automatically finalized by cascade
// monitor is weak, so it's not finalized
}
}
static box Main {
main() {
print("=== 🔥 Comprehensive fini System Test ===")
// Test 1: Basic finalization
print("\n📋 Test 1: Basic finalization and usage prohibition")
local resource = new SimpleResource("TestResource")
print("Resource value before fini: " + resource.getValue().toString())
resource.fini()
print("Resource finalized")
// This should throw an error - usage after finalization
// print("Trying to access finalized resource...")
// resource.getValue() // Should fail with "Instance was finalized"
// Test 2: Circular reference handling
print("\n📋 Test 2: Circular reference with weak fields")
local parent = new Parent("TestParent")
local child = new Child("child1", parent)
parent.setChild(child)
print("Parent: " + parent.getName().toString())
print("Before parent finalization")
parent.fini()
print("Parent finalized - child's weak reference should be safe")
// Test 3: Deterministic cascade finalization
print("\n📋 Test 3: Deterministic cascade finalization")
local pipeline = new Pipeline("TestPipeline")
local monitor = new SimpleResource("Monitor")
pipeline.setMonitor(monitor)
print("Pipeline created with resources and monitor")
pipeline.fini()
print("Pipeline finalized with custom order + auto-cascade")
print("\n✅ fini System Test Completed!")
return "All tests passed"
}
}

View File

@ -0,0 +1,51 @@
// 🔥 fini System Violation Tests - Testing guards and prohibitions
box TestResource {
init { name }
pack(resourceName) {
me.name = resourceName
}
getData() {
return "Resource: " + me.name.toString()
}
fini() {
print("🔥 TestResource.fini(): Finalizing " + me.name.toString())
}
}
box BadExample {
init { weak weakRef, strongRef }
pack(name) {
me.strongRef = new TestResource(name + "_strong")
me.weakRef = new TestResource(name + "_weak") // Will be set as weak
}
// This should trigger weak-fini prohibition
badFini() {
print("🔥 BadExample.badFini(): Attempting illegal operations")
me.weakRef.fini() // Should fail with "Cannot finalize weak field"
}
}
static box Main {
main() {
print("=== 🔥 fini System Violation Tests ===")
// Test 1: Usage after finalization prohibition
print("\n📋 Test 1: Usage after finalization (should fail)")
local resource = new TestResource("TestViolation")
print("Before fini: " + resource.getData())
resource.fini()
print("Resource finalized")
print("Attempting to access finalized resource...")
resource.getData() // Should fail with "Instance was finalized"
return "Test should have failed before reaching here"
}
}

View File

@ -0,0 +1,37 @@
// 🔥 Weak-fini Prohibition Test - Should catch me.weakField.fini()
box SimpleResource {
init { name }
pack(resourceName) {
me.name = resourceName
}
}
box BadParent {
init { weak weakChild }
pack() {
me.weakChild = new SimpleResource("WeakChild")
}
// This should trigger weak-fini prohibition
fini() {
print("🔥 BadParent.fini(): Attempting to finalize weak field")
me.weakChild.fini() // Should fail: "Cannot finalize weak field 'weakChild'"
}
}
static box Main {
main() {
print("=== 🔥 Weak-fini Prohibition Test ===")
local badParent = new BadParent()
print("BadParent created with weak child")
print("Attempting to finalize BadParent (should detect illegal weak-fini)...")
badParent.fini() // Should fail during execution of user fini()
return "Test should have failed before reaching here"
}
}