# 機能設計書 59-モジュールシステム

## 概要

本ドキュメントは、Julia の `module` / `baremodule` 定義と `export` / `public` / `import` / `using` によるモジュール機構の設計を記述する。

### 本機能の処理概要

本機能は、Julia のモジュールシステムを提供する。モジュールは名前空間の分離とコードの組織化のための基本単位であり、`module` キーワードで定義する。`export` で外部に公開するシンボルを指定し、`import` / `using` で他のモジュールのシンボルを取り込む。名前の衝突を防ぎ、コードの再利用を促進し、パッケージシステムの基盤となる。

**業務上の目的・背景**: 大規模なコードベースでは名前空間の分離が不可欠。モジュールシステムにより、異なるパッケージが同じ名前の関数を定義しても衝突せず、明示的な `using` / `import` でアクセスを制御できる。Julia のパッケージエコシステムの基盤であり、コードの配布・再利用・バージョン管理を支える。

**機能の利用シーン**: パッケージの定義（`module MyPackage ... end`）、名前空間の分離、関数のエクスポート/インポート、パッケージの使用（`using LinearAlgebra`）、選択的インポート（`using Dates: Date, DateTime`）、メソッドの拡張（`import Base: show`）。

**主要な処理内容**:
1. `module Name ... end` によるモジュール定義（暗黙的に Base を using）
2. `baremodule Name ... end` による最小モジュール定義（Core のみ import）
3. `export name1, name2, ...` によるシンボルの公開宣言
4. `public name1, name2, ...` による公開 API の宣言（Julia 1.11+）
5. `import A` / `import A: x, y` によるシンボルのインポート（メソッド拡張可能）
6. `using A` によるモジュール全体のエクスポートシンボルの取り込み
7. `using A: x, y` による選択的シンボルの取り込み
8. `import A as B` / `import A: x as y` によるリネーム

**関連システム・外部連携**: パッケージローダー（`require`）、プリコンパイルシステム、LOAD_PATH、パーサー（import/using 文の解析）。

**権限による制御**: モジュールの可視性に基づくアクセス制御。`export` されていないシンボルは `Module.name` の形式でアクセス可能だが、`public` でないシンボルは内部実装とみなされる。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 2 | Juliaプロンプト（julia>） | 補助機能 | プロンプトにアクティブモジュール名を表示。using/import によるモジュール操作を REPL から実行 |

## 機能種別

インフラストラクチャ（名前空間管理）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| モジュール名 | Symbol | Yes | 定義するモジュールの名前 | 有効な Julia 識別子 |
| imported | Bool | 暗黙 | true で import セマンティクス、false で using セマンティクス | - |
| to | Module | 暗黙 | インポート先のモジュール | 有効な Module |
| from | Expr / Nothing | No | インポート元のモジュールパス | 有効なモジュールパス式 |
| paths | Expr... | Yes | インポートする名前のパス | 有効な名前パス式 |

### 入力データソース

Julia ソースコードの import/using/export 文。パーサーにより lowered された内部表現。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Module | Module | module 定義により生成されたモジュールオブジェクト |
| バインディング | Core.Binding | import/using により作成されたシンボルバインディング |

### 出力先

モジュールオブジェクトは親スコープのバインディングとして登録。import/using によるバインディングは対象モジュールに追加。

## 処理フロー

### 処理シーケンス

```
1. モジュール定義（module Name ... end）
   └─ Module オブジェクトの生成
   └─ 暗黙的な using Core / using Base（baremodule でない場合）
   └─ 本体の評価
2. import/using 文の評価
   └─ _eval_import / _eval_using 関数の呼び出し
   └─ eval_import_path でモジュールパスを解決
   └─ require でトップレベルモジュールをロード（必要な場合）
   └─ Core._import / Core._using でバインディングを作成
3. export/public 宣言
   └─ エクスポートリストへのシンボル追加
```

### フローチャート

```mermaid
flowchart TD
    A["import A.B: x, y"] --> B["_eval_import(true, to, from, paths...)"]
    B --> C["eval_import_path_all(to, from_path)"]
    C --> D{"トップレベルモジュール?"}
    D -->|"Core/Base"| E["直接参照"]
    D -->|"その他"| F["require(at, name)"]
    F --> G["モジュールロード"]
    E --> H["eval_import_path で残りのパスを解決"]
    G --> H
    H --> I["Core._import(to, m, asname, name, imported)"]

    J["using A"] --> K["_eval_using(to, path)"]
    K --> L["eval_import_path_all"]
    L --> M["Core._using(to, from)"]
    M --> N{"Main で using?"}
    N -->|Yes| O["Core._import(Main, from, nameof(from))"]
    N -->|No| P["完了"]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-59-1 | using vs import | `using A` はエクスポートシンボルを取り込む。`import A` はモジュール名のみバインド | 常時 |
| BR-59-2 | メソッド拡張 | `import A: f` で取り込んだ関数にはメソッド追加可能。`using` では不可 | import 使用時 |
| BR-59-3 | Main での using | `using A` が Main で実行された場合、`A` の名前もバインドされる | Main モジュール |
| BR-59-4 | 相対パス | `using .A` / `import ..A` で相対パスによるインポートが可能 | ドット記法使用時 |
| BR-59-5 | as リネーム | `import A: x as y` でシンボルのリネームが可能。マクロのリネームには制約あり | as 使用時 |
| BR-59-6 | baremodule | baremodule は Core のみ import し、Base は using しない | baremodule 使用時 |

### 計算ロジック

特別な計算ロジックは存在しない。シンボル解決とバインディング管理が主要な処理。

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

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | TypeError | import パス内に Symbol でない要素 | 有効なモジュールパスを指定 |
| - | ErrorException | malformed import statement | import 文の構文を修正 |
| - | ErrorException | "v" does not name a module | パス内の名前がモジュールでない |
| - | ErrorException | cannot rename macro to non-macro | マクロのリネームルール違反 |
| - | ErrorException | invalid import path: "." in identifier | パス内に不正なドットがある |

### リトライ仕様

該当なし。

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

該当なし。

## パフォーマンス要件

- モジュール定義は初回のみ実行
- using/import はバインディングテーブルの操作で高速
- require によるパッケージロードは初回のみ（キャッシュあり）

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

- export されていないシンボルへのアクセスは `Module.name` で可能だが、internal API とみなされる
- `public` キーワード（Julia 1.11+）で安定した公開 API を明示できる

## 備考

- Julia 1.11 で `public` キーワードが導入され、export と public の使い分けが可能に
- `import A as B` でモジュール名のリネームが可能（Julia 1.6+）

---

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

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

### 推奨読解順序

#### Step 1: import/using の評価ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | module.jl | `base/module.jl` | _eval_import（98-121行目）: import/using 文の評価。imported フラグで import/using を区別 |
| 1-2 | module.jl | `base/module.jl` | _eval_using（136-143行目）: `using A` の評価。eval_import_path_all でモジュール解決後 Core._using を呼び出し |
| 1-3 | module.jl | `base/module.jl` | eval_import_path（12-57行目）: モジュールパスの解決。Core/Base は直接参照、それ以外は require |
| 1-4 | module.jl | `base/module.jl` | eval_import_path_all（59-66行目）: パス全体を解決してモジュールを返す |
| 1-5 | module.jl | `base/module.jl` | check_macro_rename（68-77行目）: マクロリネームのバリデーション |

**読解のコツ**: `_eval_import` は lowering から直接呼ばれる関数。`imported=true` は `import` 文、`imported=false` は `using A: x` 文に対応。パスの先頭が `.` なら相対パス、`:Core` / `:Base` は特別扱い、それ以外は `require` でロード。

#### Step 2: モジュールパス解決の詳細を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | module.jl | `base/module.jl` | eval_import_path の相対パス処理（42-47行目）: `.` で親モジュールを辿る |
| 2-2 | module.jl | `base/module.jl` | eval_import_path の絶対パス処理（29-40行目）: Core/Base は直接参照、他は require |
| 2-3 | module.jl | `base/module.jl` | パスの残り部分の解決（49-56行目）: getglobal でサブモジュールを辿る |

**主要処理フロー**:
- **31-32行目**: `v === :Core` → `m = Core`、`v === :Base` → `m = Base`
- **36行目**: それ以外 → `m = require(at, v)` でパッケージロード
- **44-46行目**: `.` の連鎖で `parentmodule(m)` を辿る
- **52行目**: `m = getglobal(m, v)` でサブモジュールにアクセス
- **116行目**: `Core._import(to, m, asname, name, imported)` でバインディング作成

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

```
import A.B: x as y
    │
    └─ _eval_import(true, Main, Expr(:., :A, :B), Expr(:as, Expr(:., :x), :y))
           │
           ├─ eval_import_path_all(Main, Expr(:., :A, :B), "import")
           │      └─ eval_import_path(Main, nothing, path, "import")
           │             ├─ require(Main, :A) → Module A
           │             └─ getglobal(A, :B) → Module A.B
           │
           ├─ eval_import_path(Main, A.B, Expr(:., :x), "import")
           │      └─ m=A.B, name=:x
           │
           ├─ check_macro_rename(:x, :y, "import")
           └─ Core._import(Main, A.B, :y, :x, true)

using A
    │
    └─ _eval_using(Main, Expr(:., :A))
           ├─ eval_import_path_all(Main, path, "using") → Module A
           ├─ Core._using(Main, A)
           └─ Core._import(Main, A, :A)  [Main での using の場合]
```

### データフロー図

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

import A.B: x as y          → _eval_import(true, Main, ...)  → バインディング Main.y → A.B.x
                                eval_import_path → Module A.B
                                Core._import(Main, A.B, :y, :x, true)

using A                     → _eval_using(Main, path)        → Main に A の export シンボルを追加
                                eval_import_path_all → Module A
                                Core._using(Main, A)
                                Core._import(Main, A, :A)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| module.jl | `base/module.jl` | ソース | _eval_import, _eval_using, eval_import_path の実装 |
| loading.jl | `base/loading.jl` | ソース | require 関数の実装。パッケージロードの基盤 |
| reflection.jl | `base/reflection.jl` | ソース | names, nameof, parentmodule 等のモジュールリフレクション |
| Base.jl | `base/Base.jl` | ソース | Base モジュールの定義と export リスト |
