# 機能設計書 6-JavaScriptコード生成

## 概要

本ドキュメントは、NimコンパイラのJavaScriptコード生成バックエンドの機能設計について記載する。JavaScriptコード生成は型付きASTをJavaScriptのソースコードに変換する。

### 本機能の処理概要

JavaScriptコード生成バックエンドは、セマンティック解析で型付けされたASTを入力として受け取り、等価なJavaScriptのソースコードを生成する。生成されたJavaScriptコードはブラウザやNode.jsなどのJavaScriptランタイムで実行可能である。

**業務上の目的・背景**：NimはJavaScriptへのトランスパイラとしても機能し、WebブラウザやNode.js環境でNimコードを実行可能にする。これにより、サーバーサイドとクライアントサイドで同一の言語・ロジックを共有できる。

**機能の利用シーン**：
- WebブラウザでのクライアントサイドNimアプリケーション（`nim js`）
- Node.jsでのサーバーサイドアプリケーション
- WebAssembly（Emscripten経由）との組み合わせ
- JavaScriptライブラリとの連携

**主要な処理内容**：
1. BModule/PProcの初期化（モジュール/プロシージャ単位の状態管理）
2. 型のJavaScript表現生成（mapType）
3. 式のコード生成（gen）
4. 文のコード生成（genStmt）
5. プロシージャ定義の生成（genProc）
6. マジック関数の処理（genMagic）
7. クロージャサポート
8. 例外処理の生成

**関連システム・外部連携**：
- セマンティック解析（sem.nim）から型付きASTを受け取る
- ランタイムライブラリ（lib/system/jssys.nim等）との連携
- SourceMapサポート（sourcemap.nim）
- HCR（ホットコードリロード）対応

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

## 関連画面

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

## 機能種別

コード変換処理 / コード生成処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| module | BModule | Yes | モジュール状態 | 非nil |
| n | PNode | Yes | 型付きASTノード | 非nil |
| p | PProc | Yes | プロシージャ状態 | 非nil |
| r | var TCompRes | Yes | 結果格納用 | - |

### 入力データソース

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

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| JavaScriptソースファイル | File | 生成されたJSコード（.js） |
| SourceMapファイル | File | デバッグ用マッピング（.map）（オプション） |

### 出力先

- カレントディレクトリまたは指定ディレクトリ
- JavaScriptソースファイル（`{module}.js`形式）

## 処理フロー

### 処理シーケンス

```
1. BModuleの作成（TJSGen初期化）
   └─ モジュール単位の状態初期化
2. 型マッピング（mapType）
   └─ Nim型→TJSTypeKind変換
3. プロシージャ処理（genProc）
   ├─ PProcの作成
   ├─ ヘッダ生成（generateHeader）
   └─ 本体コード生成
4. 式のコード生成（gen）
   ├─ リテラル生成
   ├─ シンボル解決（genSym）
   └─ 関数呼び出し（genCall）
5. 文のコード生成（genStmt）
   ├─ 代入文（genAsgn）
   ├─ 制御構造（genIf、genWhileStmt）
   └─ 例外処理（genTry）
6. ファイル出力
   └─ JSファイルの書き出し
```

### フローチャート

```mermaid
flowchart TD
    A[TJSGen: BModule作成] --> B[mapType: 型マッピング]
    B --> C[genProc: プロシージャ生成]
    C --> D{ノード種別}
    D -->|シンボル| E[genSym]
    D -->|呼び出し| F[genCall/genMagic]
    D -->|リテラル| G[リテラル生成]
    D -->|文| H[genStmt]
    E --> I[TCompRes: 結果]
    F --> I
    G --> I
    H --> I
    I --> J[Rope: コード断片]
    J --> K[JSファイル出力]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | Fat Pointers | var/ref/ptr型をetyBaseIndex（配列+インデックス）で表現 | MappedToObject以外 |
| BR-02 | 短絡評価 | 単純式では&&/||生成、複合式は文に変換 | and/or演算 |
| BR-03 | 名前マングリング | Nim識別子をJS互換名に変換 | 全ての識別子 |
| BR-04 | 型マッピング | Nim型をTJSTypeKindにマッピング | 型変換時 |
| BR-05 | BigInt対応 | 64ビット整数をBigIntで表現 | optJsBigInt64オプション時 |

### 計算ロジック

- **名前マングリング**: 予約語回避 + 非ASCII文字のHEXエンコード
- **型サイズ計算**: JavaScript TypedArray対応（Int32Array等）

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

該当なし（JavaScriptコード生成はデータベースを使用しない）

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| errGenerated | 内部エラー | コード生成で予期しない状態 | バグ報告 |
| errXMustBeCompileTime | コンパイル時エラー | slurp、staticExec等の不正使用 | コード修正 |

### リトライ仕様

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

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

該当なし

## パフォーマンス要件

- Rope（連結文字列）による効率的な文字列構築
- TypedArray活用による配列操作の最適化
- 定数セットの事前計算とキャッシュ

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

- 生成コードの境界チェック（optBoundsCheck）
- オーバーフローチェック（optOverflowCheck）
- 範囲チェック（optRangeCheck）

## 備考

- jsgenモジュールは単一ファイルで完結（約3000行）
- jstypes.nimをinclude
- HCR（ホットコードリロード）対応
- SourceMap生成対応

---

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

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

### 推奨読解順序

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

まず、JavaScriptコード生成で使用されるデータ構造を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | jsgen.nim | `compiler/jsgen.nim` 49-117行目 | TJSGen、TJSTypeKind、TCompRes、PProc型の定義を理解 |

**読解のコツ**:
- `TJSGen`（BModule）はモジュール単位のコード生成状態を保持（49-57行目）
- `TJSTypeKind`はJavaScript型の種類（etyNone〜etyBaseIndex）を表現（58-68行目）
- `TCompRes`は生成結果（kind、typ、res、address、tmpLoc）を保持（74-85行目）
- `PProc/TProc`はプロシージャ単位の状態を保持（100-116行目）
- `PGlobals`はグローバル状態（typeInfo、constants、code）を保持（92-98行目）

#### Step 2: 型マッピングを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | jsgen.nim | `compiler/jsgen.nim` 183-186行目 | MappedToObjectの定義を理解 |
| 2-2 | jsgen.nim | `compiler/jsgen.nim` 187-224行目 | mapType関数で型変換を理解 |

**主要処理フロー**:
- **183-186行目**: `MappedToObject`で参照型がオブジェクトにマップされる型を定義
- **187-224行目**: `mapType`でNim型をTJSTypeKindに変換
  - tyVar/tyRef/tyPtr: MappedToObject以外はetyBaseIndex（Fat Pointer）
  - tyInt..tyUInt64: etyInt
  - tyFloat..tyFloat128: etyFloat
  - tyString/tySequence: etySeq
  - tyObject/tyArray/tyTuple: etyObject

#### Step 3: Fat Pointersトリックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | jsgen.nim | `compiler/jsgen.nim` 12-28行目 | 2つのトリックの説明コメント |
| 3-2 | jsgen.nim | `compiler/jsgen.nim` 156-160行目 | rdLoc関数でFat Pointer読み取り |

**主要処理フロー**:
- **Trick 1（12-19行目）**: `var int`などは「Fat Pointers」（`etyBaseIndex`）として表現
  - (array, index)ペアで、参照解除は`array[index]`
- **Trick 2（21-27行目）**: `&&`/`||`を生成するか文に変換するかの判断
  - `isSimpleExpr`で式が単純かどうかを判定
- **156-160行目**: `rdLoc`でetyBaseIndex型の場合`$1[$2]`形式で読み取り

#### Step 4: 名前マングリングを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | jsgen.nim | `compiler/jsgen.nim` 228-282行目 | mangleName関数でJS互換名生成 |

**主要処理フロー**:
- **229-248行目**: `validJsName`でJavaScript予約語チェック
- **251-252行目**: フィールドで有効な名前ならそのまま使用
- **256-266行目**: 非ASCII文字を`HEX`+16進数にエンコード
- **269-279行目**: シンボル種別に応じた拡張（idOrSig、mangleProcNameExt等）

#### Step 5: 式のコード生成を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | jsgen.nim | `compiler/jsgen.nim` 2912-2999行目 | gen関数で式のコード生成 |

**主要処理フロー**:
- **2918-2920行目**: `nkSym`でシンボル参照
- **2921-2941行目**: リテラル（整数、BigInt対応）
- **2953-2962行目**: 文字列リテラル（Nim文字列は配列として表現）
- **2985-2994行目**: 呼び出し（genMagic、genInfixCall、genCall）

#### Step 6: マジック関数処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 6-1 | jsgen.nim | `compiler/jsgen.nim` 2330-2514行目 | genMagic関数でマジック関数処理 |
| 6-2 | jsgen.nim | `compiler/jsgen.nim` 414-474行目 | jsMagics定義で演算マッピング |

**主要処理フロー**:
- **414-474行目**: `jsMagics`配列で各マジック演算のJS関数名を定義
- **2336-2337行目**: `mOr`/`mAnd`は短絡評価（genOr、genAnd）
- **2338行目**: `mAddI..mStrToStr`は算術演算（arith）
- **2381-2388行目**: `mIsNil`でnullチェック（etyBaseIndex考慮）

#### Step 7: プロシージャ生成を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 7-1 | jsgen.nim | `compiler/jsgen.nim` 2761-2843行目 | genProc関数でプロシージャ生成 |
| 7-2 | jsgen.nim | `compiler/jsgen.nim` 1234-1257行目 | generateHeader関数でヘッダ生成 |

**主要処理フロー**:
- **2769-2773行目**: newProcでPProc作成、名前マングリング
- **2774行目**: generateHeaderでパラメータリスト生成
- **2775-2792行目**: 戻り値がある場合のresult変数とreturn文生成
- **2794-2798行目**: transformBodyで本体変換、genStmtでコード生成
- **2829-2836行目**: function定義のテンプレート組み立て

#### Step 8: 例外処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 8-1 | jsgen.nim | `compiler/jsgen.nim` 920-1028行目 | genTry関数で例外処理生成 |

**主要処理フロー**:
- **920-943行目**: try/catch/finally構造のテンプレートコメント
- **951-952行目**: `++excHandler`でハンドラカウント
- **960-961行目**: catch節で`lastJSError`に例外を保存
- **997-1002行目**: JS例外かNim例外かで型チェック方法を分岐
- **1016-1028行目**: finally節とframePtr復元

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

```
myModule (モジュールコード生成)
    │
    ├─ TJSGen作成 (BModule)
    │
    ├─ genProc (プロシージャ生成)
    │      │
    │      ├─ generateHeader (パラメータ)
    │      │
    │      └─ genStmt (本体)
    │             │
    │             ├─ gen (式生成)
    │             │      ├─ genSym (シンボル)
    │             │      ├─ genCall (呼び出し)
    │             │      ├─ genMagic (マジック)
    │             │      │      ├─ arith (算術)
    │             │      │      ├─ genOr/genAnd (論理)
    │             │      │      └─ genRepr (repr)
    │             │      ├─ genConv (変換)
    │             │      └─ リテラル生成
    │             │
    │             ├─ genAsgn (代入)
    │             ├─ genIf (if文)
    │             ├─ genWhileStmt (while文)
    │             ├─ genTry (例外)
    │             ├─ genCaseJS (case文)
    │             └─ genBlock (ブロック)
    │
    └─ 出力 (globals, constants, code)
```

### データフロー図

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

型付きAST ────────────────────▶ gen/genStmt ─────────────────────▶ PProc.body (コード断片)
(PNode)                          (コード生成)
       │
       ▼
型情報 ───────────────────────▶ mapType ──────────────────────────▶ TJSTypeKind
(PType)                          (型変換)
       │
       ▼
TCompRes ─────────────────────▶ rdLoc ────────────────────────────▶ JS式文字列
(res, address, typ)              (位置読み取り)
       │
       ▼
コード断片 ───────────────────▶ genProc ──────────────────────────▶ Rope (function定義)
(Rope)                           (プロシージャ生成)
       │
       ▼
Rope集約 ─────────────────────▶ ファイル出力 ─────────────────────▶ JSソースファイル
(globals, constants, code)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| jsgen.nim | `compiler/jsgen.nim` | ソース | JavaScriptコード生成メインモジュール |
| jstypes.nim | `compiler/jstypes.nim` | ソース | JS型情報生成（includeされる） |
| sourcemap.nim | `compiler/sourcemap.nim` | ソース | SourceMap生成 |
| ropes.nim | `compiler/ropes.nim` | ソース | 効率的な文字列連結 |
| mangleutils.nim | `compiler/mangleutils.nim` | ソース | 名前マングリングユーティリティ |
| injectdestructors.nim | `compiler/injectdestructors.nim` | ソース | デストラクタ注入 |
| transf.nim | `compiler/transf.nim` | ソース | AST変換 |
| jssys.nim | `lib/system/jssys.nim` | ランタイム | JSランタイムサポート |
| pipelineutils.nim | `compiler/pipelineutils.nim` | ソース | パイプラインユーティリティ |

