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

## はじめに

このガイドラインは、mrubyのコードベースを効率的に理解するための手引きです。
C言語およびRuby言語に精通していないエンジニアでも、段階的に学習できるよう構成されています。

mrubyは、Ruby言語の軽量実装であり、ISO 30170に準拠した組み込みシステム向けのRuby処理系です。C言語で実装されたVM(仮想マシン)コアと、Rubyで書かれた標準ライブラリを組み合わせたハイブリッド構造を持ちます。バージョンは3.4.0です。

**対象読者:**
- プロジェクトに新規参画するエンジニア
- 他言語からの経験者
- コードレビューを行う担当者

---

## 1. 言語基礎

> このセクションでは、mrubyで使用されるC言語とRuby言語の基本構文と概念を解説します。

### 1.1 プログラム構造

mrubyのコアはC言語で記述されています。各Cソースファイルは以下の構造を持ちます。

1. ライセンスコメント
2. `#include` によるヘッダファイルの読み込み
3. 内部関数（`static`）の定義
4. 公開API関数（`MRB_API`マクロ付き）の定義

```c
// ファイル: src/state.c:1-16
/*
** state.c - mrb_state open/close functions
**
** See Copyright Notice in mruby.h
*/

#include <stdlib.h>
#include <string.h>
#include <mruby.h>
#include <mruby/irep.h>
#include <mruby/variable.h>
#include <mruby/debug.h>
#include <mruby/string.h>
#include <mruby/class.h>
#include <mruby/internal.h>
```

Rubyソースファイル（`mrblib/`配下）は、ISO規格番号をコメントで参照しながらクラスやモジュールを定義します。

```ruby
# ファイル: mrblib/array.rb:1-5
##
# Array
#
# ISO 15.2.12
class Array
```

### 1.2 データ型と変数

mrubyはC言語とRuby言語の二層構造でデータ型を管理します。

**C言語側の主要な型:**

| 型名 | 定義場所 | 説明 |
|------|---------|------|
| `mrb_value` | `include/mruby/boxing_word.h:110-112` | Rubyオブジェクトの値表現（ワードサイズ） |
| `mrb_int` | `include/mruby/value.h:78-79` | mruby整数型（int64_t or int32_t） |
| `mrb_float` | `include/mruby/value.h` | mruby浮動小数点型 |
| `mrb_sym` | `include/mruby/value.h:23` | シンボル型（uint32_t） |
| `mrb_bool` | `include/mruby/value.h:35-46` | 真偽値型 |
| `mrb_state` | `include/mruby.h:263-340` | VM全体の状態 |

**値のボクシング（Word Boxing）:**

`mrb_value` はポインタサイズのワード1つでRubyの全ての値を表現します（`include/mruby/boxing_word.h:83-109`）。

```c
// ファイル: include/mruby/boxing_word.h:110-112
typedef struct mrb_value {
  uintptr_t w;
} mrb_value;
```

ビットパターンによる型判別:
```
nil   : ...0000 0000 (全ビット0)
false : ...0000 0100
true  : ...0000 1100
fixnum: ...IIII III1 (最下位ビット=1)
symbol: 上位ビットにシンボル値を格納
object: ...PPPP P000 (下位3ビット=000、ポインタ)
float : ...FFFF FF10 (ローテーション符号化)
```

**オブジェクトヘッダ:**

全てのRubyオブジェクトは共通ヘッダ `MRB_OBJECT_HEADER` を持ちます（`include/mruby/object.h:10-15`）。

```c
// ファイル: include/mruby/object.h:10-15
#define MRB_OBJECT_HEADER \
  struct RClass *c;       \
  enum mrb_vtype tt:8;    \
  unsigned int gc_color:3; \
  unsigned int frozen:1;  \
  uint32_t flags:20
```

### 1.3 制御構造

**C言語側の制御構造:**

VMのメインループ（`src/vm.c`）では巨大な `switch` 文でオペコードをディスパッチします。条件分岐やループは標準的なC言語構文です。

```c
// ファイル: src/class.c:62-69 (メソッドテーブルの線形探索)
/* Linear scan for existing key */
for (int i = 0; i < t->size; i++) {
  if (entries[i].key == sym) {
    entries[i].flags = flags;
    entries[i].val = ptrval;
    return;
  }
}
```

**Ruby側の制御構造:**

mrubyのコアライブラリでは `while` ループが多用されます（パフォーマンス上の理由で `each` の再帰呼び出しを避ける）。

```ruby
# ファイル: mrblib/array.rb:15-24
def each(&block)
  return to_enum(:each) unless block

  idx = 0
  while idx < length
    yield self[idx]
    idx += 1
  end
  self
end
```

### 1.4 関数/メソッド定義

**C言語側の関数定義パターン:**

公開API関数には `MRB_API` マクロが付与されます。第1引数は常に `mrb_state*` です。

```c
// ファイル: src/vm.c:584-601
MRB_API mrb_value
mrb_funcall(mrb_state *mrb, mrb_value self, const char *name, mrb_int argc, ...)
{
  mrb_value argv[MRB_FUNCALL_ARGC_MAX];
  mrb_sym mid = mrb_intern_cstr(mrb, name);

  if (argc > MRB_FUNCALL_ARGC_MAX) {
    mrb_raise(mrb, E_ARGUMENT_ERROR, "Too long arguments. (limit=" MRB_STRINGIZE(MRB_FUNCALL_ARGC_MAX) ")");
  }

  va_list ap;
  va_start(ap, argc);
  for (mrb_int i = 0; i < argc; i++) {
    argv[i] = va_arg(ap, mrb_value);
  }
  va_end(ap);
  return mrb_funcall_argv(mrb, self, mid, argc, argv);
}
```

内部関数は `static` キーワードで宣言されます。

```c
// ファイル: src/class.c:42-54
static mrb_mt_tbl*
mt_new(mrb_state *mrb)
{
  mrb_mt_tbl *t;

  t = (mrb_mt_tbl*)mrb_malloc(mrb, sizeof(mrb_mt_tbl));
  t->size = 0;
  t->alloc = 0;
  t->ptr = NULL;
  t->next = NULL;

  return t;
}
```

**Ruby側のメソッド定義:**

標準ライブラリのメソッドはISO規格番号をコメントで参照します。

```ruby
# ファイル: mrblib/hash.rb:54-66
# ISO 15.2.13.4.9
def each(&block)
  return to_enum(:each) unless block

  keys = self.keys
  vals = self.values
  len = self.size
  i = 0
  while i < len
    block.call([keys[i], vals[i]])
    i += 1
  end
  self
end
```

### 1.5 モジュール/インポート

**C言語のインクルード体系:**

mrubyのヘッダファイルは `include/mruby/` 配下に整理されています。メインヘッダは `mruby.h` で、サブシステムごとに個別ヘッダが存在します。

```c
// ファイル: src/vm.c:7-23
#include <mruby.h>           // メインヘッダ（mrb_state, mrb_value等）
#include <mruby/array.h>     // 配列操作
#include <mruby/class.h>     // クラス操作
#include <mruby/hash.h>      // ハッシュ操作
#include <mruby/irep.h>      // コンパイル済みバイトコード
#include <mruby/proc.h>      // Procオブジェクト
#include <mruby/string.h>    // 文字列操作
#include <mruby/opcode.h>    // VMオペコード定義
#include <mruby/internal.h>  // 内部API
#include <mruby/presym.h>    // プリセットシンボル
```

**Rubyのモジュール包含:**

```ruby
# ファイル: mrblib/array.rb:99-101
# Array is enumerable
# ISO 15.2.12.3
include Enumerable
```

```ruby
# ファイル: mrblib/numeric.rb:5-6
class Numeric
  include Comparable
```

---

## 2. プロジェクト固有の概念

> このセクションでは、mruby特有の概念を解説します。

### 2.1 フレームワーク固有の概念

#### mrb_state: VM全体の状態管理

`mrb_state` は mruby VM のグローバルな状態を保持する中心的な構造体です（`include/mruby.h:263-340`）。

```c
// ファイル: include/mruby.h:263-340（抜粋）
typedef struct mrb_state {
  struct mrb_jmpbuf *jmp;
  struct mrb_context *c;              // 現在の実行コンテキスト
  struct mrb_context *root_c;         // ルートコンテキスト
  struct iv_tbl *globals;             // グローバル変数テーブル
  struct RObject *exc;                // 例外オブジェクト
  struct RObject *top_self;
  struct RClass *object_class;        // Objectクラス
  struct RClass *class_class;
  // ... 各組み込みクラスへのポインタ
  mrb_gc gc;                          // GC状態
  mrb_bool bootstrapping;
  mrb_sym symidx;                     // シンボルインデックス
  const char **symtbl;                // シンボルテーブル
  void *ud;                           // ユーザデータ
} mrb_state;
```

#### mrb_context: 実行コンテキスト

Fiberやタスクの実行コンテキストを表現します（`include/mruby.h:196-207`）。

```c
// ファイル: include/mruby.h:196-207
struct mrb_context {
  struct mrb_context *prev;
  mrb_value *stbase, *stend;         // VMスタック
  mrb_callinfo *ci;                   // 現在のコールフレーム
  mrb_callinfo *cibase, *ciend;       // コールフレーム配列
  enum mrb_fiber_state status : 4;
  mrb_bool vmexec : 1;
  struct RFiber *fib;
};
```

#### mrb_callinfo: メソッド呼び出し情報

各メソッド呼び出しの情報を保持する構造体です（`include/mruby.h:165-181`）。

```c
// ファイル: include/mruby.h:165-181
typedef struct {
  uint8_t n:4;                  // 引数の数(15=可変長)
  uint8_t nk:4;                 // キーワード引数の数
  uint8_t cci;                  // Cから呼ばれたか
  uint8_t vis;                  // メソッドの可視性
  mrb_sym mid;                  // メソッドID
  const struct RProc *proc;     // 実行するProc
  struct RProc *blk;            // ブロック引数
  mrb_value *stack;             // このフレームのスタック
  const mrb_code *pc;           // プログラムカウンタ
  union {
    struct REnv *env;
    struct RClass *target_class;
  } u;
} mrb_callinfo;
```

#### mrb_irep: コンパイル済みバイトコード表現

Rubyコードをコンパイルした結果の中間表現です（`include/mruby/irep.h:55-80`）。

```c
// ファイル: include/mruby/irep.h:55-80
struct mrb_irep {
  uint16_t nlocals;    // ローカル変数の数
  uint16_t nregs;      // レジスタ変数の数
  uint16_t clen;       // キャッチハンドラ数
  uint8_t flags;

  const mrb_code *iseq;         // 命令列
  const mrb_irep_pool *pool;    // 定数プール
  const mrb_sym *syms;          // シンボルテーブル
  const struct mrb_irep *const *reps;  // 子irep（ブロック等）

  const mrb_sym *lv;            // ローカル変数名
  struct mrb_irep_debug_info *debug_info;

  uint32_t ilen;                // 命令数
  uint16_t plen, slen;          // プール・シンボル数
  uint16_t rlen;                // 子irep数
  uint16_t refcnt;              // 参照カウント
};
```

#### レジスタベースVM

mrubyはレジスタベースのVMを採用しています。8ビットの命令セットで最大256命令をサポートし、現在106命令が定義されています（`include/mruby/ops.h`）。

```c
// ファイル: include/mruby/ops.h:15-16（オペコード定義例）
OPCODE(NOP,        Z)        /* no operation */
OPCODE(MOVE,       BB)       /* R[a] = R[b] */
OPCODE(LOADL,      BB)       /* R[a] = Pool[b] */
OPCODE(LOADI8,     BB)       /* R[a] = mrb_int(b) */
```

オペランド型:
- `Z`: オペランドなし
- `B`: 8ビット
- `BB`: 8+8ビット
- `BBB`: 8+8+8ビット
- `BS`: 8+16ビット
- `S`: 16ビット
- `W`: 24ビット

#### 三色マーク&スウィープGC

mrubyは三色（白・灰・黒）のインクリメンタル+世代別GCを実装しています（`src/gc.c:36-60`）。

```c
// ファイル: src/gc.c:36-60（コメント抜粋）
/*
  = Tri-color Incremental Garbage Collection

  Each object can be painted in three colors:
    * White - Unmarked.
    * Gray - Marked, But the child objects are unmarked.
    * Black - Marked, the child objects are also marked.

  Extra color:
    * Red - Static (ROM object) no need to be collected.
*/
```

GC状態の構造体（`include/mruby/gc.h:41-69`）:

```c
// ファイル: include/mruby/gc.h:41-69
typedef struct mrb_gc {
  struct mrb_heap_page *heaps;        // 全ヒープページ
  struct mrb_heap_page *free_heaps;   // 割り当て用ヒープ
  struct mrb_heap_page *sweeps;       // スウィープ開始ページ
  struct RBasic *gray_stack[MRB_GRAY_STACK_SIZE]; // 灰色オブジェクトスタック
  size_t live;                        // 生存オブジェクト数
  size_t threshold;                   // GC開始閾値
  mrb_gc_state state;                 // 現在のGC状態
  mrb_bool generational  :1;          // 世代別GCモード
  mrb_bool full          :1;          // メジャーGCモード
  // ...
} mrb_gc;
```

### 2.2 プロジェクト独自のパターン

#### mrbgemsによる拡張パッケージ管理

mrubyは独自のgem管理システム `mrbgems` を持ちます。各gemは `mrbgem.rake` ファイルで仕様を定義します。

```ruby
# ファイル: mrbgems/mruby-array-ext/mrbgem.rake:1-5
MRuby::Gem::Specification.new('mruby-array-ext') do |spec|
  spec.license = 'MIT'
  spec.author  = 'mruby developers'
  spec.summary = 'Array class extension'
end
```

#### ビルドシステム（Rake DSL）

ビルド設定は Ruby DSL で記述し、`build_config/` 配下に配置します。

```ruby
# ファイル: build_config/default.rb:1-3,17,81-83
MRuby::Build.new do |conf|
  conf.toolchain
  conf.gembox 'default'
  conf.enable_bintest
  conf.enable_test
end
```

#### シンボル3段階検索

シンボルの検索は3段階で行われ、高速化されています（`src/symbol.c:242-264`）。

```c
// ファイル: src/symbol.c:242-264
static mrb_sym
find_symbol(mrb_state *mrb, const char *name, size_t len, uint8_t *hashp)
{
  mrb_sym i;

  /* 1. プリセットシンボル検索 */
  i = presym_find(name, len);
  if (i > 0) return i;

  /* 2. インラインシンボル検索 */
  i = sym_inline_pack(name, len);
  if (i > 0) return i;

  if (using_hash_table(mrb)) {
    /* 3a. ハッシュテーブルモード - O(1)平均 */
    return find_symbol_hash(mrb, name, len, hashp);
  }
  else {
    /* 3b. 線形モード - O(n)だが小さいnでは高速 */
    if (hashp) *hashp = mrb_byte_hash((const uint8_t*)name, len);
    return find_symbol_linear(mrb, name, len);
  }
}
```

#### ISO規格参照パターン

コアライブラリの各メソッドにはISO 30170の節番号がコメントされています。

```ruby
# ファイル: mrblib/hash.rb:25-31
# ISO 15.2.13.4.8
def delete(key, &block)
  if block && !self.has_key?(key)
    return block.call(key)
  end
  self.__delete(key)
end
```

#### HAL（Hardware Abstraction Layer）

プラットフォーム固有のI/O操作はHAL層で抽象化されています。

- POSIX: `mrbgems/mruby-io/src/hal-posix-io.c`, `mrbgems/mruby-dir/src/hal-posix-dir.c`
- Windows: `mrbgems/mruby-io/src/hal-win-io.c`, `mrbgems/mruby-dir/src/hal-win-dir.c`

---

## 3. 命名規則

> このセクションでは、プロジェクト全体で使用される命名規則を解説します。

### 3.1 ファイル・ディレクトリ命名

| パターン | 意味 | 例 |
|---------|------|-----|
| `src/*.c` | Cコアソースファイル | `src/vm.c`, `src/gc.c`, `src/class.c` |
| `include/mruby/*.h` | 公開ヘッダファイル | `include/mruby/array.h`, `include/mruby/class.h` |
| `mrblib/*.rb` | Rubyコアライブラリ | `mrblib/array.rb`, `mrblib/hash.rb` |
| `mrbgems/mruby-*` | gem拡張パッケージ | `mrbgems/mruby-array-ext`, `mrbgems/mruby-math` |
| `test/t/*.rb` | テストスクリプト | `test/t/array.rb`, `test/t/hash.rb` |
| `tasks/*.rake` | ビルドタスク | `tasks/core.rake`, `tasks/mrblib.rake` |
| `build_config/*.rb` | ビルド設定 | `build_config/default.rb` |
| `*_word.h`, `*_nan.h`, `*_no.h` | ボクシング方式別ヘッダ | `boxing_word.h`, `boxing_nan.h` |
| `hal-*-*.c` | HAL実装ファイル | `hal-posix-io.c`, `hal-win-dir.c` |

### 3.2 クラス・関数・変数命名

| プレフィックス/サフィックス | 意味 | 例 |
|---------------------------|------|-----|
| `mrb_` | 公開API関数 | `mrb_open()`, `mrb_funcall()` |
| `MRB_API` | 公開API関数マーカー | `MRB_API mrb_state* mrb_open(void)` |
| `MRB_` | グローバルマクロ | `MRB_TT_STRING`, `MRB_ARGS_REQ()` |
| `MRB_TT_` | 型タグ定数 | `MRB_TT_STRING`, `MRB_TT_ARRAY` |
| `MRB_ARGS_` | 引数仕様マクロ | `MRB_ARGS_REQ(2)`, `MRB_ARGS_OPT(1)` |
| `struct R*` | Rubyオブジェクト構造体 | `RClass`, `RProc`, `RArray`, `RString` |
| `mrb_obj_` | オブジェクト操作関数 | `mrb_obj_ptr()`, `mrb_obj_value()` |
| `mrb_class_` | クラス操作関数 | `mrb_class_ptr()`, `mrb_class()` |
| `mrb_str_` | 文字列操作関数 | `mrb_str_new()`, `mrb_str_intern()` |
| `mrb_ary_` | 配列操作関数 | `mrb_ary_new()`, `mrb_ary_push()` |
| `mrb_hash_` | ハッシュ操作関数 | `mrb_hash_new()`, `mrb_hash_set()` |
| `mrb_gc_` | GC関連関数 | `mrb_gc_init()`, `mrb_gc_arena_save()` |
| `mrb_vm_` | VM関連関数 | `mrb_vm_run()`, `mrb_vm_exec()` |
| `_p` | 述語関数（boolを返す） | `mrb_object_dead_p()`, `mrb_frozen_p()` |
| `*_tbl` | テーブル構造体 | `iv_tbl`（インスタンス変数）, `mrb_mt_tbl`（メソッド） |
| `mt_` | メソッドテーブル操作（内部） | `mt_new()`, `mt_put()`, `mt_get()` |
| `OP_` | VMオペコード | `OP_MOVE`, `OP_SEND`, `OP_RETURN` |
| `RSTRING_`, `RARRAY_` | オブジェクトアクセスマクロ | `RSTRING_EMBED_LEN_MAX`, `RARRAY()` |
| `E_*_ERROR` | エラークラスマクロ | `E_ARGUMENT_ERROR`, `E_RUNTIME_ERROR` |
| `SET_*_VALUE` | 値設定マクロ | `SET_NIL_VALUE()`, `SET_INT_VALUE()` |

### 3.3 プログラム分類一覧

| 分類 | ディレクトリ | 説明 |
|-----|-------------|------|
| VMコア | `src/vm.c` | バイトコードインタプリタ |
| メモリ管理 | `src/gc.c` | ガベージコレクタ |
| オブジェクトシステム | `src/class.c`, `src/object.c` | クラス・オブジェクト管理 |
| コンパイラ | `mrbgems/mruby-compiler/` | Rubyソース→バイトコード |
| パーサ | `mrbgems/mruby-compiler/core/parse.y` | 構文解析 |
| 標準型 | `src/string.c`, `src/array.c`, `src/hash.c` | 組み込み型のC実装 |
| シンボル管理 | `src/symbol.c` | シンボルテーブル |
| 状態管理 | `src/state.c` | mrb_stateの初期化・終了 |
| Rubyコアライブラリ | `mrblib/*.rb` | Rubyで書かれた標準メソッド |
| 拡張gem | `mrbgems/mruby-*` | オプション機能の拡張 |
| ツール | `mrbgems/mruby-bin-*` | コマンドラインツール |
| ビルドシステム | `lib/`, `tasks/` | Rakeベースビルド |

---

## 4. ディレクトリ構造

> このセクションでは、プロジェクトのディレクトリ構造を解説します。

```
mruby/
├── src/                  C言語コアソース (34ファイル, ~32,000行)
│   ├── vm.c              バイトコードインタプリタ（VMメインループ）
│   ├── gc.c              三色マーク&スウィープGC
│   ├── class.c           クラス・メソッドテーブル管理
│   ├── state.c           mrb_state初期化・終了
│   ├── symbol.c          シンボルテーブル管理
│   ├── string.c          文字列操作
│   ├── array.c           配列操作
│   ├── hash.c            ハッシュ操作
│   ├── object.c          オブジェクト共通操作
│   ├── numeric.c         数値操作
│   ├── range.c           Rangeオブジェクト
│   ├── proc.c            Proc/Lambda操作
│   ├── error.c           例外・エラー処理
│   ├── variable.c        変数（グローバル、インスタンス等）
│   ├── kernel.c          Kernelモジュール
│   ├── codedump.c        バイトコードダンプ
│   └── ...
├── include/              Cヘッダファイル
│   ├── mruby.h           メインヘッダ (mrb_state, mrb_value等)
│   └── mruby/
│       ├── value.h       値の型定義
│       ├── boxing_word.h Word Boxing実装
│       ├── gc.h          GCヘッダ
│       ├── irep.h        Irep構造体
│       ├── class.h       RClass定義
│       ├── proc.h        RProc/REnv定義
│       ├── opcode.h      VMオペコード
│       ├── ops.h         オペコード定義テーブル
│       ├── object.h      MRB_OBJECT_HEADER
│       ├── string.h      RString定義
│       ├── array.h       RArray定義
│       ├── hash.h        RHash定義
│       ├── compile.h     コンパイラインターフェース
│       ├── internal.h    内部API
│       └── ...
├── mrblib/               Rubyコアライブラリ (10ファイル, ~1,345行)
│   ├── array.rb          Array拡張メソッド
│   ├── hash.rb           Hash拡張メソッド
│   ├── enum.rb           Enumerableモジュール
│   ├── numeric.rb        Numeric拡張メソッド
│   ├── string.rb         String拡張メソッド
│   ├── range.rb          Range拡張メソッド
│   └── ...
├── mrbgems/              gem拡張パッケージ (57個のgem)
│   ├── mruby-compiler/   コンパイラgem
│   ├── mruby-bin-mruby/  mruby実行バイナリ
│   ├── mruby-bin-mirb/   mirb (REPL)バイナリ
│   ├── mruby-bin-mrbc/   mrbcコンパイラバイナリ
│   ├── mruby-array-ext/  Array拡張
│   ├── mruby-hash-ext/   Hash拡張
│   ├── mruby-string-ext/ String拡張
│   ├── mruby-math/       Mathモジュール
│   ├── mruby-io/         IO操作
│   ├── mruby-socket/     ソケット
│   └── ...
├── lib/                  ビルドシステム (Rake DSL)
│   └── mruby/
│       ├── build.rb      MRuby::Buildクラス
│       └── ...
├── tasks/                Rakeビルドタスク
│   ├── core.rake         コアコンパイル
│   ├── mrblib.rake       mrblibコンパイル
│   ├── mrbgems.rake      gem統合
│   ├── libmruby.rake     ライブラリ生成
│   ├── bin.rake          バイナリ生成
│   ├── presym.rake       プリセットシンボル
│   └── test.rake         テスト実行
├── build_config/         ビルド設定ファイル
│   ├── default.rb        デフォルトビルド設定
│   └── ...
├── test/                 テストスクリプト (43ファイル)
│   └── t/
│       ├── array.rb      Array ISOテスト
│       ├── hash.rb       Hash ISOテスト
│       └── ...
├── doc/                  ドキュメント
├── examples/             サンプルコード
├── benchmark/            ベンチマーク
├── tools/                外部ツール (lrama パーサ生成)
├── oss-fuzz/             ファジングテスト
├── Rakefile              メインビルドファイル
└── mruby.gembox          gem構成定義
```

### 各ディレクトリの役割

| ディレクトリ | 役割 | 主要ファイル |
|-------------|------|-------------|
| `src/` | VMコア、GC、型実装などのC言語ソース | `vm.c`, `gc.c`, `class.c`, `state.c` |
| `include/` | 公開ヘッダファイル（API定義） | `mruby.h`, `mruby/value.h`, `mruby/gc.h` |
| `mrblib/` | Rubyで書かれたコアライブラリ | `array.rb`, `hash.rb`, `enum.rb` |
| `mrbgems/` | 拡張パッケージ（コンパイラ、ツール、標準拡張含む） | `mruby-compiler/`, `mruby-bin-mruby/` |
| `lib/` | ビルドシステムのRubyコード | `mruby/build.rb` |
| `tasks/` | Rakeタスク定義 | `core.rake`, `mrblib.rake` |
| `build_config/` | ターゲットごとのビルド設定 | `default.rb` |
| `test/` | ISOテスト・機能テスト | `test/t/array.rb` |
| `tools/` | パーサ生成ツール（lrama） | `tools/lrama/` |

---

## 5. アーキテクチャ

> このセクションでは、mrubyのアーキテクチャパターンを解説します。

### 5.1 全体アーキテクチャ

mrubyはレイヤードアーキテクチャを採用しています。Rubyソースコードをコンパイラでバイトコード（irep）に変換し、レジスタベースVMで実行する構造です。

```
+-------------------------------------------------------------------+
|                       Ruby Source Code                             |
+-------------------------------------------------------------------+
                              |
                     [mruby-compiler gem]
                              |
                    パーサ (parse.y / lrama)
                              |
                    コード生成 (codegen.c)
                              |
                              v
+-------------------------------------------------------------------+
|                    mrb_irep (バイトコード)                          |
|    iseq (命令列) + pool (定数) + syms (シンボル) + reps (子irep)    |
+-------------------------------------------------------------------+
                              |
                              v
+-------------------------------------------------------------------+
|                    VM Layer (src/vm.c)                              |
|    レジスタベースVM  |  コールスタック  |  例外処理                   |
+-------------------------------------------------------------------+
          |                   |                    |
          v                   v                    v
+------------------+  +------------------+  +------------------+
| Object System    |  | Memory Mgmt      |  | Symbol Table     |
| src/class.c      |  | src/gc.c         |  | src/symbol.c     |
| src/object.c     |  | (Tri-color M&S)  |  | (3-stage lookup) |
+------------------+  +------------------+  +------------------+
          |
          v
+-------------------------------------------------------------------+
|              Built-in Types (src/)                                  |
|  string.c | array.c | hash.c | numeric.c | range.c | proc.c       |
+-------------------------------------------------------------------+
          |
          v
+-------------------------------------------------------------------+
|              Ruby Core Library (mrblib/)                            |
|  array.rb | hash.rb | enum.rb | numeric.rb | string.rb            |
+-------------------------------------------------------------------+
          |
          v
+-------------------------------------------------------------------+
|              mrbgems Extension Layer                                |
|  mruby-array-ext | mruby-math | mruby-io | mruby-socket | ...    |
+-------------------------------------------------------------------+
          |
          v
+-------------------------------------------------------------------+
|              HAL (Hardware Abstraction Layer)                       |
|  hal-posix-io | hal-posix-dir | hal-win-io | hal-win-dir | ...    |
+-------------------------------------------------------------------+
```

### 5.2 レイヤー構成

| レイヤー | 責務 | 代表的なファイル |
|---------|------|-----------------|
| コンパイラ層 | RubyソースをIrepにコンパイル | `mrbgems/mruby-compiler/core/parse.y`, `codegen.c` |
| VM層 | バイトコードの実行制御 | `src/vm.c` |
| オブジェクトシステム層 | クラス・メソッドテーブル管理 | `src/class.c`, `src/object.c` |
| メモリ管理層 | ヒープ管理・GC | `src/gc.c` |
| 組み込み型層 | String, Array, Hash等のC実装 | `src/string.c`, `src/array.c`, `src/hash.c` |
| コアライブラリ層 | Rubyで書かれた標準メソッド | `mrblib/array.rb`, `mrblib/hash.rb` |
| 拡張層 | gemによるオプション機能 | `mrbgems/mruby-*` |
| HAL層 | プラットフォーム抽象化 | `mrbgems/mruby-io/src/hal-posix-io.c` |

### 5.3 データフロー

**コンパイル時のデータフロー:**
```
Ruby Source (.rb)
  → パーサ (parse.y) → AST (mrb_ast_node)
  → コード生成 (codegen.c) → mrb_irep
  → シリアライズ (dump.c) → .mrb バイナリ (オプション)
```

**実行時のデータフロー:**
```
mrb_irep.iseq (命令列)
  → mrb_vm_exec() がオペコードをフェッチ
  → オペコードハンドラが処理実行
  → レジスタ (ci->stack) に結果を書き込み
  → OP_SEND でメソッド呼び出し → メソッドテーブル検索 (mt_get)
  → 新しいcallinfoをプッシュ → 対象メソッドのirepを実行
  → OP_RETURN でcallinfoをポップ → 呼び出し元に復帰
```

**GCのデータフロー:**
```
オブジェクト割り当て (mrb_obj_alloc)
  → フリーリストから取得 → なければadd_heap()
  → live数がthresholdを超えたらGC開始
  → マークフェーズ: ルート→灰→黒（インクリメンタル）
  → スウィープフェーズ: 白オブジェクトを解放
```

---

## 6. 主要コンポーネント

> このセクションでは、主要なコンポーネントとその連携を解説します。

### 6.1 エントリーポイント

**mrubyコマンド（main関数）:**

```c
// ファイル: mrbgems/mruby-bin-mruby/tools/mruby/mruby.c:276-307
int
main(int argc, char **argv)
{
  mrb_state *mrb = mrb_open();       // VM初期化
  int n = -1;
  struct _args args;
  mrb_value ARGV;
  mrb_value v;

  if (MRB_OPEN_FAILURE(mrb)) {
    mrb_print_error(mrb);
    mrb_close(mrb);
    return EXIT_FAILURE;
  }

  n = parse_args(mrb, argc, argv, &args);   // コマンドライン引数解析
  // ... ARGV定数の設定、コンパイル・実行 ...
}
```

**VM初期化 (mrb_open):**

```c
// ファイル: src/state.c:72-90
MRB_API mrb_state*
mrb_open(void)
{
  mrb_state *mrb = mrb_open_core();   // コア初期化

  if (mrb == NULL || mrb->exc) {
    return mrb;
  }

#ifndef MRB_NO_GEMS
  if (mrb_core_init_protect(mrb, init_mrbgems, NULL)) {
    return mrb;                        // gem初期化失敗
  }
  mrb_gc_arena_restore(mrb, 0);
#endif
  return mrb;
}
```

**コア初期化 (mrb_open_core):**

```c
// ファイル: src/state.c:39-61
MRB_API mrb_state*
mrb_open_core(void)
{
  static const mrb_state mrb_state_zero = { 0 };
  mrb_state *mrb;

  mrb = (mrb_state*)mrb_basic_alloc_func(NULL, sizeof(mrb_state));
  if (mrb == NULL) return NULL;

  *mrb = mrb_state_zero;              // ゼロ初期化
  mrb->atexit_stack_len = 0;
  mrb->bootstrapping = TRUE;

  if (mrb_core_init_protect(mrb, init_gc_and_core, NULL)) {
    return mrb;
  }

  mrb_method_cache_clear(mrb);
  mrb->bootstrapping = FALSE;

  return mrb;
}
```

**VMバイトコード実行開始 (mrb_vm_run):**

```c
// ファイル: src/vm.c:1586-1615
MRB_API mrb_value
mrb_vm_run(mrb_state *mrb, const struct RProc *proc, mrb_value self, mrb_int stack_keep)
{
  const mrb_irep *irep = proc->body.irep;
  struct mrb_context *c = mrb->c;
  mrb_int nregs = irep->nregs;

  if (!c->stbase) {
    stack_init(mrb);                   // スタック初期化
  }
  // ... スタック拡張 ...
  stack_extend(mrb, nregs);
  stack_clear(c->ci->stack + stack_keep, nregs - stack_keep);
  c->ci->stack[0] = self;
  mrb_value result = mrb_vm_exec(mrb, proc, irep->iseq);  // 実行
  return result;
}
```

### 6.2 ビジネスロジック（VM実行エンジン）

mrubyの「ビジネスロジック」に相当するのはVMの命令実行エンジンです。

**メソッド呼び出し（mrb_funcall）:**

```c
// ファイル: src/vm.c:584-601
MRB_API mrb_value
mrb_funcall(mrb_state *mrb, mrb_value self, const char *name, mrb_int argc, ...)
{
  mrb_value argv[MRB_FUNCALL_ARGC_MAX];
  mrb_sym mid = mrb_intern_cstr(mrb, name);   // 文字列→シンボル変換
  // ... 引数をva_listから配列に展開 ...
  return mrb_funcall_argv(mrb, self, mid, argc, argv);
}
```

**メソッドテーブル操作:**

メソッドの登録・検索はメソッドテーブル（`mrb_mt_tbl`）で管理されます。

```c
// ファイル: src/class.c:57-83 (mt_put: メソッド登録)
static void
mt_put(mrb_state *mrb, mrb_mt_tbl *t, mrb_sym sym, uint32_t flags, union mrb_mt_ptr ptrval)
{
  mrb_mt_entry *entries = t->ptr;

  /* 既存キーの線形探索 */
  for (int i = 0; i < t->size; i++) {
    if (entries[i].key == sym) {
      entries[i].flags = flags;
      entries[i].val = ptrval;
      return;
    }
  }

  /* 見つからなければ末尾に追加 */
  if (MT_ALLOC(t) == 0) {
    mt_grow(mrb, t, 8);               // 初期サイズ8
  }
  else if (t->size == MT_ALLOC(t)) {
    mt_grow(mrb, t, MT_ALLOC(t) * 2); // 倍増
  }
  entries = t->ptr;
  entries[t->size].key = sym;
  entries[t->size].flags = flags;
  entries[t->size].val = ptrval;
  t->size++;
}
```

```c
// ファイル: src/class.c:88-104 (mt_get: メソッド検索)
static mrb_bool
mt_get(mrb_state *mrb, mrb_mt_tbl *t, mrb_sym sym, union mrb_mt_ptr *pp, uint32_t *fp)
{
  while (t) {
    mrb_mt_entry *entries = t->ptr;
    for (int i = 0; i < t->size; i++) {
      if (entries[i].key == sym) {
        if (MRB_MT_REMOVED_P(entries[i])) return FALSE;
        *pp = entries[i].val;
        *fp = entries[i].flags;
        return TRUE;
      }
    }
    t = t->next;                      // チェーンを辿る
  }
  return FALSE;
}
```

### 6.3 データアクセス（メモリ管理・GC）

**ヒープページの追加（add_heap）:**

```c
// ファイル: src/gc.c:302-321
static void
add_heap(mrb_state *mrb, mrb_gc *gc)
{
  mrb_heap_page *page = (mrb_heap_page*)mrb_calloc(mrb, 1, sizeof(mrb_heap_page));
  RVALUE *p, *e;
  RVALUE *prev = NULL;

  for (p = page->objects, e=p+MRB_HEAP_PAGE_SIZE; p<e; p++) {
    p->as.free.tt = MRB_TT_FREE;     // フリーオブジェクトとしてマーク
    p->as.free.next = prev;           // フリーリスト構築
    prev = p;
  }
  page->freelist = prev;

  page->next = gc->heaps;
  gc->heaps = page;

  page->free_next = gc->free_heaps;
  gc->free_heaps = page;
}
```

**GC初期化（mrb_gc_init）:**

```c
// ファイル: src/gc.c:331-349
void
mrb_gc_init(mrb_state *mrb, mrb_gc *gc)
{
#ifndef MRB_GC_FIXED_ARENA
  gc->arena = (struct RBasic**)mrb_malloc(mrb, sizeof(struct RBasic*)*MRB_GC_ARENA_SIZE);
  gc->arena_capa = MRB_GC_ARENA_SIZE;
#endif

  gc->current_white_part = GC_WHITE_A;
  gc->heaps = NULL;
  gc->free_heaps = NULL;
  add_heap(mrb, gc);
  gc->interval_ratio = DEFAULT_GC_INTERVAL_RATIO;   // 200
  gc->step_ratio = DEFAULT_GC_STEP_RATIO;           // 200
#ifndef MRB_GC_TURN_OFF_GENERATIONAL
  gc->generational = TRUE;
  gc->full = TRUE;
#endif
}
```

### 6.4 ユーティリティ/共通機能

**値型判定マクロ群（boxing_word.h）:**

```c
// ファイル: include/mruby/boxing_word.h:171-207
#define mrb_fixnum_p(o) WORDBOX_SHIFT_VALUE_P(o, FIXNUM)
#define mrb_symbol_p(o) WORDBOX_SHIFT_VALUE_P(o, SYMBOL)
#define mrb_nil_p(o)    ((o).w == MRB_Qnil)
#define mrb_false_p(o)  ((o).w == MRB_Qfalse)
#define mrb_true_p(o)   ((o).w == MRB_Qtrue)
#define mrb_array_p(o)  WORDBOX_OBJ_TYPE_P(o, ARRAY)
#define mrb_string_p(o) WORDBOX_OBJ_TYPE_P(o, STRING)
#define mrb_hash_p(o)   WORDBOX_OBJ_TYPE_P(o, HASH)
```

**値設定マクロ群:**

```c
// ファイル: include/mruby/boxing_word.h:213-221
#define SET_NIL_VALUE(r)    ((r).w = MRB_Qnil)
#define SET_FALSE_VALUE(r)  ((r).w = MRB_Qfalse)
#define SET_TRUE_VALUE(r)   ((r).w = MRB_Qtrue)
#define SET_INT_VALUE(mrb,r,n) ((r) = mrb_boxing_int_value(mrb, n))
#define SET_OBJ_VALUE(r,v)  ((r).w = (uintptr_t)(v))
```

**MRB_OBJECT_HEADER（全オブジェクト共通ヘッダ）:**

```c
// ファイル: include/mruby/object.h:10-15
#define MRB_OBJECT_HEADER \
  struct RClass *c;        /* クラスポインタ */   \
  enum mrb_vtype tt:8;     /* 型タグ */          \
  unsigned int gc_color:3;  /* GCカラー */       \
  unsigned int frozen:1;    /* freeze済みフラグ */ \
  uint32_t flags:20         /* 各種フラグ */
```

**オペコードフェッチマクロ（opcode.h）:**

```c
// ファイル: include/mruby/opcode.h:26-41
#define PEEK_B(pc) (*(pc))
#define PEEK_S(pc) ((pc)[0]<<8|(pc)[1])
#define PEEK_W(pc) ((pc)[0]<<16|(pc)[1]<<8|(pc)[2])

#define READ_B() PEEK_B(pc++)
#define READ_S() (pc+=2, PEEK_S(pc-2))
#define READ_W() (pc+=3, PEEK_W(pc-3))

#define FETCH_B()   do {a=READ_B();} while (0)
#define FETCH_BB()  do {a=READ_B(); b=READ_B();} while (0)
#define FETCH_BBB() do {a=READ_B(); b=READ_B(); c=READ_B();} while (0)
```

---

## 7. よく使われるパターン

> このセクションでは、コード内で頻出するパターンを解説します。

### パターン一覧

| パターン | 説明 | 出現頻度 | 代表的なファイル |
|---------|------|---------|-----------------|
| mrb_state第一引数 | 全API関数にmrb_stateポインタを渡す | 高 | 全ソースファイル |
| GCアリーナ保存・復帰 | 一時オブジェクトのGC保護 | 高 | `src/state.c`, `mrbgems/*/tools/` |
| Xマクロによるオペコード定義 | ヘッダファイルをマクロで展開 | 中 | `include/mruby/ops.h`, `opcode.h` |
| 線形テーブル→ハッシュテーブル移行 | 小規模時は線形探索、大規模時にハッシュ化 | 中 | `src/symbol.c`, `src/class.c` |
| 埋め込み最適化（embed） | 小さなオブジェクトを構造体内に直接格納 | 中 | `string.h`, `array.h` |
| ISO規格番号コメント | 各メソッドにISO節番号を記載 | 高 | `mrblib/*.rb`, `test/t/*.rb` |
| MRB_API公開/static非公開 | 公開APIと内部関数の明確な分離 | 高 | 全Cソースファイル |
| to_enum/ブロック無しパターン | ブロックが渡されなければEnumeratorを返す | 高 | `mrblib/*.rb` |

### 各パターンの詳細

#### パターン1: mrb_state第一引数パターン

**目的:** VMの全状態を単一の構造体で管理し、複数のVM インスタンスの同時実行を可能にする。

**実装例:**
```c
// ファイル: src/state.c:72-74
MRB_API mrb_state*
mrb_open(void)
{
  mrb_state *mrb = mrb_open_core();
```

```c
// ファイル: src/vm.c:584-585
MRB_API mrb_value
mrb_funcall(mrb_state *mrb, mrb_value self, const char *name, mrb_int argc, ...)
```

**解説:** mruby の全てのAPI関数は `mrb_state*` を第一引数に取る。これにより、グローバル変数を使わずに複数のmrubyインスタンスを独立して動作させることが可能になる。

#### パターン2: GCアリーナ保存・復帰パターン

**目的:** 一時的に作成したオブジェクトがGCに回収されないよう保護し、不要になったら保護を解除する。

**実装例:**
```c
// ファイル: src/state.c:87
mrb_gc_arena_restore(mrb, 0);
```

```c
// ファイル: mrbgems/mruby-bin-mruby/tools/mruby/mruby.c:297
int ai = mrb_gc_arena_save(mrb);
```

**解説:** `mrb_gc_arena_save()` で現在のアリーナ位置を記録し、`mrb_gc_arena_restore()` で復帰する。ループ内でオブジェクトを生成する場合に特に重要。

#### パターン3: Xマクロによるオペコード定義

**目的:** オペコードの一覧を1箇所で定義し、enum/switch/テーブル等に自動展開する。

**実装例:**
```c
// ファイル: include/mruby/opcode.h:10-14
enum mrb_insn {
#define OPCODE(x,_) OP_ ## x,
#include <mruby/ops.h>
#undef OPCODE
};
```

```c
// ファイル: include/mruby/ops.h:15-17（定義側）
OPCODE(NOP,        Z)        /* no operation */
OPCODE(MOVE,       BB)       /* R[a] = R[b] */
OPCODE(LOADL,      BB)       /* R[a] = Pool[b] */
```

**解説:** `ops.h` が全オペコードの「マスターリスト」として機能する。`OPCODE` マクロを再定義して `#include` することで、enum定義、ディスパッチテーブル、デバッグ出力用文字列テーブルなど、異なる用途にも同じリストを流用できる。

#### パターン4: 埋め込み最適化（Embed Optimization）

**目的:** 小さな文字列や配列をヒープ割り当てなしで構造体内に直接格納し、メモリ効率を向上させる。

**実装例:**
```c
// ファイル: include/mruby/string.h:19-39
#define RSTRING_EMBED_LEN_MAX \
  ((mrb_int)(sizeof(void*) * 3 + sizeof(void*) - 32 / CHAR_BIT - 1))

struct RString {
  MRB_OBJECT_HEADER;
  union {
    struct {
      mrb_ssize len;
      union { mrb_ssize capa; /* ... */ } aux;
      char *ptr;
    } heap;
  } as;
};
struct RStringEmbed {
  MRB_OBJECT_HEADER;
  char ary[RSTRING_EMBED_LEN_MAX+1];   // 構造体内に直接格納
};
```

**解説:** 短い文字列はヒープ割り当てを行わず、オブジェクト構造体内のバッファに直接格納される。`flags` 内の `MRB_STR_EMBED` ビットで埋め込みモードかどうかを判別する。配列でも同様の最適化が行われている（`include/mruby/array.h:46`）。

#### パターン5: to_enum/ブロック無しパターン

**目的:** ブロックが渡されなかった場合にEnumeratorを返すRubyのイディオム。

**実装例:**
```ruby
# ファイル: mrblib/array.rb:15-16
def each(&block)
  return to_enum(:each) unless block
```

```ruby
# ファイル: mrblib/hash.rb:87-88
def each_key(&block)
  return to_enum(:each_key) unless block
```

**解説:** `mrblib/` 配下のほぼ全てのイテレータメソッドでこのパターンが使われている。ブロックが無い場合は `to_enum` でEnumeratorを返し、メソッドチェーンやlazy評価を可能にする。

---

## 8. 業務フロー追跡の実践例

> このセクションでは、実際の処理フローをコードで追跡する方法を解説します。

### 8.1 フロー追跡の基本手順

1. エントリーポイントを特定（main関数、またはmrb_open）
2. 処理の流れを追跡（関数呼び出し関係を追う）
3. データの変換を確認（mrb_value の変化）
4. VMオペコードの実行を確認
5. 最終的な出力を確認

### 8.2 フロー追跡の実例

#### 例1: mrubyコマンドによるRubyスクリプト実行フロー

**概要:** `mruby hello.rb` を実行した際の処理フロー全体を追跡する。

**処理フロー:**
```
main() → mrb_open() → parse_args() → mrb_load_file_cxt() → mrb_vm_run() → mrb_vm_exec() → cleanup()
```

**詳細な追跡:**

1. **main関数: VM初期化** (`mrbgems/mruby-bin-mruby/tools/mruby/mruby.c:276-279`)
   ```c
   int
   main(int argc, char **argv)
   {
     mrb_state *mrb = mrb_open();   // VM初期化（GC、コアクラス、gem全て含む）
   ```

2. **mrb_open: コア初期化→gem初期化** (`src/state.c:72-90`)
   ```c
   MRB_API mrb_state*
   mrb_open(void)
   {
     mrb_state *mrb = mrb_open_core();  // GC初期化、基本クラス生成
     // ...
     mrb_core_init_protect(mrb, init_mrbgems, NULL);  // gem初期化
   ```

3. **init_gc_and_core: GCとコンテキスト初期化** (`src/state.c:25-36`)
   ```c
   static void
   init_gc_and_core(mrb_state *mrb, void *opaque)
   {
     mrb_gc_init(mrb, &mrb->gc);                          // GC初期化
     mrb->c = (struct mrb_context*)mrb_malloc(mrb, sizeof(struct mrb_context));
     *mrb->c = mrb_context_zero;
     mrb->root_c = mrb->c;
     mrb_init_core(mrb);                                   // 基本クラス・メソッド登録
   }
   ```

4. **コマンドライン引数解析→コンパイル・実行** (`mrbgems/mruby-bin-mruby/tools/mruby/mruby.c:291-306`)
   ```c
   n = parse_args(mrb, argc, argv, &args);      // 引数解析
   ARGV = mrb_ary_new_capa(mrb, args.argc);     // ARGV定数作成
   mrb_define_global_const(mrb, "ARGV", ARGV);
   mrb_ccontext *c = mrb_ccontext_new(mrb);     // コンパイルコンテキスト
   ```

5. **VMバイトコード実行** (`src/vm.c:1586-1615`)
   ```c
   MRB_API mrb_value
   mrb_vm_run(mrb_state *mrb, const struct RProc *proc, mrb_value self, mrb_int stack_keep)
   {
     const mrb_irep *irep = proc->body.irep;
     // スタック初期化・拡張
     stack_extend(mrb, nregs);
     c->ci->stack[0] = self;
     mrb_value result = mrb_vm_exec(mrb, proc, irep->iseq);  // メインループ
     return result;
   }
   ```

6. **後処理** (`mrbgems/mruby-bin-mruby/tools/mruby/mruby.c:260-273`)
   ```c
   cleanup(mrb_state *mrb, struct _args *args)
   {
     // ファイルハンドル閉鎖
     // メモリ解放
     mrb_close(mrb);   // VM終了
   }
   ```

#### 例2: メソッド呼び出しの解決フロー

**概要:** `obj.method_name(arg)` というRubyコードが実行される際の内部処理を追跡する。

**処理フロー:**
```
OP_SEND → mrb_vm_exec内ハンドラ → メソッドキャッシュ確認 → mt_get()によるメソッド検索 → callinfo作成 → 対象メソッド実行
```

**詳細な追跡:**

1. **OP_SENDオペコード** (`include/mruby/ops.h:65`)
   ```c
   OPCODE(SEND, BBB)  /* R[a] = R[a].send(Syms[b],R[a+1]..,R[a+n+1]:R[a+n+2]..) (c=n|k<<4) */
   ```

2. **メソッドテーブル検索** (`src/class.c:88-104`)
   ```c
   static mrb_bool
   mt_get(mrb_state *mrb, mrb_mt_tbl *t, mrb_sym sym, union mrb_mt_ptr *pp, uint32_t *fp)
   {
     while (t) {
       mrb_mt_entry *entries = t->ptr;
       for (int i = 0; i < t->size; i++) {
         if (entries[i].key == sym) {     // シンボルで検索
           *pp = entries[i].val;
           *fp = entries[i].flags;
           return TRUE;
         }
       }
       t = t->next;                       // 継承チェーンを辿る
     }
     return FALSE;
   }
   ```

3. **Cで実装されたメソッドの場合**、`MRB_PROC_CFUNC_P` で判別し、`proc->body.func` を直接呼び出す。
4. **Rubyで実装されたメソッドの場合**、新しいcallinfoをプッシュし、対象procのirepを `mrb_vm_exec` で実行する。

### 8.3 フロー追跡チェックリスト

- [ ] エントリーポイントを特定したか（`main()` or `mrb_open()`）
- [ ] `mrb_state` の初期化フローを理解したか
- [ ] コンパイル（Ruby→irep）とVM実行の分離を理解したか
- [ ] メソッド呼び出し時の `mrb_callinfo` スタック操作を確認したか
- [ ] データの変換ポイント（mrb_value のボクシング/アンボクシング）を確認したか
- [ ] GCのアリーナ保護パターンを確認したか
- [ ] エラーハンドリング（`mrb->exc` の設定・確認）を確認したか
- [ ] 最終的な出力（戻り値 or 標準出力）を確認したか

---

## 9. 設計書の参照順序

> このセクションでは、プロジェクト理解のための設計書参照順序を案内します。

### 9.1 目的別ロードマップ

#### 全体像を把握したい場合
1. `README.md` -- プロジェクト概要、ビルド方法
2. `include/mruby.h` -- mrb_state, mrb_value, mrb_callinfo等の中核データ構造
3. `include/mruby/ops.h` -- VMオペコード一覧
4. `src/state.c` -- 初期化フロー
5. `build_config/default.rb` -- デフォルトビルド構成

#### VM・実行エンジンを理解したい場合
1. `include/mruby/irep.h` -- コンパイル済みバイトコードの構造
2. `include/mruby/ops.h` -- 全オペコードの定義と動作
3. `src/vm.c` -- VMメインループ（mrb_vm_run, mrb_vm_exec）
4. `include/mruby/proc.h` -- RProc/REnv構造
5. `src/codedump.c` -- バイトコードダンプ（デバッグ用）

#### オブジェクトシステムを理解したい場合
1. `include/mruby/object.h` -- MRB_OBJECT_HEADER
2. `include/mruby/boxing_word.h` -- mrb_value の内部表現
3. `include/mruby/class.h` -- RClass構造
4. `src/class.c` -- メソッドテーブル操作
5. `mrblib/enum.rb` -- Enumerableモジュール

#### GC・メモリ管理を理解したい場合
1. `include/mruby/gc.h` -- GC状態構造体
2. `src/gc.c` -- GC実装（三色マーク&スウィープ）
3. `include/mruby/object.h:13` -- gc_colorフィールド

#### 改修作業を行う場合
1. 対象機能の`include/mruby/*.h` ヘッダ確認
2. 対応する`src/*.c` 実装確認
3. `mrblib/*.rb` でRuby側の実装確認
4. `test/t/*.rb` でテストケース確認
5. `mrbgems/mruby-*-ext/` で拡張実装確認

#### 新しいgemを作成したい場合
1. `examples/mrbgems/` -- gemサンプル
2. 既存gemの `mrbgem.rake` を参考にする
3. `lib/mruby/build.rb` -- ビルドシステムの仕組み
4. `doc/guides/mrbgems.md` -- gem開発ガイド（存在する場合）

### 9.2 ドキュメント一覧

| ドキュメント | 概要 | 参照タイミング |
|-------------|------|---------------|
| `README.md` | プロジェクト概要・ビルド方法 | 最初に読む |
| `doc/guides/` | 各種ガイドドキュメント | 特定トピックの理解時 |
| `include/mruby.h` | メインヘッダ（中核API定義） | API理解時 |
| `include/mruby/ops.h` | VMオペコード完全リスト | VM動作理解時 |
| `build_config/default.rb` | デフォルトビルド設定 | ビルド設定変更時 |
| `mrbgems/mruby-compiler/` | コンパイラ実装 | パーサ/コンパイラ理解時 |
| `test/t/*.rb` | ISOテストスイート | 機能仕様の確認時 |
| `CONTRIBUTING.md` | コントリビュートガイド | 貢献時（存在する場合） |
| `MITL` / `LICENSE` | ライセンス情報 | 利用条件確認時 |

---

## 10. トラブルシューティング

> このセクションでは、コードリーディング時によくある問題と解決法を解説します。

### よくある疑問と回答

#### Q: `mrb_value` の中身を確認するにはどうすればよいか?
A: `include/mruby/boxing_word.h` の `mrb_type()` 関数（223-233行）で型を判別し、`mrb_fixnum()`, `mrb_float()`, `mrb_symbol()` 等のマクロで値を取り出す。デバッガでは `.w` メンバの下位ビットパターンを見ることで型を判別できる（`0` = nil, `4` = false, `12` = true, 最下位ビット1 = fixnum, 下位3ビット000 = オブジェクトポインタ）。

#### Q: `MRB_API` とは何か?
A: 動的ライブラリとしてビルドした場合のエクスポートマーカー。Windows DLLの `__declspec(dllexport)` や GCCの `__attribute__((visibility("default")))` に展開される。通常の静的リンクでは空マクロとなる。

#### Q: VMのオペコードを追加・変更するにはどうすればよいか?
A: `include/mruby/ops.h` にエントリを追加し、`src/vm.c` の `mrb_vm_exec()` 内のswitch文にハンドラを実装する。Xマクロパターンにより、enum定義は自動的に更新される。

#### Q: `struct RClass` のメソッドテーブルはどこにあるか?
A: `include/mruby/class.h:17-22` で定義された `struct RClass` の `mt` メンバが `mrb_mt_tbl*`（メソッドテーブル）。操作関数は `src/class.c:42-104` の `mt_new()`, `mt_put()`, `mt_get()` など。

#### Q: テストの実行方法は?
A: `rake test` でISOテストと全gemのテストが実行される。個別のテストは `test/t/*.rb` に配置されており、`assert()` 関数ベースのテストフレームワークを使用している。

```ruby
# ファイル: test/t/array.rb:4-6
assert('Array', '15.2.12') do
  assert_equal(Class, Array.class)
end
```

#### Q: mrbgemsの依存関係はどう管理されているか?
A: 各gemの `mrbgem.rake` で `spec.add_dependency` により依存を宣言し、`tasks/mrbgems.rake` が依存順序を解決してビルドする。gembox（`.gembox`ファイル）で関連gemをグループ化できる。

### デバッグのヒント

1. **`MRB_DEBUG`コンパイルオプション**: `mrbconf.h` で `MRB_DEBUG` を有効にすると `mrb_assert()` が有効になり、内部整合性チェックが行われる。

2. **バイトコードダンプ**: `mrbccontext` の `dump_result = TRUE` を設定するか、`mrbc -v` コマンドでコンパイル結果のバイトコードを確認できる。

3. **GCデバッグ**: `MRB_GC_STRESS` を定義すると、全てのアロケーション時にGCが実行され、GC関連のバグを早期発見できる。

4. **デバッグフック**: `MRB_USE_DEBUG_HOOK` を有効にすると、`code_fetch_hook` および `debug_op_hook` コールバックにより、VM命令実行をトレースできる（`include/mruby.h:310-311`）。

5. **`mrb->exc` の確認**: API関数呼び出し後に `mrb->exc` が NULL でない場合、例外が発生している。`mrb_print_error()` でエラーメッセージを表示できる。

---

## 付録

### A. 用語集

| 用語 | 説明 |
|-----|------|
| mrb_state | mruby VMインスタンス全体の状態を管理する構造体 |
| mrb_value | Rubyオブジェクトのワードサイズ値表現（ボクシング済み） |
| irep | Internal Representation。コンパイル済みバイトコードの中間表現 |
| iseq | Instruction Sequence。irep内の命令列 |
| callinfo (ci) | メソッド呼び出し時のコールフレーム情報 |
| RClass | Rubyクラスのメタオブジェクト構造体 |
| RProc | Proc/Lambda/メソッドオブジェクトの構造体 |
| REnv | クロージャの実行環境（キャプチャされた変数） |
| Word Boxing | ポインタサイズのワード1つで全Ruby値を表現する方式 |
| NaN Boxing | IEEE 754 NaN領域を利用した値表現方式 |
| GC Arena | GC保護対象オブジェクトを管理する配列 |
| mrbgems | mruby独自の拡張パッケージ管理システム |
| gembox | 関連gemをグループ化した設定ファイル |
| presym | ビルド時に事前生成されるシンボル |
| HAL | Hardware Abstraction Layer。プラットフォーム抽象化層 |
| Fiber | Rubyの軽量スレッド（コルーチン） |
| method cache | メソッド検索結果をキャッシュする仕組み |
| mrb_sym | シンボル型。メソッド名等の内部識別子（uint32_t） |
| RVALUE | GCヒープ上のオブジェクト共用体型 |
| Tri-color GC | 白（未マーク）・灰（マーク中）・黒（完了）の三色GC |

### B. ファイル一覧

| ファイル/ディレクトリ | 説明 | 主な内容 |
|---------------------|------|---------|
| `src/vm.c` | VMメインループ | mrb_vm_run, mrb_vm_exec, mrb_funcall |
| `src/gc.c` | GC実装 | add_heap, mrb_gc_init, マーク&スウィープ |
| `src/class.c` | クラス・メソッド管理 | mt_new, mt_put, mt_get, mrb_define_method |
| `src/state.c` | VM状態管理 | mrb_open, mrb_open_core, mrb_close |
| `src/symbol.c` | シンボル管理 | find_symbol（3段階検索） |
| `src/string.c` | 文字列操作 | RString操作、文字列処理 |
| `src/array.c` | 配列操作 | RArray操作 |
| `src/hash.c` | ハッシュ操作 | RHash操作 |
| `src/numeric.c` | 数値演算 | 整数・浮動小数点演算 |
| `src/object.c` | オブジェクト共通操作 | mrb_obj_alloc, freeze等 |
| `src/proc.c` | Proc操作 | RProc生成・呼び出し |
| `src/error.c` | 例外処理 | mrb_raise, 例外クラス定義 |
| `src/variable.c` | 変数アクセス | インスタンス変数、グローバル変数 |
| `src/kernel.c` | Kernelモジュール | puts, p, require等 |
| `include/mruby.h` | メインヘッダ | mrb_state, mrb_callinfo, mrb_context定義 |
| `include/mruby/value.h` | 値型定義 | mrb_sym, mrb_bool, mrb_int定義 |
| `include/mruby/boxing_word.h` | Word Boxing | mrb_value内部表現、型判定マクロ |
| `include/mruby/gc.h` | GCヘッダ | mrb_gc構造体 |
| `include/mruby/irep.h` | Irep定義 | mrb_irep構造体 |
| `include/mruby/ops.h` | オペコード定義 | 全106命令のマスターリスト |
| `include/mruby/class.h` | クラスヘッダ | RClass定義 |
| `include/mruby/proc.h` | Procヘッダ | RProc, REnv定義 |
| `include/mruby/object.h` | オブジェクトヘッダ | MRB_OBJECT_HEADER, RBasic |
| `include/mruby/string.h` | 文字列ヘッダ | RString, RStringEmbed |
| `include/mruby/array.h` | 配列ヘッダ | RArray定義 |
| `include/mruby/hash.h` | ハッシュヘッダ | RHash定義 |
| `include/mruby/compile.h` | コンパイラIF | mrb_ccontext定義 |
| `include/mruby/opcode.h` | オペコードIF | FETCH/READマクロ |
| `mrblib/array.rb` | Array Rubyメソッド | each, sort, collect!等 |
| `mrblib/hash.rb` | Hash Rubyメソッド | each, merge, select等 |
| `mrblib/enum.rb` | Enumerable | all?, any?, map, select等 |
| `mrblib/numeric.rb` | Numeric | abs, +@, -@等 |
| `Rakefile` | メインビルドファイル | ビルドタスク定義 |
| `build_config/default.rb` | デフォルト設定 | ツールチェーン、gembox指定 |

### C. 参考資料

- mruby公式リポジトリ: https://github.com/mruby/mruby
- mruby公式サイト: https://mruby.org/
- ISO/IEC 30170:2012 Ruby言語仕様
- mruby VMの設計: `src/vm.c` 先頭コメントおよびGCの `src/gc.c:36-60` コメント
- RiteVM命令セット: `include/mruby/ops.h` 全文
- mrbgems開発ガイド: `doc/guides/mrbgems.md`（存在する場合）
- Word Boxing解説: `include/mruby/boxing_word.h:83-109` コメント
