Files
hakorune/docs/説明書/reference/finalization-system.md

6.8 KiB
Raw Blame History

🔥 Nyash finiシステム - 論理的解放フック

最終更新: 2025年8月13日 - ChatGPT5協議による革命的設計完了

🎯 概要

Nyashのfini()システムは、物理的メモリ破棄ではなく論理的使用終了を宣言する革新的なリソース管理システムです。Everything is Box哲学と完全に統合され、予測可能で安全なリソース管理を実現します。

🌟 核心コンセプト

📝 論理的解放フック

box MyResource {
    init { name, file }
    
    fini() {
        print("Resource " + me.name + " is being finalized")
        // ファイルクローズなどのクリーンアップ処理
        // 物理的メモリは共有参照が残っていても論理的には「終了」
    }
}

重要: fini()は「このオブジェクトをもう使わない」という宣言であり、物理的な即時破棄ではありません。

🔄 実行順序(最終仕様)

自動カスケード解放

box Pipeline {
    init { r1, r2, r3, weak monitor }
    
    fini() {
        // 1) ユーザー定義処理(柔軟な順序制御可能)
        me.r3.fini()  // 依存関係でr3→r2の順
        me.r2.fini()
        
        // 2) 自動カスケード: 残りのr1がinit宣言順で自動解放
        // 3) weakフィールドは対象外lazy nil化
    }
}

決定的な解放順序

  1. finalized チェック - 既に解放済みなら何もしないidempotent
  2. 再入防止 - in_finalizationフラグで再帰呼び出し防止
  3. ユーザー定義fini()実行 - カスタムクリーンアップ処理
  4. 自動カスケード - init宣言順で未処理フィールドを解放
  5. フィールドクリア - 全フィールドを無効化
  6. finalized設定 - 以後の使用を禁止

⚠️ 厳格な禁止事項

weak フィールドへのfini呼び出し禁止

box Parent {
    init { weak child }
    
    fini() {
        // ❌ 絶対にダメ!ビルドエラーまたは実行時エラー
        // me.child.fini()  
        
        // ✅ 正しい方法
        me.child = null    // 参照解除
        // または自動nil化に任せる
    }
}

理由: weak参照は所有権を持たない非所有参照のため、fini()を呼ぶ権利がありません。

finalized後の使用禁止

box Example { }

local x = new Example()
x.fini()

// ❌ 以下は全てエラー
x.someMethod()      // → "Instance was finalized; further use is prohibited"
x.field = value     // → 同上
local val = x.field // → 同上

🏗️ 実装アーキテクチャ

InstanceBox拡張

pub struct InstanceBox {
    // 既存フィールド...
    
    init_field_order: Vec<String>,                    // 決定的カスケード順序
    weak_fields_union: HashSet<String>,               // weak判定高速化
    in_finalization: bool,                            // 再入防止
    finalized: bool,                                  // 使用禁止フラグ
}

実行時ガード

  • メソッド呼び出し: finalizedチェック → エラー
  • フィールドアクセス: finalizedチェック → エラー
  • フィールド代入: finalizedチェック → エラー

💡 使用例とパターン

基本的な使用例

box FileHandler {
    init { filename, handle }
    
    pack(name) {
        me.filename = name
        me.handle = openFile(name)
    }
    
    fini() {
        if (me.handle != null) {
            closeFile(me.handle)
            print("File " + me.filename + " closed")
        }
    }
}

// 使用
local handler = new FileHandler("data.txt")
// ... ファイル操作 ...
handler.fini()  // 明示的クリーンアップ

再代入時の自動解放

box Holder { init { resource } }
box Resource { fini() { print("Resource cleaned up") } }

local h = new Holder()
h.resource = new Resource()     // 新しいリソース設定
h.resource = new Resource()     // → 前のリソースが自動的にfini()される

カスタム解放順序

box DatabaseConnection {
    init { transaction, connection, logger }
    
    fini() {
        // 依存関係に基づく手動順序制御
        if (me.transaction != null) {
            me.transaction.rollback()
            me.transaction.fini()
        }
        
        if (me.connection != null) {
            me.connection.close()
            me.connection.fini()
        }
        
        // loggerは自動カスケードに任せる
    }
}

循環参照の安全な解決

box Node {
    init { data, weak parent, children }
    
    pack(value) {
        me.data = value
        me.children = new ArrayBox()
    }
    
    addChild(child) {
        me.children.push(child)
        child.setParent(me)  // 子→親はweak参照
    }
    
    fini() {
        // 子ノードを先に解放
        loop (me.children.length() > 0) {
            local child = me.children.pop()
            child.fini()
        }
        // 親への参照は自動的にnil化される
    }
}

🧪 テストパターン

基本動作テスト

box Counter {
    init { value }
    pack() { me.value = 0 }
    increment() { me.value = me.value + 1 }
    fini() { print("Counter finalized with value: " + me.value.toString()) }
}

local c = new Counter()
c.increment()
c.increment()
c.fini()
// c.increment()  // → エラー: finalized後の使用禁止

循環参照テスト

box Parent {
    init { child }
    pack() {
        me.child = new Child()
        me.child.setParent(me)
    }
    fini() { print("Parent finalized") }
}

box Child {
    init { weak parent }
    setParent(p) { me.parent = p }
    fini() { print("Child finalized") }
}

local p = new Parent()
p.fini()  // Parent → Child の順で解放、リークなし

🎯 期待される効果

メモリ安全性

  • 循環参照リーク完全防止: weak参照とfiniの組み合わせ
  • 二重解放防止: idempotentな設計
  • 使用禁止ガード: finalized後の誤用防止

予測可能性

  • 決定的順序: init宣言順による自動カスケード
  • 明示的制御: ユーザー定義fini()での柔軟な順序指定
  • エラーメッセージ: 明確で修正提案付きのエラー

開発体験

  • 直感的: リソースの「終了宣言」として理解しやすい
  • デバッグ容易: 解放タイミングが明確
  • 保守性: 依存関係の変更に強い設計

📚 関連ドキュメント


Everything is Box, Everything is Finalized! 🔥