# 機能設計書 11-F# Interactive（fsi）

## 概要

本ドキュメントは、F# Interactive（fsi）の機能設計を記述する。F# Interactiveは、F#コードを対話的に実行するREPL（Read-Eval-Print Loop）環境を提供する機能である。

### 本機能の処理概要

F# Interactiveは、ユーザーがコンソールまたはIDE統合環境からF#コードを入力し、即座にコンパイル・実行・結果表示を行う対話型プログラミング環境である。

**業務上の目的・背景**：F#言語の学習、プロトタイピング、データ分析、スクリプト実行など、コードを素早く試行錯誤しながら開発・検証したい場面で必要となる。従来のコンパイル・実行サイクルを短縮し、即座にフィードバックを得ることで開発効率を大幅に向上させる。

**機能の利用シーン**：
- コンソールでの対話的なF#コード実行（fsi.exe）
- Visual StudioやVS CodeなどのIDEからのコード送信・実行
- F#スクリプトファイル（.fsx）の実行
- 教育・学習目的でのF#言語の習得
- データ分析やプロトタイプ開発時の試行錯誤

**主要な処理内容**：
1. コマンドライン引数の解析とセッション設定の初期化
2. ユーザー入力の読み取り（コンソール/IDE連携）
3. 入力コードのパース・型チェック・コンパイル
4. 動的アセンブリへのILコード生成
5. コードの実行と結果の評価
6. 結果値のフォーマット・表示
7. REPLループの継続管理

**関連システム・外部連携**：
- Visual Studio統合（FSI統合機能、FsiCommandService）
- 言語サーバー（LSP経由でのIDE連携）
- NuGetパッケージマネージャー（#r "nuget:..."ディレクティブ）
- .NET ランタイム（動的アセンブリ実行）

**権限による制御**：特になし。ローカル実行環境でのコード実行権限に依存する。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 7 | F# Interactive ツールウィンドウ | 主画面 | F#コードの対話的実行、REPL機能を提供するツールウィンドウ |

## 機能種別

REPL環境（対話的コード実行）/ 動的コンパイル / スクリプト実行

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| argv | string[] | Yes | コマンドライン引数 | 有効なFSIオプション形式 |
| sourceText | ISourceText | Yes | 実行するF#コード | F#構文として妥当 |
| options | FSharpProjectOptions | No | プロジェクトオプション | - |

### 入力データソース

- コンソール標準入力（stdin）
- IDEからの送信コード（VS統合、LSP経由）
- F#スクリプトファイル（.fsx）
- #loadディレクティブで参照されるソースファイル

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| FsiValue | FsiValue option | 評価結果の値（ReflectionValue, ReflectionType, FSharpType） |
| diagnostics | FSharpDiagnostic[] | コンパイル警告・エラー |
| boundValues | FsiBoundValue list | セッションで束縛された値の一覧 |

### 出力先

- コンソール標準出力（stdout）
- エラー出力（stderr）
- IDE統合時は統合ツールウィンドウ

## 処理フロー

### 処理シーケンス

```
1. セッション初期化
   └─ TcConfigBuilder生成、参照アセンブリ解決、初期環境構築
2. REPLループ開始
   └─ コンソールまたはIDEからの入力待機
3. 入力コードの取得
   └─ 複数行入力の処理、;;による実行トリガー検出
4. パース処理
   └─ F#ソースをAST（ParsedInput）に変換
5. 型チェック
   └─ 型推論、型チェック、診断情報生成
6. ILコード生成
   └─ 型付きASTからIL中間言語を生成
7. 動的アセンブリ発行
   └─ Reflection.Emitによるランタイムアセンブリ生成
8. コード実行
   └─ 生成されたコードの実行、結果値の取得
9. 結果表示
   └─ 値と型のフォーマット、コンソール出力
10. ループ継続
    └─ 次の入力待機、または終了処理
```

### フローチャート

```mermaid
flowchart TD
    A[セッション開始] --> B[初期化処理]
    B --> C{入力待機}
    C -->|入力あり| D[パース]
    C -->|EOF/終了| K[セッション終了]
    D --> E{パース成功?}
    E -->|Yes| F[型チェック]
    E -->|No| G[エラー表示]
    G --> C
    F --> H{型チェック成功?}
    H -->|Yes| I[IL生成・実行]
    H -->|No| G
    I --> J[結果表示]
    J --> C
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 複数行入力 | `;;`で終わるまで入力を継続して蓄積 | 対話モード時 |
| BR-02 | 値の表示 | 最後に評価された式の値を`it`として束縛・表示 | 式評価時 |
| BR-03 | スクリプトモード | .fsxファイルはINTERACTIVEシンボル定義下でコンパイル | スクリプト実行時 |
| BR-04 | 参照解決 | #rディレクティブでNuGetパッケージまたはアセンブリ参照を追加 | #r使用時 |

### 計算ロジック

なし（汎用コード実行環境）

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

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

該当なし（データベース操作は行わない）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| FS0001 | パースエラー | 構文が不正 | エラー箇所を表示して次の入力を待機 |
| FS0002 | 型エラー | 型チェック失敗 | 型エラー詳細を表示して次の入力を待機 |
| - | 実行時例外 | コード実行中の例外 | スタックトレースを表示してセッション継続 |
| LGCA | アセンブリエラー | COMMAREAなしの場合 | ABEND処理 |

### リトライ仕様

エラー発生後もセッションは継続し、次の入力を受け付ける。

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

該当なし（各コード実行は独立した操作）

## パフォーマンス要件

- 単純な式評価: 100ms以下
- 初回起動時: 数秒（アセンブリロード含む）
- インクリメンタル実行: 前回状態を保持し高速化

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

- 任意のコード実行が可能なため、信頼できる環境でのみ使用
- ネットワーク経由の入力（fsi-server）使用時は適切なアクセス制御が必要
- 機密情報を含む値は表示時に注意

## 備考

- Visual Studio統合時はWinFormsイベントループと連携
- GUI表示（--guiオプション）のサポート
- 多言語対応（LCID設定可能）

---

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

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

### 推奨読解順序

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

まず、F# Interactiveで使用される主要なデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | fsi.fs | `src/Compiler/Interactive/fsi.fs` | FsiValue、FsiBoundValue、EvaluationEventArgsの定義（76-500行目） |
| 1-2 | fsi.fs | `src/Compiler/Interactive/fsi.fs` | FsiEvaluationSessionHostConfigの抽象クラス定義（506-586行目） |

**読解のコツ**: FsiValueは評価結果をReflectionValue/ReflectionType/FSharpTypeとして保持する。FsiEvaluationSessionHostConfigはホスト環境（コンソール/IDE）との接続点を定義する抽象クラスである。

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

処理の起点となるファイル・関数を特定する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | fsimain.fs | `src/fsi/fsimain.fs` | evaluateSession関数がメインエントリーポイント（172行目以降） |
| 2-2 | fsimain.fs | `src/fsi/fsimain.fs` | FsiEvaluationSession.Createでセッション生成 |

**主要処理フロー**:
1. **172-180行目**: コマンドライン引数の処理、デバッグモード判定
2. **182-185行目**: VFSI実行時のエンコーディング設定
3. **188-210行目**: コンソールリーダーの初期化
4. **213-235行目**: FSharp.Compiler.Interactive.Settings.dllのロードとfsiオブジェクト取得
5. **255-300行目**: fsiConfigの構築（イベントループ、サーバー起動等）

#### Step 3: セッション管理層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | fsi.fs | `src/Compiler/Interactive/fsi.fs` | FsiEvaluationSessionクラスの実装 |
| 3-2 | fsi.fs | `src/Compiler/Interactive/fsi.fs` | FsiCommandLineOptionsによるオプション解析（947行目以降） |

**主要処理フロー**:
- **947-972行目**: コマンドラインオプションの状態管理（gui、showTypes等）
- **506-586行目**: ホスト設定の抽象化（FormatProvider、PrintWidth等）

#### Step 4: 値の評価・表示を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | fsi.fs | `src/Compiler/Interactive/fsi.fs` | FsiValuePrinterクラス（590-800行目） |

**主要処理フロー**:
- **590-665行目**: 印刷オプションの構成、カスタムプリンターの適用
- **682-712行目**: PrintValue - 値のレイアウト生成
- **714-757行目**: InvokeDeclLayout - 宣言値の表示
- **766-800行目**: InvokeExprPrinter - 式評価結果の表示

#### Step 5: エラーハンドリングを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | fsi.fs | `src/Compiler/Interactive/fsi.fs` | FsiStdinSyphon - エラー表示用入力キャプチャ（803-846行目） |
| 5-2 | fsi.fs | `src/Compiler/Interactive/fsi.fs` | DiagnosticsLoggerThatStopsOnFirstError（891-922行目） |

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

```
fsimain.fs::evaluateSession
    │
    ├─ FsiEvaluationSession.GetDefaultConfiguration
    │
    ├─ FsiEvaluationSession.Create
    │      ├─ FsiCommandLineOptions (オプション解析)
    │      ├─ TcConfigBuilder (コンパイラ設定)
    │      └─ FsiValuePrinter (結果表示)
    │
    ├─ fsiConfig (FsiEvaluationSessionHostConfig実装)
    │      ├─ EventLoopRun (WinForms/デフォルト)
    │      ├─ GetOptionalConsoleReadLine
    │      └─ StartServer (fsi-server)
    │
    └─ fsiSession.Run / EvalInteraction
           ├─ ParseAndCheckInputs
           ├─ IlxGenerator (IL生成)
           ├─ ILDynamicAssemblyWriter (動的アセンブリ)
           └─ Reflection実行・結果取得
```

### データフロー図

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

ユーザー入力 ─────────▶ FsiStdinSyphon ─────▶ パース
   (stdin/IDE)              (入力蓄積)              │
                                                    ▼
                                              型チェック
                                                    │
                                                    ▼
                                        ILコード生成
                                   (IlxGenerator)
                                                    │
                                                    ▼
                                      動的アセンブリ発行
                                  (ILDynamicAssemblyWriter)
                                                    │
                                                    ▼
                                           実行・評価
                                    (Reflection.Emit)
                                                    │
                                                    ▼
FsiValue ◀────────────── 値の取得 ◀──────────
                              │
                              ▼
stdout ◀──────────────── FsiValuePrinter ────▶ 結果表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| fsi.fs | `src/Compiler/Interactive/fsi.fs` | ソース | F# Interactiveのコア実装 |
| fsimain.fs | `src/fsi/fsimain.fs` | ソース | fsi.exeのエントリーポイント |
| ilreflect.fs | `src/Compiler/AbstractIL/ilreflect.fs` | ソース | 動的アセンブリ生成 |
| ScriptClosure.fs | `src/Compiler/Driver/ScriptClosure.fs` | ソース | スクリプトの依存関係解決 |
| FsiCommandService.fs | `vsintegration/src/FSharp.Editor/Commands/FsiCommandService.fs` | ソース | VS統合のFSI連携 |
| ReadLineConsole.fs | `src/Compiler/Interactive/ReadLineConsole.fs` | ソース | コンソール入力処理 |
