# 機能設計書 62-存在演算子

## 概要

本ドキュメントは、CoffeeScriptの存在演算子（Existential Operator）機能の設計を記述する。存在演算子は、変数が`null`でも`undefined`でもないことを確認するための簡潔な構文を提供する言語機能である。

### 本機能の処理概要

CoffeeScriptの存在演算子は、`?`記号を使用して変数やプロパティの存在確認を行う機能である。単独の`?`演算子は後置形式で使用し、変数が存在するかどうかをブール値で返す。また、ソークアクセス（`?.`）やソークインデックス（`?[]`）と組み合わせることで、nullセーフなプロパティアクセスを実現する。

**業務上の目的・背景**：
JavaScriptでは`null`や`undefined`のチェックが煩雑になりがちで、`if (x !== null && x !== undefined)`のような冗長な条件式が必要になる。CoffeeScriptの存在演算子は、RubyのSafe Navigation Operator（`&.`）やKotlinのNull-safe operator（`?.`）に類似した簡潔な記法を提供し、null参照エラーを防ぎながら可読性の高いコードを実現する。ES2020で導入されたOptional Chaining（`?.`）の先駆けとなった機能である。

**機能の利用シーン**：
- 変数がnull/undefinedでないことを確認する場合（例：`if variable?`）
- オブジェクトのプロパティに安全にアクセスする場合（例：`user?.address?.city`）
- 関数が存在する場合のみ呼び出す場合（例：`callback?()`）
- デフォルト値を設定する場合（例：`value = input ? defaultValue`）
- 配列要素への安全なアクセス（例：`array?[index]`）

**主要な処理内容**：
1. `?`演算子の解析（後置存在確認）
2. `?.`ソークアクセスの解析（nullセーフプロパティアクセス）
3. `?[]`ソークインデックスの解析（nullセーフ配列アクセス）
4. `?(`ソーク関数呼び出しの解析（nullセーフ関数呼び出し）
5. `?`二項演算子の解析（存在確認付きデフォルト値）
6. `?=`複合代入の解析（存在しない場合のみ代入）
7. スコープに基づく`typeof`チェックの生成

**関連システム・外部連携**：
存在演算子はCoffeeScriptコンパイラの文法定義（grammar.coffee）とノード生成（nodes.coffee）によって実装され、JavaScriptの条件式（`!= null`または`typeof !== "undefined"`）に変換される。

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

## 関連画面

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

## 機能種別

計算処理 / 言語構文変換 / バリデーション

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| expression | Expression | Yes | 存在確認対象の式 | 有効な式であること |
| onlyNotUndefined | Boolean | No | undefinedのみチェックするかどうか（デフォルト値との連携用） | - |
| negated | Boolean | No | 否定形かどうか（`!`演算子との組み合わせ） | - |

### 入力データソース

CoffeeScriptソースコード内の`?`演算子を含む式

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| JavaScript | String | コンパイルされた存在確認のJavaScriptコード |
| result | Boolean | 存在確認の結果（実行時） |

### 出力先

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

## 処理フロー

### 処理シーケンス

```
1. 存在演算子の解析
   └─ grammar.coffeeで `Expression ?` パターンを認識
2. Existenceノード生成
   └─ 対象式とcomparisonTargetを設定
3. コンパイル処理（compileNode）
   └─ 3.1 対象が未宣言の識別子かどうかを判定
   └─ 3.2 未宣言の場合：typeof チェックを生成
   └─ 3.3 宣言済みの場合：!= null または !== undefined チェックを生成
   └─ 3.4 negatedの場合は比較演算子を反転
```

### フローチャート

```mermaid
flowchart TD
    A[存在演算子の開始] --> B{対象式の種類}
    B -->|識別子| C{スコープで宣言済み?}
    B -->|その他の式| D[!= null チェック生成]
    C -->|Yes| D
    C -->|No| E[typeof !== undefined チェック生成]
    E --> F{comparisonTarget}
    F -->|null| G[&& !== null を追加]
    F -->|undefined| H[typeofのみ]
    G --> I{negated?}
    H --> I
    D --> I
    I -->|Yes| J[比較演算子を反転]
    I -->|No| K[JavaScriptコード出力]
    J --> K
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-62-1 | 未宣言変数のtypeofチェック | 未宣言の識別子に対しては`typeof`を使用してReferenceErrorを防ぐ | 識別子がスコープに存在しない場合 |
| BR-62-2 | 緩い等価演算子の使用 | `null`との比較には`!=`（緩い等価）を使用し、`null`と`undefined`の両方をチェック | comparisonTargetが`null`の場合 |
| BR-62-3 | 厳密等価演算子の使用 | `undefined`のみとの比較には`!==`（厳密等価）を使用 | comparisonTargetが`undefined`の場合 |
| BR-62-4 | 否定形の反転 | `!`演算子と組み合わせた場合は比較演算子を反転 | negatedがtrueの場合 |

### 計算ロジック

- 宣言済み変数の存在確認: `variable != null`（`null`と`undefined`の両方をチェック）
- 未宣言変数の存在確認: `typeof variable !== "undefined" && variable !== null`
- デフォルト値のみ（`?=`）: `variable !== void 0`（`undefined`のみチェック）

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

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | - | 存在演算子自体はエラーを発生させない | - |

### リトライ仕様

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

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

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

## パフォーマンス要件

- コンパイル時間: 式の複雑さに対して一定時間
- 生成コードの実行時間: 通常の比較演算と同等（O(1)）

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

- `typeof`チェックにより、未宣言変数へのアクセスによるReferenceErrorを防止
- グローバル変数の存在確認に安全に使用可能

## 備考

- ES2020で導入されたOptional Chaining（`?.`）やNullish Coalescing（`??`）と類似の機能を提供
- `?`演算子は後置形式のみ（`variable?`）で、前置形式（`?variable`）は不可
- ソークアクセス（`?.`）は連鎖可能（例：`a?.b?.c?.d`）

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | grammar.coffee | `src/grammar.coffee` | `Expression ?`パターンの定義（911行目） |

**読解のコツ**:
- 911行目: `o 'Expression ?', -> new Existence $1` で後置存在演算子を定義
- `?.`（ソークアクセス）は433-439行目のAccessor規則で定義

**主要処理フロー**:
1. **911行目**: `Expression ?` - 後置存在演算子
2. **435行目**: `?. Property` - ソークプロパティアクセス
3. **437行目**: `?:: Property` - ソークプロトタイプアクセス
4. **447行目**: `INDEX_SOAK Index` - ソークインデックスアクセス

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

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

**主要処理フロー**:
- **5086行目**: `class Existence extends Base` - Existenceクラス定義
- **5087-5089行目**: コンストラクタで`comparisonTarget`を設定
- **5103-5121行目**: `compileNode`メソッドでJavaScriptコード生成
- **5106-5108行目**: 未宣言変数の場合は`typeof`チェックを生成
- **5116-5120行目**: `null`または`undefined`との比較演算子を選択

#### Step 3: ソークアクセスの実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | nodes.coffee | `src/nodes.coffee` | Valueクラスの`unfoldSoak`メソッド |

**読解のコツ**:
- ソークアクセス（`?.`）は`soak: yes`フラグで管理される
- `unfoldSoak`メソッドで条件式に展開される

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

```
CoffeeScript.compile()
    │
    ├─ Lexer.tokenize()
    │      └─ '?' トークン生成
    │
    ├─ parser.parse()
    │      └─ grammar.coffeeの規則に従いExistenceノード生成
    │             └─ new Existence(expression)
    │
    └─ Existence.compileNode()
           ├─ o.scope.check() でスコープ確認
           ├─ typeof チェック生成（未宣言の場合）
           └─ != null チェック生成（宣言済みの場合）
```

### データフロー図

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

CoffeeScript           Lexer           Parser              Compiler
存在演算子式       →  トークン列  →   Existenceノード  →    JavaScript
                                    (AST)                  条件式

例: variable?
    ↓
['IDENTIFIER', '?']
    ↓
Existence {
  expression: IdentifierLiteral('variable'),
  comparisonTarget: 'null'
}
    ↓
variable != null                      // 宣言済みの場合
// または
typeof variable !== "undefined" && variable !== null  // 未宣言の場合
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| grammar.coffee | `src/grammar.coffee` | ソース | 存在演算子の文法規則定義（911行目、433-447行目） |
| nodes.coffee | `src/nodes.coffee` | ソース | Existenceノードクラスの実装（5081-5130行目） |
| lexer.coffee | `src/lexer.coffee` | ソース | `?`、`?.`、`?::`トークンの生成 |
| scope.litcoffee | `src/scope.litcoffee` | ソース | 変数のスコープ確認（`check`メソッド） |
