# 機能設計書 94-typetraits（型特性取得）

## 概要

本ドキュメントは、Nim標準ライブラリの`typetraits`モジュールの機能設計を記述する。このモジュールは、コンパイル時に型の特性（メタ情報）を取得するためのリフレクションプロシージャを提供する。

### 本機能の処理概要

typetraitsモジュールは、ジェネリックプログラミングやマクロ開発において、型に関する情報（名前、アリティ、ジェネリックパラメータ、基底型など）をコンパイル時に取得する機能を提供する。これにより、型に応じた分岐処理やコード生成が可能になる。

**業務上の目的・背景**：ジェネリックコードやマクロでは、渡された型に応じて異なる処理を行う必要がある場合が多い。typetraitsモジュールは、型のメタ情報へのアクセスを提供し、より柔軟で型安全なジェネリックプログラミングを実現する。

**機能の利用シーン**：
- ジェネリック型の基底型（genericHead）を取得してパターンマッチ
- 型名の文字列表現を取得（name）
- distinct型の基底型を取得（distinctBase）
- range型の基底型を取得（rangeBase）
- タプルの要素数を取得（tupleLen）
- ジェネリックパラメータを取得（genericParams）
- ポインタ型の指す型を取得（pointerBase）
- 型のcopyMem安全性を確認（supportsCopyMem）

**主要な処理内容**：
1. `name`: 型の名前を文字列で取得
2. `arity`: 型のジェネリックパラメータ数を取得
3. `genericHead`: インスタンス化されたジェネリック型の非インスタンス化形式を取得
4. `stripGenericParams`: genericHeadの安全版（非ジェネリック型でもエラーにならない）
5. `distinctBase`: distinct型の基底型を取得
6. `rangeBase`: range型の基底型を取得
7. `tupleLen`: タプルの要素数を取得
8. `genericParams`: ジェネリックパラメータをタプルとして取得
9. `supportsCopyMem`: copyMemで安全にコピー可能か判定
10. `hasDefaultValue`: デフォルト値を持つ型か判定
11. `isNamedTuple`: 名前付きタプルか判定
12. `pointerBase`: ptr/ref型の指す型を取得
13. `toUnsigned`/`toSigned`: 符号付き/符号なし型への変換

**関連システム・外部連携**：
- macrosモジュール: genericParamsの実装に使用
- コンパイラマジック: 多くのプロシージャは`{.magic: "TypeTrait".}`で実装

**権限による制御**：特になし

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 画面関連なし（ライブラリモジュール） |

## 機能種別

メタプログラミング / コンパイル時リフレクション

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| t / T | typedesc | Yes | 特性を取得する型 | 有効な型記述子 |
| recursive | static bool | No | distinctBase等で再帰的に基底型を辿るか | デフォルトtrue |
| a | T (value) | Yes | 値からの型特性取得（オーバーロード版） | 有効な値 |

### 入力データソース

- コンパイル時の型情報
- ソースコード内の型記述子

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| name結果 | string | 型の名前（例: "seq[string]"） |
| arity結果 | int | ジェネリックパラメータの数 |
| genericHead結果 | typedesc | 非インスタンス化ジェネリック型 |
| distinctBase結果 | typedesc | distinct型の基底型 |
| tupleLen結果 | int | タプルの要素数 |
| genericParams結果 | tuple | ジェネリックパラメータのタプル |
| supportsCopyMem結果 | bool | copyMemで安全にコピー可能か |
| hasDefaultValue結果 | bool | デフォルト値を持つか |

### 出力先

- コンパイル時評価の結果
- 型システム（typedesc返却の場合）

## 処理フロー

### 処理シーケンス

```
1. typetraitsプロシージャ呼び出し
   └─ コンパイル時に型情報を解析

2. magic "TypeTrait"プロシージャの場合
   └─ コンパイラ内部で直接処理
      ├─ name: 型の文字列表現を構築
      ├─ arity: 型パラメータ数をカウント
      ├─ genericHead: ジェネリック型の定義を参照
      ├─ distinctBase: distinct定義を再帰的に辿る
      └─ supportsCopyMem: 型の特性フラグを確認

3. マクロ実装（genericParams等）の場合
   └─ macrosモジュールを使用してAST解析
      ├─ getTypeImpl: 型の実装ASTを取得
      ├─ nnkBracketExpr: ジェネリック型の解析
      └─ 結果のタプルを構築

4. テンプレート実装（pointerBase等）の場合
   └─ 単純な型変換として展開
```

### フローチャート

```mermaid
flowchart TD
    A[typetraits呼び出し] --> B{実装種別}
    B -->|magic| C[コンパイラ内部処理]
    B -->|macro| D[AST解析]
    B -->|template| E[単純展開]

    C --> F{プロシージャ種別}
    F -->|name| G[型名文字列構築]
    F -->|arity| H[パラメータ数カウント]
    F -->|genericHead| I[ジェネリック定義参照]
    F -->|distinctBase| J[distinct定義を辿る]
    F -->|supportsCopyMem| K[型フラグ確認]

    D --> L[getTypeImpl呼び出し]
    L --> M[AST解析]
    M --> N[結果タプル構築]

    E --> O[型変換展開]

    G --> P[結果返却]
    H --> P
    I --> P
    J --> P
    K --> P
    N --> P
    O --> P
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | genericHeadエラー | 非ジェネリック型に対してgenericHeadを呼ぶとコンパイルエラー | genericHead使用時 |
| BR-02 | distinctBase再帰 | recursive=trueでは最終的な非distinct型まで辿る | distinctBase使用時 |
| BR-03 | rangeBaseの型 | range型の基底型は範囲を定義した元の型 | rangeBase使用時 |
| BR-04 | HoleyEnum/OrdinalEnum | 穴のある列挙型とない列挙型を区別可能 | enum型判定時 |

### 計算ロジック

特になし（型システムへのクエリのため）

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

該当なし（本モジュールはデータベース操作を行わない）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| コンパイルエラー | 型エラー | 非ジェネリック型にgenericHead使用 | stripGenericParamsを使用 |
| コンパイルエラー | 型エラー | rangeを返さない型にrangeBase使用 | 型チェック後に使用 |

### リトライ仕様

該当なし（コンパイル時処理のため）

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

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

## パフォーマンス要件

- すべての処理はコンパイル時に完了する
- 実行時オーバーヘッドなし

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

特になし（コンパイル時リフレクションのため）

## 備考

- 「Unstable API」とマークされているため、将来変更の可能性あり
- system.`$`がexportされており、後方互換性のため
- HoleyEnumとOrdinalEnumで列挙型の穴の有無を判定可能

---

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

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

### 推奨読解順序

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

まず、特殊な型定義を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | typetraits.nim | `lib/pure/typetraits.nim` | 22-23行目: HoleyEnumとOrdinalEnumの型定義 |
| 1-2 | typetraits.nim | `lib/pure/typetraits.nim` | 223行目: StaticParam型の定義 |

**読解のコツ**: `HoleyEnum = (not Ordinal) and enum`という型制約式を理解する。穴のある列挙型はOrdinalではないという特性を利用している。

#### Step 2: magicプロシージャを理解する

コンパイラマジックで実装されているプロシージャを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | typetraits.nim | `lib/pure/typetraits.nim` | 37-43行目: `name`プロシージャ |
| 2-2 | typetraits.nim | `lib/pure/typetraits.nim` | 45-52行目: `arity`プロシージャ |
| 2-3 | typetraits.nim | `lib/pure/typetraits.nim` | 54-82行目: `genericHead`プロシージャ |
| 2-4 | typetraits.nim | `lib/pure/typetraits.nim` | 84-92行目: `stripGenericParams`プロシージャ |
| 2-5 | typetraits.nim | `lib/pure/typetraits.nim` | 94-97行目: `supportsCopyMem`プロシージャ |
| 2-6 | typetraits.nim | `lib/pure/typetraits.nim` | 99-114行目: `hasDefaultValue`プロシージャ |
| 2-7 | typetraits.nim | `lib/pure/typetraits.nim` | 116-121行目: `isNamedTuple`プロシージャ |
| 2-8 | typetraits.nim | `lib/pure/typetraits.nim` | 133-144行目: `rangeBase`プロシージャ |
| 2-9 | typetraits.nim | `lib/pure/typetraits.nim` | 167-179行目: `distinctBase`プロシージャ |

**主要処理フロー**:
- **37行目**: `{.magic: "TypeTrait".}`で実装される。コンパイラが直接処理
- **54-82行目**: genericHeadは非ジェネリック型でコンパイルエラー

#### Step 3: テンプレート実装を理解する

単純なテンプレートで実装されているものを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | typetraits.nim | `lib/pure/typetraits.nim` | 123-131行目: `pointerBase`テンプレート |
| 3-2 | typetraits.nim | `lib/pure/typetraits.nim` | 146-165行目: `rangeBase`テンプレート（値版） |
| 3-3 | typetraits.nim | `lib/pure/typetraits.nim` | 181-194行目: `distinctBase`テンプレート（値版） |
| 3-4 | typetraits.nim | `lib/pure/typetraits.nim` | 196-213行目: `tupleLen`プロシージャとテンプレート |
| 3-5 | typetraits.nim | `lib/pure/typetraits.nim` | 215-221行目: `get`テンプレート |
| 3-6 | typetraits.nim | `lib/pure/typetraits.nim` | 227-239行目: `elementType`テンプレート |

**主要処理フロー**:
- **123-131行目**: `pointerBase`は単純に`T`を返すテンプレート
- **227-239行目**: `elementType`はforループを使ってイテラブルの要素型を取得

#### Step 4: マクロ実装を理解する

AST操作を伴うマクロ実装を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | typetraits.nim | `lib/pure/typetraits.nim` | 243-256行目: `enumLen`マクロ |
| 4-2 | typetraits.nim | `lib/pure/typetraits.nim` | 258-310行目: `genericParamsImpl`マクロ |
| 4-3 | typetraits.nim | `lib/pure/typetraits.nim` | 312-336行目: `genericParams`テンプレート |
| 4-4 | typetraits.nim | `lib/pure/typetraits.nim` | 339-347行目: `hasClosure`プロシージャ |

**主要処理フロー**:
- **243-256行目**: enumLenはnnkEnumTyのlen - 1を返す（最初の要素はnnkEmpty）
- **258-310行目**: genericParamsImplは型定義のASTを走査してパラメータを収集

#### Step 5: 型変換テンプレートを理解する

符号付き/符号なし変換を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | typetraits.nim | `lib/pure/typetraits.nim` | 349-362行目: `toUnsigned`テンプレート |
| 5-2 | typetraits.nim | `lib/pure/typetraits.nim` | 364-376行目: `toSigned`テンプレート |

**主要処理フロー**:
- **349-362行目**: whenブロックでビットサイズに応じた型を返す

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

```
typetraitsプロシージャ呼び出し
    │
    ├─ [magic実装]
    │      ├─ name(t: typedesc): string
    │      ├─ arity(t: typedesc): int
    │      ├─ genericHead(t: typedesc): typedesc
    │      ├─ stripGenericParams(t: typedesc): typedesc
    │      ├─ supportsCopyMem(t: typedesc): bool
    │      ├─ hasDefaultValue(t: typedesc): bool
    │      ├─ isNamedTuple(T: typedesc): bool
    │      ├─ rangeBase(T: typedesc[range]): typedesc
    │      └─ distinctBase(T: typedesc): typedesc
    │
    ├─ [template実装]
    │      ├─ pointerBase[T](_: typedesc[ptr T | ref T]): typedesc
    │      ├─ rangeBase[T: range](a: T): untyped
    │      ├─ distinctBase[T](a: T, recursive: static bool): untyped
    │      ├─ tupleLen(t: tuple): int
    │      ├─ get(T: typedesc[tuple], i: static int): untyped
    │      ├─ elementType(a: untyped): typedesc
    │      ├─ toUnsigned(T: typedesc[SomeInteger]): untyped
    │      └─ toSigned(T: typedesc[SomeInteger]): untyped
    │
    └─ [macro実装]
           ├─ enumLen(T: typedesc[enum]): int
           │      └─ getType(T) → nnkEnumTy解析
           │
           ├─ genericParamsImpl(T: typedesc): untyped
           │      ├─ getTypeImpl(T)
           │      └─ nnkBracketExpr解析 → タプル構築
           │
           └─ hasClosure(fn: NimNode): bool
                  └─ hasClosureImpl（VMオーバーライド）
```

### データフロー図

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

typedesc T ───────────▶ コンパイラマジック ─────────────▶
                              │
                    ┌─────────┴─────────┐
                    ▼                   ▼
               [name]            [genericHead]
                    │                   │
                    ▼                   ▼
            型名文字列構築      ジェネリック定義参照
                    │                   │
                    ▼                   ▼
               "seq[T]"           Foo[_]

typedesc[enum] T ─────▶ enumLen macro ─────────────────▶
                              │
                              ▼
                         getType(T)
                              │
                              ▼
                         nnkEnumTy
                              │
                              ▼
                         len - 1 ───────────────────▶ int

typedesc T ───────────▶ genericParams template ────────▶
                              │
                              ▼
                         genericParamsImpl(T2)
                              │
                              ▼
                         AST解析
                              │
                              ▼
                         タプル構築 ─────────────────▶ (T1, T2, ...)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| typetraits.nim | `lib/pure/typetraits.nim` | ソース | 型特性取得のメイン実装 |
| macros.nim | `lib/core/macros.nim` | 依存元 | AST操作ユーティリティ |
| system.nim | `lib/system.nim` | 依存元 | 基本型定義、$演算子 |
| since.nim | `lib/std/private/since.nim` | 依存元 | バージョン管理マクロ |
