# 機能設計書 95-sugar（シンタックスシュガー）

## 概要

本ドキュメントは、Nim標準ライブラリの`sugar`モジュールの機能設計を記述する。このモジュールは、Nimのマクロシステムを活用した便利な構文糖衣（シンタックスシュガー）を提供する。

### 本機能の処理概要

sugarモジュールは、ラムダ式の簡潔な記法（`=>`、`->`）、コレクション内包表記（`collect`）、インプレースアルゴリズムのコピー版生成（`dup`）、ループ変数のキャプチャ（`capture`）、デバッグ出力（`dump`、`dumpToString`）などの機能を提供する。

**業務上の目的・背景**：Nimは表現力豊かな言語だが、一部の一般的なパターン（匿名関数定義、コレクション操作など）は冗長になりがちである。sugarモジュールは、これらのパターンをより簡潔に記述できるようにし、コードの可読性と開発効率を向上させる。

**機能の利用シーン**：
- 高階関数（map、filter等）に渡す匿名関数の簡潔な定義
- プロシージャ型の宣言
- コレクション内包表記によるリスト・セット・テーブルの生成
- インプレース操作を持つ型の不変的な使用
- クロージャ作成時のループ変数キャプチャ
- デバッグ時の式の値と表現の出力

**主要な処理内容**：
1. `=>`マクロ: 匿名プロシージャの簡潔な定義
2. `->`マクロ: プロシージャ型の簡潔な定義
3. `dump`マクロ: 式の文字列表現と値を出力
4. `dumpToString`マクロ: dumpの文字列版
5. `capture`マクロ: ループ変数をクロージャにキャプチャ
6. `dup`マクロ: インプレース操作をコピー版に変換
7. `collect`マクロ: コレクション内包表記

**関連システム・外部連携**：
- macrosモジュール: AST操作に使用
- sequtils: collectのseq生成に使用
- sets: collectのHashSet生成に使用
- tables: collectのTable生成に使用

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

## 関連画面

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

## 機能種別

構文糖衣 / マクロライブラリ

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| p | untyped | Yes | =>/-\>マクロの左辺（パラメータ） | 有効なパラメータリスト |
| b | untyped | Yes | =>/-\>マクロの右辺（本体/戻り型） | 有効な式/型 |
| x | untyped | Yes | dump/dumpToStringの対象式 | 有効な式 |
| locals | varargs[typed] | Yes | captureでキャプチャする変数 | 識別子のリスト |
| arg | T | Yes | dupの対象値 | コピー可能な値 |
| calls | varargs[untyped] | Yes | dupで適用する操作 | 有効なプロシージャ呼び出し |
| init | untyped | No | collectの初期化式 | newSeq/initHashSet/initTable等 |
| body | untyped | Yes | collectの本体 | forループを含む式 |

### 入力データソース

- ソースコード内のマクロ呼び出し

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| =>結果 | proc | 生成された匿名プロシージャ |
| ->結果 | typedesc | 生成されたプロシージャ型 |
| dump結果 | void | 標準出力への式の値出力 |
| dumpToString結果 | string | 式の文字列表現と値 |
| capture結果 | auto | キャプチャ済みクロージャの戻り値 |
| dup結果 | T | 操作適用後のコピー |
| collect結果 | seq/HashSet/Table | 生成されたコレクション |

### 出力先

- 生成されたコード（コンパイル時）
- 標準出力（dump）
- 戻り値（その他）

## 処理フロー

### 処理シーケンス

```
1. マクロ呼び出し
   └─ コンパイル時にAST変換

2. =>マクロの場合
   ├─ パラメータリストを解析
   ├─ ->による戻り型指定があれば抽出
   ├─ プラグマ（{.noSideEffect.}等）があれば抽出
   └─ nnkLambdaノードを構築

3. ->マクロの場合
   ├─ パラメータリストを解析
   ├─ プラグマがあれば抽出
   └─ nnkProcTyノードを構築

4. collectマクロの場合
   ├─ 本体の最終式を解析
   ├─ 式の形式でコレクション型を決定
   │   ├─ {e}: HashSet → incl
   │   ├─ {k: v}: Table → []=
   │   └─ e: seq → add
   ├─ 初期化コードを生成
   └─ ループ内にadd/incl/[]=を挿入

5. dupマクロの場合
   ├─ 引数を一時変数にコピー
   ├─ 各操作を順次適用（_を引数に置換）
   └─ 結果を返す
```

### フローチャート

```mermaid
flowchart TD
    A[sugar マクロ呼び出し] --> B{マクロ種別}

    B -->|=>| C[パラメータ解析]
    C --> D{->による戻り型?}
    D -->|Yes| E[戻り型抽出]
    D -->|No| F[auto戻り型]
    E --> G{プラグマ?}
    F --> G
    G -->|Yes| H[プラグマ抽出]
    G -->|No| I[空プラグマ]
    H --> J[nnkLambda構築]
    I --> J

    B -->|->| K[パラメータ解析]
    K --> L[nnkProcTy構築]

    B -->|collect| M[本体の最終式解析]
    M --> N{式の形式}
    N -->|{e}| O[HashSet + incl]
    N -->|{k:v}| P[Table + []=]
    N -->|e| Q[seq + add]
    O --> R[初期化 + ループ変換]
    P --> R
    Q --> R

    B -->|dup| S[一時変数にコピー]
    S --> T[各操作を適用]
    T --> U[結果返却]

    J --> V[展開コード]
    L --> V
    R --> V
    U --> V
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | セミコロン禁止 | =>と->ではパラメータ区切りにセミコロン使用不可 | =>/-\>マクロ使用時 |
| BR-02 | capture変数名 | captureの変数名に`result`は使用不可 | capture使用時 |
| BR-03 | dup アンダースコア | dupで`_`は引数の位置を示す | dup使用時 |
| BR-04 | collect最終式 | collectの本体の最終式がコレクション型を決定 | collect使用時 |

### 計算ロジック

特になし（AST変換のため）

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| コンパイルエラー | 構文エラー | 不正なパラメータ形式（=>/->） | 正しいパラメータ形式に修正 |
| コンパイルエラー | エラー | captureでresult変数を使用 | 別の変数名を使用 |
| コンパイルエラー | 構文エラー | collectの最終式が不正 | e、{e}、{k:v}の形式に修正 |

### リトライ仕様

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

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

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

## パフォーマンス要件

- すべての処理はコンパイル時に完了する
- 実行時オーバーヘッドはインライン展開により最小化

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

特になし（コンパイル時マクロのため）

## 備考

- captureはクロージャ作成時のループ変数の「値のコピー」を保証
- dupは関数チェーンを可能にし、不変的なスタイルでの記述を支援
- collectはPythonのリスト内包表記に相当する機能を提供

---

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

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

### 推奨読解順序

#### Step 1: 基本構造を理解する

モジュールの構造と依存関係を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | sugar.nim | `lib/pure/sugar.nim` | 10-14行目: モジュールドキュメントとimport文 |
| 1-2 | sugar.nim | `lib/pure/sugar.nim` | 16-21行目: checkPragmaヘルパープロシージャ |

**読解のコツ**: checkPragmaは`{.noSideEffect.}`などのプラグマを式から抽出するヘルパー。

#### Step 2: =>マクロを理解する

匿名プロシージャ生成の仕組みを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | sugar.nim | `lib/pure/sugar.nim` | 55-134行目: `=>`マクロの実装 |

**主要処理フロー**:
- **76-81行目**: 初期パラメータとプラグマの設定
- **83-87行目**: `->`演算子がある場合の戻り型抽出
- **91-123行目**: パラメータの種類に応じた処理（Par、TupleConstr、Ident等）
- **132-134行目**: newProcでラムダを構築

#### Step 3: ->マクロを理解する

プロシージャ型生成の仕組みを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | sugar.nim | `lib/pure/sugar.nim` | 22-53行目: createProcTypeヘルパープロシージャ |
| 3-2 | sugar.nim | `lib/pure/sugar.nim` | 136-153行目: `->`マクロの実装 |

**主要処理フロー**:
- **22-53行目**: nnkProcTyノードを構築するヘルパー
- **136-153行目**: createProcTypeを呼び出すだけのシンプルなマクロ

#### Step 4: dump系マクロを理解する

デバッグ出力の仕組みを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | sugar.nim | `lib/pure/sugar.nim` | 155-172行目: `dump`マクロ |
| 4-2 | sugar.nim | `lib/pure/sugar.nim` | 174-198行目: `dumpToString`マクロ |

**主要処理フロー**:
- **170-172行目**: toStrLitで式を文字列化し、debugEchoを呼び出し
- **174-181行目**: dumpToStringImplで型を考慮した文字列化

#### Step 5: captureマクロを理解する

ループ変数キャプチャの仕組みを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | sugar.nim | `lib/pure/sugar.nim` | 200-214行目: freshIdentNodesヘルパー |
| 5-2 | sugar.nim | `lib/pure/sugar.nim` | 216-249行目: `capture`マクロ |

**主要処理フロー**:
- **200-214行目**: NimIdentとNimSymを新しいidentに置換
- **230-246行目**: 引数をラムダのパラメータとして構築し、即座に呼び出し

#### Step 6: dupマクロを理解する

インプレース→コピー変換の仕組みを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 6-1 | sugar.nim | `lib/pure/sugar.nim` | 251-298行目: `dup`マクロ |

**主要処理フロー**:
- **294行目**: genSymで一時変数を生成
- **295-296行目**: 引数をコピーし、各操作を適用
- **297行目**: underscoredCallsで`_`を引数に置換

#### Step 7: collectマクロを理解する

コレクション内包表記の仕組みを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 7-1 | sugar.nim | `lib/pure/sugar.nim` | 300-342行目: `trans`プロシージャ |
| 7-2 | sugar.nim | `lib/pure/sugar.nim` | 344-364行目: `collectImpl`プロシージャ |
| 7-3 | sugar.nim | `lib/pure/sugar.nim` | 366-429行目: `collect`マクロ（2種類） |

**主要処理フロー**:
- **300-342行目**: 最終式を解析し、コレクション型とadder操作を決定
- **317-326行目**: nnkTableConstrの場合はinitTable + `[]=`
- **327-334行目**: nnkCurlyの場合はinitHashSet + incl
- **335-342行目**: その他の場合はnewSeq + add

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

```
sugar マクロ
    │
    ├─ => (匿名プロシージャ)
    │      ├─ checkPragma()
    │      └─ newProc(nnkLambda)
    │
    ├─ -> (プロシージャ型)
    │      └─ createProcType()
    │
    ├─ dump
    │      ├─ toStrLit()
    │      └─ debugEcho
    │
    ├─ dumpToString
    │      └─ dumpToStringImpl()
    │
    ├─ capture
    │      ├─ freshIdentNodes()
    │      ├─ getTypeInst()
    │      └─ newProc(nnkLambda) + 即時呼び出し
    │
    ├─ dup
    │      ├─ genSym()
    │      ├─ newVarStmt()
    │      └─ underscoredCalls()
    │
    └─ collect
           ├─ collectImpl()
           │      ├─ trans()
           │      │      ├─ [nnkTableConstr] initTable + []=
           │      │      ├─ [nnkCurly] initHashSet + incl
           │      │      └─ [その他] newSeq + add
           │      └─ newVarStmt() + resBody
           └─ freshIdentNodes()
```

### データフロー図

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

(x, y) => x + y ────────▶ パラメータ解析 ───────────────▶
                              │
                              ▼
                         nnkLambda構築
                              │
                              ▼
                         proc(x, y: auto): auto = x + y

(int, int) -> int ──────▶ createProcType ──────────────▶
                              │
                              ▼
                         nnkProcTy構築
                              │
                              ▼
                         proc(i0: int, i1: int): int

collect(newSeq): ───────▶ trans() ──────────────────────▶
  for i in 0..9: i           │
                              ▼
                         最終式解析 → add操作挿入
                              │
                              ▼
                         var result = newSeq[int]()
                         for i in 0..9:
                           result.add(i)
                         result

a.dup(sort) ────────────▶ genSym + コピー ─────────────▶
                              │
                              ▼
                         underscoredCalls
                              │
                              ▼
                         var tmp = a
                         sort(tmp)
                         tmp
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| sugar.nim | `lib/pure/sugar.nim` | ソース | シンタックスシュガーのメイン実装 |
| macros.nim | `lib/core/macros.nim` | 依存元 | AST操作ユーティリティ |
| underscored_calls.nim | `lib/std/private/underscored_calls.nim` | 依存元 | `_`置換処理 |
| since.nim | `lib/std/private/since.nim` | 依存元 | バージョン管理マクロ |
| sequtils.nim | `lib/pure/collections/sequtils.nim` | 関連 | collectのseq操作 |
| sets.nim | `lib/pure/collections/sets.nim` | 関連 | collectのHashSet操作 |
| tables.nim | `lib/pure/collections/tables.nim` | 関連 | collectのTable操作 |
