# バッチ設計書 19-rake doc:update-opcode.md

## 概要

本ドキュメントは、mrubyプロジェクトにおけるオペコードドキュメント（doc/internal/opcode.md）を自動更新する`rake doc:update-opcode.md`タスクのバッチ設計書である。

### 本バッチの処理概要

`rake doc:update-opcode.md`は、mrubyの仮想マシンオペコード定義ファイル（include/mruby/ops.h）からオペコード情報を解析し、ドキュメントファイル（doc/internal/opcode.md）内のオペコード一覧表を自動更新するRakeタスクである。ops.hのOPCODE()マクロ定義を読み取り、命令番号・命令名・オペランド型・セマンティクスの表を生成して既存のMarkdownファイルに埋め込む。

**業務上の目的・背景**：mrubyの仮想マシンオペコードが変更された際に、対応するドキュメントを手動で更新する手間を省き、ソースコードとドキュメントの整合性を自動的に維持するために必要なタスクである。オペコードの追加・削除・変更があった場合に、ドキュメントが自動的に最新の状態に更新される。

**バッチの実行タイミング**：開発者による手動実行。ops.hファイルに変更が加えられた後に実行される。未コミットの変更がopcode.mdに存在する場合は安全のため実行が中断される。

**主要な処理内容**：
1. opcode.mdに未コミットの変更がないかgit diffで確認
2. include/mruby/ops.hからOPCODE()マクロ定義を正規表現で抽出
3. 各オペコードの命令番号、命令名、オペランド型、セマンティクスコメントを解析
4. オペランド型仕様（opspecs）に基づいてオペランド表現を変換
5. doc/internal/opcode.md内の表セクションを新しい内容で置換

**前後の処理との関連**：前提として、ops.hが最新の状態であること。また、opcode.mdに未コミットのgit変更がないことが必要。後続処理として、更新されたopcode.mdのgitコミットが想定される。

**影響範囲**：doc/internal/opcode.mdファイルのみが更新される。ops.hは読み取りのみで変更されない。

## バッチ種別

ドキュメント自動更新

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | 随時 |
| 実行時刻 | 任意 |
| 実行曜日 | 該当なし |
| 実行日 | 該当なし |
| トリガー | 手動実行（ops.h変更後） |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| Ruby実行環境 | Rubyインタプリタがインストールされていること |
| Gitリポジトリ | Gitリポジトリ内で実行されること |
| 未コミット変更なし | doc/internal/opcode.mdに未コミットのgit変更がないこと |
| ops.h存在 | include/mruby/ops.hが存在すること |
| opcode.md存在 | doc/internal/opcode.mdが存在すること |

### 実行可否判定

`git diff --quiet @ -- doc/internal/opcode.md`コマンドで未コミットの変更を確認する。変更がある場合は以下のエラーメッセージを表示して処理を中断する：
```
The file "doc/internal/opcode.md" has been modified but not committed.
To avoid loss of your edits, the automatic update process has been aborted.
```

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| なし | - | - | - | 本タスクにパラメータはない |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| include/mruby/ops.h | Cヘッダー | OPCODE()マクロによるオペコード定義 |
| doc/internal/opcode.md | Markdown | 更新対象のオペコードドキュメント |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| doc/internal/opcode.md | Markdown | 更新されたオペコード一覧表を含むドキュメント |

### 出力ファイル仕様

| 項目 | 内容 |
|-----|------|
| ファイル名 | opcode.md |
| 出力先 | doc/internal/ |
| 文字コード | バイナリ書き込み（binwrite） |
| 形式 | Markdownテーブル |

## 処理フロー

### 処理シーケンス

```
1. 未コミット変更チェック
   └─ git diff --quiet @ -- doc/internal/opcode.md
   └─ 変更あり → abort でエラーメッセージ表示し中断
2. MRuby::Documentation.update_opcode_md呼び出し
   └─ include/mruby/ops.hの読み込み
3. OPCODE()マクロの正規表現パース
   └─ パターン: OPCODE(命令名, オペランド型) /* セマンティクス */
4. オペランド型の変換
   └─ opspecs辞書による表現変換（Z→"-", B→"'", BB→'"'等）
5. セマンティクスコメントの整形
   └─ ハッシュ以降の除去、L_プレフィックスへのOP_付加
   └─ Irep[x]→Irep(x)形式への変換
   └─ バックスラッシュとパイプのエスケープ
6. Markdownテーブルの生成
   └─ No., Instruction Name, Operand type, Semantics列
7. opcode.mdの表セクションを置換
   └─ spliterパターンで区切られた領域を新しい表で置換
   └─ binwriteでファイル書き込み
```

### フローチャート

```mermaid
flowchart TD
    A[rake doc:update-opcode.md 開始] --> B{opcode.md に未コミット変更あり?}
    B -->|Yes| C[abort: エラーメッセージ表示]
    B -->|No| D[ops.h 読み込み]
    D --> E[OPCODE マクロを正規表現でパース]
    E --> F[各オペコードの情報を抽出]
    F --> G[オペランド型の変換]
    G --> H[セマンティクスコメントの整形]
    H --> I[Markdown テーブル行の生成]
    I --> J[opcode.md の表セクションを置換]
    J --> K[binwrite でファイル書き込み]
    K --> L[完了]
```

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

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

本バッチはデータベースを使用しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| N/A | 未コミット変更 | opcode.mdに未コミットのgit変更がある場合 | 変更をコミットまたはstashしてから再実行 |
| N/A | 不明なオペランド型 | ops.hに未定義のオペランド型が含まれる場合 | opspecsにオペランド型を追加する |
| N/A | ops.h未発見 | include/mruby/ops.hが存在しない場合 | ファイルの存在を確認 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし |
| リトライ間隔 | N/A |
| リトライ対象エラー | N/A |

### 障害時対応

未コミット変更エラーの場合は、opcode.mdの変更をgit commitまたはgit stashしてから再実行する。不明なオペランド型エラーの場合は、lib/mruby/doc.rbのopspecs辞書に新しいオペランド型を追加する。

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

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | ファイル単位（opcode.md全体を一括書き換え） |
| コミットタイミング | ファイル書き込み完了時 |
| ロールバック条件 | 未コミット変更がある場合は実行前に中断 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | ops.h内のオペコード数（数十〜百数十件程度） |
| 目標処理時間 | 1秒以内 |
| メモリ使用量上限 | 特に制限なし |

## 排他制御

git diffチェックにより、未コミットの変更がある場合は実行が中断される。これにより、開発者の手動編集を上書きすることを防止する。

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| エラーログ | 未コミット変更検出時 | 「The file "doc/internal/opcode.md" has been modified but not committed.」 |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| 処理完了 | N/A | 手動確認 |

## 備考

- オペランド型仕様（opspecs）は以下の通り：Z（"-"）、B（"'"）、BB（'"'）、BBB（'"'）、BS（"'"）、BSS（"'"）、S（""）、W（""）
- セマンティクスコメント内の`L_`プレフィックスは`OP_`が付加される
- `Irep[x]`のような表記は`Irep(x)`に変換される
- コメント内のバックスラッシュとパイプ文字はMarkdown用にエスケープされる
- binwriteを使用するため、改行コードの自動変換は行われない
- update_opcode_mdメソッドはlib/mruby/doc.rbのMRuby::Documentationモジュールに定義されている
