# 機能設計書 17-クロージャ変換

## 概要

本ドキュメントは、Nimコンパイラにおけるクロージャ変換機能の設計仕様を記述する。この機能はクロージャイテレータの状態機械変換およびラムダリフティングを担当する。

### 本機能の処理概要

クロージャ変換機能は、クロージャイテレータを状態機械に変換し、ネストされたプロシージャのキャプチャ変数をヒープに配置するラムダリフティングを行う。closureiters.nimとlambdalifting.nimの2つのモジュールで構成される。

**業務上の目的・背景**：Nimのクロージャイテレータは、yieldステートメントで一時停止・再開可能な反復子である。これを実現するには、イテレータの本体を状態機械に変換し、各yield間の状態を保持する必要がある。また、ネストされたプロシージャが外側のスコープの変数をキャプチャする場合、これらの変数をヒープ上の環境オブジェクトに配置する必要がある。

**機能の利用シーン**：`iterator ... {.closure.}`で定義されたクロージャイテレータ、およびネストされたプロシージャがスコープ外の変数を参照する場合に使用される。

**主要な処理内容**：
1. クロージャイテレータ本体のyieldによる分割
2. 状態変数（:state）による制御フロー管理
3. 例外処理のための例外テーブル生成
4. キャプチャ変数の検出と環境オブジェクト作成
5. 環境オブジェクトへのアクセス変換
6. 親環境へのup参照チェーン構築

**関連システム・外部連携**：変換フェーズ（transf.nim）から呼び出され、コード生成フェーズに変換済みASTを渡す。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | nimコンパイラメイン画面 | 中核機能 | クロージャのコンパイル |

## 機能種別

AST変換 / メモリ管理 / コード生成支援

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| ctx | Ctx | Yes | クロージャイテレータ変換コンテキスト | nil不可 |
| n | PNode | Yes | イテレータ本体のAST | nil不可 |
| fn | PSym | Yes | クロージャイテレータシンボル | isIterator(fn) = true |
| g | ModuleGraph | Yes | モジュールグラフ | nil不可 |

### 入力データソース

- 意味解析済みのクロージャイテレータAST
- シンボルテーブル

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 変換済みAST | PNode | 状態機械に変換されたイテレータ本体 |
| 環境オブジェクト型 | PType | キャプチャ変数を含む環境型 |
| 例外テーブル | seq[int] | 状態ごとの例外着地状態 |

### 出力先

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

## 処理フロー

### 処理シーケンス

```
1. 状態分析
   └─ yield文の位置を特定
2. 本体の分割
   └─ yieldごとに新しい状態を作成
3. 状態遷移の構築
   └─ case文による状態機械生成
4. 例外処理の変換
   └─ try/except/finallyの状態機械化
5. 環境オブジェクトの作成
   └─ キャプチャ変数の検出と配置
6. 変数アクセスの変換
   └─ 直接アクセスから環境経由に変換
```

### フローチャート

```mermaid
flowchart TD
    A[クロージャイテレータ入力] --> B[hasYields: yield有無チェック]
    B -->|有| C[lowerStmtListExprs: 式の低レベル化]
    C --> D[本体のyieldで分割]
    D --> E[各状態の作成]
    E --> F{try/except内にyield?}
    F -->|Yes| G[例外テーブル生成]
    F -->|No| H[状態機械構築]
    G --> H
    H --> I[case文による分岐生成]
    I --> J[ラムダリフティング]
    J --> K[キャプチャ変数検出]
    K --> L[環境オブジェクト生成]
    L --> M[アクセス変換]
    M --> N[変換完了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-17-01 | 状態変数優先 | :state変数は環境オブジェクトの最初のフィールド | 常時 |
| BR-17-02 | 終了状態 | 状態=-1はイテレータ終了を示す | 常時 |
| BR-17-03 | キャプチャ制限 | ViewType（借用型）はキャプチャ不可 | illegalCapture判定 |
| BR-17-04 | 親環境参照 | ネストされたプロシージャは:upフィールドで親環境を参照 | ネスト時 |

### 計算ロジック

- 状態番号: yieldごとに連番を割り当て
- 例外テーブル: `exceptionTable[状態] = 例外着地状態`

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| illegalCapture | キャプチャエラー | 借用型のキャプチャ | エラーメッセージ表示 |
| 呼び出し規約エラー | 変換エラー | 非closure規約でのキャプチャ | エラーメッセージ表示 |

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

該当なし。

## パフォーマンス要件

- 状態機械変換はコンパイル時のみ実行
- varStatesテーブルで変数の複数状態使用を検出し、リフティング判断

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

- 環境オブジェクトはヒープに配置されメモリ安全性を確保

## 備考

- C codegenは:stateが最初のフィールドであることに依存
- `{.closure.}`呼び出し規約が必須
- finallyPathでfinally実行後の遷移先を制御

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | closureiters.nim | `compiler/closureiters.nim` | FinallyTarget構造体（150-153行目）: finally制御 |
| 1-2 | closureiters.nim | `compiler/closureiters.nim` | State構造体（155-160行目）: 状態の表現 |
| 1-3 | closureiters.nim | `compiler/closureiters.nim` | Ctx構造体（162-182行目）: 変換コンテキスト |

#### Step 2: クロージャイテレータ変換を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | closureiters.nim | `compiler/closureiters.nim` | hasYields()関数（300-312行目）: yield検出 |
| 2-2 | closureiters.nim | `compiler/closureiters.nim` | newState()関数（257-264行目）: 状態作成 |
| 2-3 | closureiters.nim | `compiler/closureiters.nim` | newStateAccess()/newStateAssgn()（190-197行目）: 状態アクセス |

#### Step 3: ラムダリフティングを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | lambdalifting.nim | `compiler/lambdalifting.nim` | upName/paramName/envName定数（125-127行目）: 環境変数名 |
| 3-2 | lambdalifting.nim | `compiler/lambdalifting.nim` | createEnvObj()関数（151-155行目）: 環境オブジェクト作成 |
| 3-3 | lambdalifting.nim | `compiler/lambdalifting.nim` | makeClosure()関数（219-231行目）: クロージャ作成 |
| 3-4 | lambdalifting.nim | `compiler/lambdalifting.nim` | getEnvParam()関数（178-186行目）: 環境パラメータ取得 |

#### Step 4: 検出パスを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | lambdalifting.nim | `compiler/lambdalifting.nim` | DetectionPass構造体（297-304行目）: 検出パス状態 |
| 4-2 | lambdalifting.nim | `compiler/lambdalifting.nim` | interestingVar()関数（195-198行目）: キャプチャ対象判定 |
| 4-3 | lambdalifting.nim | `compiler/lambdalifting.nim` | illegalCapture()関数（200-201行目）: 不正キャプチャ判定 |

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

```
[closureiters.nim - クロージャイテレータ変換]
transformClosureIterator()
    │
    ├─ hasYields() [yield検出]
    │
    ├─ lowerStmtListExprs() [式の低レベル化]
    │
    ├─ splitIntoStates() [状態分割]
    │      ├─ newState() [新規状態作成]
    │      └─ collectExceptState() [例外状態収集]
    │
    └─ generateStateCase() [状態機械生成]
           └─ newStateAssgn() [状態代入]

[lambdalifting.nim - ラムダリフティング]
liftLambdas()
    │
    ├─ initDetectionPass() [検出パス初期化]
    │
    ├─ detectCapturedVars() [キャプチャ変数検出]
    │      ├─ interestingVar() [対象判定]
    │      ├─ illegalCapture() [不正判定]
    │      └─ markAsClosure() [クロージャマーク]
    │
    ├─ createEnvObj() [環境オブジェクト作成]
    │      └─ createStateField() [状態フィールド作成]
    │
    └─ transformOuter() [外側変換]
           └─ makeClosure() [クロージャ生成]
```

### データフロー図

```
[入力: クロージャイテレータAST]
         │
         ▼
[yield検出] ──→ [状態分割]
         │           │
         ▼           ▼
[例外処理検出] ──→ [例外テーブル生成]
         │
         ▼
[状態機械構築] ──→ case :state
         │         of 0: ...
         │         of 1: ...
         │         else: return
         ▼
[キャプチャ変数検出]
         │
         ▼
[環境オブジェクト型生成]
  type Env = object
    :state: int
    :up: ptr ParentEnv
    capturedVar1: T1
    capturedVar2: T2
         │
         ▼
[アクセス変換]
  v → env.v
         │
         ▼
[出力: 変換済みAST]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| closureiters.nim | `compiler/closureiters.nim` | ソース | クロージャイテレータ→状態機械変換 |
| lambdalifting.nim | `compiler/lambdalifting.nim` | ソース | ラムダリフティング（約1000行） |
| transf.nim | `compiler/transf.nim` | ソース | 変換フェーズメイン |
| lowerings.nim | `compiler/lowerings.nim` | ソース | AST低レベル化ユーティリティ |
