# 機能設計書 59-分割代入

## 概要

本ドキュメントは、CoffeeScriptの分割代入（デストラクチャリング）機能の設計を記述する。配列・オブジェクトのデストラクチャリング代入をサポートする。

### 本機能の処理概要

分割代入機能は、配列やオブジェクトから値を取り出し、個別の変数に代入するための構文を提供する。ES6のデストラクチャリング構文と同等の機能を持ち、ネストしたデストラクチャリングやデフォルト値もサポートする。

**業務上の目的・背景**：複雑なデータ構造から必要な値を抽出する際、従来は複数の代入文が必要であった。分割代入を使用することで、コードをより簡潔かつ読みやすく記述でき、開発効率が向上する。関数の戻り値や外部APIからのレスポンスデータの処理において特に有用である。

**機能の利用シーン**：
- 関数から複数の値を返す場合の受け取り
- オブジェクトから特定のプロパティを抽出
- 配列の先頭要素と残りの分離
- 関数パラメータでのオブジェクト分解
- モジュールインポート時のプロパティ抽出

**主要な処理内容**：
1. 配列デストラクチャリングの解析と処理
2. オブジェクトデストラクチャリングの解析と処理
3. ネストしたデストラクチャリングの処理
4. デフォルト値の処理
5. レストパターン（...）の処理
6. ES6互換のコード生成

**関連システム・外部連携**：
- Grammar（文法定義）
- Nodes（コード生成）
- Assign（代入処理）

**権限による制御**：該当なし

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 専用の画面なし（言語機能として全般的に使用） |

## 機能種別

言語機能 / コード生成

## 入力仕様

### 入力パラメータ

#### Assignノード（分割代入）
| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| variable | Value(Arr/Obj) | Yes | 分割代入パターン | - |
| value | Expression | Yes | 代入元の値 | - |
| context | String | No | 代入コンテキスト | - |

### 入力データソース

- CoffeeScriptソースコード内の分割代入式

### 構文例

```coffeescript
# 配列の分割代入
[a, b] = [1, 2]

# 値の交換
[a, b] = [b, a]

# ネストした配列
[[a, b], [c, d]] = [[1, 2], [3, 4]]

# レストパターン
[first, rest...] = [1, 2, 3, 4]

# オブジェクトの分割代入
{name, age} = person

# プロパティのリネーム
{name: userName} = person

# デフォルト値
{name = "Unknown"} = {}

# ネストしたオブジェクト
{user: {name, email}} = response

# 関数パラメータでの使用
processPoint = ({x, y}) ->
  console.log x, y

# 混合パターン
{users: [first, ...others]} = data
```

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| compiledCode | String | ES6デストラクチャリング構文のJavaScriptコード |

### 出力先

- コンパイル済みJavaScriptファイル

### 出力例

```javascript
// 配列の分割代入
var a, b;
[a, b] = [1, 2];

// 値の交換
[a, b] = [b, a];

// オブジェクトの分割代入
var name, age;
({name, age} = person);

// デフォルト値
var name;
({name = "Unknown"} = {});
```

## 処理フロー

### 処理シーケンス

```
1. 分割代入の検出
   └─ variable.isArray() または variable.isObject() の判定
   └─ Assignノードでの処理分岐

2. ES6互換性チェック
   └─ variable.isAssignable() で直接出力可能か判定
   └─ 可能な場合はES6構文をそのまま出力

3. 非ES6互換パターンの処理
   └─ オブジェクトにスプラットがある場合 → compileObjectDestruct
   └─ その他の場合 → compileDestructuring

4. compileDestructuring処理
   └─ 空パターンの処理
   └─ スプラット/Expansionの検出
   └─ 一時変数の生成（必要な場合）
   └─ 各要素の代入文生成

5. オブジェクトレストプロパティの処理
   └─ compileObjectDestruct
   └─ レストプロパティの分離
   └─ 通常プロパティの代入後にレスト代入
```

### フローチャート

```mermaid
flowchart TD
    A[分割代入検出] --> B{配列orオブジェクト?}
    B -->|Yes| C{isAssignable?}
    B -->|No| D[通常の代入]
    C -->|Yes| E[ES6構文出力]
    C -->|No| F{オブジェクト+スプラット?}
    F -->|Yes| G[compileObjectDestruct]
    F -->|No| H[compileDestructuring]
    G --> I[レストプロパティ処理]
    H --> J{空パターン?}
    J -->|Yes| K[値のみコンパイル]
    J -->|No| L[要素ごとに処理]
    L --> M{スプラットあり?}
    M -->|Yes| N[slice処理]
    M -->|No| O[インデックスアクセス]
    N --> P[代入文生成]
    O --> P
    I --> P
    E --> Q[出力]
    K --> Q
    P --> Q
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-59-01 | ES6互換出力 | isAssignable()がtrueならES6構文をそのまま出力 | 分割代入時 |
| BR-59-02 | 空パターン | [] = aや{} = aは単にaを評価 | 空パターン時 |
| BR-59-03 | 一意スプラット | 配列パターン内のスプラットは1つのみ | 配列分割代入時 |
| BR-59-04 | 末尾スプラット | スプラットは配列の末尾でのみ使用可能 | 配列分割代入時 |
| BR-59-05 | オブジェクトレスト | オブジェクトパターンのレストは末尾のみ | オブジェクト分割代入時 |
| BR-59-06 | 一時変数 | 非冪等な式は一時変数にキャッシュ | 右辺が関数呼び出し等の場合 |
| BR-59-07 | 宣言なし括弧 | 宣言なしのオブジェクト分割代入は括弧で囲む | トップレベルでの分割代入 |

### 計算ロジック

該当なし

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

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

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 構文エラー | 複数のスプラット | "multiple splats/expansions are disallowed" |
| - | 構文エラー | 非末尾スプラット | スプラットを末尾に移動 |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- 分割代入のコンパイルは同期的に実行
- ネストが深い場合も効率的に処理

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

該当なし

## 備考

- CoffeeScriptはES6以前から分割代入をサポートしていた
- CoffeeScript 2以降はES6互換の出力を生成

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | grammar.coffee | `src/grammar.coffee` | Assignable、Array、Object規則（397-401, 456-457, 591-594行目） |

**主要処理フロー**:
- **397-401行目**: Assignable
  - SimpleAssignable
  - Array → new Value $1
  - Object → new Value $1
- **591-594行目**: Array
  - [ ] → new Arr []
  - [ Elisions ] → new Arr $2
  - [ ArgElisionList OptElisions ] → new Arr ...

**読解のコツ**: ArrayとObjectがValueでラップされ、Assignableとして扱われる。

#### Step 2: Assignノードの分割代入処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | nodes.coffee | `src/nodes.coffee` | AssignクラスのcompileNode（3563-3606行目） |

**主要処理フロー**:
- **3564行目**: isValue = @variable instanceof Value
- **3570行目**: variable.isArray() or variable.isObject() の判定
- **3571-3575行目**: isAssignable() チェックと分岐
  - compileObjectDestruct
  - compileDestructuring
- **3603行目**: オブジェクト分割代入の括弧ラップ

#### Step 3: compileDestructuring関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | nodes.coffee | `src/nodes.coffee` | compileDestructuring関数（3623-3680行目） |

**主要処理フロー**:
- **3624-3626行目**: 基本変数の初期化
- **3631-3633行目**: 空パターンの処理
- **3637行目**: スプラットとExpansionの検出
- **3658-3661行目**: 一時変数の生成
- **3664-3675行目**: スライス処理のヘルパー関数

#### Step 4: compileObjectDestruct関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | nodes.coffee | `src/nodes.coffee` | compileObjectDestruct関数（3609-3619行目） |

**主要処理フロー**:
- **3610行目**: プロパティの並べ替え
- **3612行目**: スプラットプロパティの取得
- **3614-3615行目**: 一時変数の生成
- **3616行目**: スプラットをrefValで置換
- **3617-3618行目**: 代入文の生成

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

```
Grammar: Assign規則
    │
    └─ new Assign(variable, value, context)
           │
           ├─ compileNode(o)
           │      │
           │      ├─ isValue && (isArray || isObject)
           │      │      │
           │      │      ├─ isAssignable() → ES6出力
           │      │      │
           │      │      ├─ isObject && hasSplat
           │      │      │      └─ compileObjectDestruct(o)
           │      │      │             ├─ reorderProperties
           │      │      │             ├─ スプラット分離
           │      │      │             └─ 代入文生成
           │      │      │
           │      │      └─ compileDestructuring(o)
           │      │             ├─ 空パターン処理
           │      │             ├─ スプラット検出
           │      │             ├─ 一時変数生成
           │      │             └─ 要素ごと代入
           │      │
           │      └─ isSplice → compileSplice
           │
           └─ 代入文出力
```

### データフロー図

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

[a, b] = [1, 2]         ───▶  Grammar解析  ───▶  Assignノード
                               │
                               ▼
                         compileNode
                               │
                               ▼
                         isAssignable判定
                               │
                    ┌──────────┴──────────┐
                    ▼                     ▼
               ES6互換              compileDestructuring
                    │                     │
                    ▼                     ▼
              [a, b] = [1, 2];      var a, b, ref;
                                   ref = [1, 2];
                                   a = ref[0];
                                   b = ref[1];
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| grammar.coffee | `src/grammar.coffee` | ソース | Assignable、Array、Object文法規則 |
| nodes.coffee | `src/nodes.coffee` | ソース | Assignクラス、分割代入処理の実装 |
| lexer.coffee | `src/lexer.coffee` | ソース | [、]、{、}トークンの生成 |
