🔥 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:
119
src/instance.rs
119
src/instance.rs
@ -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 {
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
@ -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>;
|
||||||
|
|||||||
@ -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
119
test_fini_system.nyash
Normal 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"
|
||||||
|
}
|
||||||
|
}
|
||||||
51
test_fini_violations.nyash
Normal file
51
test_fini_violations.nyash
Normal 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"
|
||||||
|
}
|
||||||
|
}
|
||||||
37
test_weak_fini_prohibition.nyash
Normal file
37
test_weak_fini_prohibition.nyash
Normal 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"
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user