# 機能設計書 16-Nodes

## 概要

本ドキュメントは、CoffeeScriptコンパイラにおけるNodes機能の設計を記述する。Nodesは構文木を構成するノードクラス群を定義し、各ノードがcompileNodeメソッドでJavaScriptコードを生成する中核的なモジュールである。

### 本機能の処理概要

Nodes機能は、CoffeeScriptの構文木（AST）を表現するノードクラスを定義し、各ノードがJavaScriptコードを生成するための機能を提供する。

**業務上の目的・背景**：CoffeeScriptのコンパイルプロセスでは、パーサーが生成した構文木を走査し、各ノードに対応するJavaScriptコードを生成する。Nodesモジュールは、この構文木を構成する全てのノードクラス（Base, Block, Literal, Value, Call, Class, Code等）を定義する。各ノードクラスはcompileNodeメソッドを実装し、自身をJavaScriptコードに変換する責務を持つ。このオブジェクト指向設計により、言語機能の追加・修正が容易になり、コンパイラのメンテナンス性が向上する。

**機能の利用シーン**：
- パース後：パーサーが文法アクションで各ノードクラスをインスタンス化
- コンパイル時：各ノードのcompileNodeメソッドがJavaScriptコードを生成
- AST出力時：各ノードのastメソッドがBabel互換のASTを生成
- デバッグ時：toStringメソッドでノードツリーを文字列表示

**主要な処理内容**：
1. Baseクラス：全ノードの基底クラス、compile/compileToFragmentsの共通処理
2. Block：文のリストを表現、compileRootでルートレベルのコンパイル
3. Literal系：NumberLiteral, StringLiteral, BooleanLiteral等のリテラル値
4. Value：値を表現、アクセサチェーンの管理
5. Call：関数呼び出し
6. Class：クラス定義、ES6クラス構文への変換
7. Code：関数定義、アロー関数とバウンド関数
8. Op：演算子、単項・二項演算
9. 制御構造：If, For, While, Switch, Try

**関連システム・外部連携**：
- grammar.coffee：パーサーがノードクラスをインスタンス化
- scope.litcoffee：スコープ管理と変数宣言
- helpers.coffee：ヘルパー関数の使用

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 11 | Annotated Source - Nodes | 主画面 | 構文木ノードクラスnodes.coffeeのソースコード解説表示 |
| 26 | Annotated Source - Nodes | 主画面 | 構文木ノードクラスnodes.coffeeのソースコード解説表示（v2） |

## 機能種別

コード生成 / 構文木ノード定義

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| o | Object | Yes | コンパイルオプション（indent, level, scope等） | 有効なオプションオブジェクト |
| lvl | Number | No | 式のレベル（LEVEL_TOP, LEVEL_PAREN等） | 0-6の整数 |

### 入力データソース

パーサーが生成した構文木ノードを入力として受け取る。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| fragments | Array<CodeFragment> | 生成されたコードフラグメントの配列 |
| code | String | フラグメントを結合したJavaScriptコード文字列 |

### 出力先

コンパイラの出力として最終的にJavaScriptファイルに書き出される。

## 処理フロー

### 処理シーケンス

```
1. compile(o, lvl)の呼び出し
   └─ compileToFragmentsを呼び出し、結果をfragmentsToTextで文字列化

2. compileToFragments(o, lvl)の実行
   ├─ オプションのクローン
   ├─ unfoldSoakによるソーク演算子の展開
   └─ isStatementに応じてcompileNodeまたはcompileClosureを呼び出し

3. compileNode(o)の実行
   └─ 各ノードクラス固有のJavaScript生成ロジック

4. compileClosure(o)の実行（式として使用される文の場合）
   └─ 即時実行関数でラップしてJavaScriptを生成

5. CodeFragmentの生成
   └─ makeCode(code)でフラグメントを生成

6. フラグメントの結合
   └─ fragmentsToText(fragments)で文字列化
```

### フローチャート

```mermaid
flowchart TD
    A[compile呼び出し] --> B[compileToFragments]
    B --> C{isStatement?}
    C -->|Yes| D{LEVEL_TOP?}
    D -->|Yes| E[compileNode]
    D -->|No| F[compileClosure]
    C -->|No| E
    E --> G[CodeFragment配列を返す]
    F --> G
    G --> H[fragmentsToText]
    H --> I[JavaScript文字列]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-16-01 | 式と文の区別 | isStatementがtrueのノードは文として扱う | コンパイル時 |
| BR-16-02 | クロージャラップ | 文を式として使用する場合は即時実行関数でラップ | isStatementかつ非LEVEL_TOP |
| BR-16-03 | ソーク展開 | ソーク演算子（?.）は条件式に展開 | unfoldSoak時 |
| BR-16-04 | キャッシュ | 複数回使用される式は一時変数にキャッシュ | shouldCache時 |
| BR-16-05 | 位置情報 | 各フラグメントはソース位置情報を保持 | makeCode時 |
| BR-16-06 | コメント処理 | コメントはフラグメントに付加され、適切な位置に出力 | compileCommentFragments |

### 計算ロジック

式のレベル定数:
```coffeescript
LEVEL_TOP    = 1  # トップレベル（文のコンテキスト）
LEVEL_PAREN  = 2  # 括弧内
LEVEL_LIST   = 3  # リスト/配列内
LEVEL_COND   = 4  # 条件式内
LEVEL_OP     = 5  # 演算子の被演算子
LEVEL_ACCESS = 6  # プロパティアクセス
```

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

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

データベースは使用しない。

### テーブル別操作詳細

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| SyntaxError | 構文エラー | 式のコンテキストで純粋な文が使用された場合 | checkForPureStatementInExpressionでエラー |
| SyntaxError | 代入エラー | 代入不可能なターゲットへの代入 | error(message)でエラー |

### リトライ仕様

該当なし。

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

トランザクションは使用しない。

## パフォーマンス要件

特に定められていない。

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

特になし。

## 備考

- ノードクラスは100以上定義されている
- 各ノードクラスはcompileNode, astType, astPropertiesなどを実装
- ES6以降の機能（class, arrow function, template literal等）に対応

---

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

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

### 推奨読解順序

#### Step 1: CodeFragmentクラスを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | nodes.coffee | `src/nodes.coffee` | 27-46行目のCodeFragmentクラスを理解する |

**読解のコツ**: CodeFragmentは生成されたJavaScriptコードの断片を表す。code、type、locationData、commentsを保持する。

**主要処理フロー**:
- **33-38行目**: コンストラクタでcode、type、locationData、commentsを初期化
- **40-42行目**: toStringでデバッグ用の文字列を生成
- **45-46行目**: fragmentsToTextでフラグメント配列を文字列に結合

#### Step 2: Baseクラスを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | nodes.coffee | `src/nodes.coffee` | 48-467行目のBaseクラスを理解する |

**主要処理フロー**:
- **61-62行目**: compileメソッドがcompileToFragmentsを呼び、fragmentsToTextで文字列化
- **98-109行目**: compileToFragmentsがコンパイルの中心、isStatementに応じてcompileNodeまたはcompileClosureを呼び出し
- **116-140行目**: compileClosureが文を即時実行関数でラップ
- **198-206行目**: cacheメソッドで複数回使用される式を一時変数にキャッシュ
- **450-451行目**: makeCodeでCodeFragmentを生成

#### Step 3: Blockクラスを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | nodes.coffee | `src/nodes.coffee` | 562-900行目のBlockクラスを理解する |

**主要処理フロー**:
- **567-571行目**: コンストラクタでexpressionsを初期化
- **640-677行目**: compileNodeで各式をコンパイル
- **679-683行目**: compileRootで変数宣言付きコンパイル
- **687-721行目**: compileWithDeclarationsで変数宣言を先頭に追加

#### Step 4: 主要なノードクラスを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | nodes.coffee | `src/nodes.coffee` | Call, Class, Code, If, For, Op等の主要クラスを理解する |

**読解のコツ**: 各クラスは独自のcompileNodeを実装し、対応するJavaScriptコードを生成する。

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

```
CoffeeScript.compile() (coffeescript.coffee)
    │
    └─ nodes.compile() (nodes.coffee:61)
           │
           ├─ compileToFragments() (nodes.coffee:98)
           │      │
           │      ├─ unfoldSoak() - ソーク展開
           │      │
           │      ├─ compileNode() (各クラス)
           │      │      ├─ Block.compileNode()
           │      │      ├─ Value.compileNode()
           │      │      ├─ Call.compileNode()
           │      │      ├─ Class.compileNode()
           │      │      ├─ Code.compileNode()
           │      │      └─ ...
           │      │
           │      └─ compileClosure() (nodes.coffee:116)
           │             └─ 即時実行関数でラップ
           │
           └─ fragmentsToText() (nodes.coffee:45)
                  └─ CodeFragment.codeを結合
```

### データフロー図

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

構文木ノード              compile処理                     JavaScript
    │                        │                              │
Block                   ├─ compileToFragments           ├─ コード文字列
├─ expressions ───▶    │      │                         │
│   ├─ If             │      ├─ compileNode      ───▶  │   "if (...) {"
│   ├─ For            │      ├─ makeCode               │   "for (...) {"
│   ├─ Call           │      └─ joinFragmentArrays     │   "func(...)"
│   └─ ...            │                                 │   ...
│                     └─ fragmentsToText               │
└─ scope              └─ var宣言を先頭に               └─ "var x, y;"
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| nodes.coffee | `src/nodes.coffee` | ソース | 全ノードクラスの定義 |
| grammar.coffee | `src/grammar.coffee` | ソース | ノードをインスタンス化 |
| scope.litcoffee | `src/scope.litcoffee` | ソース | スコープ管理 |
| coffeescript.coffee | `src/coffeescript.coffee` | ソース | コンパイルパイプライン |
| helpers.coffee | `src/helpers.coffee` | ソース | ヘルパー関数 |
