# 機能設計書 19-デストラクタ注入

## 概要

本ドキュメントは、Nimコンパイラにおけるデストラクタ注入機能の設計仕様を記述する。この機能はARC/ORC メモリ管理のためのデストラクタ呼び出し挿入とコピー最適化を担当する。

### 本機能の処理概要

デストラクタ注入機能（injectdestructors.nim）は、NimのARC/ORCメモリ管理を実現するAST変換モジュールである。変数のスコープ終了時にデストラクタを呼び出し、コピーをムーブに最適化する。

**業務上の目的・背景**：ARC（Automatic Reference Counting）とORC（Owned Reference Counting with cycle collector）は、Nimの最新のメモリ管理方式である。デストラクタ注入は、これらのメモリ管理を正しく機能させるために必要な変換を行う。最終読み取り解析によりコピーをムーブに変換し、パフォーマンスを最適化する。

**機能の利用シーン**：`--gc:arc`または`--gc:orc`が指定された場合、すべてのプロシージャに対してデストラクタ注入が実行される。

**主要な処理内容**：
1. 最終読み取り解析（isLastRead）によるムーブ判定
2. スコープベースのデストラクタ呼び出し挿入
3. sinkパラメータ最適化
4. 循環参照検出（ORC）
5. =destroy、=sink、=copy操作の生成

**関連システム・外部連携**：データフロー解析（dfa.nim）、変数分割（varpartitions.nim）、エイリアス解析（aliasanalysis.nim）と連携。

**権限による制御**：特になし。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | nimコンパイラメイン画面 | 中核機能 | メモリ管理コード生成 |

## 機能種別

AST変換 / メモリ管理 / 最適化

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| c | Con | Yes | 変換コンテキスト | nil不可 |
| n | PNode | Yes | 変換対象のAST | nil不可 |
| s | Scope | Yes | 現在のスコープ | 初期化済み |
| mode | ProcessMode | Yes | 処理モード（normal/consumed/sinkArg） | 有効な値 |

### 入力データソース

- 意味解析済みのAST
- 型情報（デストラクタ、コピー、ムーブ操作）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 変換済みAST | PNode | デストラクタ呼び出しが挿入されたAST |

### 出力先

- 変換済みASTとしてコード生成フェーズに渡す

## 処理フロー

### 処理シーケンス

```
1. コンテキスト初期化
   └─ Con構造体、Scope構造体の初期化
2. 制御フローグラフ構築
   └─ constructCfg()によるCFG生成
3. 変数の走査
   └─ p()による再帰的AST変換
4. 最終読み取り判定
   └─ isLastRead()による解析
5. デストラクタ/ムーブ/コピー生成
   └─ genDestroy(), genSink(), genCopy()
6. スコープ終了処理
   └─ processScope()によるfinally挿入
```

### フローチャート

```mermaid
flowchart TD
    A[AST入力] --> B[Con/Scope初期化]
    B --> C[p関数による走査]
    C --> D{ProcessMode判定}
    D -->|normal| E[通常処理]
    D -->|consumed| F[消費処理]
    D -->|sinkArg| G[sinkパラメータ処理]
    E --> H{isLastRead?}
    H -->|Yes| I[genSink: ムーブ生成]
    H -->|No| J[genCopy: コピー生成]
    F --> I
    G --> K[destructiveMoveVar]
    I --> L[スコープ終了時]
    J --> L
    K --> L
    L --> M[genDestroy: デストラクタ生成]
    M --> N[processScope: finally挿入]
    N --> O[変換済みAST出力]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-19-01 | 最終読み取り最適化 | 最終読み取りならムーブに変換 | isLastRead = true |
| BR-19-02 | firstWrite最適化 | 初回書き込みならデストラクタ省略 | nfFirstWrite in flags |
| BR-19-03 | カーソル除外 | cursor変数はデストラクタ不要 | sfCursor in flags |
| BR-19-04 | 循環参照マーク | ORC時、循環可能な代入にマーク | cyclicType判定 |
| BR-19-05 | スコープデストラクタ | スコープ終了時に逆順でデストラクタ実行 | 常時 |

### 計算ロジック

- 最終読み取り判定: CFGをuse/def命令で走査し、以降の使用がないことを確認
- エイリアス判定: aliases()関数でno/maybe/yesを判定

## データベース操作仕様

本機能はデータベースを使用しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| =copy不可 | コンパイルエラー | =copyが{.error.}の型でコピー必要 | エラーメッセージ表示 |
| ensureMove失敗 | コンパイルエラー | ensureMoveでコピーが発生 | エラーメッセージ表示 |
| 循環参照警告 | 警告 | ARCで循環参照を検出 | cursorアノテーション推奨 |

## トランザクション仕様

- スコープはネスト可能（parent参照で管理）
- try-finally構造でデストラクタの確実な実行を保証

## パフォーマンス要件

- 制御フローグラフ構築はプロシージャごとに1回
- 最終読み取り解析は必要な変数のみ

## セキュリティ考慮事項

- デストラクタの確実な実行によりリソースリークを防止
- 循環参照検出によりメモリリーク警告

## 備考

- sfInjectDestructorsフラグでデストラクタ注入が必要なプロシージャを識別
- `toDebug`定数でデバッグ対象シンボルを指定可能

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | injectdestructors.nim | `compiler/injectdestructors.nim` | Con構造体（30-41行目）: 変換コンテキスト |
| 1-2 | injectdestructors.nim | `compiler/injectdestructors.nim` | Scope構造体（43-52行目）: スコープ管理 |
| 1-3 | injectdestructors.nim | `compiler/injectdestructors.nim` | ProcessMode列挙型（54-57行目）: 処理モード |
| 1-4 | injectdestructors.nim | `compiler/injectdestructors.nim` | MoveOrCopyFlag列挙型（87-88行目）: ムーブ/コピーフラグ |

#### Step 2: コア関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | injectdestructors.nim | `compiler/injectdestructors.nim` | hasDestructor関数（68-73行目）: デストラクタ有無判定 |
| 2-2 | injectdestructors.nim | `compiler/injectdestructors.nim` | p関数宣言（84行目）: メイン変換関数 |
| 2-3 | injectdestructors.nim | `compiler/injectdestructors.nim` | moveOrCopy関数宣言（90行目）: ムーブ/コピー判定 |

#### Step 3: 最終読み取り解析を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | injectdestructors.nim | `compiler/injectdestructors.nim` | isLastReadImpl関数（100-164行目）: CFG解析 |
| 3-2 | injectdestructors.nim | `compiler/injectdestructors.nim` | isLastRead関数（171-175行目）: 最終読み取り判定 |
| 3-3 | injectdestructors.nim | `compiler/injectdestructors.nim` | isFirstWrite関数（177-179行目）: 初回書き込み判定 |

#### Step 4: 操作生成を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | injectdestructors.nim | `compiler/injectdestructors.nim` | genOp関数（229-262行目）: 操作生成 |
| 4-2 | injectdestructors.nim | `compiler/injectdestructors.nim` | genDestroy関数（264-266行目）: デストラクタ生成 |
| 4-3 | injectdestructors.nim | `compiler/injectdestructors.nim` | genSink関数（288-309行目）: sinkOperator生成 |
| 4-4 | injectdestructors.nim | `compiler/injectdestructors.nim` | genCopy関数（354-367行目）: コピー生成 |
| 4-5 | injectdestructors.nim | `compiler/injectdestructors.nim` | genWasMoved関数（405-417行目）: wasMoved生成 |

#### Step 5: スコープ処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | injectdestructors.nim | `compiler/injectdestructors.nim` | nestedScope関数（81-82行目）: ネストスコープ作成 |
| 5-2 | injectdestructors.nim | `compiler/injectdestructors.nim` | processScope関数（584-604行目）: スコープ終了処理 |
| 5-3 | injectdestructors.nim | `compiler/injectdestructors.nim` | pVarTopLevel関数（570-582行目）: 変数宣言処理 |

### プログラム呼び出し階層図

```
injectDestructorCalls() [エントリーポイント]
    │
    ├─ Con初期化
    │
    └─ p(n, c, s, mode) [メイン変換関数]
           │
           ├─ 変数参照の処理
           │      ├─ isLastRead() [最終読み取り判定]
           │      │      └─ constructCfg() [CFG構築]
           │      └─ moveOrCopy() [ムーブ/コピー決定]
           │             ├─ genSink() [ムーブ生成]
           │             └─ genCopy() [コピー生成]
           │
           ├─ 代入文の処理
           │      ├─ isFirstWrite() [初回書き込み判定]
           │      └─ genSink() / genCopy()
           │
           ├─ 関数呼び出しの処理
           │      └─ passCopyToSink() [sink引数処理]
           │             └─ destructiveMoveVar() [破壊的ムーブ]
           │
           └─ スコープ終了
                  ├─ processScope() [スコープ終了処理]
                  │      ├─ genDestroy() [デストラクタ生成]
                  │      └─ newTryFinally() [finally挿入]
                  └─ genWasMoved() [wasMoved挿入]
```

### データフロー図

```
[入力: 意味解析済みAST]
         │
         ▼
[制御フローグラフ構築]
  use/def/fork/goto/loop命令
         │
         ▼
[p()による走査]
         │
    ┌────┴────┬────────┐
    ▼         ▼        ▼
[変数参照]  [代入]   [呼出]
    │         │        │
    ▼         ▼        ▼
[isLastRead] [isFirstWrite] [sinkパラメータ判定]
    │         │        │
    ├─Yes─→ [genSink] ←─┤
    │         │        │
    └─No──→ [genCopy] [passCopyToSink]
                       │
                       ▼
                [destructiveMoveVar]
         │
         ▼
[スコープ終了]
  final: seq[PNode] (逆順でデストラクタ)
         │
         ▼
[processScope]
  try-finally構造生成
         │
         ▼
[出力: 変換済みAST]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| injectdestructors.nim | `compiler/injectdestructors.nim` | ソース | デストラクタ注入メイン（約1200行） |
| dfa.nim | `compiler/dfa.nim` | ソース | データフロー解析・CFG構築 |
| varpartitions.nim | `compiler/varpartitions.nim` | ソース | 変数分割解析 |
| aliasanalysis.nim | `compiler/aliasanalysis.nim` | ソース | エイリアス解析 |
| liftdestructors.nim | `compiler/liftdestructors.nim` | ソース | デストラクタ生成 |
| optimizer.nim | `compiler/optimizer.nim` | ソース | 最適化 |
