# 機能設計書 58-eval

## 概要

本ドキュメントは、Julia の `eval` / `@eval` によるプログラム実行時のコード評価機能の設計を記述する。

### 本機能の処理概要

本機能は、Julia の式（Expr）をプログラム実行時に動的に評価（eval）する機能を提供する。`Core.eval(m, expr)` は指定モジュール `m` のグローバルスコープで式を評価し、その結果を返す。`@eval` マクロは構文糖衣であり、式の補間（`$`）を使った便利な eval 呼び出しを提供する。REPL の対話的実行、`include` によるファイル読み込み、動的なコード生成・実行の基盤となるプリミティブ。

**業務上の目的・背景**: プログラムの実行中に動的にコードを生成・実行する必要がある場面で不可欠。REPL の対話的実行（ユーザー入力の逐次評価）、`include` によるソースファイルの読み込み・評価、メタプログラミングでの動的定義生成、プラグインシステムでの拡張コード実行などに使用される。

**機能の利用シーン**: REPL でのユーザー入力評価、`include` によるファイル読み込み、パッケージ読み込み時のモジュール初期化、動的なメソッド定義・型定義、スクリプトの動的実行。

**主要な処理内容**:
1. `Core.eval(m::Module, expr)` によるモジュール内での式の評価
2. `@eval expr` による現在モジュールでの式の評価
3. `@eval m expr` による指定モジュールでの式の評価
4. `include_string` による文字列コードの評価（内部的に `Core.eval` を使用）

**関連システム・外部連携**: Julia パーサー（文字列→Expr 変換）、lowering フェーズ（Expr→IR 変換）、JIT コンパイラ（IR→ネイティブコード変換）、REPL（対話的評価）。

**権限による制御**: eval は指定されたモジュールのグローバルスコープで実行されるため、モジュールの可視性に依存。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 2 | Juliaプロンプト（julia>） | 主機能 | 入力された Julia 式を eval で評価し結果を返す REPL バックエンドの中核処理 |
| 11 | フォールバックREPL | 主機能 | eval_user_input() による Julia 式の評価。行編集・補完なしの最小限 eval-print ループ |

## 機能種別

計算処理（動的コード評価）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| m | Module | Yes (Core.eval) / 暗黙 (@eval) | 式を評価するモジュールコンテキスト | 有効な Module |
| expr | Any | Yes | 評価対象の式 | 有効な Julia 式（Expr, Symbol, リテラル等） |

### 入力データソース

ユーザーコード、パーサー出力、マクロ出力、`include_string` 経由のソースコード。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 評価結果 | Any | 式を評価した結果の値 |

### 出力先

関数の戻り値として呼び出し元に返却。副作用としてグローバル変数の定義、メソッドの追加、型の定義等が発生しうる。

## 処理フロー

### 処理シーケンス

```
1. 式の受取
   └─ Core.eval(m, expr) または @eval expr
2. マクロ展開
   └─ 式内のマクロ呼び出しを展開
3. lowering
   └─ 高レベル AST を低レベル IR（CodeInfo）に変換
4. 型推論・最適化
   └─ コンパイラによる型推論と最適化パスの適用
5. コード生成
   └─ LLVM IR → ネイティブコードの生成
6. 実行
   └─ 生成されたネイティブコードの実行
7. 結果返却
   └─ 評価結果を呼び出し元に返す
```

### フローチャート

```mermaid
flowchart TD
    A["Core.eval(m, expr)"] --> B["マクロ展開"]
    B --> C["lowering (AST → IR)"]
    C --> D["型推論・最適化"]
    D --> E["コード生成 (LLVM)"]
    E --> F["ネイティブコード実行"]
    F --> G["結果返却"]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-58-1 | グローバルスコープ | eval は常にモジュールのグローバルスコープで実行される。ローカル変数を生成しない | 常時 |
| BR-58-2 | ワールドエイジ | eval で定義されたメソッドは次のワールドエイジまで呼び出し元から見えない | メソッド定義時 |
| BR-58-3 | @eval の補間 | @eval 内の $ は eval 前にローカルスコープで評価される | @eval 使用時 |
| BR-58-4 | :toplevel ラッピング | include_string は式を Expr(:toplevel, loc, ex) でラップして eval する | include_string 使用時 |

### 計算ロジック

eval 自体は式をコンパイル・実行するプリミティブ。具体的な計算は評価される式の内容に依存。

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

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | LoadError | include_string 経由の eval でエラー発生 | ソースコードを修正 |
| - | 構文エラー | 式が無効な構文の場合 | 式の構文を修正 |
| - | UndefVarError | 未定義変数の参照 | 変数を定義するか適切なモジュールを指定 |
| - | MethodError | 未定義メソッドの呼び出し | メソッドを定義 |
| - | 任意の例外 | 式の実行中にエラーが発生 | 式の内容を修正 |

### リトライ仕様

該当なし。

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

eval は原子的でない。途中でエラーが発生した場合、それまでの副作用（変数定義等）はロールバックされない。

## パフォーマンス要件

- eval は JIT コンパイルパイプライン全体を通すため、初回実行にコンパイルコストが発生する
- ホットパス内での eval は避けるべき（パフォーマンス上の理由）
- `invokelatest` を使用することでワールドエイジ問題を回避可能だが追加コストあり

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

eval は任意のコードを実行できるため、信頼できない入力を eval に渡すことは避けるべき。コードインジェクション攻撃のリスクがある。

## 備考

- `eval` は REPL の基盤であり、Julia の対話的プログラミング体験の中核
- ワールドエイジ問題: eval で定義されたメソッドは `invokelatest` を使わないと同一関数内から呼べない
- `Base.@eval` はモジュールコンテキスト付きの eval、`Core.eval` はプリミティブ

---

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

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

### 推奨読解順序

#### Step 1: Core.eval の定義を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | expr.jl | `base/expr.jl` | Core.eval の docstring（295-298行目）: 「モジュール内で式を評価し結果を返す」 |

**読解のコツ**: `Core.eval` は C ランタイムで実装されたプリミティブ。Julia ソースでは docstring のみが定義されている。実際の実装は `src/toplevel.c` の `jl_toplevel_eval_in` にある。

#### Step 2: include_string での eval 使用を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | loading.jl | `base/loading.jl` | include_string（3085-3138行目）: パース→式ごとに Core.eval を呼び出し |

**主要処理フロー**:
- **3089行目**: `Meta.parseall(code; filename, _parse)` でソースコード全体をパース
- **3098行目**: `for ex in ast.args` で各式をイテレート
- **3104行目**: `ex = mapexpr(ex)` でオプショナルな式変換を適用
- **3107行目**: `line_and_ex.args[2] = ex` で式を :toplevel ラッパーに設定
- **3130行目**: `result = Core.eval(mod, line_and_ex)` で各式を評価

#### Step 3: REPL での eval 使用を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | loading.jl | `base/loading.jl` | evalfile（3225-3234行目）: 匿名モジュール内での eval。Module(:__anon__) を生成して include を実行 |

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

```
Core.eval(m::Module, expr)  [C プリミティブ]
    │
    ├─ マクロ展開 (jl_macroexpand)
    ├─ lowering (jl_fl_lower)
    ├─ 型推論 (typeinf)
    ├─ 最適化 (optimize)
    ├─ コード生成 (codegen)
    └─ 実行

include_string(mapexpr, mod, code, filename)
    │
    ├─ Meta.parseall(code) → AST
    └─ for ex in ast.args
           ├─ mapexpr(ex) → 変換後の式
           └─ Core.eval(mod, Expr(:toplevel, loc, ex))

@eval expr
    └─ Core.eval(__module__, :(expr))

evalfile(path)
    ├─ Module(:__anon__) → 匿名モジュール
    └─ Core.eval(m, Expr(:toplevel, ..., include(path)))
```

### データフロー図

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

Julia 式 (Expr)           → Core.eval(m, expr)            → 評価結果 (Any)
                              マクロ展開
                              lowering
                              型推論・最適化
                              コード生成
                              実行

ソースコード (String)     → include_string(m, code)       → 最後の式の結果
                              parseall → AST
                              for each expr:
                                Core.eval(m, expr)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| expr.jl | `base/expr.jl` | ソース | Core.eval の docstring |
| loading.jl | `base/loading.jl` | ソース | include_string, evalfile の実装。eval を使ったファイル読み込み |
| toplevel.c | `src/toplevel.c` | ソース (C) | jl_toplevel_eval_in の実装。eval の C ランタイム |
| Base.jl | `base/Base.jl` | ソース | EvalInto 構造体の定義。モジュール付き eval のラッパー |
