# 帳票設計書 12-p (inspect出力)

## 概要

本ドキュメントは、mrubyにおけるKernel#pメソッドによるオブジェクトのinspect結果の標準出力機能の設計仕様を記述する。デバッグ用途でオブジェクトの詳細な内部表現を人間が読める形式で出力する。

### 本帳票の処理概要

Kernel#pメソッドは、引数として渡されたRubyオブジェクトに対してinspectメソッドを呼び出し、その結果を改行付きで標準出力(stdout)に出力する。printやputsとは異なり、オブジェクトの詳細な内部表現（文字列の場合はクォート付き、配列の場合は括弧付き等）が表示される。

**業務上の目的・背景**：pメソッドはRubyにおける最も基本的なデバッグツールの一つである。ISO規格(ISO 15.3.1.3.34 Kernel#p, ISO 15.3.1.2.9 Kernel.p)に定義されており、オブジェクトの型や値を正確に把握するための出力手段を提供する。printやputsがto_s変換を行うのに対し、pはinspect変換を行うことで、デバッグに適した詳細な情報を表示する。

**帳票の利用シーン**：mrubyスクリプトの開発中にオブジェクトの中身を確認する場面で使用される。変数の値確認、データ構造の検証、処理結果の確認など、デバッグ全般で利用される。

**主要な出力内容**：
1. オブジェクトのinspect結果（型情報を含む人間可読な表現）
2. 末尾の改行文字
3. 複数引数の場合は各オブジェクトを1行ずつ出力

**帳票の出力タイミング**：mrubyスクリプト内でpメソッドが呼び出された時点で即座に標準出力へ出力される。

**帳票の利用者**：mrubyスクリプトの開発者、デバッグ担当者

## 帳票種別

デバッグ出力(テキスト出力)

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| N/A | コンソール/ターミナル | N/A (標準出力) | Rubyスクリプト内でpメソッドを呼び出し |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | テキスト(標準出力ストリーム) |
| 用紙サイズ | N/A |
| 向き | N/A |
| ファイル名 | N/A (stdoutへの直接出力) |
| 出力方法 | 標準出力(stdout)への書き込み |
| 文字コード | UTF-8 (Windows環境ではUTF-16への変換あり) |

### PDF固有設定

N/A (本帳票はPDF出力ではない)

### Excel固有設定

N/A (本帳票はExcel出力ではない)

## 帳票レイアウト

### レイアウト概要

pメソッドは各引数のinspect結果を1行ずつ出力する。

```
┌─────────────────────────────────────┐
│ [引数1のinspect結果]\n               │
│ [引数2のinspect結果]\n               │
│ ...                                 │
└─────────────────────────────────────┘
```

出力例:
```
"hello"
42
[1, 2, 3]
nil
```

### ヘッダー部

N/A (ヘッダーなし)

### 明細部

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 1 | inspect結果 | 引数オブジェクトのinspect変換結果 | mrb_inspect(mrb, obj) | 文字列そのまま + 改行 | 可変 |

### フッター部

N/A (フッターなし)

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| MRB_NO_STDIO未定義 | MRB_NO_STDIOが定義されている場合、出力は何も行わない(空実装) | Yes |
| HAVE_MRUBY_IO_GEM未定義 | IO gemが存在する場合はmrb_p_mの代わりにIO gem側の実装が使用される | No |

### ソート順

N/A (順次出力のためソート不要)

### 改ページ条件

N/A (標準出力のため改ページなし)

## データベース参照仕様

### 参照テーブル一覧

N/A (データベースを参照しない)

### テーブル別参照項目詳細

N/A

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| inspect結果 | mrb_inspect(mrb, obj) | N/A | オブジェクトの人間可読な内部表現を生成 |
| メモリ不足判定 | mrb_type(obj) == MRB_TT_EXCEPTION && mrb_obj_ptr(obj) == mrb->nomem_err | N/A | OOM例外時は固定文字列"Out of memory"を出力 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[p メソッド呼び出し] --> B{HAVE_MRUBY_IO_GEM?}
    B -->|未定義| C[mrb_p_m - src/kernel.c]
    B -->|定義済| D[IO gem側の実装]
    C --> E{引数の数は?}
    E -->|0個| F[nil を返す]
    E -->|1個以上| G[各引数に対して mrb_p を呼び出し]
    G --> H[mrb_p - src/print.c]
    H --> I{OOM例外オブジェクト?}
    I -->|Yes| J[固定文字列 Out of memory を出力]
    I -->|No| K[mrb_inspect で inspect 文字列生成]
    K --> L[printstrln で改行付き出力]
    J --> M{tty接続?}
    L --> M
    M -->|Yes| N[fflush stdout]
    M -->|No| O[終了]
    N --> O
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| MRB_NO_STDIO | MRB_NO_STDIOマクロが定義されている場合 | (出力なし - 空実装) | ビルド設定を変更 |
| メモリ不足 | 引数がnomem_err例外オブジェクトの場合 | "Out of memory\n" | 固定文字列で対応、inspectは呼ばない |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | 制限なし(引数の個数に制限なし) |
| 目標出力時間 | 即時(inspectの計算時間に依存) |
| 同時出力数上限 | N/A (シングルスレッド実行) |

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

- inspectはオブジェクトの内部状態を詳細に表示するため、本番環境での使用には注意が必要
- 標準出力への出力であるため、出力内容にアクセス制御は適用されない

## 備考

- pメソッドの戻り値は、引数が1個の場合はその引数自体、複数の場合は引数の配列、0個の場合はnil
- mrb_p関数はMRB_APIとして公開されており、C言語からも呼び出し可能
- OOM(Out of Memory)例外オブジェクトの場合、inspectの呼び出しが更なるメモリ確保を引き起こす可能性があるため、固定文字列を使用する特別処理が実装されている

---

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

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

### 推奨読解順序

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

inspect処理で使用されるmrb_value型とその型判定メカニズムを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | mruby.h | `include/mruby.h` | mrb_value型、mrb_type()マクロ、MRB_TT_EXCEPTION |
| 1-2 | string.h | `include/mruby/string.h` | RSTRING_PTR/RSTRING_LENによる文字列アクセス |

**読解のコツ**: mrb_type()で型判別し、MRB_TT_EXCEPTIONの場合はOOMチェックが入る点に注意。

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

Kernel#pのRuby側エントリーポイントからC実装への対応を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | kernel.c | `src/kernel.c` | mrb_p_m関数(行652-665) - pメソッドのRubyインターフェース |
| 2-2 | kernel.c | `src/kernel.c` | メソッド登録(行697-698) - HAVE_MRUBY_IO_GEM未定義時のみ登録 |

**主要処理フロー**:
1. **行658 (kernel.c)**: mrb_get_argsで可変長引数を取得
2. **行659 (kernel.c)**: 引数0個ならnil返却
3. **行660-661 (kernel.c)**: 各引数に対してmrb_p()を呼び出し
4. **行663-664 (kernel.c)**: 戻り値を引数数に応じて返却(1個:そのまま, 複数:配列)

#### Step 3: mrb_p関数の実装を理解する

実際の出力処理を行うmrb_p関数のロジックを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | print.c | `src/print.c` | mrb_p関数(行84-95) - inspectと出力の実行 |
| 3-2 | print.c | `src/print.c` | printstrln関数(行54-59) - 改行付き出力 |
| 3-3 | print.c | `src/print.c` | printcstr関数(行26-43) - プラットフォーム依存の出力 |

**主要処理フロー**:
- **行87-90 (print.c)**: OOM例外チェック - nomem_errと一致する場合は"Out of memory"を出力
- **行92 (print.c)**: mrb_inspect()でinspect文字列を生成し、printstrln()で改行付き出力
- **行94 (print.c)**: tty接続時はfflush(stdout)を実行

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

```
Kernel#p (Ruby側)
    |
    +-- mrb_p_m (src/kernel.c:652)
           |
           +-- mrb_p (src/print.c:84)   ※MRB_API公開関数
                  |
                  +-- [OOM例外時] printcstr("Out of memory\n")
                  |
                  +-- [通常時] mrb_inspect(mrb, obj)
                  |              |
                  |              +-- 各型のinspectメソッド呼び出し
                  |
                  +-- printstrln (src/print.c:54)
                         |
                         +-- printstr (src/print.c:46)
                         |      +-- printcstr (src/print.c:26)
                         |             +-- [Win tty] WriteConsoleW
                         |             +-- [Other] fwrite
                         |
                         +-- printcstr("\n")
```

### データフロー図

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

Ruby引数         mrb_inspect()              printstrln()
(mrb_value) ───> (inspect変換) ───> (改行付加) ───> stdout
                      |
                      +── [OOM例外] 固定文字列出力
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| print.c | `src/print.c` | ソース | mrb_p関数(MRB_API)、printstrln/printstr/printcstr |
| kernel.c | `src/kernel.c` | ソース | mrb_p_m関数(Kernel#pのRubyインターフェース)、メソッド登録 |
| mruby.h | `include/mruby.h` | ヘッダ | mrb_value型、mrb_type()マクロ、MRB_TT_EXCEPTION定義 |
| string.h | `include/mruby/string.h` | ヘッダ | RSTRING_PTR/RSTRING_LENマクロ |
| error.h | `include/mruby/error.h` | ヘッダ | エラー関連定義(nomem_err) |
