# 機能設計書 3-変数定義（let/mut/const）

## 概要

本ドキュメントは、Nushellにおける変数定義機能（let、mut、const）について定義する。Nushellでは不変変数（let）、可変変数（mut）、パース時定数（const）の3種類の変数を使い分けることができる。

### 本機能の処理概要

**業務上の目的・背景**：変数はプログラミングの基本要素であり、データの一時保存と再利用を可能にする。Nushellでは関数型プログラミングの影響を受け、デフォルトで不変（immutable）な変数を採用している。これによりバグの原因となる意図しない値の変更を防ぎ、コードの予測可能性を高める。

**機能の利用シーン**：
- 計算結果の一時保存
- パイプライン中間結果のキャプチャ
- 設定値の定義（const）
- ループカウンターや累積値の管理（mut）

**主要な処理内容**：
1. `let` - 不変変数の定義。値は初期化後に変更不可
2. `mut` - 可変変数の定義。値は後から変更可能
3. `const` - パース時定数の定義。パース時に評価され、実行時は定数として扱う
4. パイプライン入力からの変数定義（`input | let x`）
5. 型注釈による明示的な型指定

**関連システム・外部連携**：nu-parser（構文解析）、nu-engine（評価）と連携する。

**権限による制御**：特になし。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | メインREPL | 主画面 | 変数定義の入力と実行 |

## 機能種別

変数管理 / データバインディング

## 入力仕様

### 入力パラメータ

#### let コマンド
| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| var_name | VarWithOptType | Yes | 変数名（オプションで型注釈付き） | 有効な識別子 |
| initial_value | Keyword(=, MathExpression) | No | 初期値（= の後に式） | 型が一致すること |

#### mut コマンド
| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| var_name | VarWithOptType | Yes | 可変変数名 | 有効な識別子 |
| initial_value | Keyword(=, MathExpression) | Yes | 初期値 | 必須 |

#### const コマンド
| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| const_name | VarWithOptType | Yes | 定数名 | 有効な識別子 |
| initial_value | Keyword(=, MathExpression) | Yes | 定数値 | パース時評価可能 |

### 入力データソース

- ユーザーからのコマンドライン入力
- スクリプトファイル
- パイプライン入力（letのみ）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| PipelineData | PipelineData | let（=なし）の場合は値をパススルー、それ以外はEmpty |

### 出力先

- スタック（変数の登録）
- EngineState（constの場合、パース時に登録）

## 処理フロー

### 処理シーケンス

```
1. パース時
   └─ 変数名と型の解析
   └─ VarIdの割り当て
   └─ constの場合は値の評価と登録
2. 実行時（let/mut）
   └─ 右辺式の評価
   └─ 型の検証
   └─ スタックへの変数登録
```

### フローチャート

```mermaid
flowchart TD
    A[変数定義コマンド] --> B{コマンド種別}
    B -->|let| C[不変変数処理]
    B -->|mut| D[可変変数処理]
    B -->|const| E[定数処理]
    C --> F{= あり?}
    F -->|Yes| G[右辺式を評価]
    F -->|No| H[パイプライン入力を使用]
    G --> I[stack.add_var]
    H --> J[値をパススルー]
    J --> I
    D --> K[右辺式を評価]
    K --> L[stack.add_var（mutable=true）]
    E --> M[パース時に評価]
    M --> N[EngineStateに登録]
    I --> O[終了]
    L --> O
    N --> O
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | 不変性 | let変数は再代入不可 | let定義の変数 |
| BR-002 | 可変性 | mut変数は$var = value で再代入可能 | mut定義の変数 |
| BR-003 | パース時評価 | constはパース時に評価される | const定義 |
| BR-004 | glob型変換 | let g: glob = "*.txt" は展開可能なglobに変換 | glob型注釈付き |
| BR-005 | パイプライン入力 | let x でパイプライン入力を変数化 | = なしのlet |

### 計算ロジック

glob型変換:
```rust
if variable.ty == Type::Glob {
    match &rhs {
        Value::String { val, .. } => Value::glob(val.clone(), false, rhs.span()),
        _ => rhs.clone(),
    }
}
```

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| NushellFailed | 実行エラー | 変数名が不正 | 有効な識別子を使用 |
| AssignmentRequiresMutableVar | 代入エラー | let変数への再代入 | mutを使用 |
| TypeMismatch | 型エラー | 型注釈と値の不一致 | 型を確認 |

### リトライ仕様

リトライは行わない。

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

変数定義は単一の操作として処理される。

## パフォーマンス要件

特になし。

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

特になし。

## 備考

- IRモードではmut/constの`run`は呼び出されない（IRコンパイラが特別処理）
- letの`run`はパイプライン入力対応のため実装あり

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Variable | `crates/nu-protocol/src/engine/variable.rs` | Variable構造体の定義。mutableフラグ、const_val |

**読解のコツ**: Variable構造体のmutableフィールドがlet/mutの区別を決定する。

#### Step 2: コマンド定義を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | let_.rs | `crates/nu-cmd-lang/src/core_commands/let_.rs` | letコマンドの実装 |
| 2-2 | mut_.rs | `crates/nu-cmd-lang/src/core_commands/mut_.rs` | mutコマンドの実装 |
| 2-3 | const_.rs | `crates/nu-cmd-lang/src/core_commands/const_.rs` | constコマンドの実装 |

**主要処理フロー（let_.rs）**:
- **19-34行目**: シグネチャ定義。var_name, initial_valueパラメータ
- **49-118行目**: run関数。式評価、glob型変換、スタック登録
- **98-108行目**: glob型の特別処理

#### Step 3: パーサーでの処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | parse_keywords.rs | `crates/nu-parser/src/parse_keywords.rs` | parse_let, parse_mut, parse_const 関数 |

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

```
ユーザー入力: let x = 10
    │
    ├─ パース時
    │      └─ parse_let (parse_keywords.rs)
    │             ├─ VarId 割り当て
    │             └─ Variable 登録 (mutable=false)
    │
    └─ 実行時
           └─ Let.run (let_.rs)
                  ├─ eval_expression (右辺評価)
                  ├─ glob型変換 (必要時)
                  └─ stack.add_var
```

### データフロー図

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

let x = expr ───▶ パーサー ──────────────▶ VarId生成
                     │
                     ▼
              StateWorkingSet
                     │
                     ▼
              eval_expression ────────▶ Value
                     │
                     ▼
               stack.add_var ─────────▶ 変数登録完了
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| let_.rs | `crates/nu-cmd-lang/src/core_commands/let_.rs` | ソース | letコマンドの実装 |
| mut_.rs | `crates/nu-cmd-lang/src/core_commands/mut_.rs` | ソース | mutコマンドの実装 |
| const_.rs | `crates/nu-cmd-lang/src/core_commands/const_.rs` | ソース | constコマンドの実装 |
| parse_keywords.rs | `crates/nu-parser/src/parse_keywords.rs` | ソース | 変数定義のパース処理 |
| variable.rs | `crates/nu-protocol/src/engine/variable.rs` | ソース | Variable構造体定義 |
| eval.rs | `crates/nu-engine/src/eval.rs` | ソース | 代入処理（eval_assignment） |
