# 機能設計書 13-動的アセンブリ生成

## 概要

本ドキュメントは、F#コンパイラの動的アセンブリ生成機能の設計を記述する。この機能は、F#コードをコンパイルして得られたIL（中間言語）表現を、.NETのReflection.Emit APIを使用してランタイム上に動的にアセンブリとして生成する。

### 本機能の処理概要

動的アセンブリ生成機能は、F#コンパイラが生成したAbsIL（Abstract IL）表現を、System.Reflection.Emit APIを使用して実行時にアセンブリを構築し、即座に実行可能な状態にする。

**業務上の目的・背景**：F# Interactiveのような対話的実行環境では、ユーザーが入力したコードを即座に実行する必要がある。ディスクにアセンブリを書き出すことなく、メモリ上に動的にアセンブリを生成することで、REPLの即時性と柔軟性を実現する。

**機能の利用シーン**：
- F# Interactive（fsi）でのコード実行
- スクリプト実行時の動的コード生成
- ランタイムコード生成が必要なシナリオ

**主要な処理内容**：
1. ILモジュールとアセンブリの定義生成
2. 型定義（TypeBuilder）の生成
3. メソッド定義（MethodBuilder）とIL命令の発行
4. フィールド・プロパティ・イベントの定義
5. 型の凍結（CreateType）と最終化
6. 生成された型・値の参照解決

**関連システム・外部連携**：
- F# Interactiveセッション（fsi.fs）
- IlxGenerator（IL生成器）
- .NET Reflection.Emit API

**権限による制御**：特になし。ランタイムのコード実行権限に依存する。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 7 | F# Interactive ツールウィンドウ | 補助機能 | 動的に生成されたコードの実行 |

## 機能種別

コード生成 / ランタイムコンパイル / Reflection.Emit

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| ilModule | ILModuleDef | Yes | IL形式のモジュール定義 | 有効なIL構造 |
| assemblyBuilder | AssemblyBuilder | Yes | 動的アセンブリビルダー | - |
| moduleBuilder | ModuleBuilder | Yes | 動的モジュールビルダー | - |

### 入力データソース

- IlxGeneratorから生成されたAbsIL表現
- 参照アセンブリ情報

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| generatedTypes | Type[] | 生成されたSystem.Type |
| generatedMethods | MethodInfo[] | 生成されたメソッド |
| assemblyEmitEnv | ILAssemblyEmitEnv | 発行環境（型/メソッド/フィールドのマッピング） |

### 出力先

- メモリ上の動的アセンブリ

## 処理フロー

### 処理シーケンス

```
1. cenv（変換環境）の構築
   └─ アセンブリリファレンスとILグローバルの設定
2. 型定義の前方宣言
   └─ すべてのTypeBuilderを先に生成（相互参照解決のため）
3. 型の詳細定義
   └─ 継承、インターフェース実装、属性の設定
4. フィールド定義
   └─ FieldBuilderの生成
5. メソッド定義
   └─ MethodBuilder生成とILコード発行
6. プロパティ・イベント定義
   └─ アクセサメソッドとの関連付け
7. 型の凍結
   └─ CreateType()の呼び出し
8. エントリーポイント設定（必要な場合）
```

### フローチャート

```mermaid
flowchart TD
    A[ILModuleDef入力] --> B[cenv構築]
    B --> C[型の前方宣言]
    C --> D{すべての型を宣言?}
    D -->|No| C
    D -->|Yes| E[型の詳細定義]
    E --> F[フィールド定義]
    F --> G[メソッド定義]
    G --> H[IL命令発行]
    H --> I[プロパティ/イベント定義]
    I --> J[CreateType]
    J --> K{すべて完了?}
    K -->|No| E
    K -->|Yes| L[エントリーポイント設定]
    L --> M[完了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 型の前方宣言 | 相互参照を解決するため、すべての型を先に宣言 | 常時 |
| BR-02 | 型の凍結順序 | 依存関係の順序でCreateTypeを呼び出す | 型階層がある場合 |
| BR-03 | preferCreated | CreateType後は作成済み型を優先使用 | 型参照時 |
| BR-04 | 遅延フィールド初期化 | 一部のフィールド初期化は型凍結後に実行 | 静的フィールド等 |

### 計算ロジック

**型変換アルゴリズム（convType）**：
1. ILTypeRefをemTypMapから検索
2. 発行済み型があればそのTypeBuilderを返す
3. なければ外部アセンブリから解決

**IL命令発行**：
- ILGenerator経由で各IL命令を発行
- 分岐先ラベルはemLabelsマップで管理

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

### 操作別データベース影響一覧

該当なし（データベース操作は行わない）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| itemNotFoundDuringDynamicCodeGen | 型解決失敗 | 参照型が見つからない | エラーメッセージで型名とスコープを報告 |
| - | envGetTypB失敗 | 発行環境に型が未登録 | failwithで処理中断 |
| - | envGetMethB失敗 | 発行環境にメソッドが未登録 | failwithで処理中断 |

### リトライ仕様

リトライは行わない。エラー発生時は処理を中断。

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

該当なし（メモリ上の一連の操作）

## パフォーマンス要件

- 型定義はZmapでO(log n)のルックアップ
- IL発行は順次処理

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

- 動的コード生成は完全信頼が必要
- 生成されたコードは呼び出し元と同じ権限で実行

## 備考

- TypeBuilder.CreateType()は型を「凍結」し、以後変更不可
- デバッグ情報の発行もサポート（debugPointsForMethodオプション）

---

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

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

### 推奨読解順序

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

まず、動的アセンブリ生成で使用される主要なデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ilreflect.fs | `src/Compiler/AbstractIL/ilreflect.fs` | ILDynamicAssemblyEmitEnv型（520-532行目） |
| 1-2 | ilreflect.fs | `src/Compiler/AbstractIL/ilreflect.fs` | emEnv0 - 初期発行環境（539-551行目） |

**読解のコツ**: ILDynamicAssemblyEmitEnvは発行状態を管理する核心的な型。emTypMap、emMethMap、emFieldMap等がIL構造とビルダーのマッピングを保持する。

**主要フィールド**：
- **emTypMap**: ILTypeRef -> (Type, TypeBuilder, ILTypeDef, createdType option)
- **emConsMap**: ILMethodRef -> ConstructorBuilder
- **emMethMap**: ILMethodRef -> MethodBuilder
- **emFieldMap**: ILFieldRef -> FieldBuilder
- **emLabels**: ILCodeLabel -> Label（分岐先管理）

#### Step 2: 環境操作関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ilreflect.fs | `src/Compiler/AbstractIL/ilreflect.fs` | envBindTypeRef（553-559行目） |
| 2-2 | ilreflect.fs | `src/Compiler/AbstractIL/ilreflect.fs` | envUpdateCreatedTypeRef（561-578行目） |
| 2-3 | ilreflect.fs | `src/Compiler/AbstractIL/ilreflect.fs` | envBindMethodRef, envGetMethB（594-600行目） |

**主要処理フロー**:
- **553-559行目**: envBindTypeRef - 型参照とTypeBuilderのバインド
- **561-578行目**: envUpdateCreatedTypeRef - CreateType後の更新
- **594-600行目**: メソッドのバインドと取得

#### Step 3: 型変換を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ilreflect.fs | `src/Compiler/AbstractIL/ilreflect.fs` | convTypeRef（580-584行目） |
| 3-2 | ilreflect.fs | `src/Compiler/AbstractIL/ilreflect.fs` | convTypeSpec（696-709行目） |
| 3-3 | ilreflect.fs | `src/Compiler/AbstractIL/ilreflect.fs` | convTypeAux（711-739行目） |

**主要処理フロー**:
- **580-584行目**: convTypeRef - preferCreatedフラグで作成済み型を優先
- **696-709行目**: convTypeSpec - ジェネリック型のインスタンス化
- **711-739行目**: convTypeAux - IL型から.NET Typeへの変換

**読解のコツ**: convTypeAuxは再帰的に型を変換。配列型（MakeArrayType）、ポインタ型（MakePointerType）、参照型（MakeByRefType）などを処理。

#### Step 4: IL命令発行を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | ilreflect.fs | `src/Compiler/AbstractIL/ilreflect.fs` | convCallConv（674-690行目） |

**主要処理フロー**:
- **674-690行目**: IL呼び出し規約から.NET CallingConventionsへの変換

#### Step 5: 型参照解決を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | ilreflect.fs | `src/Compiler/AbstractIL/ilreflect.fs` | convTypeRefAux（502-515行目） |

**主要処理フロー**:
- **506-515行目**: ILScopeRef（Assembly/Module/Local/PrimaryAssembly）に応じた解決
- 外部アセンブリはconvResolveAssemblyRefで解決
- ローカルはType.GetTypeで取得

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

```
EmitDynamicAssembly (エントリーポイント)
    │
    ├─ cenv構築
    │      └─ convResolveAssemblyRef (アセンブリ参照解決)
    │
    ├─ 型の前方宣言ループ
    │      ├─ DefineType (TypeBuilder作成)
    │      └─ envBindTypeRef (環境に登録)
    │
    ├─ 型の詳細定義ループ
    │      ├─ SetParent (基底クラス設定)
    │      ├─ AddInterfaceImplementation
    │      ├─ DefineField → envBindFieldRef
    │      ├─ DefineMethod → envBindMethodRef
    │      │      └─ emitILCode (IL命令発行)
    │      │             ├─ convType (型変換)
    │      │             └─ ILGenerator.Emit
    │      ├─ DefineProperty → envBindPropRef
    │      └─ DefineEvent
    │
    └─ 型凍結ループ
           ├─ TypeBuilder.CreateType
           └─ envUpdateCreatedTypeRef (作成済み型を登録)
```

### データフロー図

```
[入力]                     [処理]                           [出力]

ILModuleDef ─────────▶ 型定義抽出 ─────────▶ TypeBuilder
(AbsIL表現)                  │                     │
                             ▼                     ▼
                    envBindTypeRef ─────▶ emTypMap更新
                             │
                             ▼
                    メソッド定義 ─────▶ MethodBuilder
                             │                     │
                             ▼                     ▼
                    envBindMethodRef ──▶ emMethMap更新
                             │
                             ▼
ILCode ─────────────▶ emitILCode ─────────▶ ILGenerator.Emit
                             │
                             ▼
                    TypeBuilder.CreateType
                             │
                             ▼
                    envUpdateCreatedTypeRef
                             │
                             ▼
Type / MethodInfo ◀──── 完成したアセンブリ
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ilreflect.fs | `src/Compiler/AbstractIL/ilreflect.fs` | ソース | 動的アセンブリ生成のコア実装 |
| il.fs | `src/Compiler/AbstractIL/il.fs` | ソース | AbsIL型定義（ILTypeDef, ILMethodDef等） |
| ilwrite.fs | `src/Compiler/AbstractIL/ilwrite.fs` | ソース | ILバイナリ書き出し（ディスク出力用） |
| IlxGen.fs | `src/Compiler/CodeGen/IlxGen.fs` | ソース | F# ASTからILへの変換 |
| fsi.fs | `src/Compiler/Interactive/fsi.fs` | ソース | F# Interactiveからの利用 |
