# 機能設計書 54-ユーティリティ関数

## 概要

本ドキュメントは、CoffeeScriptコンパイラの共通ユーティリティ関数群の設計を記述する。文字列操作、配列操作、オブジェクトマージ等の共通処理を提供する。

### 本機能の処理概要

ユーティリティ関数は、CoffeeScriptコンパイラの各コンポーネント（Lexer、Rewriter、Nodes）で共有される基本的なヘルパー関数群である。これらはコード生成、構文解析、エラー処理などの様々な場面で使用される。

**業務上の目的・背景**：コンパイラの各モジュールには、文字列の先頭・末尾チェック、配列のフラット化、オブジェクトのマージなど、共通して必要となる処理が多数存在する。これらを個別に実装すると、コードの重複や不整合が発生するリスクがある。本機能は、そのような共通処理を一箇所に集約し、コードの再利用性と保守性を向上させる。

**機能の利用シーン**：
- Lexer：トークン解析時の文字列操作
- Rewriter：トークン変換時の配列操作
- Nodes：コード生成時のオブジェクト操作
- Parser：構文解析時の位置情報管理
- エラー処理：エラーメッセージのフォーマット

**主要な処理内容**：
1. 文字列操作関数（starts, ends, repeat）
2. 配列操作関数（compact, flatten）
3. オブジェクト操作関数（merge, extend, del）
4. 位置情報管理関数（buildLocationData, locationDataToString）
5. ファイル名操作関数（baseFileName, isCoffee, isLiterate）
6. 型判定関数（isFunction, isNumber, isString, isBoolean, isPlainObject）

**関連システム・外部連携**：特になし（内部ユーティリティ）

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 17 | Annotated Source - Helpers | 主画面 | ヘルパー関数helpers.coffeeのソースコード解説表示 |
| 32 | Annotated Source - Helpers | 主画面 | ヘルパー関数helpers.coffeeのソースコード解説表示（v2） |

## 機能種別

ヘルパー機能 / ユーティリティ

## 入力仕様

### 入力パラメータ

各関数ごとに異なるパラメータを受け取る。主要な関数のパラメータを以下に示す。

#### starts関数
| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| string | String | Yes | チェック対象の文字列 | - |
| literal | String | Yes | マッチさせるシーケンス | - |
| start | Number | No | 開始位置（デフォルト: 0） | - |

#### ends関数
| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| string | String | Yes | チェック対象の文字列 | - |
| literal | String | Yes | マッチさせるシーケンス | - |
| back | Number | No | 末尾からのオフセット | - |

#### repeat関数
| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| str | String | Yes | 繰り返す文字列 | - |
| n | Number | Yes | 繰り返し回数 | 0以上の整数 |

#### merge関数
| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| options | Object | Yes | ベースオブジェクト | - |
| overrides | Object | Yes | 上書きオブジェクト | - |

#### flatten関数
| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| array | Array | Yes | フラット化対象の配列 | - |

### 入力データソース

- コンパイラ内部の各モジュールからの呼び出し

## 出力仕様

### 出力データ

| 関数名 | 戻り値型 | 説明 |
|--------|---------|------|
| starts | Boolean | 文字列が指定シーケンスで始まるか |
| ends | Boolean | 文字列が指定シーケンスで終わるか |
| repeat | String | n回繰り返された文字列 |
| compact | Array | 偽値を除去した配列 |
| count | Number | 部分文字列の出現回数 |
| merge | Object | マージされた新しいオブジェクト |
| extend | Object | 拡張されたオブジェクト |
| flatten | Array | フラット化された配列 |
| del | Any | 削除されたプロパティの値 |
| some | Boolean | 条件を満たす要素があるか |
| baseFileName | String | 拡張子を除いたファイル名 |
| isCoffee | Boolean | CoffeeScriptファイルか |
| isLiterate | Boolean | Literate CoffeeScriptファイルか |
| isFunction | Boolean | 関数オブジェクトか |
| isNumber | Boolean | 数値か |
| isString | Boolean | 文字列か |
| isBoolean | Boolean | 真偽値か |
| isPlainObject | Boolean | プレーンオブジェクトか |

### 出力先

- 呼び出し元への戻り値

## 処理フロー

### 処理シーケンス（repeat関数の例）

```
1. 入力値の確認
   └─ str: 繰り返す文字列
   └─ n: 繰り返し回数

2. 結果変数の初期化
   └─ res = ''

3. ビット演算による高速繰り返し
   └─ while n > 0:
      └─ n & 1 が真なら res += str
      └─ n >>>= 1 で右シフト
      └─ str += str で文字列を倍化

4. 結果を返す
   └─ return res
```

### フローチャート

```mermaid
flowchart TD
    subgraph repeat関数
        A[開始] --> B[res = 空文字列]
        B --> C{n > 0?}
        C -->|No| D[resを返す]
        C -->|Yes| E{n & 1?}
        E -->|Yes| F[res += str]
        E -->|No| G[スキップ]
        F --> H[n >>>= 1]
        G --> H
        H --> I[str += str]
        I --> C
    end
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-54-01 | O(log n)繰り返し | repeat関数はビット演算を用いてO(log n)の文字列連結を実現 | repeat呼び出し時 |
| BR-54-02 | 浅いコピー | merge/extendは浅いコピーを行う | マージ処理時 |
| BR-54-03 | 無限大カウント | count関数で空文字列を検索するとInfinityを返す | substr.length === 0の場合 |
| BR-54-04 | 配列フラット化 | flattenはネイティブのArray.prototype.flat(Infinity)を使用 | flatten呼び出し時 |
| BR-54-05 | CoffeeScript判定 | .coffee, .litcoffee, .coffee.mdをCoffeeScriptファイルと判定 | isCoffee呼び出し時 |
| BR-54-06 | Literate判定 | .litcoffee, .coffee.mdをLiterate CoffeeScriptと判定 | isLiterate呼び出し時 |

### 計算ロジック

**repeat関数のアルゴリズム（高速べき乗法の応用）**:
```
repeat("ab", 5):
  n=5: 101(2進)
  n=5: n&1=1, res="ab", n=2, str="abab"
  n=2: n&1=0, n=1, str="abababab"
  n=1: n&1=1, res="ababababab", n=0
  結果: "ababababab"
```

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

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

該当なし（内部ユーティリティ関数のため、データベース操作は行わない）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| TypeError | 型エラー | 不正な引数型 | 呼び出し元でバリデーション |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- repeat関数: O(log n)の計算量
- flatten関数: ネイティブArray.prototype.flatを使用
- その他の関数: O(n)またはO(1)の計算量

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

該当なし（内部ユーティリティ関数）

## 備考

- helpers.coffeeはCoffeeScriptコンパイラ全体で使用される基盤モジュール
- Array.prototype.someのポリフィルが含まれる（古いブラウザ対応）

---

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

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

### 推奨読解順序

#### Step 1: 基本的な文字列操作関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | helpers.coffee | `src/helpers.coffee` | starts, ends, repeat関数（6-22行目） |

**主要処理フロー**:
- **6-7行目**: `starts`関数 - substrで先頭をチェック
- **10-12行目**: `ends`関数 - 末尾からの位置を計算してチェック
- **15-22行目**: `repeat`関数 - ビット演算による高速繰り返し

**読解のコツ**: repeat関数は高速べき乗法と同じアルゴリズムを使用。ビット演算 `n & 1` で最下位ビットをチェックし、`n >>>= 1` で右シフト。

#### Step 2: 配列・オブジェクト操作関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | helpers.coffee | `src/helpers.coffee` | compact, count, merge, extend, flatten, del関数（25-57行目） |

**主要処理フロー**:
- **25-26行目**: `compact`関数 - 内包表記でtruthyな要素のみ抽出
- **29-33行目**: `count`関数 - indexOfで出現回数をカウント
- **38-39行目**: `merge`関数 - 2回のextendで新しいオブジェクトを生成
- **42-45行目**: `extend`関数 - for-ofで浅いコピー
- **49-50行目**: `flatten`関数 - ネイティブflatを使用
- **54-57行目**: `del`関数 - プロパティを削除して値を返す

#### Step 3: 位置情報管理関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | helpers.coffee | `src/helpers.coffee` | buildLocationData, locationDataToString関数（96-183行目） |

**主要処理フロー**:
- **96-109行目**: `buildLocationData`関数 - 位置情報オブジェクトの構築
- **175-183行目**: `locationDataToString`関数 - 位置情報の文字列化

#### Step 4: 型判定関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | helpers.coffee | `src/helpers.coffee` | isFunction, isNumber, isString, isBoolean, isPlainObject関数（290-294行目） |

**主要処理フロー**:
- **290行目**: `isFunction` - Object.prototype.toStringで判定
- **291行目**: `isNumber` - 同上
- **292行目**: `isString` - 同上
- **293行目**: `isBoolean` - yesまたはnoとの比較、またはtoStringで判定
- **294行目**: `isPlainObject` - typeofと各種条件で判定

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

```
helpers.coffee
    │
    ├─ 文字列操作
    │      ├─ starts(string, literal, start)
    │      ├─ ends(string, literal, back)
    │      └─ repeat(str, n)
    │
    ├─ 配列操作
    │      ├─ compact(array)
    │      ├─ count(string, substr)
    │      ├─ flatten(array)
    │      └─ some(fn)
    │
    ├─ オブジェクト操作
    │      ├─ merge(options, overrides)
    │      ├─ extend(object, properties)
    │      └─ del(obj, key)
    │
    ├─ 位置情報
    │      ├─ buildLocationData(first, last)
    │      ├─ locationDataToString(obj)
    │      └─ addDataToNode(...)
    │
    ├─ ファイル操作
    │      ├─ anonymousFileName()
    │      ├─ baseFileName(file, stripExt, useWinPathSep)
    │      ├─ isCoffee(file)
    │      └─ isLiterate(file)
    │
    └─ 型判定
           ├─ isFunction(obj)
           ├─ isNumber(obj)
           ├─ isString(obj)
           ├─ isBoolean(obj)
           └─ isPlainObject(obj)
```

### データフロー図

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

文字列/配列/       ───▶  ユーティリティ関数  ───▶  変換結果
オブジェクト              helpers.coffee
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| helpers.coffee | `src/helpers.coffee` | ソース | ユーティリティ関数の実装 |
| lexer.coffee | `src/lexer.coffee` | ソース | helpersを使用（starts, ends等） |
| rewriter.coffee | `src/rewriter.coffee` | ソース | helpersを使用（flatten等） |
| nodes.coffee | `src/nodes.coffee` | ソース | helpersを使用（merge, extend等） |
