# 機能設計書 1-CoffeeScriptコンパイル

## 概要

本ドキュメントは、CoffeeScriptソースコードをJavaScriptにコンパイルする機能について、その処理内容、入出力仕様、およびコードリーディングガイドを記載したものである。

### 本機能の処理概要

CoffeeScriptコンパイル機能は、CoffeeScript言語で記述されたソースコードを、実行可能なJavaScriptコードに変換する機能である。

**業務上の目的・背景**：CoffeeScriptは、JavaScriptのシンタックスシュガーを提供する言語であり、より簡潔で可読性の高いコードを記述できる。しかし、ブラウザやNode.jsで直接実行するためには、JavaScriptへの変換が必要である。本機能は、開発者がCoffeeScriptで記述したコードを、実行環境で動作するJavaScriptに変換するために不可欠である。

**機能の利用シーン**：開発者がCoffeeScriptファイルを作成し、本番環境向けのJavaScriptファイルを生成する場合、CLIツールからの`coffee --compile`コマンド実行時、ブラウザ上でのリアルタイムコンパイル時、Node.js APIを通じたプログラマティックなコンパイル時に利用される。

**主要な処理内容**：
1. ソースコードの前処理（BOM除去、キャリッジリターン正規化、リテラルCoffeeScript対応）
2. 字句解析（Lexer）によるトークン列生成
3. 構文解析（Parser）による構文木（AST）生成
4. コード生成（Nodes.compileToFragments）によるJavaScriptフラグメント生成
5. ソースマップ生成（オプション）
6. Babelトランスパイル（オプション）
7. インラインソースマップ埋め込み（オプション）

**関連システム・外部連携**：Babelトランスパイラ（オプション機能として連携）、Node.js vm モジュール（実行時）、ブラウザ環境（ブラウザコンパイラ使用時）

**権限による制御**：特になし（すべてのユーザーが利用可能）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | トップページ | 主画面 | ページ内のコード例をリアルタイムでCoffeeScriptからJavaScriptにコンパイルして表示 |
| 2 | Try CoffeeScript | 主画面 | ユーザー入力のCoffeeScriptコードをJavaScriptにコンパイル |
| 3 | テストスイート | 主画面 | CoffeeScript.runによるテストコードのコンパイルと実行 |
| 4 | v1ドキュメント | 主画面 | v1系のCoffeeScriptコンパイル機能をドキュメント表示 |
| 5 | v1テストスイート | 主画面 | テストコードのコンパイルと実行 |
| 6 | v2ドキュメント | 主画面 | v2系のCoffeeScriptコンパイル機能をドキュメント表示 |
| 7 | v2テストスイート | 主画面 | テストコードのコンパイルと実行 |
| 8 | CoffeeScript 2発表ページ | 補助画面 | ページ内のコード例のコンパイル表示 |
| 16 | Annotated Source - CoffeeScript | 参照画面 | メインモジュールcoffeescript.coffeeのソースコード解説表示 |
| 31 | Annotated Source - CoffeeScript | 参照画面 | メインモジュールcoffeescript.coffeeのソースコード解説表示（v2） |

## 機能種別

計算処理 / コード変換

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| code | string | Yes | CoffeeScriptソースコード | 文字列であること |
| options.filename | string | No | ソースファイル名（ソースマップ生成時に使用） | - |
| options.sourceMap | boolean | No | ソースマップを生成するかどうか | - |
| options.inlineMap | boolean | No | ソースマップをインラインで埋め込むかどうか | - |
| options.bare | boolean | No | トップレベル関数ラッパーなしでコンパイルするかどうか | - |
| options.header | boolean | No | 生成コードにCoffeeScriptバージョンヘッダーを追加するかどうか | - |
| options.shiftLine | boolean | No | 行番号をシフトするかどうか | - |
| options.ast | boolean | No | ASTを返すかどうか | - |
| options.transpile | object | No | Babelトランスパイルオプション | オブジェクトであること |
| options.literate | boolean | No | Literate CoffeeScriptとして処理するかどうか | - |

### 入力データソース

- 直接のソースコード文字列入力
- ファイルシステムからの読み込み（`_compileFile`関数使用時）
- 標準入力（CLI使用時）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| js | string | コンパイルされたJavaScriptコード |
| sourceMap | SourceMap | ソースマップオブジェクト（sourceMapオプション指定時） |
| v3SourceMap | string | V3形式ソースマップJSON文字列（sourceMapオプション指定時） |
| ast | object | Babel互換AST（astオプション指定時） |

### 出力先

- 戻り値として返却（API使用時）
- ファイル出力（CLI使用時、--outputオプション指定時）
- 標準出力（CLI使用時、--printオプション指定時）

## 処理フロー

### 処理シーケンス

```
1. オプションのクローン
   └─ 入力オプションを変更しないようにコピーを作成

2. ソースマップ生成判定
   └─ sourceMap/inlineMap/filenameオプションに基づき判定

3. シバン行チェック
   └─ Linux環境での互換性警告

4. 字句解析（tokenize）
   └─ Lexerを使用してトークン列を生成

5. 参照変数リスト抽出
   └─ 識別子トークンから変数名を収集

6. import/exportチェック
   └─ ES6モジュール構文があればbareモードを強制

7. 構文解析（parse）
   └─ Jisonパーサーでトークン列を構文木に変換

8. AST生成（astオプション時）
   └─ Babel互換ASTを生成して返却

9. コード生成（compileToFragments）
   └─ 構文木からJavaScriptフラグメントを生成

10. フラグメント結合とソースマップ構築
    └─ フラグメントを結合しながらソースマップにマッピング追加

11. ヘッダー追加（headerオプション時）
    └─ CoffeeScriptバージョンコメントを先頭に追加

12. Babelトランスパイル（transpileオプション時）
    └─ BabelでES5互換コードに変換

13. インラインソースマップ埋め込み（inlineMapオプション時）
    └─ Base64エンコードしたソースマップをコードに追加

14. キャッシュ登録
    └─ スタックトレース変換用にソースマップをキャッシュ

15. 結果返却
    └─ JavaScript文字列またはオブジェクト形式で返却
```

### フローチャート

```mermaid
flowchart TD
    A[開始: compile関数] --> B[オプションをクローン]
    B --> C{sourceMap or inlineMap or filename未指定?}
    C -->|Yes| D[generateSourceMap = true]
    C -->|No| E[generateSourceMap = false]
    D --> F[シバン行チェック]
    E --> F
    F --> G[Lexerでトークン化]
    G --> H[参照変数リスト抽出]
    H --> I{import/exportあり?}
    I -->|Yes| J[bare = true]
    I -->|No| K[パーサーで構文解析]
    J --> K
    K --> L{ast オプション?}
    L -->|Yes| M[AST生成して返却]
    L -->|No| N[compileToFragmentsでコード生成]
    N --> O[フラグメント結合 + ソースマップ構築]
    O --> P{header オプション?}
    P -->|Yes| Q[ヘッダー追加]
    P -->|No| R{transpile オプション?}
    Q --> R
    R -->|Yes| S[Babelトランスパイル]
    R -->|No| T{inlineMap オプション?}
    S --> T
    T -->|Yes| U[インラインソースマップ埋め込み]
    T -->|No| V[キャッシュ登録]
    U --> V
    V --> W{sourceMap オプション?}
    W -->|Yes| X[オブジェクト形式で返却]
    W -->|No| Y[JavaScript文字列で返却]
    X --> Z[終了]
    Y --> Z
    M --> Z
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | ES6モジュール自動bareモード | import/export文が含まれる場合、自動的にbareモードでコンパイル | ソースコードにIMPORT/EXPORTトークンが存在する場合 |
| BR-02 | シバン行警告 | 複数引数のシバン行はLinuxで動作しないため警告表示 | シバン行に2つ以上の引数がある場合 |
| BR-03 | ソースマップ自動生成 | filename未指定時は匿名ファイル名で自動的にソースマップ生成 | filenameオプションが未指定の場合 |

### 計算ロジック

特になし

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| SyntaxError | 構文エラー | 不正なCoffeeScript構文 | エラー位置と詳細メッセージを表示 |
| Error | transpileオプションエラー | transpileオプションがオブジェクトでない | オブジェクト形式でオプションを指定 |
| Error | base64エンコードエラー | Buffer/btoaが利用不可 | 実行環境を確認 |

### リトライ仕様

リトライは行わない（同期処理）

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

本機能はトランザクション管理を行わない（ステートレスな変換処理）

## パフォーマンス要件

- 通常のソースファイル（数百行）は数十ミリ秒以内で処理
- 大規模ファイル（数万行）でも数秒以内で処理

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

- 入力コードの検証は構文チェックのみ（セキュリティスキャンは行わない）
- eval関数使用時は信頼できるコードのみを処理すること

## 備考

- CoffeeScript 2.x系はES6+の出力をサポート
- Babelトランスパイルは`@babel/core`または`babel-core`モジュールが必要

---

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

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

### 推奨読解順序

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

まず、コンパイル処理で使用されるデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | sourcemap.litcoffee | `src/sourcemap.litcoffee` | LineMapクラスとSourceMapクラスの構造を理解。位置情報（line, column, sourceLine, sourceColumn）の管理方法を確認 |
| 1-2 | nodes.coffee | `src/nodes.coffee` | CodeFragmentクラス（コードフラグメント）の構造を理解。locationDataプロパティの形式を確認 |

**読解のコツ**: Literate CoffeeScriptファイル（.litcoffee）は、Markdown形式のドキュメントの中にインデントされたコードブロックとしてコードが記述されている。

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

処理の起点となる`compile`関数を読み解く。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | coffeescript.coffee | `src/coffeescript.coffee` | `compile`関数（62-180行目）がメインエントリーポイント。オプション処理からコード生成までの全体フローを把握 |

**主要処理フロー**:
1. **62-64行目**: `withPrettyErrors`ラッパーによるエラーハンドリング設定
2. **66-68行目**: ソースマップ生成フラグとファイル名の決定
3. **69行目**: シバン行チェック
4. **71行目**: SourceMapインスタンス生成
5. **73行目**: Lexerによるトークン化
6. **77-79行目**: 参照変数リスト抽出
7. **82-86行目**: import/exportチェックとbareモード強制
8. **88行目**: パーサーによる構文解析
9. **94-107行目**: ASTオプション時の処理
10. **109行目**: compileToFragmentsによるコード生成
11. **116-133行目**: フラグメント結合とソースマップ構築
12. **142-163行目**: Babelトランスパイル処理
13. **165-169行目**: インラインソースマップ埋め込み
14. **171行目**: キャッシュ登録
15. **173-180行目**: 結果返却

#### Step 3: 字句解析処理を理解する

Lexerクラスによるトークン化処理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | lexer.coffee | `src/lexer.coffee` | `tokenize`メソッド（37-92行目）がエントリーポイント。各種トークンマッチャーの優先順位と処理フローを確認 |

**主要処理フロー**:
- **37-63行目**: 初期化処理（インデント、スタック、フラグのリセット）
- **69-85行目**: メインループ（各種トークンマッチャーを順次実行）
- **92行目**: Rewriterによるトークン正規化

#### Step 4: 構文解析処理を理解する

パーサーによる構文木生成を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | coffeescript.coffee | `src/coffeescript.coffee` | `parser.lexer`オブジェクト（207-224行目）がパーサーとLexerの接続層。Jisonパーサーへのトークン供給方法を確認 |
| 4-2 | grammar.coffee | `src/grammar.coffee` | 文法定義ファイル。各構文規則とノード生成ルールを確認 |

**読解のコツ**: parser.coffeeはgrammar.coffeeから自動生成されるため、直接読む必要はない。grammar.coffeeの文法定義を理解することが重要。

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

ノードからJavaScriptコードを生成する処理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | nodes.coffee | `src/nodes.coffee` | 各ノードクラスの`compileNode`メソッドを確認。CodeFragmentの生成方法を理解 |

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

```
CoffeeScript.compile (coffeescript.coffee:62)
    │
    ├─ withPrettyErrors (coffeescript.coffee:44)
    │      └─ helpers.updateSyntaxError (helpers.coffee:227)
    │
    ├─ checkShebangLine (coffeescript.coffee:325)
    │
    ├─ new SourceMap (sourcemap.litcoffee:43)
    │
    ├─ lexer.tokenize (lexer.coffee:37)
    │      ├─ clean (lexer.coffee:97)
    │      ├─ identifierToken (lexer.coffee:125)
    │      ├─ numberToken (lexer.coffee:264)
    │      ├─ stringToken (lexer.coffee:291)
    │      └─ ... (その他トークンマッチャー)
    │
    ├─ parser.parse (parser.coffee - 自動生成)
    │      └─ parser.yy (nodes.coffee - ノードクラス群)
    │
    ├─ nodes.compileToFragments (nodes.coffee)
    │      └─ 各ノードのcompileNode
    │
    ├─ map.add (sourcemap.litcoffee:52)
    │
    ├─ map.generate (sourcemap.litcoffee:89)
    │
    ├─ transpiler (Babel - 外部モジュール)
    │
    ├─ base64encode (coffeescript.coffee:29)
    │
    └─ registerCompiled (sourcemap.litcoffee:73)
```

### データフロー図

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

CoffeeScript      ──▶  Lexer.tokenize          ──▶  トークン列
ソースコード             (字句解析)                    [tag, value, location]
                           │
                           ▼
                  parser.parse              ──▶  構文木 (AST)
                  (構文解析)                      Nodeインスタンスツリー
                           │
                           ▼
                  nodes.compileToFragments  ──▶  CodeFragment[]
                  (コード生成)                    [{code, locationData}]
                           │
                           ▼
                  フラグメント結合           ──▶  JavaScript文字列
                  + ソースマップ構築               + V3SourceMap (オプション)
                           │
                           ▼
                  Babelトランスパイル       ──▶  トランスパイル済みJS
                  (オプション)                     (ES5互換)
                           │
                           ▼
                  インラインマップ埋め込み  ──▶  最終JavaScript
                  (オプション)                     + インラインSourceMap
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| coffeescript.coffee | `src/coffeescript.coffee` | ソース | メインコンパイラモジュール。compile, tokens, nodes関数を提供 |
| index.coffee | `src/index.coffee` | ソース | Node.js向けエントリーポイント。run, eval関数を追加提供 |
| lexer.coffee | `src/lexer.coffee` | ソース | 字句解析器。ソースコードをトークン列に変換 |
| grammar.coffee | `src/grammar.coffee` | ソース | Jison文法定義。パーサー生成元 |
| parser.coffee | `lib/coffeescript/parser.js` | 生成物 | Jison自動生成パーサー |
| nodes.coffee | `src/nodes.coffee` | ソース | 構文木ノードクラス群。コード生成ロジック含む |
| rewriter.coffee | `src/rewriter.coffee` | ソース | トークン列の正規化処理 |
| sourcemap.litcoffee | `src/sourcemap.litcoffee` | ソース | ソースマップ生成・管理 |
| helpers.coffee | `src/helpers.coffee` | ソース | ユーティリティ関数群 |
| scope.litcoffee | `src/scope.litcoffee` | ソース | スコープ管理 |
