# 機能設計書 4-セマンティック解析

## 概要

本ドキュメントは、Nimコンパイラのセマンティック解析（意味解析）の機能設計について記載する。セマンティック解析はASTに対して型チェック、名前解決、マクロ展開等を行い、型付きASTを生成する。

### 本機能の処理概要

セマンティック解析は、パーサーから出力されたAST（抽象構文木）を入力として受け取り、型チェック、名前解決（シンボル解決）、オーバーロード解決、マクロ/テンプレート展開、コンパイル時評価などを行う。これにより、型情報が付加された意味的に正しいASTを生成し、コード生成フェーズに渡す。

**業務上の目的・背景**：セマンティック解析は、プログラムの意味的な正しさを検証するコンパイルの中核フェーズである。構文的に正しいプログラムでも、型の不一致、未定義の識別子、無効な操作などの意味的エラーを含む可能性がある。セマンティック解析はこれらのエラーを検出し、プログラマに報告するとともに、後続のコード生成に必要な情報（型情報、シンボル情報など）をASTに付加する。

**機能の利用シーン**：
- Nimソースコードのコンパイル時（全コマンドで使用）
- 型チェックのみ実行（`nim check`コマンド）
- IDEサポート（nimsuggestでの型情報提供、定義ジャンプ）
- マクロ/テンプレートの展開と評価
- コンパイル時定数の評価

**主要な処理内容**：
1. コンテキスト（PContext）の初期化
2. シンボルテーブルとスコープの管理
3. 式の型チェック（semExpr、semExprWithType）
4. 文の型チェック（semStmt）
5. 型の解析と検証（semTypeNode）
6. 名前解決とシンボルルックアップ
7. オーバーロード解決（sigmatch）
8. マクロ/テンプレートの展開（semMacroExpr、semTemplateExpr）
9. ジェネリクスのインスタンス化
10. コンパイル時定数の評価（semConstExpr）

**関連システム・外部連携**：
- パーサー（parser.nim）からASTを受け取る
- VM（vm.nim）でコンパイル時評価を実行
- コード生成バックエンド（cgen.nim等）に型付きASTを提供
- モジュールグラフ（modulegraphs.nim）でモジュール間依存を管理

**権限による制御**：セマンティック解析自体には権限制御はない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| N/A | コマンドラインインターフェース | 参照画面 | 型エラー、未定義識別子エラーの表示 |

## 機能種別

意味解析処理 / 型チェック処理 / シンボル解決処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| n | PNode | Yes | 解析対象のASTノード | 非nil |
| c | PContext | Yes | セマンティック解析コンテキスト | 非nil |
| flags | TExprFlags | No | 解析フラグ | 有効なフラグセット |
| expectedType | PType | No | 期待される型（型推論用） | nil許容 |

### 入力データソース

- パーサーからのAST（PNode）
- モジュールグラフ（ModuleGraph）
- 識別子キャッシュ（IdentCache）
- 設定（ConfigRef）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| result | PNode | 型付きASTノード |
| result.typ | PType | ノードの型情報 |
| result.sym | PSym | シンボル情報（シンボルノードの場合） |
| c.generics | seq | インスタンス化されたジェネリクス |

### 出力先

- 型付きAST（PNode）としてコード生成に渡される
- エラーメッセージ（標準エラー出力）
- 警告メッセージ（設定に応じて）

## 処理フロー

### 処理シーケンス

```
1. コンテキスト準備（preparePContext）
   └─ スコープ、モジュール情報の初期化
2. トップレベル文の解析（myProcess）
   └─ 各文に対してsemStmtを呼び出し
3. 式の解析（semExpr/semExprWithType）
   ├─ 識別子解決（lookups）
   ├─ 関数呼び出し解決（semcall/sigmatch）
   └─ 型チェック
4. 型の解析（semTypeNode）
   └─ 型定義の解析と検証
5. マクロ/テンプレート展開
   ├─ semMacroExpr（マクロ展開）
   └─ semTemplateExpr（テンプレート展開）
6. ジェネリクスインスタンス化（seminst）
   └─ 型パラメータの具体化
7. コンパイル時評価（semConstExpr）
   └─ VM経由で定数式を評価
```

### フローチャート

```mermaid
flowchart TD
    A[preparePContext] --> B[myProcess: トップレベル解析]
    B --> C{ノード種別}
    C -->|式| D[semExpr]
    C -->|文| E[semStmt]
    C -->|型| F[semTypeNode]
    D --> G[シンボルルックアップ]
    G --> H{シンボル種別}
    H -->|関数| I[semOverloadedCall]
    H -->|マクロ| J[semMacroExpr]
    H -->|テンプレート| K[semTemplateExpr]
    H -->|変数/定数| L[型チェック]
    I --> M[sigmatch: オーバーロード解決]
    M --> N[fitNode: 型適合]
    J --> O[evalMacroCall: VM実行]
    O --> P[semAfterMacroCall]
    K --> Q[evalTemplateCall]
    Q --> P
    L --> N
    N --> R[型付きAST]
    E --> R
    F --> S[PType生成]
    P --> R
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 型一致規則 | 代入や引数渡しで型が一致または変換可能であること | 全ての型チェック |
| BR-02 | スコープ規則 | 識別子は現在のスコープまたは上位スコープで定義されていること | 名前解決時 |
| BR-03 | オーバーロード解決 | 引数の型に基づいて最適な関数を選択 | 関数呼び出し時 |
| BR-04 | マクロ展開制限 | テンプレート/マクロの再帰展開に制限（evalTemplateLimit） | マクロ展開時 |
| BR-05 | 暗黙変換規則 | 安全な暗黙変換のみ許可（整数拡大など） | 型変換時 |
| BR-06 | 副作用チェック | noSideEffect関数内で副作用禁止 | 関数解析時 |

### 計算ロジック

- **オーバーロード解決スコア**：sigmatchモジュールで引数の型適合度をスコア計算
- **共通型計算**：commonType関数で複数の型から共通の型を計算
- **コンパイル時評価**：semConstExpr/tryConstExprでVM経由の定数評価

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

該当なし（セマンティック解析はデータベースを使用しない）

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| errGenerated | 型エラー | 型の不一致 | 正しい型を使用 |
| errUndeclaredIdentifier | 未定義識別子 | 識別子が未定義 | 識別子を定義 |
| errAmbiguousCall | 曖昧な呼び出し | オーバーロード解決失敗 | 型を明示 |
| errRecursiveDependency | 再帰依存 | マクロ/テンプレートの自己呼び出し | 構造を修正 |
| errConstExprExpected | 定数式エラー | コンパイル時評価不可 | 定数式に修正 |

### リトライ仕様

セマンティック解析はリトライを行わない。エラー発生時はエラーメッセージを出力し、可能な限り解析を継続する。

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

該当なし

## パフォーマンス要件

- シンボルテーブルのハッシュベース検索
- ジェネリクスのキャッシュによる再インスタンス化回避
- テンプレート/マクロ展開の深度制限（evalTemplateLimit）

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

- コンパイル時評価（VM）の反復/深度制限
- マクロ展開の再帰制限

## 備考

- セマンティック解析は複数のincludeファイルで構成される
  - semstmts.nim: 文の解析
  - semexprs.nim: 式の解析
  - semtypes.nim: 型の解析
  - semtempl.nim: テンプレート解析
  - seminst.nim: ジェネリクスインスタンス化
  - semcall.nim: 関数呼び出し解析
- nimsuggest対応の条件付きコード（when defined(nimsuggest)）

---

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

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

### 推奨読解順序

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

まず、セマンティック解析で使用されるコンテキストと型のデータ構造を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | semdata.nim | `compiler/semdata.nim` | PContext型でセマンティック解析の状態管理を理解 |
| 1-2 | types.nim | `compiler/types.nim` | PType型で型システムを理解 |
| 1-3 | ast.nim | `compiler/ast.nim` | PSym型でシンボル構造を理解 |

**読解のコツ**:
- `PContext`はセマンティック解析の全状態を保持
- `p`フィールドはプロシージャコンテキスト（ローカルスコープ）
- `module`フィールドは現在のモジュール
- `generics`フィールドはインスタンス化されたジェネリクスのリスト

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | sem.nim | `compiler/sem.nim` | preparePContext（756-790行目）でコンテキスト初期化を理解 |
| 2-2 | sem.nim | `compiler/sem.nim` | semExpr/semExprWithType（37-41行目）の宣言を理解 |

**主要処理フロー**:
1. **757行目**: `newContext`でコンテキスト生成
2. **758行目**: `result.idgen = idgen`でID生成器設定
3. **763-779行目**: 各種セマンティック関数をコンテキストに設定
4. **782-783行目**: プロシージャコンテキストとオーナーをプッシュ
5. **785-790行目**: モジュールスコープとトップレベルスコープを開く

#### Step 3: 式の解析を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | semexprs.nim | `compiler/semexprs.nim` | semExpr関数で式解析の全体像を理解 |
| 3-2 | sem.nim | `compiler/sem.nim` | fitNode（99-121行目）で型適合処理を理解 |

**主要処理フロー**:
- semExprはノード種別に応じて適切な解析関数を呼び出す
- fitNodeは期待される型と実際の型を照合し、必要に応じて変換を挿入

#### Step 4: 名前解決を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | lookups.nim | `compiler/lookups.nim` | シンボルルックアップの仕組みを理解 |

**主要処理フロー**:
- スコープチェーンを辿って識別子を解決
- インポートされたモジュールからもシンボルを検索
- オーバーロードされたシンボルはシンボルチョイスとして返す

#### Step 5: オーバーロード解決を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | sigmatch.nim | `compiler/sigmatch.nim` | オーバーロード解決アルゴリズムを理解 |
| 5-2 | semcall.nim | `compiler/semcall.nim` | 関数呼び出し解析を理解 |

**主要処理フロー**:
- 各候補関数に対して引数の型適合度をスコア計算
- 最も高いスコアの候補を選択
- 同点の場合は曖昧エラー

#### Step 6: マクロ/テンプレート展開を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 6-1 | sem.nim | `compiler/sem.nim` | semMacroExpr（542-569行目）でマクロ展開を理解 |
| 6-2 | sem.nim | `compiler/sem.nim` | semAfterMacroCall（457-522行目）で展開後の処理を理解 |
| 6-3 | semtempl.nim | `compiler/semtempl.nim` | テンプレート展開を理解 |

**主要処理フロー**:
- **544行目**: `rememberExpansion`で展開を記録
- **561行目**: `evalMacroCall`でVMを使ってマクロを実行
- **563行目**: `semAfterMacroCall`で結果のASTを再解析
- **464-466行目**: 展開深度チェック（evalTemplateLimit）

#### Step 7: 型解析を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 7-1 | semtypes.nim | `compiler/semtypes.nim` | semTypeNode関数で型解析を理解 |

**主要処理フロー**:
- ノード種別に応じた型の構築
- ジェネリック型パラメータの処理
- 型制約の検証

#### Step 8: コンパイル時評価を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 8-1 | sem.nim | `compiler/sem.nim` | tryConstExpr（362-402行目）で定数式評価を理解 |
| 8-2 | sem.nim | `compiler/sem.nim` | semConstExpr（407-431行目）で必須定数評価を理解 |

**主要処理フロー**:
- **363行目**: `semExprWithType`で式を型チェック
- **366行目**: `getConstExpr`でコンパイル時畳み込み
- **382行目**: `evalConstExpr`でVM経由の評価

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

```
preparePContext
    └─ newContext (semdata.nim)
    └─ openScope

myProcess (トップレベル解析)
    │
    ├─ semStmt (semstmts.nim)
    │      ├─ semIf / semWhile / semFor / semCase
    │      ├─ semProc / semFunc / semIterator
    │      ├─ semVar / semLet / semConst
    │      └─ semExprStmt
    │
    └─ semExpr (semexprs.nim)
           ├─ semSym (シンボル解析)
           │      └─ lookups.nim
           │
           ├─ semCall (関数呼び出し)
           │      ├─ semOverloadedCall (semcall.nim)
           │      │      └─ sigmatch (sigmatch.nim)
           │      │
           │      ├─ semMacroExpr (マクロ)
           │      │      ├─ evalMacroCall (vm.nim)
           │      │      └─ semAfterMacroCall
           │      │
           │      └─ semTemplateExpr (テンプレート)
           │             └─ evalTemplateCall (evaltempl.nim)
           │
           ├─ semTypeNode (semtypes.nim)
           │      └─ 型の構築と検証
           │
           └─ fitNode
                  └─ indexTypesMatch (型適合)
```

### データフロー図

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

AST (PNode) ──────────────────▶ semExpr ─────────────────────────▶ 型付きAST
                                (式解析)
       │
       ▼
識別子 ───────────────────────▶ lookups ─────────────────────────▶ PSym (シンボル)
                                (名前解決)
       │
       ▼
関数呼び出し ─────────────────▶ semOverloadedCall ───────────────▶ 解決済み呼び出し
                                (オーバーロード解決)
       │
       ▼
マクロ呼び出し ───────────────▶ semMacroExpr ────────────────────▶ 展開済みAST
                                (マクロ展開)
       │
       │  ┌─ evalMacroCall (VM実行)
       ├──┤
       │  └─ semAfterMacroCall (結果解析)
       │
       ▼
型付きAST ────────────────────▶ cgen.nim / jsgen.nim ────────────▶ コード生成
                                (コード生成)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| sem.nim | `compiler/sem.nim` | ソース | セマンティック解析のメインモジュール |
| semdata.nim | `compiler/semdata.nim` | ソース | PContext等のデータ構造定義 |
| semexprs.nim | `compiler/semexprs.nim` | ソース | 式の解析（includeされる） |
| semstmts.nim | `compiler/semstmts.nim` | ソース | 文の解析（includeされる） |
| semtypes.nim | `compiler/semtypes.nim` | ソース | 型の解析（includeされる） |
| semtempl.nim | `compiler/semtempl.nim` | ソース | テンプレート解析（includeされる） |
| seminst.nim | `compiler/seminst.nim` | ソース | ジェネリクスインスタンス化（includeされる） |
| semcall.nim | `compiler/semcall.nim` | ソース | 関数呼び出し解析（includeされる） |
| sigmatch.nim | `compiler/sigmatch.nim` | ソース | オーバーロード解決 |
| lookups.nim | `compiler/lookups.nim` | ソース | シンボルルックアップ |
| types.nim | `compiler/types.nim` | ソース | 型操作ユーティリティ |
| ast.nim | `compiler/ast.nim` | ソース | AST定義 |
| vm.nim | `compiler/vm.nim` | ソース | コンパイル時評価用VM |
| evaltempl.nim | `compiler/evaltempl.nim` | ソース | テンプレート評価 |
