# 機能設計書 58-関数定義

## 概要

本ドキュメントは、CoffeeScriptの関数定義機能の設計を記述する。アロー関数（`->`）およびバウンド関数（`=>`）の定義をサポートする。

### 本機能の処理概要

関数定義機能は、CoffeeScriptにおける関数リテラルの構文を提供する。シンプルな`->`（通常関数）と`=>`（バウンド関数）の2種類の関数定義をサポートし、パラメータリスト、デフォルト値、スプラットパラメータ、デストラクチャリングなど豊富な機能を備える。

**業務上の目的・背景**：関数はプログラミングの基本的な構成要素であり、コードの再利用性と可読性に直結する。CoffeeScriptは、JavaScriptの関数定義をよりシンプルで読みやすい構文で表現し、開発者の生産性を向上させる。特にバウンド関数（`=>`）は、コールバックやイベントハンドラでの`this`バインディング問題を解決する重要な機能である。

**機能の利用シーン**：
- コールバック関数の定義
- イベントハンドラの定義
- 高階関数への関数渡し
- メソッド定義
- 即時実行関数式（IIFE）

**主要な処理内容**：
1. 関数定義構文の解析（パラメータ、本体）
2. パラメータリストの処理（デフォルト値、スプラット、デストラクチャリング）
3. バウンド関数のthisバインディング処理
4. ジェネレーター関数（yield）の検出
5. async関数（await）の検出
6. ES6関数構文へのコード生成

**関連システム・外部連携**：
- Grammar（文法定義）
- Nodes（コード生成）
- Scope（変数スコープ管理）

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

## 関連画面

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

## 機能種別

言語機能 / コード生成

## 入力仕様

### 入力パラメータ

#### Codeノード（文法定義）
| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| params | Array | No | パラメータリスト | - |
| body | Block | No | 関数本体 | - |
| funcGlyph | FuncGlyph | Yes | 関数記号（->または=>） | - |
| paramStart | Literal | No | パラメータ開始括弧 | - |

### 入力データソース

- CoffeeScriptソースコード内の関数定義

### 構文例

```coffeescript
# 基本的な関数
square = (x) -> x * x

# 複数パラメータ
add = (a, b) -> a + b

# パラメータなし
sayHello = -> console.log "Hello"

# デフォルト値
greet = (name = "World") -> console.log "Hello, #{name}"

# スプラットパラメータ
sum = (numbers...) ->
  total = 0
  total += n for n in numbers
  total

# デストラクチャリング
processPoint = ({x, y}) -> console.log x, y

# バウンド関数
button.onClick = => console.log @value

# ジェネレーター
fibonacci = ->
  [a, b] = [0, 1]
  loop
    yield a
    [a, b] = [b, a + b]

# async関数
fetchData = ->
  response = await fetch url
  await response.json()
```

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| compiledCode | String | ES6関数構文のJavaScriptコード |

### 出力先

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

### 出力例

```javascript
// 基本的な関数
var square = function(x) {
  return x * x;
};

// バウンド関数
button.onClick = () => {
  return console.log(this.value);
};

// async関数
var fetchData = async function() {
  var response;
  response = await fetch(url);
  return await response.json();
};
```

## 処理フロー

### 処理シーケンス

```
1. 関数定義の解析
   └─ PARAM_START/PARAM_END でパラメータリスト取得
   └─ FuncGlyph（-> または =>）の取得
   └─ Block で関数本体取得

2. Codeノードの生成
   └─ new Code(params, body, funcGlyph, paramStart)
   └─ bound = funcGlyph.glyph === '=>'
   └─ 本体を走査してisGenerator、isAsyncを設定

3. パラメータ処理
   └─ thisアサインメントの分離（@paramの処理）
   └─ スプラットパラメータの処理
   └─ デフォルト値の処理
   └─ デストラクチャリングの処理

4. コード生成
   └─ スコープの作成
   └─ パラメータリストの生成
   └─ 関数本体の生成
   └─ バウンド関数の場合はアロー関数として出力
```

### フローチャート

```mermaid
flowchart TD
    A[関数定義解析] --> B{パラメータあり?}
    B -->|Yes| C[PARAM_START...PARAM_END]
    B -->|No| D[空リスト]
    C --> E[FuncGlyph取得]
    D --> E
    E --> F[Block取得]
    F --> G[Codeノード生成]
    G --> H{glyph === '=>'?}
    H -->|Yes| I[bound = true]
    H -->|No| J[bound = false]
    I --> K[本体走査]
    J --> K
    K --> L{yield検出?}
    L -->|Yes| M[isGenerator = true]
    L -->|No| N[isGenerator = false]
    M --> O{await検出?}
    N --> O
    O -->|Yes| P[isAsync = true]
    O -->|No| Q[isAsync = false]
    P --> R[compileNode]
    Q --> R
    R --> S[パラメータ処理]
    S --> T[本体生成]
    T --> U[関数出力]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-58-01 | バウンド関数 | =>で定義された関数はthisをレキシカルにバインド | =>使用時 |
| BR-58-02 | ジェネレーター検出 | 本体にyieldがあればジェネレーター関数 | 関数定義時 |
| BR-58-03 | async検出 | 本体にawaitがあればasync関数 | 関数定義時 |
| BR-58-04 | bound + yield禁止 | バウンド関数内ではyieldを使用不可 | 関数定義時 |
| BR-58-05 | thisパラメータ | @param形式はthis.paramへのアサインに変換 | パラメータ処理時 |
| BR-58-06 | スプラット後パラメータ | スプラット後のパラメータは関数本体で処理 | パラメータ処理時 |
| BR-58-07 | 暗黙のreturn | 関数本体の最後の式が戻り値 | 関数定義時 |

### 計算ロジック

該当なし

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

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

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 構文エラー | バウンド関数内でyield使用 | "yield cannot occur inside bound (fat arrow) functions" |
| - | 構文エラー | 重複パラメータ名 | "multiple parameters named '{name}'" |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- 関数定義のコンパイルは同期的に実行
- ネストした関数定義も効率的に処理

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

該当なし

## 備考

- CoffeeScriptの関数はES6のfunction式またはアロー関数に変換
- 暗黙のreturnはCoffeeScriptの重要な特徴の一つ

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | grammar.coffee | `src/grammar.coffee` | Code、CodeLine、FuncGlyph規則（330-347行目） |

**主要処理フロー**:
- **331行目**: `PARAM_START ParamList PARAM_END FuncGlyph Block` - パラメータ付き関数
- **332行目**: `FuncGlyph Block` - パラメータなし関数
- **336-339行目**: CodeLine - 単一行関数
- **344-346行目**: FuncGlyph - ->と=>の定義

**読解のコツ**: FuncGlyphはnew FuncGlyph($1)で生成され、glyphプロパティに->または=>が格納される。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | nodes.coffee | `src/nodes.coffee` | Codeクラス（3897-4096行目以上） |

**主要処理フロー**:
- **3897-3916行目**: constructor
  - params、bodyの初期化
  - bound = funcGlyph?.glyph is '=>'
  - 本体を走査してisGenerator、isAsyncを検出
- **3924行目**: makeScope - 新しいスコープの作成
- **3932-4096行目以上**: compileNode - コンパイル処理

#### Step 3: パラメータ処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | nodes.coffee | `src/nodes.coffee` | compileNode内のパラメータ処理 |

**主要処理フロー**:
- **3950-3966行目**: thisアサインメントの分離（@paramの処理）
- **3976-4059行目**: パラメータループ
  - スプラットパラメータの処理
  - デフォルト値の処理
  - デストラクチャリングの処理
- **4063-4067行目**: スプラット後パラメータの処理

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | nodes.coffee | `src/nodes.coffee` | 関数出力部分 |

**主要処理フロー**:
- **4087-4093行目**: modifiers配列の構築（static、async、function/function*）
- **4095行目以降**: シグネチャとボディの生成
- バウンド関数の場合はアロー関数構文を使用

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

```
Grammar: Code規則
    │
    └─ new Code(params, body, funcGlyph, paramStart)
           │
           ├─ constructor
           │      ├─ params = params or []
           │      ├─ body = body or new Block
           │      ├─ bound = funcGlyph?.glyph is '=>'
           │      └─ body.traverseChildren → isGenerator, isAsync設定
           │
           └─ compileNode(o)
                  │
                  ├─ checkForAsyncOrGeneratorConstructor
                  │
                  ├─ updateOptions(o)
                  │
                  ├─ [パラメータ処理]
                  │      ├─ thisアサインメント分離
                  │      ├─ スプラット処理
                  │      ├─ デフォルト値処理
                  │      └─ デストラクチャリング処理
                  │
                  ├─ [本体処理]
                  │      ├─ exprs.unshift thisAssignments...
                  │      └─ body.makeReturn()
                  │
                  └─ [出力生成]
                         ├─ modifiers: static?, async?, function*?
                         ├─ signature: (params)
                         └─ body fragments
```

### データフロー図

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

(x) -> x * x            ───▶  Grammar解析  ───▶  Codeノード
                               │
                               ▼
                         compileNode
                               │
                    ┌──────────┼──────────┐
                    ▼          ▼          ▼
              パラメータ     本体      修飾子
                処理        処理       設定
                    │          │          │
                    └──────────┼──────────┘
                               ▼
                         function(x) {
                           return x * x;
                         }
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| grammar.coffee | `src/grammar.coffee` | ソース | Code、FuncGlyph文法規則の定義 |
| nodes.coffee | `src/nodes.coffee` | ソース | Codeノードクラスの実装 |
| scope.litcoffee | `src/scope.litcoffee` | ソース | 関数スコープの管理 |
| lexer.coffee | `src/lexer.coffee` | ソース | PARAM_START、->、=>トークンの生成 |
