# 機能設計書 135-深いコピー

## 概要

本ドキュメントは、Julia の `copy` / `deepcopy` によるオブジェクトのシャローコピーとディープコピー機能について、その設計・処理仕様を記述するものである。

### 本機能の処理概要

`deepcopy` 関数は、Julia のオブジェクトを再帰的に完全コピーし、元のオブジェクトから完全に独立した新しいオブジェクトを生成する機能である。循環参照や共有構造を正しく処理し、コピー済みオブジェクトの追跡により無限再帰を防止する。

**業務上の目的・背景**：ミュータブルなオブジェクトを変更する際に、元のオブジェクトに影響を与えたくない場合がある。`copy` は浅いコピー（第一階層のみ）を行い、`deepcopy` は全階層の再帰的コピーを行う。特に、ネストされたデータ構造（配列の配列、辞書のネストなど）を安全に複製する際に不可欠である。

**機能の利用シーン**：ミュータブルデータ構造の安全な複製、関数引数の防御的コピー、テスト用データの独立したコピー作成、アルゴリズムの状態保存とロールバックなど。

**主要な処理内容**：
1. `deepcopy(x)` -- isbitstype の高速パス判定
2. `deepcopy_internal(x, stackdict)` -- IdDict による循環参照の追跡と型別再帰コピー
3. ミュータブル構造体のコピー（`jl_new_struct_uninit` + フィールドごとの再帰コピー）
4. イミュータブル構造体のコピー（`jl_new_structv` による新規構築）
5. Array / Memory / MemoryRef のコピー（メモリレベルの複製）
6. Dict / IdDict のコピー（キー・値の再帰コピー）
7. String のコピー（unsafe_string によるバイトレベルの複製）
8. Lock / Condition の特殊コピー（新しいインスタンスとして再初期化）

**関連システム・外部連携**：Julia ランタイムの C API（jl_new_struct_uninit / jl_set_nth_field / jl_new_structv）、GC システム、メモリ管理システムと連携する。

**権限による制御**：特に権限による制御はない。Module の deepcopy はエラーとなる。

## 関連画面

本機能は特定の画面との紐付けはない。

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | REPLやスクリプトから deepcopy / copy を呼び出して利用する |

## 機能種別

ユーティリティ / データ操作

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| x | Any | Yes | コピー対象のオブジェクト | Module の場合はエラー |

### 入力データソース

Julia のコード内での直接利用。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| コピー結果 | typeof(x) | 入力と同じ型の完全独立したコピー |

### 出力先

呼び出し元への戻り値。

## 処理フロー

### 処理シーケンス

```
1. deepcopy(x) の呼び出し
   └─ isbitstype チェック。true なら即座に x を返す（コピー不要）
2. deepcopy_internal(x, IdDict()) の呼び出し
   └─ 空の IdDict を stackdict として初期化
3. 型に応じた処理分岐
   a. Symbol/MethodInstance/Method/GlobalRef/DataType/Union/UnionAll/Task/Regex → x をそのまま返す（不変型）
   b. Tuple → 各要素を再帰的に deepcopy_internal
   c. Module → エラー（deepcopy of Modules not supported）
   d. SimpleVector → 各要素を再帰的にコピー
   e. String → unsafe_string でバイトコピー
   f. Array → undef 配列を作成し、ref と size をコピー
   g. Memory → isbitstype なら copy、そうでなければ要素ごとに再帰コピー
   h. Dict/IdDict → isbitstype(eltype) なら copy、そうでなければキー・値を再帰コピー
   i. AbstractLock → 新しいインスタンスとして再初期化
   j. GenericCondition → lock を再帰コピーして新しいインスタンスを構築
   k. ミュータブル構造体 → jl_new_struct_uninit + フィールドごとの再帰コピー
   l. イミュータブル構造体 → フィールドを収集して jl_new_structv で新規構築
4. stackdict への登録
   └─ コピーしたオブジェクトを stackdict に登録し、循環参照で同じオブジェクトが再度処理されるのを防ぐ
```

### フローチャート

```mermaid
flowchart TD
    A["deepcopy(x)"] --> B{"isbitstype(typeof(x))?"}
    B -->|Yes| C["x を返す"]
    B -->|No| D["deepcopy_internal(x, IdDict())"]
    D --> E{"型で分岐"}
    E -->|Symbol等の不変型| F["x を返す"]
    E -->|Module| G["エラー"]
    E -->|Tuple| H["各要素を再帰コピー"]
    E -->|String| I["unsafe_string でバイトコピー"]
    E -->|Array| J["undef配列 + ref/size コピー"]
    E -->|Memory| K{"isbitstype(T)?"}
    K -->|Yes| L["copy(x)"]
    K -->|No| M["要素ごとに再帰コピー"]
    E -->|Dict| N{"isbitstype(eltype)?"}
    N -->|Yes| O["copy(x)"]
    N -->|No| P["キー・値を再帰コピー"]
    E -->|ミュータブル構造体| Q["jl_new_struct_uninit + フィールドコピー"]
    E -->|イミュータブル構造体| R["jl_new_structv で新規構築"]
    E -->|Lock| S["typeof(x)() で再初期化"]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-135-01 | isbitstype 高速パス | isbitstype のオブジェクトはコピー不要（値型として振る舞う） | isbitstype(typeof(x)) == true |
| BR-135-02 | 循環参照追跡 | IdDict で既にコピー済みのオブジェクトを追跡し、同一オブジェクトのコピーは共有する | mutable 型 |
| BR-135-03 | 不変型の非コピー | Symbol / DataType / Method 等は immutable かつシステム管理されるため、コピーせずそのまま返す | 該当型 |
| BR-135-04 | Module コピー禁止 | Module の deepcopy はサポートされず、エラーをスロー | Module 型 |
| BR-135-05 | Lock の再初期化 | Lock / Condition のコピーは新しいインスタンスとして再初期化する（ロック状態はコピーしない） | AbstractLock / GenericCondition |
| BR-135-06 | isbits 要素最適化 | Array / Memory / Dict で要素が isbits なら copy で高速コピー | isbitstype(eltype) |

### 計算ロジック

**ミュータブル構造体のコピー**（64-78行目）:
1. `jl_new_struct_uninit` で未初期化のインスタンスを作成
2. stackdict に登録（循環参照対策）
3. 各フィールドについて: isdefined チェック -> isbits チェック -> 非isbits なら再帰コピー -> `jl_set_nth_field` で設定

**イミュータブル構造体のコピー**（79-98行目）:
1. nfields == 0 または isbitstype なら x をそのまま返す
2. フィールドを Vector{Any} に収集（各フィールドを再帰コピー）
3. `jl_new_structv` で新しいインスタンスを構築

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

本機能はデータベース操作を行わない。

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

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ErrorException | `deepcopy(module)` の呼び出し | Module のコピーは非サポート。代替手段を検討する |

### リトライ仕様

該当なし。

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

該当なし。

## パフォーマンス要件

- isbitstype の高速パスにより、値型のコピーは即座に完了する
- IdDict による O(1) の循環参照チェック
- isbits 要素の配列・辞書は `copy` による一括コピー
- deepcopy は低速であり、公式ドキュメントでは可能な限り `copy` やカスタムコピーの使用を推奨

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

- `ccall` で C ランタイム関数を直接呼び出しているため、型安全性はランタイムに依存する
- `unsafe_string` による String のコピーは GC.@preserve で安全に行われる

## 備考

- 公式ドキュメントでは `deepcopy` の使用は推奨されず、カスタム `copy` メソッドの実装が推奨されている（docstring 参照）
- `deepcopy_internal` はライブラリが型ごとの特殊化を提供するためにのみ公開されている
- `deepcopy` は serialize/deserialize と概念的に等価（docstring: "Calling deepcopy on an object should generally have the same effect as serializing and then deserializing it"）

---

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

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

### 推奨読解順序

#### Step 1: エントリーポイントと高速パスを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | deepcopy.jl | `base/deepcopy.jl` | **32-35行目**: `deepcopy(x)` -- isbitstype チェック後に deepcopy_internal を呼び出す |

**読解のコツ**: `isbitstype` は型がポインタを含まない純粋な値型かどうかを判定する。isbitstype なら、変数の代入で既にコピーされるため deepcopy は不要。

#### Step 2: 不変型の即時返却を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | deepcopy.jl | `base/deepcopy.jl` | **37-41行目**: 不変型の特殊化（Symbol, DataType, Module 等） |

**主要処理フロー**:
- **37-38行目**: Symbol / MethodInstance / Method / GlobalRef / DataType / Union / UnionAll / Task / Regex はそのまま返す
- **39-40行目**: Tuple は各要素を再帰的に deepcopy_internal
- **41行目**: Module はエラー

#### Step 3: 構造体のコピーを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | deepcopy.jl | `base/deepcopy.jl` | **61-98行目**: 汎用 deepcopy_internal -- ミュータブル/イミュータブルの分岐 |

**主要処理フロー**:
- **62行目**: `T = typeof(x)::DataType` -- 型を取得
- **64行目**: `ismutable(x)` でミュータブル/イミュータブルを判定
- **64-78行目**: ミュータブル: `jl_new_struct_uninit` -> stackdict 登録 -> フィールドごとの再帰コピー
- **79-98行目**: イミュータブル: nfields==0/isbitstype なら即返却、そうでなければフィールド収集 -> `jl_new_structv`

#### Step 4: コレクション型のコピーを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | deepcopy.jl | `base/deepcopy.jl` | **100-127行目**: Memory のコピー（isbitstype 分岐 + 要素ごとの再帰コピー）|
| 4-2 | deepcopy.jl | `base/deepcopy.jl` | **128-146行目**: Array / GenericMemoryRef のコピー |
| 4-3 | deepcopy.jl | `base/deepcopy.jl` | **149-164行目**: Dict / IdDict のコピー |

#### Step 5: 特殊型のコピーを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | deepcopy.jl | `base/deepcopy.jl` | **43-50行目**: SimpleVector のコピー |
| 5-2 | deepcopy.jl | `base/deepcopy.jl` | **52-59行目**: String のコピー（unsafe_string + GC.@preserve）|
| 5-3 | deepcopy.jl | `base/deepcopy.jl` | **166-182行目**: AbstractLock / GenericCondition のコピー（再初期化）|

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

```
deepcopy(x)
    |
    +-- [isbitstype] → x を返す
    |
    +-- deepcopy_internal(x, IdDict())
            |
            +-- [Symbol等] → x を返す
            +-- [Module] → error
            +-- [Tuple] → ntuple(deepcopy_internal)
            +-- [String] → unsafe_string(pointer, sizeof)
            +-- [Array] → Array{T,N}(undef, ...) + deepcopy_internal(ref)
            +-- [Memory]
            |       +-- [isbitstype] → copy(x)
            |       +-- [else] → 要素ごとに deepcopy_internal
            +-- [Dict]
            |       +-- [isbitstype(eltype)] → copy(x)
            |       +-- [else] → キー・値ごとに deepcopy_internal
            +-- [mutable struct]
            |       +-- jl_new_struct_uninit
            |       +-- stackdict[x] = y
            |       +-- フィールドごとに deepcopy_internal → jl_set_nth_field
            +-- [immutable struct]
                    +-- [nf==0 or isbitstype] → x を返す
                    +-- [else] → フィールド収集 → jl_new_structv
```

### データフロー図

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

deepcopy([1, [2, 3]])       --> Array deepcopy_internal
                                 +-- ref の deepcopy_internal
                                     +-- Memory deepcopy_internal
                                         +-- 要素 1: isbits → そのまま
                                         +-- 要素 [2,3]: 再帰コピー  --> [1, [2, 3]] (独立コピー)

deepcopy(Dict(1=>"a"))      --> Dict deepcopy_internal
                                 +-- キー 1: isbits → そのまま
                                 +-- 値 "a": String コピー     --> Dict(1=>"a") (独立コピー)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| deepcopy.jl | `base/deepcopy.jl` | ソース | deepcopy / deepcopy_internal の全実装 |
| essentials.jl | `base/essentials.jl` | ソース | isbitstype / ismutable の定義 |
| array.jl | `base/array.jl` | ソース | copy(Array) の定義（shallow copy） |
| dict.jl | `base/dict.jl` | ソース | copy(Dict) の定義（shallow copy） |
| genericmemory.jl | `base/genericmemory.jl` | ソース | Memory 型の定義 |
| lock.jl | `base/lock.jl` | ソース | ReentrantLock / Condition の定義 |
| test/copy.jl | `test/copy.jl` | テスト | copy / deepcopy の回帰テスト |
