# 機能設計書 95-C#スクリプト

## 概要

本ドキュメントは、Roslyn の C# スクリプト機能の設計を定義する。C# スクリプトは、コンパイル済みアセンブリを作成せずに C# コードを直接実行できるスクリプティング機能を提供する。

### 本機能の処理概要

C# スクリプト (CSharpScript) は、文字列またはストリームとして提供された C# コードを動的にコンパイルし、実行する機能を提供する。スクリプトは状態を保持しながら連続して実行でき、REPL (Read-Eval-Print Loop) 環境やスクリプトファイル (.csx) の実行に使用される。

**業務上の目的・背景**：.NET アプリケーションにスクリプティング機能を組み込みたい場面や、C# を使った簡単なスクリプト作成、インタラクティブな実験環境が必要な場面に対応する。コンパイル・ビルドのサイクルを省略し、素早くコードを試行できる。

**機能の利用シーン**：
- csi.exe (C# Interactive) での対話的なコード実行
- .csx スクリプトファイルの実行
- アプリケーションへのスクリプト機能の埋め込み

**主要な処理内容**：
1. ソースコードのパース
2. セマンティック分析とコンパイル
3. IL 生成とメモリ内アセンブリ作成
4. スクリプトの実行と結果の取得
5. スクリプト状態の管理（変数、using など）

**関連システム・外部連携**：Roslyn コンパイラ、.NET ランタイム、NuGet パッケージ参照。

**権限による制御**：スクリプト実行時のファイルアクセス権限、ネットワークアクセス権限は呼び出し元プロセスの権限に従う。

## 関連画面

本機能はライブラリ/API として提供され、直接的な UI 画面は持たない。

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | API 呼び出しによるスクリプト実行 |

## 機能種別

スクリプト実行 / コンパイル / ランタイム

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| code | string/Stream | Yes | スクリプトのソースコード | null チェック |
| options | ScriptOptions | No | スクリプトオプション | デフォルトで ScriptOptions.Default |
| globalsType | Type | No | グローバル変数の型 | null 許容 |
| globals | object | No | グローバル変数のインスタンス | globalsType と一致 |
| assemblyLoader | InteractiveAssemblyLoader | No | アセンブリローダー | null 許容 |

### 入力データソース

- 文字列またはストリームとしてのソースコード
- ScriptOptions による参照・インポート設定

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Script<T> | Script<T> | コンパイル済みスクリプトオブジェクト |
| ScriptState<T> | ScriptState<T> | 実行後のスクリプト状態 |
| ReturnValue | T | スクリプトの戻り値 |
| Variables | ImmutableArray<ScriptVariable> | 宣言された変数一覧 |
| Exception | Exception | 実行時例外（catchException で捕捉した場合） |

### 出力先

- メソッド戻り値

## 処理フロー

### 処理シーケンス

```
1. スクリプト作成
   └─ CSharpScript.Create<T>(code, options, globalsType, assemblyLoader)
2. コンパイル
   └─ script.Compile() でコンパイルと診断情報取得
3. 実行
   └─ script.RunAsync(globals) でスクリプト実行
4. 結果取得
   └─ ScriptState から戻り値・変数を取得
5. 継続
   └─ script.ContinueWith(code) で次のスクリプトを連結
```

### フローチャート

```mermaid
flowchart TD
    A[CSharpScript.Create] --> B[Script<T> オブジェクト作成]
    B --> C[GetCompilation]
    C --> D[CSharpScriptCompiler.CreateSubmission]
    D --> E{コンパイルエラー?}
    E -->|Yes| F[CompilationErrorException]
    E -->|No| G[RunAsync]
    G --> H[GetExecutor]
    H --> I[ScriptBuilder.CreateExecutor]
    I --> J[IL 生成・アセンブリ作成]
    J --> K[スクリプト実行]
    K --> L[ScriptState<T> 返却]
    L --> M{ContinueWith?}
    M -->|Yes| N[次のスクリプト作成]
    N --> C
    M -->|No| O[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-95-01 | グローバル変数の検証 | globals の型が globalsType と一致する必要がある | globals != null の場合 |
| BR-95-02 | スクリプトチェーン | ContinueWith で連結されたスクリプトは前のスクリプトの状態を継承 | Previous != null の場合 |
| BR-95-03 | 参照継承 | ContinueWith 時は参照とインポートを継承せず適用済みとして扱う | InheritOptions メソッド |
| BR-95-04 | 例外キャッチ | catchException で true を返すと例外を ScriptState に格納 | catchException 指定時 |

### 計算ロジック

スクリプトのコンパイルは Submission として扱われ、前のスクリプトからの参照を自動的に解決する。

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

本機能はデータベースを直接操作しない。

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| - | - | - | データベース操作なし |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ArgumentNullException | code が null | code を指定 |
| - | ArgumentException | globals の型が不一致 | 正しい型を指定 |
| - | CompilationErrorException | コンパイルエラー | コードを修正 |
| - | 実行時例外 | スクリプト実行中のエラー | catchException で処理 |

### リトライ仕様

スクリプト実行のリトライは呼び出し元で制御する。

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

トランザクション不要。スクリプト実行は独立した操作。

## パフォーマンス要件

- 初回コンパイル: ソースサイズに依存
- 2回目以降: Executor キャッシュにより高速
- メモリ使用: スクリプト状態は明示的に解放されるまで保持

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

- スクリプトはホストプロセスと同じ権限で実行される
- 信頼できないスクリプトの実行には注意が必要
- AllowUnsafe オプションで unsafe コードを制御可能

## 備考

NuGet パッケージ `Microsoft.CodeAnalysis.CSharp.Scripting` として公開。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | CSharpScript.cs | `src/Scripting/CSharp/CSharpScript.cs` | C# スクリプトのファクトリクラス |

**主要処理フロー**:
- **33-38行目**: Create<T> - スクリプト作成（文字列入力）
- **50-55行目**: Create<T> - スクリプト作成（ストリーム入力）
- **98-101行目**: RunAsync<T> - スクリプト実行
- **128-131行目**: EvaluateAsync<T> - スクリプト評価と結果取得

#### Step 2: コアのスクリプトクラスを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Script.cs | `src/Scripting/Core/Script.cs` | Script 基底クラス、Script<T> ジェネリッククラス |

**主要処理フロー**:
- **39-52行目**: コンストラクタ - スクリプトの初期化
- **144-153行目**: GetCompilation - コンパイル取得
- **178-179行目**: RunAsync - スクリプト実行の開始
- **100-118行目**: ContinueWith<TResult> - スクリプトチェーン
- **231-234行目**: Compile - 明示的コンパイル
- **339-396行目**: Script<T>.GetExecutor - 実行デリゲート取得

#### Step 3: スクリプトオプションを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ScriptOptions.cs | `src/Scripting/Core/ScriptOptions.cs` | スクリプト実行オプション |

**主要プロパティ**:
- **25-37行目**: Default - デフォルトオプション
- **88行目**: MetadataReferences - メタデータ参照
- **103行目**: Imports - インポート
- **119行目**: FilePath - ファイルパス
- **134行目**: AllowUnsafe - unsafe 許可

#### Step 4: スクリプト状態を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | ScriptState.cs | `src/Scripting/Core/ScriptState.cs` | スクリプト実行状態 |
| 4-2 | ScriptVariable.cs | `src/Scripting/Core/ScriptVariable.cs` | スクリプト変数 |

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

```
CSharpScript (Static Factory)
    │
    └─ Create<T>(code, options, globalsType, assemblyLoader)
           └─ Script.CreateInitialScript<T>()
                  └─ new Script<T>()
                         │
                         ├─ GetCompilation()
                         │      └─ CSharpScriptCompiler.CreateSubmission()
                         │
                         ├─ Compile()
                         │      └─ GetExecutor()
                         │             └─ ScriptBuilder.CreateExecutor<T>()
                         │
                         ├─ RunAsync(globals)
                         │      ├─ ValidateGlobals()
                         │      ├─ GetPrecedingExecutors()
                         │      ├─ GetExecutor()
                         │      └─ RunSubmissionsAsync()
                         │             └─ ScriptState<T>
                         │
                         └─ ContinueWith<TResult>(code)
                                └─ new Script<TResult>(Previous = this)
```

### データフロー図

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

string code ─────────────▶ SourceText.From() ──────────────▶ SourceText
                                 │
                                 ▼
ScriptOptions ───────────▶ CSharpScriptCompiler ───────────▶ Compilation
                                 │
                                 ▼
globalsType/globals ─────▶ ScriptBuilder.CreateExecutor() ─▶ Func<object[], Task<T>>
                                 │
                                 ▼
                         RunSubmissionsAsync() ────────────▶ ScriptState<T>
                                 │                                │
                                 ▼                                ▼
                         ReturnValue ─────────────────────▶ T (戻り値)
                         Variables ───────────────────────▶ ScriptVariable[]
                         Exception ───────────────────────▶ Exception (オプション)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| CSharpScript.cs | `src/Scripting/CSharp/` | ソース | ファクトリクラス |
| CSharpScriptCompiler.cs | `src/Scripting/CSharp/` | ソース | コンパイラ実装 |
| Script.cs | `src/Scripting/Core/` | ソース | Script 基底クラス |
| ScriptOptions.cs | `src/Scripting/Core/` | ソース | オプションクラス |
| ScriptState.cs | `src/Scripting/Core/` | ソース | 実行状態 |
| ScriptVariable.cs | `src/Scripting/Core/` | ソース | 変数情報 |
| ScriptCompiler.cs | `src/Scripting/Core/` | ソース | コンパイラ抽象クラス |
| ScriptBuilder.cs | `src/Scripting/Core/` | ソース | 実行デリゲート生成 |
| ScriptExecutionState.cs | `src/Scripting/Core/` | ソース | 実行状態管理 |
| InteractiveAssemblyLoader.cs | `src/Scripting/Core/Hosting/` | ソース | アセンブリローダー |
