# 機能設計書 86-コレクション計算変換

## 概要

本ドキュメントは、F#コンパイラにおけるリスト内包表記や配列内包表記などのコレクション計算式の最適化変換機能の設計について記述する。この機能は、`[| for x in xs -> f x |]`のような式を効率的なループベースの実装に変換する。

### 本機能の処理概要

**業務上の目的・背景**：
F#のリスト内包表記（`[ for x in xs -> ... ]`）や配列内包表記（`[| for x in xs -> ... |]`）は、宣言的にコレクションを生成できる便利な構文である。しかし、これらは内部的に`seq { ... } |> Seq.toList`や`seq { ... } |> Seq.toArray`として実装されており、遅延評価のオーバーヘッドが発生する。本機能は、これらの式をコレクターパターン（ListCollector/ArrayCollector）を使用した効率的なループに変換することで、パフォーマンスを向上させる。

**機能の利用シーン**：
- リスト内包表記（`[ for x in xs -> ... ]`）のコンパイル時
- 配列内包表記（`[| for x in xs -> ... |]`）のコンパイル時
- `seq { ... } |> Seq.toList`パターンのコンパイル時
- `seq { ... } |> Seq.toArray`パターンのコンパイル時
- 整数範囲ループ（`[1..10]`）のコンパイル時

**主要な処理内容**：
1. `SeqToList`/`SeqToArray`パターンの検出
2. 内部シーケンス式の解析（SeqYield, SeqForEach, SeqWhile等）
3. ListCollector/ArrayCollectorを使用したループ生成
4. 整数範囲の最適化（`List.mkFromIntegralRange`/`Array.mkFromIntegralRange`）
5. `List.map`/`Array.map`パターンの最適化

**関連システム・外部連携**：
- TypedTree: 型付き抽象構文木の入力元
- LowerSequenceExpressions: シーケンス式パターンの共有
- FSharp.Core.CompilerServices: ListCollector/ArrayCollector型

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

## 関連画面

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

## 機能種別

コンパイラ最適化機能（コレクション計算式変換）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| tcVal | TcValF | Yes | 値解決関数 | null不可 |
| g | TcGlobals | Yes | コンパイラグローバル状態 | null不可 |
| amap | ImportMap | Yes | インポートマップ | null不可 |
| expr | Expr | Yes | 変換対象の式 | SeqToList/SeqToArrayパターン |

### 入力データソース

- 型検査済みTAST（TypedTree）
- コレクション型情報（ListCollector, ArrayCollector）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| expr | Expr option | 変換後の式（変換不可の場合はNone） |

### 出力先

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

## 処理フロー

### 処理シーケンス

```
1. パターン検出
   ├─ SeqToList g: seq { ... } |> Seq.toList
   └─ SeqToArray g: seq { ... } |> Seq.toArray

2. シーケンス式の解析
   └─ LowerComputedListOrArraySeqExpr
      └─ ConvertSeqExprCode
         ├─ SeqYield: yieldをcollector.Addに変換
         ├─ SeqDelay: 遅延式の展開
         ├─ SeqAppend: 連結式の処理
         ├─ SeqWhile: whileループの生成
         ├─ SeqUsing: useバインディング（try/finally）
         ├─ SeqForEach: forループの生成
         ├─ SeqTryFinally: try/finally
         ├─ SeqEmpty: 空式
         └─ 任意のシーケンス式: collector.AddMany

3. コレクターのクローズ
   └─ collector.Close()で最終コレクションを取得

4. 特殊最適化
   ├─ List.mkMap: List.mapのインライン展開
   ├─ List.mkFromIntegralRange: 整数範囲の最適化
   ├─ Array.mkMap: Array.mapのインライン展開
   └─ Array.mkFromIntegralRange: 整数範囲の最適化
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{SeqToList/SeqToArray?}
    B -->|No| Z[None返却]
    B -->|Yes| C[OptionalSeq検出]
    C --> D{シーケンス式あり?}
    D -->|No| Z
    D -->|Yes| E[ConvertSeqExprCode]
    E --> F{変換成功?}
    F -->|No| Z
    F -->|Yes| G[コレクター式生成]
    G --> H{closed?}
    H -->|Yes| I[AddManyAndCloseで終了]
    H -->|No| J[Closeを追加]
    I --> K[Some返却]
    J --> K
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-86-01 | yieldの変換 | `yield e` → `collector.Add(e)` | SeqYieldパターン |
| BR-86-02 | yield!の変換 | `yield! e` → `collector.AddMany(e)` | 任意のシーケンス式 |
| BR-86-03 | 末尾yield! | 末尾の`yield! e` → `collector.AddManyAndClose(e)` | isTailcall=true |
| BR-86-04 | 構造体Dispose | 構造体型のDisposeは直接呼び出し | isStructTy判定 |
| BR-86-05 | 空リスト最適化 | 空範囲は`[]`に最適化 | count=0の場合 |

### 計算ロジック

- **ListCollector型**: `g.mk_ListCollector_ty elemTy`
- **ArrayCollector型**: 配列要素型に基づいて構築
- **Add**: 単一要素の追加
- **AddMany**: シーケンスの追加
- **Close**: コレクションの完成と取得

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| InternalError | 内部エラー | Disposeメソッドが見つからない | エラー終了 |
| - | 変換不可 | 対応していないシーケンス式パターン | None返却 |

### リトライ仕様

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

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

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

## パフォーマンス要件

- 変換処理はコンパイル時のみ実行
- ListCollector/ArrayCollectorによる効率的なメモリ管理
- ループベースの実装による遅延評価オーバーヘッドの排除
- 整数範囲の最適化による高速なリスト/配列生成

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

該当なし

## 備考

- FSharp.Coreでは`seq { ... }`が省略されることがある（234-235行目コメント）
- isUninteresting=trueの場合、認識されないシーケンス式はエラーとして扱う（200-202行目）
- 構造体型のDisposeは特別処理（28-35行目）

---

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

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

### 推奨読解順序

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

まず、コレクション計算式の検出パターンを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | LowerComputedCollections.fs | `src/Compiler/Optimize/LowerComputedCollections.fs` | SeqToList/SeqToArrayパターン（250-259行目） |
| 1-2 | LowerComputedCollections.fs | `src/Compiler/Optimize/LowerComputedCollections.fs` | OptionalSeqパターン（236-247行目） |

**主要なパターン**:
- **250-253行目**: `SeqToList` - `seq { ... } |> Seq.toList`パターン
- **255-259行目**: `SeqToArray` - `seq { ... } |> Seq.toArray`パターン
- **236-247行目**: `OptionalSeq` - `seq { ... }`またはシーケンス型の検出

#### Step 2: コレクターメソッドを理解する

コレクターに対するメソッド呼び出しの生成を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | LowerComputedCollections.fs | `src/Compiler/Optimize/LowerComputedCollections.fs` | mkCallCollectorMethod（42-49行目） |
| 2-2 | LowerComputedCollections.fs | `src/Compiler/Optimize/LowerComputedCollections.fs` | Add/AddMany/Close（51-61行目） |

**主要処理フロー**:
- **42-49行目**: `mkCallCollectorMethod` - コレクターメソッド呼び出しの生成
- **51-52行目**: `mkCallCollectorAdd` - 単一要素追加
- **54-55行目**: `mkCallCollectorAddMany` - シーケンス追加
- **57-58行目**: `mkCallCollectorAddManyAndClose` - 追加とクローズ
- **60-61行目**: `mkCallCollectorClose` - クローズのみ

#### Step 3: シーケンス式変換を理解する

ConvertSeqExprCodeの再帰的な変換ロジックを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | LowerComputedCollections.fs | `src/Compiler/Optimize/LowerComputedCollections.fs` | LowerComputedListOrArraySeqExpr（63-227行目） |
| 3-2 | LowerComputedCollections.fs | `src/Compiler/Optimize/LowerComputedCollections.fs` | ConvertSeqExprCode（67-211行目） |

**主要処理フロー**:
- **69-71行目**: `SeqYield` - yieldをcollector.Addに変換
- **73-74行目**: `SeqDelay` - 遅延式の展開
- **76-83行目**: `SeqAppend` - 連結式の処理
- **85-91行目**: `SeqWhile` - whileループの生成
- **93-103行目**: `SeqUsing` - useバインディング（try/finally）
- **105-132行目**: `SeqForEach` - forループの生成
- **134-141行目**: `SeqTryFinally` - try/finally
- **143-145行目**: `SeqEmpty` - 空式
- **198-211行目**: 任意のシーケンス式 - AddMany/AddManyAndClose

#### Step 4: 特殊最適化を理解する

List.map/Array.mapおよび整数範囲の最適化を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | LowerComputedCollections.fs | `src/Compiler/Optimize/LowerComputedCollections.fs` | List.mkMap（263-302行目） |
| 4-2 | LowerComputedCollections.fs | `src/Compiler/Optimize/LowerComputedCollections.fs` | List.mkFromIntegralRange（305-356行目） |
| 4-3 | LowerComputedCollections.fs | `src/Compiler/Optimize/LowerComputedCollections.fs` | Array.mkMap（376行目〜） |

**主要処理フロー**:
- **263-302行目**: `List.mkMap` - List.mapのインライン展開
  - ListCollectorを使用
  - リストをイテレートしながらcollector.Addを呼び出し
- **305-356行目**: `List.mkFromIntegralRange` - 整数範囲からリスト生成
  - カウントが0の場合は空リストに最適化（348-349行目）
- **376行目〜**: `Array.mkMap` - Array.mapのインライン展開
  - 配列を直接インデックスアクセス

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

```
LowerComputedListOrArrayExpr (tcVal, g, amap, m, collectorTy, overallSeqExpr)
    │
    ├─ SeqToList g (seqExpr, m) / SeqToArray g (seqExpr, m)
    │
    ├─ OptionalSeq g amap (seqExpr)
    │
    └─ LowerComputedListOrArraySeqExpr (tcVal, g, amap, m, collectorTy, overallSeqExpr)
           │
           ├─ mkMutableCompGenLocal (collVal, collExpr)
           │
           └─ ConvertSeqExprCode (isUninteresting, isTailcall, expr)
                  │
                  ├─ SeqYield g (e, m)
                  │      └─ mkCallCollectorAdd
                  │
                  ├─ SeqDelay g (delayedExpr, _)
                  │      └─ ConvertSeqExprCode (recursive)
                  │
                  ├─ SeqAppend g (e1, e2, m)
                  │      ├─ ConvertSeqExprCode (e1)
                  │      └─ ConvertSeqExprCode (e2)
                  │
                  ├─ SeqWhile g (guardExpr, bodyExpr, ...)
                  │      └─ mkWhile
                  │
                  ├─ SeqUsing g (resource, v, bodyExpr, ...)
                  │      ├─ BuildDisposableCleanup
                  │      └─ mkTryFinally
                  │
                  ├─ SeqForEach g (inp, v, bodyExpr, ...)
                  │      ├─ callNonOverloadedILMethod "GetEnumerator"
                  │      ├─ callNonOverloadedILMethod "MoveNext"
                  │      └─ mkTryFinally
                  │
                  ├─ SeqTryFinally g (bodyExpr, compensation, ...)
                  │      └─ mkTryFinally
                  │
                  ├─ SeqEmpty g m
                  │      └─ mkUnit
                  │
                  └─ arbitrarySeqExpr
                         ├─ (isTailcall) mkCallCollectorAddManyAndClose
                         └─ mkCallCollectorAddMany
```

### データフロー図

```
[入力]                        [パターン検出]                  [変換]

Expr
    │
    ▼
SeqToList / SeqToArray ────▶ OptionalSeq
                                   │
                                   ├─▶ (seqExpr, elemTy)
                                   │
                                   ▼
                            LowerComputedListOrArraySeqExpr
                                   │
                                   ├─▶ collVal: ListCollector<T> / ArrayCollector<T>
                                   │
                                   ├─▶ ConvertSeqExprCode
                                   │       │
                                   │       ├─▶ SeqYield → collector.Add(e)
                                   │       ├─▶ SeqForEach → while (enum.MoveNext()) { ... }
                                   │       ├─▶ SeqWhile → while (guard) { body }
                                   │       ├─▶ SeqUsing → let v = resource; try ... finally dispose
                                   │       └─▶ arbitrary → collector.AddMany(seq) / .AddManyAndClose(seq)
                                   │
                                   └─▶ closed?
                                         │
                                         ├─▶ (true) overallSeqExprR
                                         │
                                         └─▶ (false) overallSeqExprR; collector.Close()
                                                  │
                                                  ▼
                                           変換済みExpr (Some)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| LowerComputedCollections.fs | `src/Compiler/Optimize/LowerComputedCollections.fs` | ソース | コレクション計算式変換の実装 |
| LowerSequenceExpressions.fs | `src/Compiler/Optimize/LowerSequences.fs` | ソース | シーケンス式パターン（SeqYield等） |
| TypedTree.fs | `src/Compiler/TypedTree/TypedTree.fs` | ソース | TAST型定義 |
| TypedTreeOps.fs | `src/Compiler/TypedTree/TypedTreeOps.fs` | ソース | TAST操作ユーティリティ |
| TcGlobals.fs | `src/Compiler/TypedTree/TcGlobals.fs` | ソース | mk_ListCollector_ty等 |
| MethodCalls.fs | `src/Compiler/Checking/MethodCalls.fs` | ソース | BuildMethodCall |
