# 機能設計書 35-@babel/plugin-transform-exponentiation-operator

## 概要

本ドキュメントは、Babelの変換プラグイン「@babel/plugin-transform-exponentiation-operator」の機能設計を記述する。本プラグインはES2016のべき乗演算子（`**`）を、Math.pow関数呼び出しに変換する。

### 本機能の処理概要

本プラグインは、べき乗演算子（`**`）およびべき乗代入演算子（`**=`）を検出し、Math.pow関数呼び出しに変換する機能を提供する。これにより、ES2016以前の環境でもべき乗計算を実行できる。

**業務上の目的・背景**：ES2016で導入されたべき乗演算子は、`2 ** 3`のような直感的な記法でべき乗計算を表現できる。しかし、古いブラウザやNode.jsバージョンではこの演算子をサポートしていないため、トランスパイルが必要となる。本プラグインにより、開発者はモダンな構文を使用しながらも、幅広い環境での互換性を確保できる。

**機能の利用シーン**：
- 数学的計算を行うアプリケーション開発
- 科学計算やデータ分析のためのJavaScriptコード
- `@babel/preset-env`の一部として自動的に適用される場合

**主要な処理内容**：
1. BinaryExpression（operator: "**"）を検出し、Math.pow(left, right)に変換
2. AssignmentExpression（operator: "**="）を検出し、代入式とMath.powの組み合わせに変換
3. MemberExpression左辺の場合、オブジェクトとプロパティをメモ化して二重評価を防止
4. 計算プロパティの場合も適切にメモ化処理
5. 関数パラメータ内での使用時はIIFEでラップ

**関連システム・外部連携**：
- `@babel/helper-plugin-utils`: プラグインユーティリティ
- `@babel/core`: Babelコアとの統合

**権限による制御**：特になし。変換はビルド時に実行される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | CLIまたはビルドツール経由で使用されるため、画面との関連なし |

## 機能種別

コード変換処理 / AST操作

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| - | - | - | オプションなし | - |

### 入力データソース

- Babelによってパースされたソースコード（AST形式）
- BinaryExpression（operator: "**"）、AssignmentExpression（operator: "**="）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| transformedAST | AST | 変換後のAST |

### 出力先

- 変換されたASTは`@babel/generator`によってJavaScriptコードとして出力

## 処理フロー

### 処理シーケンス

```
1. プラグイン初期化
   └─ build関数を定義（Math.pow呼び出し生成）

2. BinaryExpressionの処理
   ├─ operator === "**" をチェック
   └─ Math.pow(left, right) に変換

3. AssignmentExpressionの処理
   ├─ operator === "**=" をチェック
   ├─ 左辺がMemberExpressionの場合
   │      ├─ オブジェクトのメモ化
   │      ├─ 計算プロパティの場合はプロパティもメモ化
   │      └─ 代入式 + Math.pow に変換
   └─ 左辺が単純な識別子の場合
          └─ 直接 Math.pow に変換
```

### フローチャート

```mermaid
flowchart TD
    A[ASTノードの訪問] --> B{ノードの種類}
    B -->|BinaryExpression| C{operator === "**"?}
    B -->|AssignmentExpression| D{operator === "**="?}
    C -->|Yes| E[Math.pow left, right に変換]
    C -->|No| Z[変換なし]
    D -->|Yes| F{左辺の種類}
    D -->|No| Z
    F -->|MemberExpression| G{計算プロパティ?}
    F -->|Identifier| H[直接Math.powに変換]
    G -->|Yes| I[オブジェクトとプロパティをメモ化]
    G -->|No| J[オブジェクトのみメモ化]
    I --> K[代入式 + Math.pow に変換]
    J --> K
    E --> L[変換完了]
    H --> L
    K --> L
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-35-01 | 二重評価防止 | MemberExpression左辺のオブジェクトを一時変数にメモ化 | 左辺がMemberExpression時 |
| BR-35-02 | 計算プロパティメモ化 | 計算プロパティキーを一時変数にメモ化 | 計算プロパティ使用時 |
| BR-35-03 | パターン内IIFE | 関数パラメータ等のパターン内ではIIFEでラップ | パターン内使用時 |

### 計算ロジック

- 変換: `a ** b` → `Math.pow(a, b)`
- 変換: `a **= b` → `a = Math.pow(a, b)`
- 変換: `obj.prop **= b` → `_obj = obj, _obj.prop = Math.pow(_obj.prop, b)`

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

該当なし（コンパイル時変換のため）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | SyntaxError | 不正なべき乗演算子構文 | パーサーレベルでエラー |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- 変換処理は同期的に実行される
- Math.powはネイティブ関数のため、実行時のパフォーマンス影響は最小限

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

- 特になし

## 備考

- 本プラグインは`@babel/preset-env`に含まれており、ターゲット環境に応じて自動的に適用される
- ES2016をサポートしない環境向けの変換

---

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

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

### 推奨読解順序

#### Step 1: データ構造を理解する

本プラグインはBinaryExpression（**演算子）とAssignmentExpression（**=演算子）を変換対象とする。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | index.ts | `packages/babel-plugin-transform-exponentiation-operator/src/index.ts` | シンプルな構造。build関数とmaybeMemoize関数が中心 |

**読解のコツ**: 本プラグインは比較的シンプルで、1ファイルで完結している。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.ts | `packages/babel-plugin-transform-exponentiation-operator/src/index.ts` | build関数、maybeMemoize関数、2つのビジター |

**主要処理フロー**:
1. **1-2行目**: 必要なモジュールのインポート
2. **4-5行目**: APIバージョン検証
3. **9-14行目**: build関数 - Math.pow呼び出しを生成
4. **16-41行目**: maybeMemoize関数 - 式のメモ化処理
5. **47-95行目**: AssignmentExpression visitor - べき乗代入演算子の変換
6. **97-108行目**: BinaryExpression visitor - べき乗演算子の変換

#### Step 3: メモ化ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | index.ts (16-41行目) | `packages/babel-plugin-transform-exponentiation-operator/src/index.ts` | maybeMemoize関数 - 静的式の判定、一時変数の生成 |

**主要処理フロー**:
- **20行目**: scope.isStatic()で静的式かチェック
- **21行目**: 静的なら元のノードとクローンを返す
- **24-27行目**: パターン内の場合はnullを返す（IIFE対応）
- **29-40行目**: 一時変数を生成し、代入式と参照を返す

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

```
@babel/plugin-transform-exponentiation-operator/src/index.ts
    │
    ├─ build(left, right)
    │      └─ t.callExpression(Math.pow, [left, right])
    │
    ├─ maybeMemoize(node, scope)
    │      ├─ scope.isStatic() チェック
    │      └─ scope.generateUidIdentifierBasedOnNode()
    │
    ├─ visitor.AssignmentExpression()
    │      ├─ operator === "**=" チェック
    │      ├─ MemberExpressionの場合
    │      │      ├─ maybeMemoize(object)
    │      │      └─ maybeMemoize(property) (computed時)
    │      └─ build() で Math.pow 生成
    │
    └─ visitor.BinaryExpression()
           ├─ operator === "**" チェック
           └─ build() で Math.pow 生成
```

### データフロー図

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

a ** b              ─▶  BinaryExpression visitor   ─▶  Math.pow(a, b)

a **= b             ─▶  AssignmentExpression       ─▶  a = Math.pow(a, b)
                         visitor

obj.prop **= b      ─▶  AssignmentExpression       ─▶  (_obj = obj,
                         visitor                        _obj.prop = Math.pow(_obj.prop, b))
                              │
                              └─ maybeMemoize(obj)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.ts | `packages/babel-plugin-transform-exponentiation-operator/src/index.ts` | ソース | プラグインエントリーポイント、変換ロジック |
| package.json | `packages/babel-plugin-transform-exponentiation-operator/package.json` | 設定 | パッケージ依存関係定義 |
| test/index.js | `packages/babel-plugin-transform-exponentiation-operator/test/index.js` | テスト | テストランナー設定 |
| fixtures/exponentiation-operator/ | `packages/babel-plugin-transform-exponentiation-operator/test/fixtures/exponentiation-operator/` | テスト | 変換テストケース |
| fixtures/regression/ | `packages/babel-plugin-transform-exponentiation-operator/test/fixtures/regression/` | テスト | 回帰テストケース |
