# 機能設計書 7-NIFフォーマット生成

## 概要

本ドキュメントは、NimコンパイラのNIFフォーマット生成機能の設計について記載する。NIFフォーマット生成は型付きASTをNIF（Nim Intermediate Format）に変換する。

### 本機能の処理概要

NIFフォーマット生成は、セマンティック解析で型付けされたASTを入力として受け取り、NIF形式のテキスト出力を生成する。NIFはNimonyプロジェクトで使用される中間表現形式であり、ASTをシリアライズした形式である。

**業務上の目的・背景**：NIFはNimの新しいコンパイラ（Nimony）との相互運用を目的とした中間フォーマットである。既存のNimコンパイラからセマンティック解析済みのASTをNIFに変換することで、Nimonyがそのまま処理できる形式にする。

**機能の利用シーン**：
- Nimonyプロジェクトへの移行準備
- ASTのシリアライズと永続化
- コンパイラ間の中間表現交換
- 増分コンパイルのキャッシュ

**主要な処理内容**：
1. TranslationContextの初期化
2. ノード種別変換（nodeKindTranslation）
3. 型のNIF表現生成（toNifType）
4. 式/文のNIF表現生成（toNif）
5. マジック関数の変換（magicToNifTag）
6. シンボルのNIF表現生成（symToNif）
7. ファイル出力

**関連システム・外部連携**：
- セマンティック解析（sem.nim）から型付きASTを受け取る
- Nimonyプロジェクト（dist/nimony）との連携
- nifbuilder.nimでNIF構文を構築
- nifler_tags.nimでNIFタグを定義

**権限による制御**：コード生成自体には権限制御はない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| N/A | コマンドラインインターフェース | 参照画面 | 出力ファイルパス表示 |

## 機能種別

コード変換処理 / 中間表現生成処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| n | PNode | Yes | 型付きASTノード | 非nil |
| parent | PNode | No | 親ノード（位置情報用） | - |
| c | var TranslationContext | Yes | 変換コンテキスト | - |

### 入力データソース

- 型付きAST（PNode）
- 型情報（PType）
- シンボル情報（PSym）
- コンパイラ設定（ConfigRef）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| NIFファイル | File | 生成されたNIFフォーマット |
| 依存ファイル | File | モジュール依存情報（オプション） |

### 出力先

- nimcacheディレクトリまたは指定ディレクトリ
- NIFファイル（`.nif`形式）

## 処理フロー

### 処理シーケンス

```
1. NifModuleの作成
   └─ TranslationContext初期化
2. ノード変換（toNif）
   ├─ シンボル変換（symToNif）
   ├─ 型変換（toNifType）
   └─ マジック変換（magicCall）
3. nodeKindTranslation
   └─ TNodeKind→NIFタグ変換
4. 位置情報（relLineInfo/absLineInfo）
5. Builder出力
   └─ NIFファイル書き出し
```

### フローチャート

```mermaid
flowchart TD
    A[NifModule作成] --> B[TranslationContext初期化]
    B --> C[toNif: ノード変換]
    C --> D{ノード種別}
    D -->|シンボル| E[symToNif]
    D -->|リテラル| F[リテラル出力]
    D -->|呼び出し| G[magicCall]
    D -->|型定義| H[toNifType]
    E --> I[Builder: NIF構築]
    F --> I
    G --> I
    H --> I
    I --> J[NIFファイル出力]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | ノード変換 | TNodeKindをNIFタグに変換 | 全てのノード |
| BR-02 | 型変換 | Nim型をNIF型表現に変換 | 型情報 |
| BR-03 | マジック変換 | TMagicをNIFオペレーションに変換 | マジック関数 |
| BR-04 | シンボル名生成 | 名前.disamb.モジュールサフィックス形式 | シンボル参照 |
| BR-05 | ポータブルパス | 相対パスで位置情報を記録 | portablePaths有効時 |

### 計算ロジック

- **シンボル名**: `s.name.s & '.' & $s.disamb & '.' & modname(c, idx)`
- **モジュールサフィックス**: `moduleSuffix(fp, searchPaths)`

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

該当なし（NIFフォーマット生成はデータベースを使用しない）

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| N/A | N/A | N/A | データベース操作なし |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| err | 変換エラー | 未対応のノード種別 | nodeKindTranslationで"err"を返す |
| bug | 内部エラー | mNoneマジック | magicToNifTagで"bug"を返す |

### リトライ仕様

コード生成はリトライを行わない。

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

該当なし

## パフォーマンス要件

- Builder（nifbuilder）による効率的なNIF構築
- IntSetによる重複処理防止（handled）
- ポータブルパスキャッシュ（toSuffix）

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

- 外部ファイルパスの適切なエスケープ
- アトミックファイル作成（tempFilename→finalFilename）

## 備考

- Nimonyプロジェクト（dist/nimony）との連携が前提
- nifbuilder.nimでNIF構文構築
- nifler_tags.nimでセクション種別定義（NiflerKind）
- TypedMagic/TypedMagicOp1で型情報付きマジック演算

---

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

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

### 推奨読解順序

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

まず、NIFフォーマット生成で使用されるデータ構造を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | nifgen.nim | `compiler/nifgen.nim` 28-46行目 | TranslationContext、NifModule型の定義を理解 |

**読解のコツ**:
- `TranslationContext`は変換状態を保持（29-40行目）
  - `conf`: コンパイラ設定
  - `b, deps`: Builder（NIFビルダー）
  - `section`: 現在のセクション種別（NiflerKind）
  - `portablePaths`: 相対パス使用フラグ
  - `toSuffix`: モジュールサフィックスキャッシュ
  - `handled`: 処理済みシンボルセット
- `NifModule`はモジュール単位の状態を保持（42-46行目）
  - `graph`: ModuleGraph
  - `module`: モジュールシンボル
  - `tc`: TranslationContext
  - `outfile`: 出力ファイルパス

#### Step 2: ノード種別変換を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | nifgen.nim | `compiler/nifgen.nim` 48-148行目 | nodeKindTranslation関数でTNodeKind→NIFタグ変換 |

**主要処理フロー**:
- **50-51行目**: nkCommand→"cmd"、nkCall→"call"
- **66行目**: nkAsgn/nkFastAsgn→"asgn"
- **67行目**: nkIfExpr/nkIfStmt→"if"
- **94-100行目**: プロシージャ定義（proc/func/method/converter/macro/template/iterator）
- **129-135行目**: リテラル系は"err"（特別処理）

#### Step 3: マジック関数変換を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | nifgen.nim | `compiler/nifgen.nim` 213-220行目 | 特殊ビット値の定数定義 |
| 3-2 | nifgen.nim | `compiler/nifgen.nim` 222-501行目 | magicToNifTag関数でTMagic→NIFタグ変換 |

**主要処理フロー**:
- **213-220行目**: 特殊ビット値定義
  - `NewOperator = -2`: new演算子
  - `TypedMagic = -3`: 型付きマジック
  - `TypedMagicOp1 = -4`: 第1引数型付きマジック
  - `NoMagic = -5`: 通常変換
  - `ArrayType = -6`: 配列型
  - `StringType = -7`: 文字列型
  - `BecomesCall = -8`: 呼び出しに変換
- **270-286行目**: 算術演算（add/sub/mul/div/shr/shl等）
- **294-316行目**: 比較演算（eq/le/lt等）

#### Step 4: シンボル変換を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | nifgen.nim | `compiler/nifgen.nim` 503-508行目 | modname関数でモジュールサフィックス取得 |
| 4-2 | nifgen.nim | `compiler/nifgen.nim` 513-551行目 | symToNif関数でシンボルをNIF形式に変換 |

**主要処理フロー**:
- **503-508行目**: `modname`でFileIndex→モジュールサフィックス変換
- **516-519行目**: ジェネリックインスタンスの場合は所有者を使用
- **521-527行目**: シンボル名を`名前.disamb.モジュールサフィックス`形式に構築
- **528-529行目**: 定義の場合は`addSymbolDef`
- **530-540行目**: インスタンス化の場合は`at`ツリーで型引数付き
- **541-547行目**: マジック型の場合はmagicToNifTagで変換

#### Step 5: 型変換を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | nifgen.nim | `compiler/nifgen.nim` 602-668行目 | toNifTag(TTypeKind)で型種別→NIFタグ変換 |
| 5-2 | nifgen.nim | `compiler/nifgen.nim` 702-937行目 | toNifType関数で型をNIF形式に変換 |

**主要処理フロー**:
- **602-668行目**: `toNifTag`で型種別をNIFタグに変換
  - tyBool→"bool"、tyChar→"c"、tyInt→"int"等
- **707-728行目**: プリミティブ型（整数、浮動小数点）の処理
- **744-757行目**: ジェネリック型（tyGenericInst、tyGenericInvocation、tyGenericBody）
- **850-880行目**: プロシージャ型（パラメータ、戻り値、エフェクト、呼び出し規約）

#### Step 6: ノード変換を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 6-1 | nifgen.nim | `compiler/nifgen.nim` 1070-1399行目 | toNif関数でPNodeをNIF形式に変換 |

**主要処理フロー**:
- **1072-1073行目**: シンボル（nkSym）→symToNif
- **1079-1135行目**: リテラル（nil、文字列、整数、浮動小数点）
- **1139-1164行目**: 型定義（nkTypeDef）
- **1170-1181行目**: 変数セクション（var/let/const）
- **1357-1394行目**: プロシージャ定義（proc/func/converter/macro/template/iterator/method）

#### Step 7: マジック呼び出しを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 7-1 | nifgen.nim | `compiler/nifgen.nim` 939-966行目 | magicCall関数でマジック関数をNIF形式に変換 |

**主要処理フロー**:
- **941-945行目**: NoMagicの場合はnodeKindTranslationで通常変換
- **946-951行目**: ArrayTypeの場合は引数順序を逆転
- **952-957行目**: BecomesCallの場合はcall形式に変換
- **959-966行目**: TypedMagic/TypedMagicOp1の場合は型情報付きで出力

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

```
myModule (モジュール処理)
    │
    ├─ NifModule作成
    │      └─ TranslationContext初期化
    │
    └─ toNif (メイン変換)
           │
           ├─ nodeKindTranslation (ノード種別変換)
           │
           ├─ symToNif (シンボル変換)
           │      ├─ modname (モジュールサフィックス)
           │      └─ magicToNifTag (マジック型)
           │
           ├─ toNifType (型変換)
           │      ├─ toNifTag (型種別変換)
           │      ├─ atom (単純型)
           │      └─ typeHead (複合型)
           │
           ├─ magicCall (マジック呼び出し)
           │      └─ magicToNifTag
           │
           ├─ リテラル出力
           │      ├─ addStrLit
           │      ├─ addIntLit
           │      └─ addFloatLit
           │
           └─ Builder出力
                  ├─ withTree (ツリー開始/終了)
                  ├─ addTree/endTree
                  └─ addSymbol/addSymbolDef
```

### データフロー図

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

型付きAST ────────────────────▶ toNif ───────────────────────────▶ NIF構文
(PNode)                          (ノード変換)
       │
       ▼
ノード種別 ───────────────────▶ nodeKindTranslation ─────────────▶ NIFタグ文字列
(TNodeKind)                      (種別変換)
       │
       ▼
型情報 ───────────────────────▶ toNifType ───────────────────────▶ NIF型表現
(PType)                          (型変換)
       │
       ▼
マジック種別 ─────────────────▶ magicToNifTag ───────────────────▶ NIFオペレーション
(TMagic)                         (マジック変換)
       │
       ▼
シンボル ─────────────────────▶ symToNif ────────────────────────▶ NIF参照
(PSym)                           (シンボル変換)
       │
       ▼
Builder ──────────────────────▶ ファイル出力 ─────────────────────▶ NIFファイル
                                (nifbuilder)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| nifgen.nim | `compiler/nifgen.nim` | ソース | NIFフォーマット生成メインモジュール |
| nifbuilder.nim | `dist/nimony/src/lib/nifbuilder.nim` | ソース | NIF構文ビルダー |
| nifler_tags.nim | `dist/nimony/src/models/nifler_tags.nim` | ソース | NIFタグ/セクション定義 |
| modnames.nim | `dist/nimony/src/gear2/modnames.nim` | ソース | モジュール名サフィックス計算 |
| ast.nim | `compiler/ast.nim` | ソース | AST定義 |
| types.nim | `compiler/types.nim` | ソース | 型定義 |
| modulegraphs.nim | `compiler/modulegraphs.nim` | ソース | モジュールグラフ |

