# 機能設計書 12-プラグマ処理

## 概要

本ドキュメントは、Nimコンパイラにおけるプラグマ処理機能の設計仕様を記述する。プラグマはNimコードに対してコンパイラへの指示やメタデータを付与するための構文であり、本機能はそれらの意味解析と処理を担当する。

### 本機能の処理概要

プラグマ処理機能は、Nimソースコード内に記述されたプラグマ（`{.pragma.}`形式のアノテーション）を解析し、シンボル（関数、型、変数等）に対応するフラグやプロパティを設定する機能である。

**業務上の目的・背景**：Nimは「プラグマティック」な言語設計を採用しており、コンパイラへの詳細な指示をソースコードレベルで記述できることが特徴である。これにより、外部C関数のインポート、最適化ヒントの指定、呼び出し規約の設定、実験的機能の有効化など、多様な制御がプラグマを通じて可能となる。プラグマ処理機能は、これらの指示を正しく解析し、コンパイラ内部の表現に変換する役割を担う。

**機能の利用シーン**：この機能はセマンティック解析フェーズで使用される。具体的には、関数定義（`proc`, `func`, `method`, `iterator`）、型定義、変数宣言、定数定義、ステートメント等にプラグマが付与されている場合に呼び出される。FFI（Foreign Function Interface）を使用する際の`{.importc.}`、`{.exportc.}`や、スレッド安全性を示す`{.thread.}`、`{.gcsafe.}`などの利用時に不可欠である。

**主要な処理内容**：
1. プラグマの構文解析とキーワード識別
2. プラグマの種別に応じたシンボルフラグの設定
3. プラグマ引数の評価（定数式評価を含む）
4. 呼び出し規約の設定
5. 外部ライブラリ連携設定（dynlib, header）
6. コンパイラオプションの動的変更（push/pop）

**関連システム・外部連携**：外部Cコンパイラ連携（extccomp.nim）との連携により、`{.passc.}`, `{.passl.}`等のプラグマでコンパイル・リンクオプションを追加する。また、`{.compile.}`プラグマで外部Cファイルのコンパイルを指示できる。

**権限による制御**：一部のプラグマ（`{.magic.}`, `{.compilerProc.}`等）はsystemモジュールでのみ使用可能、または特別な意味を持つ。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | nimコンパイラメイン画面 | 補助機能 | プラグマ解析はセマンティック解析の一部として呼び出される |
| 8 | nim check（構文チェック） | 補助機能 | プラグマの妥当性チェック |

## 機能種別

メタデータ処理 / コンパイラ指示解析

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| c | PContext | Yes | セマンティック解析コンテキスト | nil不可 |
| sym | PSym | No | プラグマ対象のシンボル | nil可（ステートメントプラグマの場合） |
| n | PNode | Yes | プラグマノード（AST） | nkPragma or nkPragmaExpr |
| validPragmas | TSpecialWords | Yes | このコンテキストで有効なプラグマ集合 | 空集合可 |
| isStatement | bool | No | ステートメントプラグマかどうか | デフォルトfalse |
| comesFromPush | bool | No | push経由のプラグマかどうか | デフォルトfalse |

### 入力データソース

- パーサーが生成したAST（nkPragma, nkPragmaExpr, nkPragmaCallKinds）
- シンボルテーブル（プラグマ対象のシンボル情報）
- コンパイラ設定（ConfigRef）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| シンボルフラグ | TSymFlags | シンボルに設定されるフラグ（sfImportc, sfExportc等） |
| 型フラグ | TTypeFlags | 型に設定されるフラグ（tfThread, tfGcSafe等） |
| 呼び出し規約 | TCallingConvention | 関数の呼び出し規約 |
| ライブラリ情報 | PLib | dynlib/header情報 |
| コンパイルオプション | TOptions | push/popで変更されるオプション |

### 出力先

- シンボルテーブル（PSym構造体のflags, loc, typ等）
- コンパイラ設定（c.config.options, c.config.notes等）
- オプションスタック（c.optionStack）

## 処理フロー

### 処理シーケンス

```
1. プラグマノードの走査
   └─ nkPragmaの各子ノードを処理
2. プラグマキーワードの識別
   └─ whichKeyword()でTSpecialWordに変換
3. 有効性チェック
   └─ validPragmasに含まれるか確認
4. プラグマ種別に応じた処理分岐
   └─ case文で100以上のプラグマを処理
5. 引数の評価（必要な場合）
   └─ semConstExpr()で定数評価
6. シンボル/型/設定への反映
   └─ フラグ設定、プロパティ変更
```

### フローチャート

```mermaid
flowchart TD
    A[pragma関数開始] --> B[プラグマノード取得]
    B --> C{各プラグマを走査}
    C --> D[whichKeyword識別]
    D --> E{validPragmasに含まれる?}
    E -->|No| F{カスタムプラグマ?}
    E -->|Yes| G[singlePragma処理]
    F -->|No| H[invalidPragmaエラー]
    F -->|Yes| I[カスタムプラグマ処理]
    G --> J{プラグマ種別判定}
    J -->|importc系| K[外部インポート設定]
    J -->|exportc系| L[外部エクスポート設定]
    J -->|オプション系| M[コンパイルオプション変更]
    J -->|その他| N[対応する処理実行]
    K --> C
    L --> C
    M --> C
    N --> C
    C -->|完了| O[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-12-01 | コンテキスト制限 | プラグマは適用対象に応じた有効範囲がある | procPragmas, typePragmas等で定義 |
| BR-12-02 | 引数型チェック | 特定プラグマは文字列/整数引数を要求 | expectStrLit, expectIntLit |
| BR-12-03 | 排他制御 | 一部のプラグマは相互排他的 | 例: importc/exportc同時指定不可 |
| BR-12-04 | push/pop対応 | オプション系プラグマはスコープ管理可能 | {.push.}/{.pop.}で制御 |
| BR-12-05 | 呼び出し規約優先度 | 明示的指定 > dynlib暗黙設定 > デフォルト | tfExplicitCallConv判定 |

### 計算ロジック

- 呼び出し規約変換: `wordToCallConv(sw)` = `TCallingConvention(ord(ccNimCall) + ord(sw) - ord(wNimcall))`
- アライメント: `sym.alignment = max(sym.alignment, alignment)` (2のべき乗のみ許可)

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

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| invalidPragma | 構文エラー | 不正なプラグマ構文 | エラーメッセージ表示、コンパイル継続 |
| errStringLiteralExpected | 引数エラー | 文字列が必要な場所に他の型 | エラー訂正として空文字列を使用 |
| errIntLiteralExpected | 引数エラー | 整数が必要な場所に他の型 | エラー訂正として0を使用 |
| illegalCustomPragma | 適用エラー | カスタムプラグマを付与できない対象 | エラーメッセージ表示 |

### リトライ仕様

プラグマ処理にリトライ機構はない。エラー発生時はエラー訂正を行い、可能な限りコンパイルを継続する。

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

- push/popプラグマによりオプションスタックを管理
- popは対応するpushがない場合はエラー
- モジュール終了時にスタックは自動的にクリア

## パフォーマンス要件

- プラグマ処理はセマンティック解析の一部であり、O(n)で処理（nはプラグマ数）
- whichKeywordによるキーワード検索は効率的なハッシュベース

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

- `{.emit.}`プラグマは任意のC/Cコードを挿入可能であり、注意が必要
- `{.compile.}`, `{.link.}`は外部ファイルを参照するため、パス検証が重要
- `{.importc.}`は任意の外部関数を呼び出し可能

## 備考

- プラグマの一覧と詳細な仕様は公式ドキュメント参照
- カスタムプラグマはマクロ/テンプレートで定義可能
- `{.experimental.}`で実験的機能を有効化

---

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

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

### 推奨読解順序

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

まず、プラグマの種類を定義するデータ構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | pragmas.nim | `compiler/pragmas.nim` | procPragmas, typePragmas等の定義（28-96行目）: 各コンテキストで有効なプラグマの集合 |
| 1-2 | wordrecg.nim | `compiler/wordrecg.nim` | TSpecialWord列挙型: 全プラグマキーワードの定義 |
| 1-3 | ast.nim | `compiler/ast.nim` | TSymFlag, TTypeFlag: プラグマにより設定されるフラグ |

**読解のコツ**: プラグマセット（procPragmas等）はTSpecialWordの集合として定義されている。`+`や`-`で集合演算を行い、コンテキストごとの有効プラグマを決定している。

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

プラグマ処理のメイン関数を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | pragmas.nim | `compiler/pragmas.nim` | pragma()関数（107-108行目）: メインエントリーポイント（前方宣言） |
| 2-2 | pragmas.nim | `compiler/pragmas.nim` | singlePragma()関数: 個々のプラグマを処理するメイン関数 |

**主要処理フロー**:
1. **107-108行**: pragma()関数の宣言（実装は後方）
2. **case k of ...**: 100以上のプラグマを巨大なcase文で処理

#### Step 3: 外部連携プラグマを理解する

importc, exportc等の重要なプラグマ処理を把握。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | pragmas.nim | `compiler/pragmas.nim` | makeExternImport()関数（169-172行目）: importc処理 |
| 3-2 | pragmas.nim | `compiler/pragmas.nim` | makeExternExport()関数（174-176行目）: exportc処理 |
| 3-3 | pragmas.nim | `compiler/pragmas.nim` | processImportCpp()関数（184-192行目）: C++インポート処理 |
| 3-4 | pragmas.nim | `compiler/pragmas.nim` | processDynLib()関数（348-366行目）: 動的ライブラリ設定 |

**主要処理フロー**:
- **169-172行**: setExternNameでC名を設定し、sfImportcフラグを追加
- **184-192行**: C++の場合はsfInfixCall追加、optMixedMode有効化

#### Step 4: オプション系プラグマを理解する

コンパイラオプションを変更するプラグマの処理。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | pragmas.nim | `compiler/pragmas.nim` | pragmaToOptions()関数（393行目以降）: プラグマからオプションへの変換 |
| 4-2 | pragmas.nim | `compiler/pragmas.nim` | processOption()関数: オプション処理 |
| 4-3 | pragmas.nim | `compiler/pragmas.nim` | processPush/processPop(): オプションスタック管理 |

#### Step 5: エラー処理を理解する

不正なプラグマへの対処方法。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | pragmas.nim | `compiler/pragmas.nim` | invalidPragma()関数（120-121行目）: 無効プラグマのエラー出力 |
| 5-2 | pragmas.nim | `compiler/pragmas.nim` | illegalCustomPragma()関数（123-132行目）: カスタムプラグマエラー |

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

```
pragma()
    │
    ├─ singlePragma() [各プラグマを処理]
    │      │
    │      ├─ whichKeyword() [キーワード識別]
    │      │
    │      ├─ makeExternImport() / makeExternExport()
    │      │      └─ setExternName()
    │      │
    │      ├─ processImportCpp() / processImportObjC()
    │      │
    │      ├─ processDynLib()
    │      │      └─ getLib()
    │      │
    │      ├─ processMagic()
    │      │
    │      ├─ processOption()
    │      │      └─ onOff() / pragmaToOptions()
    │      │
    │      └─ processPush() / processPop()
    │
    └─ implicitPragmas() [暗黙プラグマ処理]
```

### データフロー図

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

PNode(nkPragma) ────────▶ pragma()
    │                         │
    ▼                         ▼
whichKeyword() ──────────▶ singlePragma()
    │                         │
    ▼                         ▼
TSpecialWord ────────────▶ case分岐
                              │
                              ├────────────────────▶ PSym.flags (sfImportc等)
                              │
                              ├────────────────────▶ PType.flags (tfThread等)
                              │
                              ├────────────────────▶ c.config.options
                              │
                              └────────────────────▶ c.optionStack
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| pragmas.nim | `compiler/pragmas.nim` | ソース | プラグマ処理のメイン実装（1422行） |
| wordrecg.nim | `compiler/wordrecg.nim` | ソース | キーワード・プラグマの識別 |
| ast.nim | `compiler/ast.nim` | ソース | シンボルフラグ、型フラグの定義 |
| options.nim | `compiler/options.nim` | ソース | コンパイラオプション管理 |
| semdata.nim | `compiler/semdata.nim` | ソース | PContext定義、オプションスタック |
| extccomp.nim | `compiler/extccomp.nim` | ソース | passc/passl処理との連携 |
| lookups.nim | `compiler/lookups.nim` | ソース | カスタムプラグマのシンボル検索 |
