# 機能設計書 55-式オブジェクト（Expr）

## 概要

本ドキュメントは、Julia の `Expr` / `QuoteNode` / `quote ... end` による抽象構文木（AST）の構築と操作機能の設計を記述する。

### 本機能の処理概要

本機能は、Julia プログラムのソースコードを内部的に表現する抽象構文木（AST）の構築・操作・比較を提供する。`Expr` 型は Julia の式を表すコアデータ構造であり、`head`（式の種類を示すシンボル）と `args`（子要素のリスト）で構成される。メタプログラミング、マクロ定義、コード生成、コンパイラ内部処理の基盤となる。

**業務上の目的・背景**: Julia のメタプログラミングの中核を成す。プログラムをデータとして操作する（ホモイコニシティ）ことで、マクロによるコード変換、@generated 関数によるステージドプログラミング、コンパイラ解析・最適化を実現する。Lisp 系言語のS式に相当する、Julia コードの構造的な表現を提供する。

**機能の利用シーン**: マクロ定義内での式操作、`Meta.parse` によるコード文字列のAST変換、`quote ... end` / `:()` によるリテラル式の構築、`$` による補間、IR（中間表現）の構築・変換（PhiNode, GotoIfNot 等）、コンパイラ内部でのコード解析。

**主要な処理内容**:
1. `Expr(head, args...)` による式オブジェクトの構築
2. `quote ... end` / `:()` による式のクォーティング
3. `$` による式内への値の補間（アンクォート）
4. `QuoteNode(value)` による値の不活性クォート
5. `copy(::Expr)` による式のディープコピー
6. `==(::Expr, ::Expr)` による式の構造的等値比較
7. `isexpr(ex, head)` による式の種別判定
8. IR ノード型（PhiNode, PhiCNode, GotoNode, ReturnNode 等）の操作

**関連システム・外部連携**: パーサー（JuliaSyntax.jl）による文字列→Expr変換、lowering フェーズでの Expr→IR 変換、コンパイラの抽象解釈・最適化パスでの IR 操作。

**権限による制御**: 特に権限制御は行われない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 2 | Juliaプロンプト（julia>） | 補助機能 | 入力文字列の Meta.parse による AST 構築と REPL バックエンドでの式評価 |
| 3 | ヘルプモード（help?>） | 補助機能 | Meta.parse による入力の AST 解析。キーワード/演算子/マクロの判定に使用 |
| 11 | フォールバックREPL | 補助機能 | parse_input_line() による入力の AST 構築。:toplevel ノードの逐次評価 |

## 機能種別

データ構造（抽象構文木の表現と操作）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| head | Symbol | Yes (Expr) | 式の種類（:call, :block, :if, :function 等） | 有効な Symbol |
| args | Vector{Any} | Yes (Expr) | 式の子要素リスト | Array{Any,1} |
| value | Any | Yes (QuoteNode) | クォートする値 | 任意の値 |
| ex | Any | Yes (isexpr) | 判定対象の式 | 任意 |
| heads | Symbol / tuple | Yes (isexpr) | 判定対象のヘッドシンボル | Symbol または Symbol のコレクション |

### 入力データソース

ユーザーコードから直接構築、またはパーサーの出力として生成。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Expr | Expr | head と args を持つ式オブジェクト |
| QuoteNode | QuoteNode | 不活性にクォートされた値 |
| isexpr 結果 | Bool | 式が指定されたヘッドを持つかどうか |
| copy 結果 | Expr / PhiNode / CodeInfo | 式のディープコピー |
| == 結果 | Bool | 2つの式の構造的等値性 |

### 出力先

関数の戻り値として返却。マクロやコンパイラパスで使用。

## 処理フロー

### 処理シーケンス

```
1. 式の構築
   └─ Expr(head, args...) / quote ... end / :()
   └─ QuoteNode(value) で値を不活性にクォート
2. 式の操作
   └─ ex.head で種別アクセス
   └─ ex.args で子要素アクセス
   └─ push!(ex.args, child) で子要素追加
3. 式の複製
   └─ copy(::Expr) で再帰的ディープコピー
   └─ copy_exprargs で引数配列のコピー
4. 式の比較
   └─ ==(::Expr, ::Expr) で head と args の再帰的比較
   └─ isequal_exprarg で個別要素の比較
5. 式の判定
   └─ isexpr(ex, head) / isexpr(ex, head, n)
   └─ is_function_def / is_short_function_def
   └─ isa_ast_node / is_self_quoting
```

### フローチャート

```mermaid
flowchart TD
    A["ソースコード / マクロ"] --> B{構築方法}
    B -->|"Expr(head, args)"| C["Expr オブジェクト"]
    B -->|"quote ... end"| C
    B -->|":(...)"| C
    B -->|"QuoteNode(val)"| D["QuoteNode オブジェクト"]
    C --> E{操作}
    E -->|アクセス| F["ex.head / ex.args"]
    E -->|判定| G["isexpr(ex, :head)"]
    E -->|コピー| H["copy(ex)"]
    E -->|比較| I["ex1 == ex2"]
    E -->|マクロ展開| J["macroexpand"]
    E -->|lowering| K["コンパイラへ"]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-55-1 | 構造的等値性 | Expr の == は head の同一性と args の再帰的等値性で判定 | == 演算子使用時 |
| BR-55-2 | QuoteNode の不活性性 | QuoteNode 内の値は $ 補間やマクロ展開で評価されない | quote 内で使用時 |
| BR-55-3 | AST ノード判定 | isa_ast_node は AST/IR として特別扱いされる型を判定 | コード生成時 |
| BR-55-4 | self-quoting | is_self_quoting は AST ノードでない値（数値、文字列等）を判定 | クォート処理時 |
| BR-55-5 | ディープコピー | copy(::Expr) は args 配列と IR ノード（PhiNode 等）を再帰的にコピー | 式の複製時 |

### 計算ロジック

特別な計算ロジックは存在しない。AST のツリー構造操作が主要な処理。

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

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ErrorException | findmeta で非関数式に対して呼び出し | 関数定義式に対してのみ使用 |
| - | BoundsError | ex.args のインデックス範囲外アクセス | args の長さを事前確認 |

### リトライ仕様

該当なし。

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

該当なし。

## パフォーマンス要件

- Expr は比較的軽量なオブジェクト
- copy は再帰的にツリーを走査するため、大きな AST では O(n) のコスト
- == 比較も再帰的で O(n)

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

Expr を eval で評価する場合、任意コード実行のリスクがある。信頼できないソースから構築された Expr の eval は避けるべき。

## 備考

- Expr は Julia のホモイコニシティ（コードがデータ）の基盤
- IR ノード型（PhiNode, GotoNode 等）はコンパイラ内部の SSA IR で使用される
- CodeInfo は関数の中間表現を保持し、copy で完全なディープコピーが可能

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | boot.jl | `base/boot.jl` | Expr 型は Core で定義。head::Symbol と args::Vector{Any} の2フィールド |
| 1-2 | expr.jl | `base/expr.jl` | exprarray（81行目）: Expr の内部コンストラクタ。`Expr(:new, :Expr, :head, :arg)` |
| 1-3 | expr.jl | `base/expr.jl` | isexpr 関数（1行目, 3-4行目, 42-43行目）: 4つのオーバーロード |

**読解のコツ**: `Expr` は Julia の最も基本的なメタプログラミング型。`:call` ヘッドは関数呼び出し、`:block` はコードブロック、`:if` は条件分岐など、ヘッドシンボルが式の種類を決定する。`args` は任意の値を持てる Vector{Any}。

#### Step 2: 式のコピーと比較を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | expr.jl | `base/expr.jl` | copy(::Expr)（45行目）: exprarray で新しい Expr を生成し、args を copy_exprargs でディープコピー |
| 2-2 | expr.jl | `base/expr.jl` | copy(::PhiNode)（46-55行目）: PhiNode のディープコピー。未定義要素のハンドリング |
| 2-3 | expr.jl | `base/expr.jl` | copy(::CodeInfo)（84-97行目）: ccall(:jl_copy_code_info) + ミュータブルフィールドのコピー |
| 2-4 | expr.jl | `base/expr.jl` | copy_exprs / copy_exprargs（69-79行目）: IR コピーのヘルパー関数 |
| 2-5 | expr.jl | `base/expr.jl` | ==(::Expr, ::Expr)（135行目）: head の同一性 + args の再帰的比較 |
| 2-6 | expr.jl | `base/expr.jl` | isequal_exprarg / isequal_exprargs（99-131行目）: 個別要素・配列の等値比較 |

**主要処理フロー**:
- **45行目**: `copy(e::Expr) = exprarray(e.head, copy_exprargs(e.args))`
- **79行目**: `copy_exprargs(x) = Any[copy_exprs(x[i]) for i in eachindex(x)]`
- **135行目**: `==(x::Expr, y::Expr) = x.head === y.head && isequal_exprargs(x.args, y.args)`

#### Step 3: ユーティリティ関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | expr.jl | `base/expr.jl` | remove_linenums!（1212-1229行目）: 式からの行番号メタデータ除去 |
| 3-2 | expr.jl | `base/expr.jl` | replace_linenums!（1231-1249行目）: 行番号の一括置換 |
| 3-3 | expr.jl | `base/expr.jl` | isa_ast_node（1769-1789行目）: AST/IR 特殊ノード型の判定 |
| 3-4 | expr.jl | `base/expr.jl` | is_self_quoting（1791行目）: AST ノードでない値の判定 |
| 3-5 | expr.jl | `base/expr.jl` | quoted（1801行目）: AST ノードを QuoteNode で安全にラップ |

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

```
Expr(head, args...)
    │
    ├─ isexpr(ex, head) / isexpr(ex, head, n) → Bool
    │
    ├─ copy(ex::Expr)
    │      └─ exprarray(head, copy_exprargs(args))
    │             └─ copy_exprs(arg) [各要素]
    │                    ├─ copy(::Expr) [再帰]
    │                    ├─ copy(::PhiNode)
    │                    └─ copy(::PhiCNode)
    │
    ├─ ==(ex1::Expr, ex2::Expr)
    │      └─ isequal_exprargs(args1, args2)
    │             └─ isequal_exprarg(x, y) [各要素]
    │
    ├─ remove_linenums!(ex)
    │      └─ filter!(args) + 再帰的 remove_linenums!
    │
    └─ quoted(x)
           └─ isa_ast_node(x) ? QuoteNode(x) : x
```

### データフロー図

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

ソースコード              → パーサー                 → Expr ツリー
  "1 + 2"                   Meta.parse("1+2")         Expr(:call, :+, 1, 2)

Expr ツリー               → マクロ展開               → 変換後 Expr
  Expr(:macrocall, ...)      macroexpand(mod, ex)

Expr ツリー               → lowering                 → CodeInfo (IR)
                             jl_fl_lower

Expr ツリー               → copy                     → 新しい Expr ツリー
                             再帰的コピー
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| expr.jl | `base/expr.jl` | ソース | Expr 操作ユーティリティ、コピー、比較、マクロ関連関数 |
| boot.jl | `base/boot.jl` | ソース | Expr 型の Core レベル定義 |
| meta.jl | `base/meta.jl` | ソース | Meta モジュール（parse, show_sexpr 等） |
| show.jl | `base/show.jl` | ソース | Expr の表示（show）実装 |
