# 機能設計書 18-Nilチェック

## 概要

本ドキュメントは、NimコンパイラにおけるNilチェック機能の設計仕様を記述する。この機能は静的解析によりnilポインタ参照の可能性を検出する。

### 本機能の処理概要

Nilチェック機能（nilcheck.nim）は、参照型変数のnil可能性を追跡し、潜在的なnilポインタ参照を検出する静的解析モジュールである。データフロー解析に基づき、各変数のnil状態を追跡する。

**業務上の目的・背景**：nilポインタ参照はランタイムエラーの主要な原因の一つである。静的解析によりコンパイル時にこれらの問題を検出することで、より安全なコードを生成できる。Nimの`not nil`型アノテーションと連携して、nil安全性を保証する。

**機能の利用シーン**：`--strictNotNil`コンパイラオプションが有効な場合、または`not nil`型が使用されている場合に静的解析が実行される。

**主要な処理内容**：
1. 変数のnil状態追跡（Safe, MaybeNil, Nil, Unreachable）
2. 制御フロー分岐での状態マージ
3. 条件式によるnil状態の絞り込み
4. エイリアス集合による関連変数の追跡
5. 履歴によるエラーメッセージの改善

**関連システム・外部連携**：意味解析（sem.nim）から呼び出され、警告・エラーメッセージを生成する。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | nimコンパイラメイン画面 | 中核機能 | コンパイル時静的解析 |

## 機能種別

静的解析 / 型安全性検証

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| n | PNode | Yes | 解析対象のAST | nil不可 |
| ctx | NilCheckerContext | Yes | Nilチェックコンテキスト | nil不可 |
| map | NilMap | Yes | 現在のnil状態マップ | nil不可 |

### 入力データソース

- 意味解析済みのAST
- 型情報

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Check | Check | チェック結果（nilability, map, elements） |
| 警告 | seq[string] | nil参照の可能性に関する警告 |

### 出力先

- コンパイラ警告・エラーメッセージ

## 処理フロー

### 処理シーケンス

```
1. コンテキスト初期化
   └─ 式のインデックス付け
2. 各ノードの解析
   └─ check()による再帰的走査
3. 状態の更新
   └─ 代入、条件分岐での状態変更
4. マップのマージ
   └─ 分岐の合流点での状態統合
5. 警告生成
   └─ MaybeNil/Nilでのderef検出
```

### フローチャート

```mermaid
flowchart TD
    A[解析開始] --> B[式インデックス構築]
    B --> C[check関数による走査]
    C --> D{ノード種別判定}
    D -->|代入| E[nilability更新]
    D -->|条件分岐| F[分岐ごとにマップ分岐]
    D -->|参照解決| G{nil状態チェック}
    D -->|関数呼び出し| H[引数の状態更新]
    G -->|Nil| I[エラー報告]
    G -->|MaybeNil| J[警告報告]
    G -->|Safe| K[処理継続]
    F --> L[checkCondition: 条件解析]
    L --> M[分岐マップ生成]
    M --> N[合流点でマージ]
    E --> O[結果返却]
    H --> O
    N --> O
    K --> O
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-18-01 | 初期状態 | ref型パラメータはMaybeNil | 関数パラメータ |
| BR-18-02 | new後Safe | new(ref)の後はSafe | new呼び出し |
| BR-18-03 | 代入伝播 | a = bでaはbのnilability継承 | 代入文 |
| BR-18-04 | 条件絞り込み | if isNil(x)の条件内でxはNil | 条件分岐 |
| BR-18-05 | 分岐マージ | 分岐の合流点ではunionを取る | 分岐終了 |

### 計算ロジック

- Nilability列挙: Parent, Safe, MaybeNil, Nil, Unreachable
- マージルール: Safe + Nil = Unreachable, Safe + MaybeNil = MaybeNil

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| nilDeref | 警告 | MaybeNilのderef | if isNilガード追加を提案 |
| nilError | エラー | Nilのderef | エラーメッセージ表示 |

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

該当なし。

## パフォーマンス要件

- データフロー解析はコンパイル時のみ実行
- Herb Sutter方式: ループは0,1,2回の反復を仮定

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

- nilポインタ参照の防止によりメモリ安全性向上

## 備考

- resultIdは-1で特別扱い
- SeqOfDistinct型で型安全なインデックス管理

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | nilcheck.nim | `compiler/nilcheck.nim` | Nilability列挙型（166行目）: Safe, MaybeNil, Nil等 |
| 1-2 | nilcheck.nim | `compiler/nilcheck.nim` | TransitionKind列挙型（125行目）: 状態遷移の理由 |
| 1-3 | nilcheck.nim | `compiler/nilcheck.nim` | History構造体（128-132行目）: 遷移履歴 |
| 1-4 | nilcheck.nim | `compiler/nilcheck.nim` | NilCheckerContext構造体（135-144行目）: チェッカーコンテキスト |
| 1-5 | nilcheck.nim | `compiler/nilcheck.nim` | NilMap構造体（148-154行目）: nil状態マップ |

#### Step 2: 型安全なインデックスを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | nilcheck.nim | `compiler/nilcheck.nim` | Symbol型（114行目）: シンボルID |
| 2-2 | nilcheck.nim | `compiler/nilcheck.nim` | ExprIndex型（117行目）: 式インデックス |
| 2-3 | nilcheck.nim | `compiler/nilcheck.nim` | SetIndex型（120行目）: エイリアス集合インデックス |
| 2-4 | nilcheck.nim | `compiler/nilcheck.nim` | SeqOfDistinct型（65行目）: 型安全シーケンス |

#### Step 3: 主要な関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | nilcheck.nim | `compiler/nilcheck.nim` | check関数宣言（218行目）: メイン解析関数 |
| 3-2 | nilcheck.nim | `compiler/nilcheck.nim` | checkCondition関数宣言（219行目）: 条件解析 |
| 3-3 | nilcheck.nim | `compiler/nilcheck.nim` | newNilMap関数（223-251行目）: マップ初期化 |
| 3-4 | nilcheck.nim | `compiler/nilcheck.nim` | symbol関数（292-308行目）: シンボル取得 |
| 3-5 | nilcheck.nim | `compiler/nilcheck.nim` | store関数（392-397行目）: 状態格納 |

#### Step 4: エイリアス解析を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | nilcheck.nim | `compiler/nilcheck.nim` | aliasSet関数（384-388行目）: エイリアス集合取得 |

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

```
checkNilability() [エントリーポイント]
    │
    ├─ NilCheckerContext初期化
    │      └─ 式のインデックス付け
    │
    └─ check(n, ctx, map) [再帰的解析]
           │
           ├─ 代入文の処理
           │      └─ store() [状態更新]
           │
           ├─ 条件分岐の処理
           │      ├─ checkCondition() [条件解析]
           │      │      └─ 条件に基づくマップ分岐
           │      └─ マップマージ
           │
           ├─ 参照解決の処理
           │      └─ nilability判定 → 警告生成
           │
           └─ 関数呼び出しの処理
                  └─ 引数状態更新
```

### データフロー図

```
[入力: AST + 型情報]
         │
         ▼
[式インデックス構築]
  symbolIndices: Table[Symbol, ExprIndex]
  expressions: SeqOfDistinct[ExprIndex, PNode]
         │
         ▼
[NilMap初期化]
  expressions: Nilability[]
  history: History[][]
  sets: IntSet[] (エイリアス集合)
         │
         ▼
[check()による走査]
         │
    ┌────┴────┐
    ▼         ▼
[Safe]    [MaybeNil/Nil]
    │         │
    ▼         ▼
[継続]    [警告/エラー生成]
         │
         ▼
[出力: Check結果]
  nilability: 最終状態
  map: 更新されたNilMap
  elements: 各要素の状態
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| nilcheck.nim | `compiler/nilcheck.nim` | ソース | Nilチェック静的解析（約800行） |
| sem.nim | `compiler/sem.nim` | ソース | 意味解析メイン（nilcheckを呼び出し） |
| ast.nim | `compiler/ast.nim` | ソース | AST定義 |
| renderer.nim | `compiler/renderer.nim` | ソース | AST表示（エラーメッセージ用） |
