# 機能設計書 61-内包表記

## 概要

本ドキュメントは、CoffeeScriptの内包表記（Comprehension）機能の設計を記述する。内包表記は、配列やオブジェクトを反復処理しながら新しい配列を生成するための簡潔な構文を提供する言語機能である。

### 本機能の処理概要

CoffeeScriptの内包表記は、`for...in`、`for...of`、`for...from`構文を使用して、配列やオブジェクト、イテレータを反復処理し、各要素に対して式を評価して新しい配列を生成する機能である。Pythonのリスト内包表記やRubyのブロックに似ているが、複数行に渡って記述でき、ループ中のインデックスも参照可能である。

**業務上の目的・背景**：
JavaScriptでは配列の変換やフィルタリングに`map`や`filter`を使用するが、CoffeeScriptの内包表記はこれらをより直感的かつ簡潔に記述できる。特に、ループ内で複雑な条件分岐や変換を行う場合に、ネストしたコールバックを避けて可読性の高いコードを記述できる。これにより、開発効率の向上とコードの保守性向上を実現する。

**機能の利用シーン**：
- 配列の各要素を変換して新しい配列を生成する場合（例：`squares = (x * x for x in list)`）
- 条件付きで要素をフィルタリングする場合（例：`evens = (x for x in list when x % 2 is 0)`）
- オブジェクトのキー・バリューを反復処理する場合（例：`pairs = ([k, v] for k, v of obj)`）
- レンジを使った数値シーケンスの生成（例：`countdown = (i for i in [10..1])`）
- 非同期イテレータの反復処理（例：`for await item from asyncIterator`）

**主要な処理内容**：
1. `for`キーワードと変数宣言（name, index）の解析
2. `in`（配列）、`of`（オブジェクト）、`from`（イテレータ）による反復対象の指定
3. `when`句によるガード条件のフィルタリング
4. `by`句によるステップ値の指定（配列反復時）
5. `own`キーワードによるオブジェクト自身のプロパティのみの反復
6. `await`キーワードによる非同期イテレータ対応
7. 式としての評価と結果配列の生成

**関連システム・外部連携**：
内包表記はCoffeeScriptコンパイラの文法定義（grammar.coffee）とノード生成（nodes.coffee）によって実装され、JavaScriptの`for`ループに変換される。生成されるJavaScriptはES5互換であるが、`for await...from`はES2018のasync iterationに対応。

**権限による制御**：
本機能はコンパイル時の言語機能であり、権限による制御は適用されない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 画面関連なし（言語機能） |

## 機能種別

計算処理 / 言語構文変換

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| name | ForValue | No | ループ変数（値を受け取る変数） | Identifier, ThisProperty, Array, Object |
| index | ForValue | No | インデックス変数（配列）またはキー変数（オブジェクト） | Identifier, ThisProperty |
| source | Expression | Yes | 反復対象の式（配列、オブジェクト、Range、イテレータ） | 有効な式であること |
| guard | Expression | No | `when`句のフィルタ条件式 | Boolean値を返す式 |
| step | Expression | No | `by`句のステップ値 | 数値を返す式 |
| own | Boolean | No | `own`キーワードの有無 | `of`構文でのみ有効 |
| await | Boolean | No | `await`キーワードの有無 | `from`構文でのみ有効 |
| from | Boolean | No | `from`構文かどうか | - |
| object | Boolean | No | `of`構文（オブジェクト反復）かどうか | - |

### 入力データソース

CoffeeScriptソースコード内の`for`式

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| JavaScript | String | コンパイルされたJavaScriptの`for`ループコード |
| results | Array | 内包表記の結果配列（式として評価された場合） |

### 出力先

JavaScriptコード（標準出力またはファイル）

## 処理フロー

### 処理シーケンス

```
1. For構文の解析
   └─ grammar.coffeeでトークン列からForノードを生成
2. ソース追加処理（addSource）
   └─ source, guard, step, own, await, object, fromの各属性を設定
3. バリデーション
   └─ from+index、own+in、range+index等の不正な組み合わせをエラー
4. コンパイル処理（compileNode）
   └─ 4.1 ループ変数とインデックス変数をスコープに登録
   └─ 4.2 結果配列用変数を確保（式として使用される場合）
   └─ 4.3 Range/配列/オブジェクト/fromに応じたforループを生成
   └─ 4.4 guard条件がある場合はcontinue文を追加
   └─ 4.5 パターンマッチング（分割代入）がある場合は代入文を追加
```

### フローチャート

```mermaid
flowchart TD
    A[For式の開始] --> B{反復対象の種類}
    B -->|Range| C[Rangeループ生成]
    B -->|配列 in| D[配列ループ生成]
    B -->|オブジェクト of| E[for-inループ生成]
    B -->|イテレータ from| F[for-ofループ生成]
    C --> G{guard条件あり?}
    D --> G
    E --> G
    F --> G
    G -->|Yes| H[if+continue追加]
    G -->|No| I[ボディ処理]
    H --> I
    I --> J{結果を返す?}
    J -->|Yes| K[results.push追加]
    J -->|No| L[ループ終了]
    K --> L
    L --> M[JavaScriptコード出力]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-61-1 | index制約（from） | `from`構文ではindexを使用不可 | `from`かつ`index`指定時 |
| BR-61-2 | own制約 | `own`は`of`構文でのみ有効 | `own`かつ非`of`時 |
| BR-61-3 | await制約 | `await`は`from`構文でのみ有効 | `await`かつ非`from`時 |
| BR-61-4 | range制約（index） | Rangeループではindexを使用不可 | `range`かつ`index`指定時 |
| BR-61-5 | range制約（pattern） | Rangeループではパターンマッチング不可 | `range`かつパターン時 |
| BR-61-6 | object変数交換 | `of`構文ではnameとindexを交換（key, value順） | `object`が`true`時 |

### 計算ロジック

- 配列ループのインクリメント: `step`が指定されている場合は`i += step`、そうでなければ`i++`または`++i`
- 降順判定: `step`が負の数の場合、比較演算子が`>=`になり、初期値が`length - 1`になる
- 結果配列生成: ループボディの最後の式の値が`results.push()`で収集される

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

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| SyntaxError | 構文エラー | index cannot be a pattern matching expression | indexにパターン（配列/オブジェクト）を指定しない |
| SyntaxError | 構文エラー | cannot use index with for-from | from構文でindex指定を削除する |
| SyntaxError | 構文エラー | cannot use own with for-in/for-from | ownはfor-of構文でのみ使用する |
| SyntaxError | 構文エラー | await must be used with for-from | awaitはfor-from構文でのみ使用する |
| SyntaxError | 構文エラー | indexes do not apply to range loops | Rangeループでのindex指定を削除する |
| SyntaxError | 構文エラー | cannot pattern match over range loops | Rangeループでパターンマッチングを使用しない |

### リトライ仕様

コンパイル時エラーのため、リトライは適用されない。

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

本機能はデータベーストランザクションを使用しない。

## パフォーマンス要件

- コンパイル時間: ソースコードサイズに対して線形時間
- 生成コードの実行時間: 元のJavaScriptループと同等

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

- 生成されるJavaScriptコードは入力されたCoffeeScriptを忠実に変換するため、悪意のあるコードが入力された場合はそのまま出力される
- ソースコードの検証はCoffeeScriptコンパイラの責務外

## 備考

- 内包表記は式として評価できるため、変数への代入や関数の引数として使用可能
- 後置形式（`body for x in list`）と前置形式（`for x in list then body`または`for x in list\n  body`）の両方をサポート
- `for await...from`構文はES2018のasync iterationを利用するため、対応環境が必要

---

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

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

### 推奨読解順序

#### Step 1: 文法定義を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | grammar.coffee | `src/grammar.coffee` | For、ForBody、ForStart、ForVariables、ForSource、ForLineSourceの各規則 |

**読解のコツ**:
- `o()`関数はJison文法規則を定義する。第1引数がパターン、第2引数がアクション
- `For`規則（742-747行目）で前置形式と後置形式を定義
- `ForSource`規則（790-810行目）で`in`/`of`/`from`とオプションの組み合わせを定義

**主要処理フロー**:
1. **742行目**: `Statement ForBody` - 後置for文
2. **743行目**: `Expression ForBody` - 後置for式
3. **745行目**: `ForBody Block` - 前置forブロック
4. **761行目**: `FOR ForVariables` - ループ変数の解析
5. **791行目**: `FORIN Expression` - 配列反復
6. **792行目**: `FOROF Expression` - オブジェクト反復
7. **807行目**: `FORFROM Expression` - イテレータ反復

#### Step 2: ノードクラスを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | nodes.coffee | `src/nodes.coffee` | Forクラスの定義（5339-5508行目） |

**主要処理フロー**:
- **5339行目**: `class For extends While` - ForはWhileを継承
- **5340-5343行目**: コンストラクタでbodyとsourceを初期化
- **5356-5385行目**: `addSource`メソッドで各属性を設定し、バリデーション
- **5391-5480行目**: `compileNode`メソッドでJavaScriptコード生成
- **5416-5418行目**: Rangeの場合のコンパイル
- **5459-5461行目**: オブジェクト反復の`for...in`生成
- **5462-5467行目**: イテレータ反復の`for...of`生成（awaitの場合は`for await...of`）

#### Step 3: Whileクラス（親クラス）を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | nodes.coffee | `src/nodes.coffee` | Whileクラスの定義（Forの親クラス） |

**読解のコツ**:
- ForはWhileを継承しており、`addBody`メソッドなどの共通ロジックを利用
- `makeReturn`メソッドにより、内包表記を式として評価可能

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

```
CoffeeScript.compile()
    │
    ├─ Lexer.tokenize()
    │      └─ トークン列生成
    │
    ├─ parser.parse()
    │      └─ grammar.coffeeの規則に従いForノード生成
    │             ├─ For.addBody()
    │             └─ For.addSource()
    │
    └─ For.compileNode()
           ├─ Range.compileToFragments() [Rangeの場合]
           ├─ source.compile() [配列/オブジェクト/イテレータ]
           ├─ body.compileToFragments()
           └─ makeCode() でJavaScript文字列生成
```

### データフロー図

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

CoffeeScript           Lexer           Parser              Compiler
For式             →  トークン列  →   Forノード      →    JavaScript
                                    (AST)                  forループ

例:
squares = (x * x for x in list)
    ↓
['(', 'IDENTIFIER', 'MATH', 'IDENTIFIER', 'FOR', 'IDENTIFIER', 'FORIN', 'IDENTIFIER', ')']
    ↓
For {
  name: IdentifierLiteral('x'),
  source: Value(IdentifierLiteral('list')),
  body: Block([Op('*', x, x)])
}
    ↓
var squares = (function() {
  var i, len, results, x;
  results = [];
  for (i = 0, len = list.length; i < len; i++) {
    x = list[i];
    results.push(x * x);
  }
  return results;
})();
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| grammar.coffee | `src/grammar.coffee` | ソース | For構文の文法規則定義（742-832行目） |
| nodes.coffee | `src/nodes.coffee` | ソース | Forノードクラスの実装（5339-5508行目） |
| lexer.coffee | `src/lexer.coffee` | ソース | FOR, FORIN, FOROF, FORFROMトークンの生成 |
| rewriter.coffee | `src/rewriter.coffee` | ソース | トークン列の正規化（暗黙の括弧追加等） |
| scope.litcoffee | `src/scope.litcoffee` | ソース | ループ変数のスコープ管理 |
