# 機能設計書 56-コード生成

## 概要

本ドキュメントは、Julia の `@generated` 関数によるステージドプログラミング・コンパイル時コード生成機能の設計を記述する。

### 本機能の処理概要

本機能は、`@generated` アノテーションを使って、関数の引数の**型**に基づいてコンパイル時にコードを動的に生成するステージドプログラミング機構を提供する。通常の関数が引数の**値**に基づいて処理を行うのに対し、`@generated` 関数は引数の型情報のみにアクセスし、その型に最適化されたコードを生成して返す。生成されたコードはキャッシュされ、同じ型の組み合わせで再利用される。

**業務上の目的・背景**: ジェネリックプログラミングにおいて、型に応じた特化コードを自動生成する必要がある場合がある。例えば、タプルの各要素に対する処理、構造体のフィールドアクセスの自動生成、型パラメータに基づく最適化されたアルゴリズム選択など。マクロでは型情報にアクセスできないため、型に基づくコード生成には `@generated` 関数が必要。

**機能の利用シーン**: 型に特化したシリアライズ/デシリアライズコードの生成、タプル操作の展開（map, filter等）、構造体のフィールド操作の自動生成、数値型に応じた最適化コード生成。

**主要な処理内容**:
1. `@generated function f(args...) ... end` による生成関数の定義
2. 関数本体内での型情報（`x <: Integer` 等）へのアクセス
3. 返り値としてのコード式（quoted expression）の構築
4. コンパイラによる生成コードの評価・キャッシュ
5. `generated_body_to_codeinfo` による生成式の CodeInfo への変換
6. `Core.GeneratedFunctionStub` によるスタブ機構

**関連システム・外部連携**: Julia コンパイラの型推論エンジン、lowering フェーズ、JIT コンパイラとの連携。

**権限による制御**: 特に権限制御は行われない。

## 関連画面

本機能は GUI 画面を持たないライブラリ機能であり、直接的に関連する画面はない。

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | REPL から @generated 関数を定義・呼び出して使用 |

## 機能種別

コード生成（ステージドプログラミング）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| 関数定義 | Expr（:function / 短縮形） | Yes | @generated で修飾された関数定義式 | 有効な関数定義であること |
| 引数型 | Type... | 暗黙 | 関数呼び出し時の引数の型。生成関数本体内でアクセス | - |
| spvals | Any... | 暗黙 | 静的パラメータ（型パラメータの値） | - |

### 入力データソース

コンパイラからの型推論結果として渡される引数の型情報。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 生成コード | Expr | 生成関数本体が返すクォートされた式 |
| CodeInfo | CodeInfo | 生成コードを lowering した中間表現。キャッシュされる |

### 出力先

コンパイラの型推論・最適化パイプラインに渡される。

## 処理フロー

### 処理シーケンス

```
1. @generated マクロによる関数定義の変換
   └─ 関数本体を Expr(:if, Expr(:generated), body, fallback) に変換
   └─ fallback は :generated_only メタを含む（通常実行パスなし）
2. 関数呼び出し時のコード生成
   └─ コンパイラが引数の型を確定
   └─ Core.GeneratedFunctionStub の呼び出し
   └─ g.gen(argtypes...) で生成関数本体を実行
   └─ 返された式を lambda でラップ
3. CodeInfo への変換
   └─ generated_body_to_codeinfo で lowering
   └─ ccall(:jl_fl_lower) で Flisp lowering を実行
   └─ GlobalRef のバインディング解決
4. 生成コードのキャッシュと実行
   └─ 同じ型の組み合わせでの再呼び出しではキャッシュを使用
```

### フローチャート

```mermaid
flowchart TD
    A["@generated function f(x)\n    ...\nend"] --> B["マクロ展開:\nExpr(:if, :generated, body, fallback)"]
    B --> C["関数呼び出し f(42)"]
    C --> D["コンパイラが型を確定\nx::Int64"]
    D --> E["GeneratedFunctionStub 呼び出し"]
    E --> F["g.gen(Int64) で本体実行"]
    F --> G["クォート式を返却\n:(x ^ 2)"]
    G --> H["generated_body_to_codeinfo"]
    H --> I["jl_fl_lower で lowering"]
    I --> J["CodeInfo 生成・キャッシュ"]
    J --> K["生成コードを実行"]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-56-1 | 型のみアクセス | 生成関数本体内では引数の値にはアクセスできず、型情報のみ利用可能 | 常時 |
| BR-56-2 | 純粋性要件 | 生成関数本体はグローバル状態に依存したり変更可能なオブジェクトに依存してはならない | 常時 |
| BR-56-3 | 式の返却 | 生成関数本体はクォートされた式（Expr）を返す必要がある | 常時 |
| BR-56-4 | キャッシュ | 同じ引数型の組み合わせでは生成コードがキャッシュされ再利用される | 2回目以降の呼び出し |
| BR-56-5 | クロージャ禁止 | 生成関数本体でクロージャや内包表記は使用できない（純粋な式のみ） | 常時 |

### 計算ロジック

生成関数が返す式の内容がそのまま計算ロジックとなる。具体的な計算は各 @generated 関数の実装に依存。

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

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ErrorException | @generated が関数定義以外に適用された場合 | 関数定義に対してのみ使用 |
| - | ErrorException | 生成関数本体がクロージャや内包表記を含む場合 | 純粋な式構築のみを使用 |
| - | 構文エラー | 生成された式が無効な構文の場合 | 生成式のデバッグ |

### リトライ仕様

該当なし。

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

該当なし。

## パフォーマンス要件

- 生成コードは型ごとにキャッシュされるため、2回目以降の呼び出しはオーバーヘッドなし
- 初回呼び出し時は生成関数本体の実行 + lowering のコストが発生
- 型の組み合わせが多い場合、キャッシュサイズが増大する可能性

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

生成関数本体は任意のコードを生成できるため、信頼できないソースからの @generated 関数の使用には注意が必要。

## 備考

- `@generated` はマクロとは異なり、型情報に基づくコード生成が可能
- マクロ（機能 No.54）は構文レベルの変換、@generated は型レベルの変換
- 生成関数の本体で `@generated()` マクロ（引数なし）を使うと、生成モードかどうかを判定できる

---

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

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

### 推奨読解順序

#### Step 1: @generated マクロの展開を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | expr.jl | `base/expr.jl` | @generated マクロ（1284-1300行目）: 関数定義を条件分岐式に変換。`Expr(:if, Expr(:generated), body, fallback)` 形式 |
| 1-2 | expr.jl | `base/expr.jl` | @generated() 引数なし版（1251-1253行目）: `Expr(:generated)` を返し、本体内で生成モード判定に使用 |

**読解のコツ**: `@generated function f(x) ... end` は内部的に `function f(x) if @generated() ... else ... end end` 相当に変換される。生成モード（コンパイル時）では body が実行され、通常モードでは fallback（`:generated_only` + `return nothing`）に分岐する。

#### Step 2: 生成コードの CodeInfo 変換を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | expr.jl | `base/expr.jl` | generated_body_to_codeinfo（1804-1827行目）: 生成式を CodeInfo に変換 |
| 2-2 | expr.jl | `base/expr.jl` | GeneratedFunctionStub の呼び出し（1830-1846行目）: スタブからの生成コード実行フロー |

**主要処理フロー**:
- **1805-1806行目**: `ccall(:jl_fl_lower, ...)` で Flisp lowering を実行
- **1807-1812行目**: CodeInfo でない結果の場合はエラー処理
- **1816-1825行目**: GlobalRef から Core.Binding を収集して edges に設定
- **1832行目**: `g.gen(args...)` で生成関数本体を実行
- **1835-1841行目**: 返された式を lambda でラップ、:push_loc/:pop_loc メタを付加
- **1843-1845行目**: 静的パラメータがあれば `with-static-parameters` 式でラップ

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

```
@generated function f(x) ... end
    │
    ├─ @generated マクロ展開
    │      └─ Expr(:if, Expr(:generated), body, Expr(:block, :generated_only, return nothing))
    │
    └─ 関数呼び出し f(42)
           │
           ├─ コンパイラ型推論
           │      └─ 引数型の確定: (Int64,)
           │
           └─ Core.GeneratedFunctionStub(world, source, argtypes...)
                  │
                  ├─ g.gen(Int64) → body 実行 → クォート式
                  │
                  ├─ lambda でラップ + メタ情報付加
                  │
                  └─ generated_body_to_codeinfo(expr, mod, isva)
                         ├─ ccall(:jl_fl_lower, ...) → lowering
                         ├─ GlobalRef → Core.Binding 収集
                         └─ CodeInfo 返却 → キャッシュ
```

### データフロー図

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

@generated function f(x)    → マクロ展開                     → 条件分岐付き関数定義
    if x <: Integer            Expr(:if, :generated, ...)
        return :(x^2)
    end
end

f(42) 呼び出し              → 型推論: x::Int64              → 生成式 :(x^2)
                               g.gen(Int64) 実行

生成式 :(x^2)              → generated_body_to_codeinfo     → CodeInfo
                               jl_fl_lower + binding解決

CodeInfo                    → JIT コンパイル                 → ネイティブコード
                               キャッシュ
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| expr.jl | `base/expr.jl` | ソース | @generated マクロ定義、generated_body_to_codeinfo、GeneratedFunctionStub |
| boot.jl | `base/boot.jl` | ソース | Core.GeneratedFunctionStub 型の定義 |
| abstractinterpretation.jl | `Compiler/src/abstractinterpretation.jl` | ソース | 型推論エンジンでの @generated 関数のハンドリング |
| gf.c | `src/gf.c` | ソース (C) | ジェネリック関数ディスパッチ。生成コードキャッシュの管理 |
