# 機能設計書 102-REPL

## 概要

本ドキュメントは、Julia標準ライブラリ `REPL` モジュールが提供する対話型コマンドライン（Read-Eval-Print Loop）機能の設計を記述する。Juliaのインタラクティブセッションの中核であり、行編集、補完、ヘルプモード、シェルモード、Pkgモード、履歴検索、シンタックスハイライト等の機能を統合的に提供する。

### 本機能の処理概要

**業務上の目的・背景**：Juliaの対話型開発環境の根幹をなす機能であり、コードの探索的実行、ドキュメント参照、パッケージ管理、シェルコマンド実行をシームレスに行える環境を提供する。REPLは科学技術計算やデータ分析における試行錯誤型の開発ワークフローに不可欠である。

**機能の利用シーン**：Juliaの `julia` コマンド起動時の対話的セッション、IDEのターミナルパネル、リモートJuliaセッション、Jupyter Notebookのバックエンド等で利用される。

**主要な処理内容**：
1. LineEditREPL / BasicREPL / StreamREPL の3種類のREPL実装
2. フロントエンド（入力受付・表示）とバックエンド（式評価）の分離アーキテクチャ
3. モーダルインターフェース（julia>, help?>, shell>, pkg>）の切り替え
4. 履歴管理（ファイル永続化、インクリメンタル検索、プレフィックス検索）
5. タブ補完（REPLCompletions）とシンタックスハイライト（StylingPasses）
6. TerminalMenus サブモジュール（RadioMenu, MultiSelectMenu, Pager）
7. ソフトスコーピング、AST変換、番号付きプロンプト

**関連システム・外部連携**：JuliaSyntaxHighlighting, StyledStrings, Sockets, InteractiveUtils, FileWatching, Pkg（遅延ロード）。

**権限による制御**：特になし。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | 起動バナー画面 | 補助機能 | REPLモジュール内のbanner()関数として実装 |
| 2 | Juliaプロンプト（julia>） | 主機能 | LineEditREPL/BasicREPL/StreamREPLの3実装によるメインのRead-Eval-Print Loop処理 |
| 3 | ヘルプモード（help?>） | 補助機能 | REPLモジュール内のdocview.jlとして実装。helpmode関数がメインエントリポイント |
| 4 | シェルモード（shell>） | 補助機能 | REPLモジュール内のシェルモードプロンプトとして実装 |
| 5 | Pkgモード（pkg>） | 補助機能 | REPLモジュール内のPkgモードプロンプトとして実装。Pkg読み込み前はダミーモード表示 |
| 6 | 履歴検索モード | 主機能 | REPL.History.runsearch()によるインクリメンタル履歴検索 |
| 7 | プレフィックス検索モード | 主機能 | LineEdit.jlのPrefixHistoryPromptによるプレフィックスベース履歴検索 |
| 8 | RadioMenu（単一選択メニュー） | 主機能 | REPL.TerminalMenusサブモジュール内のRadioMenu型 |
| 9 | MultiSelectMenu（複数選択メニュー） | 主機能 | REPL.TerminalMenusサブモジュール内のMultiSelectMenu型 |
| 10 | Pager（ページャ） | 主機能 | REPL.TerminalMenusサブモジュール内のPager型 |
| 11 | フォールバックREPL | 補助機能 | 行編集・補完なしの最小限eval-printループ |

## 機能種別

対話型インターフェース / CRUD操作（履歴管理）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| terminal | TextTerminal | Yes | 入出力ターミナル | TTYTerminal推奨 |
| hascolor | Bool | No | カラー出力の有無 | デフォルトはターミナルの色サポートに依存 |
| history_file | Bool | No | 履歴ファイルの使用有無 | デフォルトfalse |

### 入力データソース

- ターミナルからのキーボード入力（stdin）
- 履歴ファイル（`~/.julia/logs/repl_history.jl` または `JULIA_HISTORY` 環境変数）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| evaluation_result | Any | 入力式の評価結果 |
| error_output | String | エラーメッセージ・スタックトレース |
| display_output | String | show/display によるフォーマット済み出力 |

### 出力先

- ターミナル（stdout/stderr）
- 履歴ファイル

## 処理フロー

### 処理シーケンス

```
1. run_repl(repl) でREPLセッション開始
   └─ REPLBackend を生成し、フロントエンド・バックエンドタスクを起動
2. setup_interface(repl) でモーダルインターフェース構築
   └─ julia_prompt, help_mode, shell_mode, dummy_pkg_mode を設定
3. run_frontend(repl, backend) でフロントエンドループ開始
   └─ LineEdit.run_interface() でキーイベント処理ループ
4. ユーザー入力をパースし評価要求をバックエンドに送信
   └─ put!(backend.repl_channel, (ast, show_value))
5. バックエンドで eval_user_input() が式を評価
   └─ toplevel_eval_with_hooks() -> Core._lower -> jl_toplevel_eval_flex
6. 評価結果をフロントエンドに返送
   └─ put!(backend.response_channel, (value, iserr))
7. print_response() で結果を表示
```

### フローチャート

```mermaid
flowchart TD
    A["run_repl(repl)"] --> B["setup_interface(): モーダルIF構築"]
    B --> C["run_frontend(): フロントエンドタスク"]
    B --> D["start_repl_backend(): バックエンドタスク"]
    C --> E["LineEdit.run_interface(): 入力ループ"]
    E --> F{"モード判定"}
    F -->|julia>| G["parse_repl_input_line()"]
    F -->|help?>| H["helpmode()"]
    F -->|shell>| I["Base.repl_cmd()"]
    F -->|pkg>| J["Pkg遅延ロード"]
    G --> K["eval_on_backend(ast)"]
    K --> L["eval_user_input(): 式評価"]
    L --> M["print_response(): 結果表示"]
    M --> E
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-102-1 | ソフトスコーピング | REPLではforループ等のグローバルスコープでの変数代入をローカルスコープとして扱う | julia>モードでの式評価時 |
| BR-102-2 | セミコロン抑制 | 式末尾のセミコロンで出力を抑制する | julia>モードでの式評価時 |
| BR-102-3 | モード遷移 | `?`でヘルプ、`;`でシェル、`]`でPkgモードに遷移。Backspaceで戻る | 入力バッファが空の状態でキー押下時 |
| BR-102-4 | 出力サイズ制限 | LimitIOにより最大1MBまでの表示出力に制限 | display実行時 |
| BR-102-5 | Pkg遅延ロード | Pkgモードへの遷移時に初めてPkgを別スレッドでロードする | `]`キー押下時 |

### 計算ロジック

特になし。

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

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | LimitIOException | 表示出力が SHOW_MAXIMUM_BYTES (1MB) を超過 | `show(stdout, MIME"text/plain"(), ans)` で制限なし表示 |
| - | InterruptException | Ctrl+C押下 | REPLループは継続、入力バッファをクリア |
| - | EOFError | Ctrl+D押下またはストリーム終端 | REPLセッションを終了 |

### リトライ仕様

該当なし。REPLループ自体がエラー後も継続する設計。

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

該当なし。

## パフォーマンス要件

- `@optlevel 1` と `@max_methods 1` によりコンパイル時間を短縮
- precompile.jl による事前コンパイルでREPL起動時間を最適化
- Pkgの遅延ロードにより初期起動時間を低減

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

- シェルモード（`;`）を介したOSコマンド実行が可能（Juliaプロセスの権限で実行）
- 履歴ファイルにユーザーが入力した全コマンドが記録される
- `JULIA_HISTORY` 環境変数で履歴ファイルパスを制御可能

## 備考

- `REPL.numbered_prompt!()` で番号付きプロンプト（In[N]/Out[N]）を有効化可能
- `REPL.activate(mod)` でアクティブモジュールを切り替え可能
- プロンプトペースト機能により、`julia>` プレフィックス付きのコード例をそのまま貼り付け実行可能

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | REPL.jl | `stdlib/REPL/src/REPL.jl` | `REPLBackend` 構造体（118-132行目）: フロントエンド・バックエンド間のChannel通信の核 |
| 1-2 | REPL.jl | `stdlib/REPL/src/REPL.jl` | `LineEditREPL` 構造体（764-798行目）: 主要REPL実装。色設定、履歴、インターフェース等を保持 |
| 1-3 | REPL.jl | `stdlib/REPL/src/REPL.jl` | `REPLHistoryProvider`（885-896行目）: 履歴管理プロバイダ |

**読解のコツ**: REPLはフロントエンド（入力UI）とバックエンド（評価エンジン）がChannelで通信する非同期アーキテクチャ。`repl_channel` に式（AST）を送り、`response_channel` から結果を受け取る。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | REPL.jl | `stdlib/REPL/src/REPL.jl` | `run_repl(repl)`（677-701行目）: メインエントリポイント。フロントエンド・バックエンドの起動と制御 |
| 2-2 | REPL.jl | `stdlib/REPL/src/REPL.jl` | `setup_interface(repl)`（1254-1677行目）: モーダルインターフェース構築。全モードのプロンプト・キーマップを設定 |
| 2-3 | REPL.jl | `stdlib/REPL/src/REPL.jl` | `run_frontend(repl::LineEditREPL)`（1679-1700行目）: フロントエンドメインループ |

**主要処理フロー**:
1. **677行目**: `run_repl` がREPLBackendとREPLBackendRefを生成
2. **688行目**: フロントエンドを@asyncで起動、バックエンドをcurrent_taskで実行
3. **1684-1685行目**: `setup_interface` でモーダルIF構築
4. **1695行目**: `LineEdit.run_interface` でイベントループ開始

#### Step 3: バックエンド評価ループを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | REPL.jl | `stdlib/REPL/src/REPL.jl` | `repl_backend_loop(backend)`（448-473行目）: バックエンドのメインループ。Channelからの式取得と評価 |
| 3-2 | REPL.jl | `stdlib/REPL/src/REPL.jl` | `eval_user_input(ast, backend, mod)`（329-358行目）: AST変換適用と式評価、結果Channel送信 |
| 3-3 | REPL.jl | `stdlib/REPL/src/REPL.jl` | `toplevel_eval_with_hooks(mod, ast)`（316-327行目）: lowering + パッケージ自動インストールフック + 評価 |

#### Step 4: モード遷移メカニズムを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | REPL.jl | `stdlib/REPL/src/REPL.jl` | `repl_keymap`（1405-1645行目）: `;`/`?`/`]`キーによるモード遷移定義 |
| 4-2 | REPL.jl | `stdlib/REPL/src/REPL.jl` | `mode_keymap(julia_prompt)`（1203-1228行目）: BackspaceとCtrl+Cでjuliaモードに戻るキーマップ |

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

```
run_repl(repl)
    │
    ├─ REPLBackend() / REPLBackendRef()
    │
    ├─ @async run_frontend(repl, backend_ref)
    │      │
    │      ├─ setup_interface(repl)
    │      │      ├─ julia_prompt (Prompt)
    │      │      ├─ help_mode (Prompt)
    │      │      ├─ shell_mode (Prompt)
    │      │      ├─ dummy_pkg_mode (Prompt)
    │      │      └─ REPLHistoryProvider
    │      │
    │      └─ LineEdit.run_interface(terminal, interface, mistate)
    │             └─ on_done -> respond() -> eval_on_backend()
    │
    └─ start_repl_backend(backend)
           └─ repl_backend_loop(backend)
                  └─ eval_user_input(ast, backend, mod)
                         ├─ ast_transforms (softscope等)
                         └─ toplevel_eval_with_hooks(mod, ast)
                                ├─ __repl_entry_lower_with_loc()
                                ├─ check_for_missing_packages_and_run_hooks()
                                └─ __repl_entry_eval_expanded_with_loc()
```

### データフロー図

```
[入力]                  [フロントエンド]              [バックエンド]           [出力]

キーボード入力 ──▶ LineEdit.run_interface() ──▶ repl_channel ──▶ eval_user_input()
                        │                                              │
                        │                                              ▼
                        │                                    toplevel_eval_with_hooks()
                        │                                              │
                        ▼                                              ▼
                  print_response() ◀── response_channel ◀── (value, iserr)
                        │
                        ▼
                  ターミナル出力
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| REPL.jl | `stdlib/REPL/src/REPL.jl` | ソース | REPLメインモジュール（バックエンド、フロントエンド、表示） |
| LineEdit.jl | `stdlib/REPL/src/LineEdit.jl` | ソース | 行編集・キーマップ・プロンプト管理 |
| REPLCompletions.jl | `stdlib/REPL/src/REPLCompletions.jl` | ソース | タブ補完エンジン |
| docview.jl | `stdlib/REPL/src/docview.jl` | ソース | ヘルプモードのドキュメント表示 |
| StylingPasses.jl | `stdlib/REPL/src/StylingPasses.jl` | ソース | シンタックスハイライト・括弧ハイライト |
| options.jl | `stdlib/REPL/src/options.jl` | ソース | REPLオプション設定 |
| History/ | `stdlib/REPL/src/History/` | ソース | 履歴検索サブモジュール |
| TerminalMenus/ | `stdlib/REPL/src/TerminalMenus/` | ソース | TerminalMenusサブモジュール（RadioMenu等） |
| Pkg_beforeload.jl | `stdlib/REPL/src/Pkg_beforeload.jl` | ソース | Pkg遅延ロード処理 |
| precompile.jl | `stdlib/REPL/src/precompile.jl` | ソース | 事前コンパイルワークロード |
