# 機能設計書 17-Rangeクラス

## 概要

本ドキュメントは、mrubyにおけるRangeクラスの機能設計を記述する。Rangeクラスは範囲オブジェクトの生成・イテレーション・包含判定等を提供する組み込み型クラスである。

### 本機能の処理概要

Rangeクラスは、開始値から終了値までの範囲を表現するオブジェクトを実装する。ISO 15.2.14に準拠し、`..`（終了値含む）および`...`（終了値含まない）演算子で生成される。整数範囲、文字列範囲、無限範囲（beginless/endless）をサポートし、Enumerableモジュールをインクルードすることで豊富なイテレーション機能を提供する。内部的には、ビルド設定に応じて埋め込み構造（MRB_RANGE_EMBED）またはポインタ経由のエッジ構造を使用する。

**業務上の目的・背景**：範囲オブジェクトは、ループの範囲指定、配列のスライス、条件判定（between?）、case式のパターンマッチングなど、多用途に使用される基本的なデータ型である。組み込み環境では、整数範囲のイテレーションを最適化（succメソッドを使わず直接整数インクリメント）することで性能を確保している。

**機能の利用シーン**：`(1..10).each { |i| ... }`のようなイテレーション、`array[0..5]`のような配列スライス、`case value when 1..10`のようなパターンマッチング、`(1...n)`のようなインデックス生成等。

**主要な処理内容**：
1. 範囲オブジェクトの生成と初期化（begin, end, exclude_end?）
2. イテレーション（each）- 整数/文字列の特殊最適化
3. 包含判定（include?, ===, cover?）
4. 開始値・終了値の取得（begin/first, end/last）
5. 排他判定（exclude_end?）
6. ハッシュ値の計算
7. 配列変換（to_a/entries）
8. 範囲の比較関数による端点検証

**関連システム・外部連携**：Enumerableモジュールをインクルード。Comparableモジュールの<=>演算子に依存（端点の比較）。Arrayのスライスアクセスで使用される（mrb_range_beg_len）。

**権限による制御**：Rangeはイミュータブル（initializeの2回目呼び出しはエラー）。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | CLIベースのランタイム機能のため関連画面なし |

## 機能種別

データ操作 / イテレーション / 範囲表現

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| beg | Object | Yes | 範囲の開始値 | <=>で比較可能であること |
| end | Object | No | 範囲の終了値（nilで無限範囲） | begと<=>で比較可能 |
| excl | Boolean | No | 終了値を除外するか（デフォルトfalse） | なし |

### 入力データソース

範囲リテラル（`..` / `...`）、Range.new、C APIからのmrb_range_new。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 範囲 | Range | 生成された範囲オブジェクト |
| 配列 | Array | to_a/entries の変換結果 |
| 真偽値 | Boolean | include?, ===, exclude_end? の判定結果 |
| オブジェクト | Object | begin, end, first, last の取得結果 |

### 出力先

呼び出し元への戻り値として返却。

## 処理フロー

### 処理シーケンス

```
1. 範囲オブジェクトの生成
   └─ r_check: begin と end の比較可能性チェック
   └─ 初期化済みフラグの確認（二重初期化防止）
   └─ エッジ構造体の割り当て（非EMBEDモード時）
   └─ begin, end, excl の設定
2. eachイテレーション
   └─ 整数範囲: 直接インクリメントで最適化
   └─ 文字列範囲: uptoメソッドに委譲
   └─ その他: succメソッドによる汎用イテレーション
3. 包含判定
   └─ <=> 演算子による比較
```

### フローチャート

```mermaid
flowchart TD
    A[Range.new / .. / ...] --> B[r_check: 比較可能性チェック]
    B --> C{比較不能?}
    C -->|Yes| D[ArgumentError]
    C -->|No| E[RRange 構造体初期化]
    E --> F[RANGE_INITIALIZED フラグ設定]
    F --> G[Range オブジェクト返却]

    H[each 呼び出し] --> I{要素型?}
    I -->|Integer| J[直接インクリメント]
    I -->|String| K[upto メソッド委譲]
    I -->|Other| L[succ メソッド呼び出し]
    J --> M[ブロック実行]
    K --> M
    L --> M
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-17-01 | イミュータブル | Rangeは生成後に変更不可（initializeの再呼び出し不可） | 常時 |
| BR-17-02 | 比較可能性 | begin/endは<=>で比較可能でなければならない | Range生成時 |
| BR-17-03 | nil端点 | begin/endにnilを指定して無限範囲を表現可能 | Range生成時 |
| BR-17-04 | 整数最適化 | 整数範囲のeachはsuccを使わず直接インクリメント | eachイテレーション時 |
| BR-17-05 | Enumerable包含 | RangeはEnumerableをインクルードする | 常時 |
| BR-17-06 | 無限範囲のto_a | 無限範囲のto_aはRangeErrorを発生 | to_a呼び出し時 |

### 計算ロジック

- **hash計算**: `h = self.begin.hash ^ self.end.hash; h += 1 if exclude_end?`
- **比較**: `mrb_cmp` 関数による<=>の呼び出し（-2は比較不能）

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

該当なし（インメモリ操作のみ）。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ArgumentError | 比較不能なbegin/end | <=>を実装するオブジェクトを使用する |
| - | NameError | initializeの2回目呼び出し | 範囲は再初期化不可 |
| - | TypeError | succメソッドが未定義でeachを呼び出し | succメソッドを実装する |
| - | RangeError | 無限範囲のto_a | 有限範囲を使用する |

### リトライ仕様

該当なし。

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

該当なし。

## パフォーマンス要件

- 整数範囲のeachは直接インクリメントで最適（succメソッド呼び出しのオーバーヘッド回避）
- MRB_RANGE_EMBED時はポインタ経由のメモリ確保なし

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

- 特になし

## 備考

- ISO 15.2.14に準拠
- MRB_RANGE_EMBED: NaN Boxing（64bit）またはWord Boxing時は端点をRRange内に直接格納
- __num_to_aは整数範囲の高速配列変換用内部メソッド

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | range.h | `include/mruby/range.h` | RRange構造体（EMBED/非EMBEDの2形態） |

**読解のコツ**: `MRB_RANGE_EMBED`が定義されている場合、begとendはRRange構造体内に直接格納される。未定義の場合、mrb_range_edges構造体をポインタ経由で保持する。RANGE_BEG/RANGE_ENDマクロがこの違いを吸収している。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | range.c | `src/range.c` | `mrb_init_range()`関数（588行目）でクラス定義 |

**主要処理フロー**:
1. **588-597行目**: Rangeクラス定義、ROMメソッドテーブル初期化

#### Step 3: 範囲生成と検証を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | range.c | `src/range.c` | r_check, range_ptr_init等の初期化ロジック |

**主要処理フロー**:
- **16-18行目**: RANGE_INITIALIZED フラグ管理マクロ
- **20-41行目**: r_check - begin/endの比較可能性検証
- **43-56行目**: r_le, r_gt, r_ge - 比較ヘルパー関数
- **67-73行目**: range_ptr_alloc_edges - エッジ構造体のメモリ確保
- **75-100行目**: range_ptr_init - Range初期化（二重初期化防止あり）

#### Step 4: Rubyレベルメソッドを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | range.rb | `mrblib/range.rb` | each, hash, to_a等のRuby実装 |

**主要処理フロー**:
- **10行目**: `include Enumerable` 宣言
- **17-73行目**: `each` - 型に応じた最適化イテレーション
  - **23-29行目**: 無限整数範囲の処理
  - **40-49行目**: 有限整数範囲の最適化（直接インクリメント）
  - **51-57行目**: 文字列範囲の処理（uptoに委譲）
  - **59-72行目**: 汎用範囲の処理（succメソッド使用）
- **76-81行目**: `hash` - begin/endのハッシュXOR + exclude_end補正
- **92-97行目**: `to_a` - __num_to_a優先、なければsuper（Enumerable#entries）

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

```
mrb_init_range()
    |
    +-- mrb_define_class_id(Range)
    +-- MRB_MT_INIT_ROM(range_rom_entries)
            |
            +-- C実装メソッド群（initialize, begin, end, include?等）
            |       |
            |       +-- range_ptr_init (初期化)
            |       +-- r_check (比較可能性チェック)
            |
            +-- mrblib/range.rb
                    |
                    +-- include Enumerable
                    +-- each (型別最適化)
                    +-- hash, to_a
```

### データフロー図

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

begin, end, excl     range_ptr_init                    RRange オブジェクト
             ---->   r_check (比較可能性)          ---->
                       |
each呼び出し       型判定                             ブロック実行結果
             ---->   Integer: 直接ループ         ---->  self
                     String: upto委譲
                     Other: succ呼び出し
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| range.c | `src/range.c` | ソース（C） | Rangeクラスの主要実装（598行） |
| range.rb | `mrblib/range.rb` | ソース（Ruby） | each, hash, to_a等のRuby実装 |
| range.h | `include/mruby/range.h` | ヘッダ | RRange構造体とC APIの宣言 |
| enum.rb | `mrblib/enum.rb` | ソース（Ruby） | Enumerableモジュール（Rangeがインクルード） |
