# 機能設計書：98-genasts（ASTジェネレータ）

## 1. 概要

### 本機能の処理概要
genastsモジュールは、マクロ内でキャプチャ変数を使用してASTを生成するための機能を提供する。`genAst`マクロは、明示的にキャプチャした変数とコードブロックを受け取り、そのブロックを表すASTノードを返す。これは従来の`quote do:`構文の改良版であり、変数キャプチャの制御がより明確になっている。

### 関連画面
本機能は標準ライブラリのマクロユーティリティであり、特定の画面には関連しない。

### 機能種別
ライブラリ機能（メタプログラミング・マクロユーティリティ）

## 2. 入力仕様

### オプション型定義
```nim
type GenAstOpt* = enum
  kDirtyTemplate,  # dirtyテンプレートを使用
  kNoNewLit,       # newLitの自動呼び出しを無効化
```

### マクロシグネチャ
```nim
macro genAstOpt*(options: static set[GenAstOpt], args: varargs[untyped]): untyped
template genAst*(args: varargs[untyped]): untyped
```

### 入力パラメータ

| パラメータ | 型 | 説明 |
|----------|-----|------|
| options | static set[GenAstOpt] | 動作オプション |
| args | varargs[untyped] | キャプチャ変数とコードブロック |

### キャプチャ変数の形式

| 形式 | 説明 | 例 |
|-----|------|-----|
| `a=b` | 変数`a`に式`b`の値を束縛 | `cond, s = repr(cond)` |
| `a` | 変数`a`をそのままキャプチャ | `cond` |

## 3. 出力仕様

### 戻り値
`NimNode` - 指定されたコードブロックを表すAST

### 生成される内部構造
1. 一時テンプレート定義（`nskTemplate`）
2. `getAst`呼び出しによるAST取得

## 4. 処理フロー

### 4.1 genAstOpt展開フロー

```
[genAstOpt(options, args)呼び出し]
    |
    v
[パラメータリスト作成]
    |
    v
[プラグマ決定]
    +-- [kDirtyTemplate in options] --> [dirty]プラグマ
    +-- [それ以外] --> 空
    |
    v
[テンプレート名生成（genSym）]
    |
    v
[各キャプチャ引数を処理]
    |
    +-- [nnkExprEqExpr] --> varName=a[0], varVal=a[1]
    |
    +-- [nnkIdent] --> varName=a, varVal=a
    |
    +-- [その他] --> エラー
    |
    v
[kNoNewLitチェック]
    +-- [なし] --> newLitMaybeでラップ
    |
    v
[テンプレート定義ノード作成]
    |
    v
[getAst呼び出しノード追加]
    |
    v
[結果ステートメントリストを返却]
```

### 4.2 newLitMaybe変換

```
[newLitMaybe(a)評価]
    |
    v
[型チェック]
    |
    +-- [a is type] --> aをそのまま返す
    |
    +-- [typeof(a) is (proc|iterator|func|NimNode)] --> aをそのまま返す
    |
    +-- [その他] --> newLit(a)
```

## 5. ビジネスルール

### BR-01: 明示的キャプチャ
`genAst`内でアクセスするローカル変数は、明示的にキャプチャリストに含める必要がある。キャプチャされていない変数はアクセスできない（`var not init`エラー）。

### BR-02: injectシンボルの自動キャプチャ
`{.inject.}`プラグマが付いたシンボル（procなど）は、`kDirtyTemplate`が設定されていない限り、キャプチャなしでアクセス可能。

### BR-03: newLitの自動適用
デフォルトでは、キャプチャした値は`newLitMaybe`を通じて`newLit`が適用される。ただし、型、proc、iterator、func、NimNodeは変換されない。

### BR-04: kDirtyTemplateの用途
`kDirtyTemplate`を設定すると、dirtyテンプレートが使用される。これは#8220などの問題の回避策として有用だが、呼び出し元スコープのシンボルによるハイジャックの可能性がある。

### BR-05: 静的パラメータの転送
マクロの`static`パラメータはgenAst内でも静的パラメータとして扱われる。

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

本機能はデータベース操作を行わない。

## 7. エラー処理

### コンパイル時エラー

| 条件 | エラーメッセージ |
|-----|----------------|
| 無効な引数形式 | "invalid argument kind: " & kind |
| 未キャプチャ変数アクセス | "var not init"（コンパイラエラー） |

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

本機能はトランザクション処理を行わない。

## 9. パフォーマンス要件

### コンパイル時間
- マクロ展開はコンパイル時に完了
- 一時テンプレートの生成と`getAst`呼び出し

### 実行時オーバーヘッド
- なし（すべてコンパイル時に解決）

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

### 安全性
- 型安全性はコンパイラが保証
- `kDirtyTemplate`使用時はシンボルハイジャックに注意

### 注意点
- `kDirtyTemplate`は必要な場合のみ使用

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

### 11.1 推奨される読み解き順序

1. **モジュールドキュメント**（1行目）
   - 機能概要の把握

2. **GenAstOpt型定義**（5-13行目）
   - `kDirtyTemplate`：dirtyテンプレート使用
   - `kNoNewLit`：newLit自動適用の無効化

3. **genAstOptマクロ**（15-85行目）
   - runnableExamples（19-43行目）：使用例
   - パラメータ準備（45-50行目）
   - newLitMaybeテンプレート（52-55行目）
   - 引数処理ループ（60-74行目）
   - テンプレート定義生成（76-85行目）

4. **genAstテンプレート**（87-89行目）
   - genAstOptへの委譲

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

```
genAst*(args: varargs[untyped]): untyped
└── genAstOpt*({}, args)
    ├── [パラメータリスト作成]
    │   └── newTree(nnkFormalParams, newEmptyNode())
    ├── [プラグマ決定]
    │   └── nnkPragma.newTree(ident"dirty") / newEmptyNode()
    ├── [テンプレート名生成]
    │   └── genSym(nskTemplate, "_fun")
    ├── [引数処理]
    │   ├── [nnkExprEqExpr] → varName, varVal抽出
    │   ├── [nnkIdent] → 同一変数
    │   └── newLitMaybe(varVal) [kNoNewLitでない場合]
    │       ├── [type/proc/iterator/func/NimNode] → そのまま
    │       └── [その他] → newLit(a)
    ├── [テンプレート定義]
    │   └── nnkTemplateDef.newTree(...)
    └── [AST取得]
        └── newCall(bindSym"getAst", call)
```

### 11.3 データフロー図

```
入力:
  genAst(a, b = expr, c):
    body_code

変換プロセス:
  ┌─────────────────────────────────┐
  │ args[0..^2]: キャプチャ変数      │
  │   a → (a, a)                    │
  │   b = expr → (b, expr)          │
  │   c → (c, c)                    │
  │                                 │
  │ args[^1]: コードブロック         │
  │   body_code                     │
  └─────────────────────────────────┘
              |
              v
  ┌─────────────────────────────────┐
  │ 一時テンプレート生成              │
  │ template _fun(a, b, c) =        │
  │   body_code                     │
  └─────────────────────────────────┘
              |
              v
  ┌─────────────────────────────────┐
  │ getAst呼び出し                   │
  │ getAst(_fun(                    │
  │   newLitMaybe(a),               │
  │   newLitMaybe(expr),            │
  │   newLitMaybe(c)))              │
  └─────────────────────────────────┘
              |
              v
  出力: NimNode (AST)
```

### 11.4 関連ファイル一覧

| ファイル | 役割 | 行数 |
|---------|------|------|
| lib/std/genasts.nim | genAst/genAstOptマクロの実装 | 90 |
| lib/core/macros.nim | NimNode操作、getAst、genSym | - |

### 11.5 重要な実装詳細

#### newLitMaybeテンプレート（52-55行目）
```nim
template newLitMaybe(a): untyped =
  when (a is type) or (typeof(a) is (proc | iterator | func | NimNode)):
    a
  else: newLit(a)
```

型、プロシージャ、イテレータ、関数、NimNodeはリテラル変換せずそのまま使用。その他の値は`newLit`でAST表現に変換される。

#### キャプチャ変数処理（60-74行目）
```nim
for a in args[0..^2]:
  var varName: NimNode
  var varVal: NimNode
  case a.kind
  of nnkExprEqExpr:
    varName = a[0]
    varVal = a[1]
  of nnkIdent:
    varName = a
    varVal = a
  else: error("invalid argument kind: " & $a.kind, a)
  if kNoNewLit notin options: varVal = newCall(bindSym"newLitMaybe", varVal)
```

最後の引数（コードブロック）を除く全引数をキャプチャ変数として処理。`=`形式と単純識別子形式の両方をサポート。

#### テンプレート定義とgetAst呼び出し（76-85行目）
```nim
result = newStmtList()
result.add nnkTemplateDef.newTree(
    name,
    newEmptyNode(),
    newEmptyNode(),
    params,
    pragmas,
    newEmptyNode(),
    args[^1])
result.add newCall(bindSym"getAst", call)
```

一時テンプレートを定義し、`getAst`を呼び出してASTを取得する。この方式により、変数置換とAST生成が正しく行われる。
