# 機能設計書 15-テンプレート展開

## 概要

本ドキュメントは、Nimコンパイラにおけるテンプレート展開機能の設計仕様を記述する。テンプレートはコンパイル時にコードを展開するマクロの一種であり、本機能はその意味解析と展開処理を担当する。

### 本機能の処理概要

テンプレート展開機能は、Nimのテンプレート定義を解析し、呼び出しサイトでテンプレート本体を展開する機能である。衛生的（hygienic）なテンプレートを実現するため、シンボルのスコープ管理と名前解決を行う。

**業務上の目的・背景**：テンプレートはNimのメタプログラミング機能の中核であり、コンパイル時のコード生成を可能にする。マクロよりも軽量で、単純なコード置換から高度な抽象化まで幅広く使用される。衛生的なテンプレートにより、マクロ展開時の名前衝突を防止し、予測可能な動作を保証する。この機能により、DSLの構築、ボイラープレートコードの削減、パフォーマンスクリティカルな抽象化が可能となる。

**機能の利用シーン**：テンプレート定義時（`template`キーワード）およびテンプレート呼び出し時に使用される。コントロールフロー抽象化（カスタムループ構造など）、遅延評価、コンパイル時コード生成などの場面で活用される。

**主要な処理内容**：
1. テンプレート本体の予備的シンボル解析
2. gensym/injectプラグマによるシンボルバインディング制御
3. テンプレートパラメータの識別と置換
4. 衛生的マクロのための名前空間管理
5. 呼び出しサイトでのテンプレート展開
6. オープン/クローズドシンボル選択の管理

**関連システム・外部連携**：セマンティック解析（sem.nim）に含まれ、式評価（semexprs.nim）から呼び出される。テンプレート評価（evaltempl.nim）と連携してテンプレートを展開する。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 27 | nimprettyメイン画面 | 補助機能 | コード整形のための構文解析 |
| 1 | nimコンパイラメイン画面 | 補助機能 | テンプレートはセマンティック解析の一部 |

## 機能種別

メタプログラミング / コード展開 / シンボル管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| c | TemplCtx | Yes | テンプレート解析コンテキスト | nil不可 |
| n | PNode | Yes | テンプレート本体のAST | nil不可 |
| s | PSym | No | 対象シンボル | nil可 |
| toBind | IntSet | No | バインド対象シンボルID集合 | 初期化済み |
| toMixin | IntSet | No | ミックスイン対象シンボルID集合 | 初期化済み |

### 入力データソース

- パーサーが生成したテンプレート定義AST
- シンボルテーブル
- テンプレートパラメータ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 展開されたAST | PNode | テンプレート本体を処理したAST |
| シンボル | PSym | 生成されたgensymシンボル |

### 出力先

- AST（呼び出しサイトに展開）
- シンボルテーブル（gensymシンボル登録）

## 処理フロー

### 処理シーケンス

```
1. テンプレート定義の解析開始
   └─ TemplCtxの初期化
2. シンボルバインディングの解析
   └─ gensym/injectプラグマの処理
3. テンプレート本体の走査
   └─ semTemplBody()で再帰的に処理
4. シンボルの解決
   └─ symChoice()でオープン/クローズド選択
5. gensymシンボルの生成
   └─ newGenSym()で新しいシンボル作成
6. 展開結果の返却
```

### フローチャート

```mermaid
flowchart TD
    A[テンプレート定義] --> B[TemplCtx初期化]
    B --> C[本体AST走査開始]
    C --> D{ノード種別判定}
    D -->|識別子| E[シンボル検索]
    D -->|宣言| F[ローカル宣言処理]
    D -->|その他| G[子ノード再帰処理]
    E --> H{テンプレートパラメータ?}
    H -->|Yes| I[パラメータ参照に変換]
    H -->|No| J{gensym/inject判定}
    J -->|gensym| K[オープンシンボル選択]
    J -->|inject| L[クローズドシンボル選択]
    F --> M{gensymデフォルト?}
    M -->|Yes| N[gensymシンボル生成]
    M -->|No| O[inject処理]
    I --> P[結果AST構築]
    K --> P
    L --> P
    N --> P
    O --> P
    G --> P
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-15-01 | gensymデフォルト | ローカル変数はデフォルトでgensym | フィールド以外の宣言 |
| BR-15-02 | injectデフォルト | フィールドはデフォルトでinject | skField |
| BR-15-03 | オープンシンボル | gensymシンボルはオープン選択で解決 | sfGenSym in flags |
| BR-15-04 | 衛生性保証 | gensymシンボルは呼び出しサイトの同名シンボルと衝突しない | 常時 |

### 計算ロジック

- シンボルバインディング判定: `symBinding(n)` - spNone/spGenSym/spInject を返却
- テンプレートパラメータ判定: `isTemplParam(c, s)` - 所有者とフラグで判定

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

本機能はデータベースを使用しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| illFormedAst | 構文エラー | 不正なAST構造 | エラーメッセージ表示 |

### リトライ仕様

テンプレート展開にリトライ機構はない。

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

- スコープはopenScope/closeScope で管理
- テンプレート本体処理中はスコープをネスト

## パフォーマンス要件

- テンプレート展開はコンパイル時のみ実行
- 再帰的なAST走査のため、深いネストに注意

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

- テンプレートは信頼されたコードとして扱われる

## 備考

- `{.dirty.}`プラグマで衛生性を無効化可能
- openSym機能で後方互換性のある動作を制御

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | semtempl.nim | `compiler/semtempl.nim` | TSymBinding列挙型（33-34行目）: シンボルバインディングの種類 |
| 1-2 | semtempl.nim | `compiler/semtempl.nim` | TSymChoiceRule列挙型（48-49行目）: シンボル選択ルール |
| 1-3 | semtempl.nim | `compiler/semtempl.nim` | TemplCtx構造体（131-139行目）: テンプレート解析コンテキスト |

#### Step 2: シンボル処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | semtempl.nim | `compiler/semtempl.nim` | symBinding()関数（36-45行目）: バインディング判定 |
| 2-2 | semtempl.nim | `compiler/semtempl.nim` | symChoice()関数（51-92行目）: シンボル選択処理 |
| 2-3 | semtempl.nim | `compiler/semtempl.nim` | newGenSym()関数（181-183行目）: gensymシンボル生成 |

#### Step 3: テンプレート本体処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | semtempl.nim | `compiler/semtempl.nim` | semTemplBody()関数（168行目）: メイン処理の前方宣言 |
| 3-2 | semtempl.nim | `compiler/semtempl.nim` | addLocalDecl()関数（185-220行目）: ローカル宣言処理 |
| 3-3 | semtempl.nim | `compiler/semtempl.nim` | semTemplSymbol()関数（222-291行目）: シンボル処理 |

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

```
semTemplateDef()
    │
    ├─ TemplCtx初期化
    │
    └─ semTemplBody()
           ├─ symBinding() [バインディング判定]
           ├─ symChoice() [シンボル選択]
           │      └─ initOverloadIter() / nextOverloadIter()
           ├─ addLocalDecl() [ローカル宣言]
           │      └─ newGenSym()
           └─ semTemplSymbol() [シンボル処理]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| semtempl.nim | `compiler/semtempl.nim` | ソース | テンプレート意味解析（約929行） |
| evaltempl.nim | `compiler/evaltempl.nim` | ソース | テンプレート評価・展開 |
| sem.nim | `compiler/sem.nim` | ソース | セマンティック解析メイン（semtempl.nimをinclude） |
| ast.nim | `compiler/ast.nim` | ソース | AST定義 |
