# 機能設計書 5-型変換・型昇格

## 概要

本ドキュメントは、Julia言語における `convert` / `promote` / `promote_rule` / `promote_type` による型変換と数値型昇格に関する機能設計書である。

### 本機能の処理概要

異なる型間の値変換（conversion）と、混合型演算時の自動型昇格（promotion）を提供する。型変換は明示的な型の変更を行い、型昇格は二項演算子等に異なる型の引数が渡された場合に共通の型を自動決定する仕組みである。

**業務上の目的・背景**：数値計算において、異なる型の値を混合して使用することは日常的である（例: `1 + 1.5` はIntとFloatの混合）。型昇格システムにより、ユーザーは明示的な型変換を書かずに自然な数式を記述でき、かつ型安全性が保たれる。また、ユーザー定義型に対しても `promote_rule` を定義することで型昇格システムに参加できる拡張性を持つ。

**機能の利用シーン**：異なる数値型間の演算（`Int + Float64`等）、コンテナへの代入時の型変換、ユーザー定義型の型昇格ルール定義、`convert(T, x)` による明示的な型変換等で使用される。

**主要な処理内容**：
1. `convert(T, x)` - 値xを型Tに変換
2. `promote(x, y, ...)` - 複数の値を共通の型に昇格
3. `promote_type(T, S, ...)` - 型Tと型Sの共通昇格先型を決定
4. `promote_rule(T, S)` - 型TとSの昇格ルールを定義

**関連システム・外部連携**：多重ディスパッチ（`src/gf.c`）における引数型の自動変換と連携する。

**権限による制御**：特になし。すべてのユーザーが利用可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 型変換・昇格は画面に直接関連しないが、REPLでの演算結果表示に影響する |

## 機能種別

型変換・型昇格処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| T | Type | Yes（convert） | 変換先の型 | 有効な型であること |
| x | Any | Yes（convert） | 変換する値 | Tに変換可能であること |
| args | Tuple | Yes（promote） | 昇格する値の組 | 各要素が昇格可能であること |

### 入力データソース

関数呼び出し引数として直接渡される。二項演算子の内部で暗黙的に呼び出される場合もある。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 変換結果 | T | convert(T, x) の結果（型Tの値） |
| 昇格結果 | Tuple{T,...} | promote(x, y, ...) の結果（共通型Tのタプル） |
| 昇格型 | Type | promote_type(T, S) の結果（共通型） |

### 出力先

関数の戻り値として返される。

## 処理フロー

### 処理シーケンス

```
1. promote_type(T, S) の呼び出し
   └─ promote_rule(T, S) と promote_rule(S, T) の両方を試行
2. promote_result による結果の決定
   └─ promote_rule の結果がBottomでなければそれを採用
   └─ 両方Bottomの場合は typejoin(T, S) にフォールバック
3. promote(x, y) の呼び出し
   └─ promote_type で共通型を決定後、convert で各値を変換
4. 二項演算子での利用
   └─ +(x::Number, y::Number) = +(promote(x, y)...)
```

### フローチャート

```mermaid
flowchart TD
    A["promote_type(T, S)"] --> B["promote_rule(T, S)"]
    A --> C["promote_rule(S, T)"]
    B --> D["promote_result(T, S, R1, R2)"]
    C --> D
    D --> E{R1またはR2がBottom以外?}
    E -->|Yes| F["promote_type(R1, R2)"]
    E -->|No| G["typejoin(T, S)"]
    F --> H[共通型を返す]
    G --> H

    I["promote(x, y)"] --> J["promote_type(typeof(x), typeof(y))"]
    J --> K["convert(共通型, x)"]
    J --> L["convert(共通型, y)"]
    K --> M["(変換済x, 変換済y)を返す"]
    L --> M
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 対称性 | promote_type(T, S) == promote_type(S, T) でなければならない | 常時 |
| BR-02 | 情報保持 | 昇格先はなるべく両方の型の値を近似的に表現できる型であるべき | 常時 |
| BR-03 | フォールバック | promote_ruleが未定義の場合、typejoinにフォールバックする | promote_ruleがBottomを返す場合 |
| BR-04 | InexactError | convertが精度を失う場合（例: Float64→Int、端数あり）はInexactErrorを投げる | convert時 |
| BR-05 | ユーザー拡張 | promote_ruleの片方向のみ定義すればよい | カスタム型定義時 |

### 計算ロジック

```
promote_type(T, S) =
  let R1 = promote_rule(T, S), R2 = promote_rule(S, T)
    if R1 == Bottom && R2 == Bottom
      typejoin(T, S)
    else
      promote_type(R1, R2)  # 再帰的に解決
    end
  end
```

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

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

該当なし（データベースを使用しない）。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| InexactError | InexactError | 変換先型で正確に表現できない場合 | round等で丸めてから変換する |
| MethodError | MethodError | convert メソッドが未定義の場合 | 適切なconvertメソッドを定義する |
| OverflowError | OverflowError | 変換先型の範囲を超える場合 | より広い型を使用する |

### リトライ仕様

型変換は純粋関数であり、リトライは適用されない。

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

該当なし。

## パフォーマンス要件

- promote_type はコンパイル時に解決可能な場合が多く、実行時オーバーヘッドはゼロに近い
- convert はインライン化されることが多く、ネイティブ型間の変換はCPU命令1〜2個程度

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

- 整数オーバーフローを伴う変換（unsigned→signedの範囲外等）に注意が必要

## 備考

- boot.jl 346-349行目に Core モジュールでの基本的な convert 定義がある
- promotion.jl に promote_type, promote_rule, promote_result, promote 関数の本体実装がある

---

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

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

### 推奨読解順序

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

型昇格システムの基本概念を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | boot.jl | `base/boot.jl` | **346-349行目**: Core内のconvert基本定義。`convert(::Type{Any}, x) = x` および `convert(::Type{T}, x::T) = x` |
| 1-2 | essentials.jl | `base/essentials.jl` | **7行目**: `const Bottom = Union{}` - promote_ruleのデフォルト戻り値 |

**読解のコツ**: Juliaの型昇格は「二段階方式」で動作する。まず `promote_type` で共通型を決定し、次に `convert` で各値をその共通型に変換する。`promote_rule` は片方向のみ定義すればよく、`promote_type` が両方向を試行する。

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

promote_type関数の実装を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | promotion.jl | `base/promotion.jl` | **263-323行目**: promote_type関数群。単一引数・複数引数のオーバーロード |
| 2-2 | promotion.jl | `base/promotion.jl` | **315-323行目**: 二引数promote_typeの本体。promote_rule(T,S) と promote_rule(S,T) を両方呼び出す |

**主要処理フロー**:
1. **305行目**: `promote_type() = Bottom` - 引数なしの場合
2. **306行目**: `promote_type(T) = T` - 単一型の場合
3. **315-323行目**: `promote_type(::Type{T}, ::Type{S})` - 二引数の場合、promote_ruleを両方向で呼び出し
4. **342行目**: `promote_result` が両方向の結果からpromote_typeを再帰的に解決
5. **345行目**: 両方Bottomの場合は `typejoin(T, S)` にフォールバック

#### Step 3: promote_ruleとpromote関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | promotion.jl | `base/promotion.jl` | **325-340行目**: promote_rule関数。デフォルトはBottomを返す |
| 3-2 | promotion.jl | `base/promotion.jl` | **347行目以降**: promote関数 - promote_typeで型を決定し、convertで変換 |
| 3-3 | complex.jl | `base/complex.jl` | **49-52行目**: Complex型のpromote_rule定義例 |

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

```
二項演算子 (例: +(x::Number, y::Number))
    │
    └─ promote(x, y)
           │
           ├─ promote_type(typeof(x), typeof(y))
           │      │
           │      ├─ promote_rule(T, S) ... ユーザー定義可能
           │      ├─ promote_rule(S, T) ... ユーザー定義可能
           │      │
           │      └─ promote_result(T, S, R1, R2)
           │             │
           │             ├─ promote_type(R1, R2) ... R1/R2がBottom以外
           │             └─ typejoin(T, S) ... 両方Bottom
           │
           ├─ convert(共通型, x)
           └─ convert(共通型, y)
```

### データフロー図

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

異なる型の値 (x::Int, y::Float64)
    │
    ├───▶ promote_type(Int, Float64) ───▶ Float64 (共通型)
    │
    ├───▶ convert(Float64, x)        ───▶ Float64(x)
    └───▶ convert(Float64, y)        ───▶ y (変換不要)
                                          │
                                          ▼
                                     (Float64(x), y) ... 昇格済みタプル
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| promotion.jl | `base/promotion.jl` | ソース | promote_type, promote_rule, promote, typejoinの主要実装 |
| boot.jl | `base/boot.jl` | ソース | convertの基本定義 |
| essentials.jl | `base/essentials.jl` | ソース | Bottom定義 |
| complex.jl | `base/complex.jl` | ソース | Complex型のpromote_rule定義例 |
| rational.jl | `base/rational.jl` | ソース | Rational型のpromote_rule定義例 |
| int.jl | `base/int.jl` | ソース | 整数型間のpromote_rule定義 |
| float.jl | `base/float.jl` | ソース | 浮動小数点型間のpromote_rule定義 |
