# 機能設計書 81-シーケンス変換

## 概要

本ドキュメントは、F#コンパイラにおけるシーケンス式（`seq { ... }`）の最適化変換機能の設計について記述する。この機能は、シーケンス式を状態マシンベースの効率的な列挙子実装に変換する。

### 本機能の処理概要

**業務上の目的・背景**：
F#のシーケンス式（`seq { ... }`）は遅延評価されるシーケンスを宣言的に記述できる強力な構文である。しかし、ナイーブな実装ではクロージャや継続の多用によりメモリ効率が悪化する。本機能は、シーケンス式を状態マシンにコンパイルすることで、効率的な`IEnumerable<T>`実装を生成し、ランタイムパフォーマンスを向上させる。

**機能の利用シーン**：
- `seq { ... }` 構文を使用したシーケンス式のコンパイル時
- `yield`、`yield!`、`for`、`while` などのシーケンスビルダー構文の処理時
- `try/finally` や `use` を含むリソース管理付きシーケンスの変換時

**主要な処理内容**：
1. TASTからシーケンス式パターン（SeqYield, SeqDelay, SeqAppend等）を検出
2. 2フェーズ変換：状態変数とラベルの収集（フェーズ1）、状態マシンコードの生成（フェーズ2）
3. GenerateNext（MoveNext相当）、Dispose、CheckDisposeの3メソッド生成
4. プログラムカウンタ（pc）によるジャンプテーブルの構築

**関連システム・外部連携**：
- TypedTree: 型付き抽象構文木の入力元
- TypedTreeOps: TAST操作ユーティリティ
- 最適化パイプライン: Optimizer.fsから呼び出し

**権限による制御**：
特になし。コンパイラ内部の最適化フェーズとして自動的に適用される。

## 関連画面

該当なし（コンパイラ内部機能）

## 機能種別

コンパイラ最適化機能（シーケンス式変換）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| g | TcGlobals | Yes | コンパイラグローバル状態 | null不可 |
| amap | ImportMap | Yes | インポートマップ | null不可 |
| overallExpr | Expr | Yes | 変換対象のシーケンス式 | Seq パターンにマッチすること |

### 入力データソース

- 型検査済みTAST（TypedTree）
- F#コンパイラサービスのグローバル状態

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| nextVarRef | ValRef | nextEnumerator変数への参照 |
| pcVarRef | ValRef | プログラムカウンタ変数への参照 |
| currVarRef | ValRef | 現在の値変数への参照 |
| stateVars | ValRef list | 状態変数のリスト |
| generateExpr | Expr | GenerateNext（MoveNext）メソッドの本体 |
| disposalExpr | Expr | Disposeメソッドの本体 |
| checkDisposeExpr | Expr | CheckDisposeメソッドの本体 |
| ty | TType | 生成される要素の型 |
| m | range | ソース位置情報 |

### 出力先

最適化済みTASTとしてコンパイルパイプラインに渡される

## 処理フロー

### 処理シーケンス

```
1. シーケンス式の検出
   └─ Seq g パターンでマッチング

2. フェーズ1：ConvertSeqExprCode
   ├─ 再帰的に式を解析
   ├─ SeqYield: yield式の処理、ラベル生成
   ├─ SeqDelay: 遅延式の展開
   ├─ SeqAppend: 連結式の処理
   ├─ SeqWhile: whileループの変換
   ├─ SeqUsing: useバインディングの変換
   ├─ SeqForEach: forループの変換
   ├─ SeqTryFinally: try/finallyの変換
   └─ 状態変数・エントリーポイントの収集

3. 状態マシン変数の割り当て
   ├─ pc（プログラムカウンタ）変数
   ├─ current（現在値）変数
   ├─ next（次の列挙子）変数
   └─ ラベルからPCへのマッピング

4. フェーズ2：phase2関数の実行
   ├─ generate式の生成（MoveNext相当）
   ├─ dispose式の生成
   └─ checkDispose式の生成

5. ジャンプテーブルの構築
   └─ addJumpTable関数でPC値に基づくswitch生成

6. 例外ハンドリングの追加（Dispose用）
   └─ handleExceptionsInDisposeで複数finallyの処理
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{Seq パターン?}
    B -->|No| Z[None返却]
    B -->|Yes| C[ConvertSeqExprCode フェーズ1]
    C --> D{変換成功?}
    D -->|No| Z
    D -->|Yes| E[状態変数割り当て]
    E --> F[PC・ラベルマッピング生成]
    F --> G[phase2実行]
    G --> H[GenerateNext式生成]
    H --> I[Dispose式生成]
    I --> J[CheckDispose式生成]
    J --> K[ジャンプテーブル追加]
    K --> L{significantClose?}
    L -->|Yes| M[例外ハンドラ追加]
    L -->|No| N[単純Dispose]
    M --> O[結果返却]
    N --> O
    O --> P[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-81-01 | ローカル変数判定 | let束縛変数がasyncVarsに含まれない場合はローカル変数として扱う | 変数がyield後に使用されない場合 |
| BR-81-02 | 状態変数昇格 | asyncVarsに含まれる変数は状態マシンのフィールドに昇格 | 変数がyield後も参照される場合 |
| BR-81-03 | 重要クローズ判定 | try/finallyが存在する場合はsignificantClose=true | リソース解放が必要な場合 |
| BR-81-04 | 末尾呼び出し最適化 | isTailCall=trueの場合、yield!は直接委譲 | シーケンス末尾のyield!の場合 |

### 計算ロジック

- **PC割り当て**: `pcInit = 0`, `pcs = labs |> List.mapi (fun i _ -> i + 1)`, `pcDone = labs.Length + 1`
- **戻り値コード**: `return 0` = 終了, `return 1` = 値あり, `return 2` = 末尾委譲

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

該当なし（メモリ内変換のみ）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| InternalError | 内部エラー | 非ILメソッドが解決された場合 | エラー終了 |
| - | 変換不可 | 対応していないシーケンス式パターン | None返却で通常コンパイルにフォールバック |

### リトライ仕様

リトライなし。変換不可の場合はNone返却で代替実装にフォールバック。

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

該当なし（ステートレス変換）

## パフォーマンス要件

- 変換処理はコンパイル時のみ実行
- 生成される状態マシンはヒープ割り当てを最小化
- ジャンプテーブルによる効率的な状態遷移

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

該当なし

## 備考

- 制約付きジェネリック関数を含むシーケンス式は未サポート（369行目コメント）
- or-patternやアクティブパターンを含む複雑なパターンマッチは一部未対応（415-418行目コメント）
- 再帰的なyield!は末尾呼び出し最適化されるが、完全な最適化には至らない（475-488行目コメント）

---

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

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

### 推奨読解順序

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

まず、シーケンス式変換で使用される主要なデータ型を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | LowerSequences.fs | `src/Compiler/Optimize/LowerSequences.fs` | LoweredSeqFirstPhaseResult型定義（39-66行目） |

**主要な型定義**:
- **39-66行目**: `LoweredSeqFirstPhaseResult`レコード型
  - `phase2`: 第2フェーズの変換関数（pcVar, currVar, nextVar, pcMapを受け取り、generate/dispose/checkDisposeを返す）
  - `entryPoints`: コードラベルのリスト
  - `significantClose`: Disposeで実際の処理が必要かどうか
  - `stateVars`: 状態変数のリスト
  - `asyncVars`: 非同期パスで捕捉される変数

**読解のコツ**: この型は2フェーズコンパイルの中間表現。phase2はクロージャとして保持され、ラベルからPCへのマッピングが確定した後に実行される。

#### Step 2: エントリーポイントを理解する

メインの変換関数から読み始める。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | LowerSequences.fs | `src/Compiler/Optimize/LowerSequences.fs` | ConvertSequenceExprToObject関数（98-723行目） |

**主要処理フロー**:
- **98行目**: `ConvertSequenceExprToObject` - メインエントリーポイント
- **68-69行目**: `IsPossibleSequenceExpr` - シーケンス式かどうかの事前判定
- **531-532行目**: `Seq g` パターンでシーケンス式を検出

#### Step 3: パターンマッチング処理を理解する

シーケンス式の各構文要素がどのように変換されるかを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | LowerSequences.fs | `src/Compiler/Optimize/LowerSequences.fs` | ConvertSeqExprCode関数内のパターン |

**主要処理フロー**:
- **151-156行目**: `ConvertSeqExprCode`再帰関数の定義
- **159-186行目**: `SeqYield` - yield式の処理、ラベル生成と戻り値設定
- **188-191行目**: `SeqDelay` - 遅延式の展開
- **193-221行目**: `SeqAppend` - シーケンス連結
- **223-244行目**: `SeqWhile` - whileループ
- **246-252行目**: `SeqUsing` - useバインディング（try/finallyへの変換）
- **254-286行目**: `SeqForEach` - forループ（GetEnumerator/MoveNext/Currentへの展開）
- **288-340行目**: `SeqTryFinally` - try/finally処理
- **342-352行目**: `SeqEmpty` - 空シーケンス
- **367-383行目**: `Expr.Let` - let束縛の処理（ローカル vs 状態変数の判定）

#### Step 4: 状態マシン生成を理解する

フェーズ2とジャンプテーブル生成を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | LowerSequences.fs | `src/Compiler/Optimize/LowerSequences.fs` | 状態マシン生成部分 |

**主要処理フロー**:
- **543-556行目**: PC変数、current変数、next変数の生成とラベルマッピング
- **559-560行目**: phase2の実行
- **568-578行目**: GenerateNext式のクリーンアップコード追加
- **591-612行目**: `addJumpTable`関数 - PC値に基づくswitch文生成
- **624-689行目**: `handleExceptionsInDispose` - 複数finallyの例外処理

#### Step 5: ヘルパー関数を理解する

バインディング表現の決定ロジックを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | LowerSequences.fs | `src/Compiler/Optimize/LowerSequences.fs` | 内部ヘルパー関数 |

**主要処理フロー**:
- **100-111行目**: `RepresentBindingAsLocal` - ローカル変数としての表現
- **114-137行目**: `RepresentBindingAsStateMachineLocal` - 状態変数としての表現
- **139-149行目**: `RepresentBindingsAsLifted` - トップレベル束縛としての表現
- **23-24行目**: `mkLambdaNoType` - 型なしラムダ生成
- **26-34行目**: `callNonOverloadedILMethod` - ILメソッド呼び出し

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

```
ConvertSequenceExprToObject (g, amap, overallExpr)
    │
    ├─ IsPossibleSequenceExpr (g, overallExpr)
    │
    └─ match overallExpr with Seq g (e, ty) ->
           │
           ├─ ConvertSeqExprCode (isWholeExpr, isTailCall, noDisposeLabel, currentDisposeLabel, e)
           │      │
           │      ├─ SeqYield g (e, m)
           │      │      └─ generateCodeLabel()
           │      │
           │      ├─ SeqDelay g (delayedExpr, _)
           │      │      └─ ConvertSeqExprCode (recursive)
           │      │
           │      ├─ SeqAppend g (e1, e2, m)
           │      │      ├─ ConvertSeqExprCode (e1)
           │      │      └─ ConvertSeqExprCode (e2)
           │      │
           │      ├─ SeqWhile g (guard, inner, spWhile, m)
           │      │      └─ ConvertSeqExprCode (inner)
           │      │
           │      ├─ SeqUsing g (resource, v, body, ...)
           │      │      └─ ConvertSeqExprCode (reduction)
           │      │
           │      ├─ SeqForEach g (inp, v, body, ...)
           │      │      └─ ConvertSeqExprCode (reduction)
           │      │
           │      ├─ SeqTryFinally g (e1, compensation, ...)
           │      │      └─ ConvertSeqExprCode (e1)
           │      │
           │      ├─ RepresentBindingAsLocal / RepresentBindingAsStateMachineLocal
           │      │
           │      └─ LoweredSeqFirstPhaseResult
           │
           ├─ mkMutableCompGenLocal (pcVar, currVar, nextVar)
           │
           ├─ res.phase2 (pcVarRef, currVarRef, nextVarRef, lab2pc)
           │      └─ generate, dispose, checkDispose
           │
           ├─ addJumpTable (isDisposal, expr)
           │      └─ TDSwitch / MatchBuilder
           │
           └─ handleExceptionsInDispose (disposalExpr)
                  └─ mkTryWith
```

### データフロー図

```
[入力]                        [フェーズ1]                    [フェーズ2]                    [出力]

Expr (シーケンス式)
    │
    ▼
Seq g パターン検出 ────────▶ ConvertSeqExprCode
                                   │
                                   ├─▶ entryPoints (ラベル一覧)
                                   │
                                   ├─▶ stateVars (状態変数)
                                   │
                                   ├─▶ significantClose
                                   │
                                   └─▶ phase2 (クロージャ)
                                              │
                            PC割り当て◀──────┘
                            lab2pc マップ
                                   │
                                   ▼
                            phase2(pcVar, currVar, nextVar, lab2pc)
                                   │
                                   ├──▶ generateExpr (MoveNext本体)
                                   │         │
                                   │         ▼
                                   │    addJumpTable ──▶ generateExprWithJumpTable
                                   │
                                   ├──▶ disposeExpr
                                   │         │
                                   │         ▼
                                   │    addJumpTable
                                   │         │
                                   │         ▼
                                   │    handleExceptionsInDispose ──▶ disposalExprWithJumpTable
                                   │
                                   └──▶ checkDisposeExpr
                                             │
                                             ▼
                                        addJumpTable ──▶ checkDisposeExprWithJumpTable
                                                               │
                                                               ▼
                                                    Some (nextVarRef, pcVarRef, currVarRef,
                                                          stateVars, generateExpr,
                                                          disposalExpr, checkDisposeExpr, ty, m)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| LowerSequences.fs | `src/Compiler/Optimize/LowerSequences.fs` | ソース | シーケンス式変換の実装 |
| TypedTree.fs | `src/Compiler/TypedTree/TypedTree.fs` | ソース | TAST型定義 |
| TypedTreeOps.fs | `src/Compiler/TypedTree/TypedTreeOps.fs` | ソース | TAST操作ユーティリティ |
| TypedTreeBasics.fs | `src/Compiler/TypedTree/TypedTreeBasics.fs` | ソース | 基本的なTAST操作 |
| Optimizer.fs | `src/Compiler/Optimize/Optimizer.fs` | ソース | 最適化パイプライン（呼び出し元） |
| TcGlobals.fs | `src/Compiler/TypedTree/TcGlobals.fs` | ソース | グローバル型情報 |
| MethodCalls.fs | `src/Compiler/Checking/MethodCalls.fs` | ソース | BuildILMethInfoCall等 |
