# 機能設計書 83-引数の分解

## 概要

本ドキュメントは、F#コンパイラにおけるタプル引数の分解（Detuple）最適化機能の設計について記述する。この機能は、呼び出しサイトでのタプル割り当てを排除し、関数引数を個別のパラメータに展開することでパフォーマンスを向上させる。

### 本機能の処理概要

**業務上の目的・背景**：
F#では非カリー化スタイルでコードを書くと、呼び出しサイトでタプルが割り当てられる。例えば、`f(a, b)`という呼び出しでは、引数を格納するためにタプルオブジェクトがヒープに割り当てられる。本機能は、すべての呼び出しサイトでタプル引数が明示的に構築される場合、その関数を個別引数を取る形式に変換することで、冗長なタプル割り当てを排除する。

**機能の利用シーン**：
- 内部関数（トップレベルでない関数）のタプル引数の最適化時
- 非カリー化スタイルで書かれたコードのコンパイル時
- 再帰関数でタプル引数を使用している場合

**主要な処理内容**：
1. 使用情報の収集（GetUsageInfoOfImplFile）
2. 呼び出しパターンの分析（commonCallPattern）
3. 変換の決定（determineTransforms）
4. バインディングの変換（passBind）
5. 呼び出しサイトの修正（fixupApp）

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

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

## 関連画面

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

## 機能種別

コンパイラ最適化機能（タプル分解）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| ccu | CcuThunk | Yes | コンパイル単位 | null不可 |
| g | TcGlobals | Yes | コンパイラグローバル状態 | null不可 |
| expr | TypedImplFile | Yes | 変換対象の型付き実装ファイル | 有効なTAST |

### 入力データソース

- 型検査済みTAST（TypedTree）
- 関数の使用情報（呼び出しサイト情報）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| expr | TypedImplFile | 変換後の型付き実装ファイル |

### 出力先

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

## 処理フロー

### 処理シーケンス

```
1. 使用情報の収集
   └─ GetUsageInfoOfImplFile
      ├─ 各値の呼び出しサイト情報を収集
      ├─ バインディング情報を収集
      └─ 再帰バインディング情報を収集

2. 呼び出しパターンの分析
   ├─ sitesCPs: 各呼び出しサイトのCallPatternを抽出
   └─ commonCallPattern: すべてのサイトで共通のパターンを計算

3. 変換の決定
   └─ determineTransforms
      ├─ eligibleVal: 変換対象かどうかを判定
      ├─ decideFormalSuggestedCP: 定義側のタプル構造を分析
      ├─ zipCallPatternArgTys: 型とパターンをマッチング
      └─ mkTransform: 変換情報を生成

4. バインディングの変換
   └─ passBind
      ├─ transformedFormals: 新しい仮引数を生成
      └─ transRebind: 元の変数への再束縛を生成

5. 呼び出しサイトの修正
   └─ fixupApp
      ├─ collapseArgs: 引数を展開
      └─ mkLets: let束縛でラップ
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[GetUsageInfoOfImplFile]
    B --> C[各値の呼び出しサイト収集]
    C --> D[determineTransforms]
    D --> E{eligibleVal?}
    E -->|No| F[変換対象外]
    E -->|Yes| G[commonCallPattern計算]
    G --> H{trivialCP?}
    H -->|Yes| F
    H -->|No| I[mkTransform]
    I --> J[passImplFile]
    J --> K[passBind - バインディング変換]
    K --> L[fixupApp - 呼び出し修正]
    L --> M[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-83-01 | 適格性チェック | InlineInfo=Never、mutable、byref、メンバー、トップレベルの値は変換対象外 | eligibleVal関数 |
| BR-83-02 | タプル構造一致 | すべての呼び出しサイトで同じタプル構造がある場合のみ変換 | commonCallPattern |
| BR-83-03 | 参照タプルのみ | 構造体タプル（ValueTuple）は変換対象外 | evalTupInfoIsStruct判定 |
| BR-83-04 | 使用パターン優先 | 定義側のタプル射影使用が変換パターンを制限 | decideFormalSuggestedCP |

### 計算ロジック

- **TupleStructure**: `UnknownTS`（不明）または`TupleTS of TupleStructure list`（タプル構造）
- **CallPattern**: 各引数位置のTupleStructureのリスト
- **andTS**: 2つのTupleStructureの交差を計算
- **commonCallPattern**: すべての呼び出しパターンの交差を計算

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| internalError | 内部エラー | 空タプル/シングルトンタプル検出 | エラー終了（発生すべきでない） |
| internalError | 内部エラー | rebuildTS で fringe 不足 | エラー終了（発生すべきでない） |

### リトライ仕様

リトライなし。内部エラーはバグを示す。

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

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

## パフォーマンス要件

- 変換処理はコンパイル時のみ実行
- タプル割り当てを排除することでランタイムパフォーマンス向上
- ヒープ割り当ての削減によりGC圧力を軽減

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

該当なし

## 備考

- トップレベル関数とメソッドはF#の表現選択により自動的に分解される（33-35行目コメント）
- この最適化は内部関数、特にラムダリフティング（TLR）されていない関数にのみ適用される
- すべての呼び出しサイトで明示的なタプルがない場合は変換しない（関数内にタプル割り当てが発生するため）

---

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

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

### 推奨読解順序

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

まず、タプル分解で使用される主要なデータ型を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | DetupleArgs.fs | `src/Compiler/Optimize/DetupleArgs.fs` | TupleStructure型（378-380行目） |
| 1-2 | DetupleArgs.fs | `src/Compiler/Optimize/DetupleArgs.fs` | Results型（180-197行目） |
| 1-3 | DetupleArgs.fs | `src/Compiler/Optimize/DetupleArgs.fs` | Transform型（489-492行目） |
| 1-4 | DetupleArgs.fs | `src/Compiler/Optimize/DetupleArgs.fs` | TransformedFormal型（475-484行目） |

**主要な型定義**:
- **378-380行目**: `TupleStructure` - タプル構造を表す判別共用体
  - `UnknownTS`: 不明な構造（タプルでない、または分解不可）
  - `TupleTS of TupleStructure list`: タプル構造（要素もTupleStructure）

- **180-197行目**: `Results` - 使用情報を保持するレコード
  - `Uses`: 値から使用コンテキストへのマップ
  - `Defns`: 値からバインディング式へのマップ
  - `RecursiveBindings`: 相互再帰情報
  - `TopLevelBindings`: トップレベルバインディングの集合

- **489-492行目**: `Transform` - 変換情報を保持するレコード
  - `transformCallPattern`: 変換するCallPattern
  - `transformedFormals`: 新しい仮引数の情報
  - `transformedVal`: 置換後の値

**読解のコツ**: TupleStructureは再帰的なデータ構造で、ネストしたタプル`(a, (b, c))`は`TupleTS [UnknownTS; TupleTS [UnknownTS; UnknownTS]]`として表現される。

#### Step 2: 使用情報収集を理解する

グローバル使用分析の実装を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | DetupleArgs.fs | `src/Compiler/Optimize/DetupleArgs.fs` | GlobalUsageAnalysisモジュール（160-345行目） |
| 2-2 | DetupleArgs.fs | `src/Compiler/Optimize/DetupleArgs.fs` | GetUsageInfoOfImplFile関数（342-345行目） |

**主要処理フロー**:
- **160-171行目**: `GetValsBoundInExpr` - 式内でバインドされる値を収集
- **173行目**: `accessor`型 - タプルフィールドアクセスを表す
- **207-214行目**: `logUse` - 値の使用を記録
- **280-336行目**: `UsageFolders` - 式をフォールドして使用情報を収集
- **287-320行目**: `exprUsageIntercept` - 値参照と関数適用をインターセプト

#### Step 3: 呼び出しパターン分析を理解する

CallPatternの計算ロジックを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | DetupleArgs.fs | `src/Compiler/Optimize/DetupleArgs.fs` | CallPattern関連（443-469行目） |
| 3-2 | DetupleArgs.fs | `src/Compiler/Optimize/DetupleArgs.fs` | TupleStructure操作（387-418行目） |

**主要処理フロー**:
- **387-395行目**: `andTS` - 2つのTupleStructureの交差
- **443行目**: `CallPattern`型 - TupleStructure list
- **445行目**: `argsCP` - 引数リストからCallPatternを生成
- **448-455行目**: `minimalCallPattern` - 末尾のUnknownTSを削除
- **458-466行目**: `commonCallPattern` - すべてのCallPatternの交差

#### Step 4: 変換決定を理解する

変換の決定ロジックを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | DetupleArgs.fs | `src/Compiler/Optimize/DetupleArgs.fs` | determineTransforms関数（689-709行目） |
| 4-2 | DetupleArgs.fs | `src/Compiler/Optimize/DetupleArgs.fs` | decideTransform関数（641-667行目） |
| 4-3 | DetupleArgs.fs | `src/Compiler/Optimize/DetupleArgs.fs` | eligibleVal関数（677-687行目） |

**主要処理フロー**:
- **677-687行目**: `eligibleVal` - 変換対象かどうかの判定
  - InlineInfo=Never、mutable、byref、メンバー、トップレベルは除外
- **641-667行目**: `decideTransform` - 変換の決定
- **604-635行目**: `decideFormalSuggestedCP` - 定義側の使用パターンからCallPatternを決定
- **499-561行目**: `mkTransform` - 変換情報の生成

#### Step 5: 変換実行を理解する

実際の変換処理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | DetupleArgs.fs | `src/Compiler/Optimize/DetupleArgs.fs` | passBind関数（878-909行目） |
| 5-2 | DetupleArgs.fs | `src/Compiler/Optimize/DetupleArgs.fs` | fixupApp関数（821-842行目） |
| 5-3 | DetupleArgs.fs | `src/Compiler/Optimize/DetupleArgs.fs` | collapseArgs関数（783-811行目） |

**主要処理フロー**:
- **878-909行目**: `passBind` - バインディングの変換
  - 仮引数の展開（transFormal）
  - 元変数への再束縛（transRebind）
- **821-842行目**: `fixupApp` - 呼び出しサイトの修正
- **783-811行目**: `collapseArgs` - タプル引数の展開
- **755-761行目**: `noEffectExpr` - 副作用のある式をlet束縛で抽出

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

```
DetupleImplFile (ccu, g, expr)
    │
    ├─ GetUsageInfoOfImplFile (g, expr)
    │      │
    │      └─ FoldImplFile (UsageFolders g)
    │             ├─ exprUsageIntercept
    │             │      └─ logUse
    │             ├─ logNonRecBinding
    │             ├─ logRecBindings
    │             └─ logBinding
    │
    ├─ determineTransforms (g, z)
    │      │
    │      └─ selectTransform (f, sites)
    │             ├─ eligibleVal (g, m, f)
    │             │
    │             ├─ sitesCPs (sites)
    │             │      └─ siteCP / argsCP
    │             │
    │             └─ decideTransform (g, z, f, callPatterns, ...)
    │                    ├─ commonCallPattern (callPatterns)
    │                    │      └─ andCPs / andTS
    │                    │
    │                    ├─ decideFormalSuggestedCP (g, z, tys, vss)
    │                    │      └─ trimTsByAccess / trimTsByVal
    │                    │
    │                    ├─ zipCallPatternArgTys (m, g, callPattern, vss)
    │                    │
    │                    └─ mkTransform (g, f, m, tps, tys, retTy, ...)
    │
    └─ passImplFile (penv, expr)
           │
           └─ RewriteImplFile (postTransformExpr)
                  │
                  ├─ passBind (penv, bind)
                  │      ├─ transFormal
                  │      └─ transRebind
                  │
                  └─ fixupApp (penv, ...)
                         └─ collapseArgs (env, bindings, callPattern, args)
                                ├─ collapseArg
                                ├─ noEffectExpr
                                └─ buildProjections
```

### データフロー図

```
[入力]                        [使用分析]                     [変換決定]                   [変換実行]

TypedImplFile
    │
    ▼
GetUsageInfoOfImplFile ────▶ Results
                                │
                                ├─▶ Uses (Val → 使用サイト一覧)
                                │
                                ├─▶ Defns (Val → バインディング式)
                                │
                                └─▶ RecursiveBindings
                                          │
                                          ▼
                            determineTransforms
                                          │
                                          ├─▶ CallPattern (サイトから)
                                          │
                                          ├─▶ formalCallPattern (定義から)
                                          │
                                          └─▶ Transform
                                                    │
                                                    ├─▶ transformCallPattern
                                                    │
                                                    ├─▶ transformedFormals
                                                    │       (SameArg | NewArgs)
                                                    │
                                                    └─▶ transformedVal
                                                              │
                                                              ▼
                                                    passImplFile
                                                              │
                                                              ├─▶ passBind
                                                              │       (仮引数展開 + 再束縛)
                                                              │
                                                              └─▶ fixupApp
                                                                      (引数展開 + let束縛)
                                                                            │
                                                                            ▼
                                                                    変換済みTypedImplFile
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| DetupleArgs.fs | `src/Compiler/Optimize/DetupleArgs.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` | ソース | グローバル型情報 |
