# 機能設計書 41-printf系関数

## 概要

本ドキュメントは、F#コアライブラリにおける型安全なprintf形式の書式化関数群（printf系関数）の機能設計を記述する。

### 本機能の処理概要

printf系関数は、C言語のprintf関数に類似した書式化機能を提供するが、F#の型システムを活用して完全な型安全性を実現している。書式文字列をコンパイル時に解析し、引数の型と数を静的に検証することで、実行時エラーを防止する。

**業務上の目的・背景**：デバッグ出力、ログ出力、文字列生成など、開発者が頻繁に行う文字列フォーマット操作において、型安全性を保証しつつ、簡潔で可読性の高いコードを記述可能にする。C言語由来のprintf構文に馴染みのある開発者が容易に習得でき、かつコンパイル時に書式文字列と引数の型不整合を検出できる。

**機能の利用シーン**：
- コンソールへの標準出力・エラー出力
- 文字列の動的生成（sprintf）
- ログメッセージのフォーマット
- StringBuilderへの効率的な文字列追加
- TextWriterへの書き込み

**主要な処理内容**：
1. 書式文字列の解析（%d, %s, %f等の書式指定子の検出）
2. 書式指定子に対応する型情報の生成
3. カリー化された関数の動的生成
4. 引数のキャプチャと文字列への変換
5. 結果文字列の構築と出力先への送出

**関連システム・外部連携**：標準入出力（Console.Out, Console.Error）、StringBuilder、TextWriter等の.NETストリームクラスとの連携

**権限による制御**：特になし（純粋なライブラリ機能）

## 関連画面

本機能はコアライブラリ機能のため、直接関連する画面はない。

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | - |

## 機能種別

文字列処理 / フォーマット変換

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| format | PrintfFormat<'Printer, 'State, 'Residue, 'Result> | Yes | 書式文字列 | コンパイル時に型チェック |
| args | 可変長引数 | No | 書式指定子に対応する値 | 型が書式指定子と一致すること |

### 入力データソース

プログラムコード内のリテラル文字列または変数

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 結果文字列 | string | フォーマットされた文字列（sprintf） |
| unit | unit | 出力完了を示す（printf, fprintf等） |

### 出力先

- 標準出力（printf, printfn）
- 標準エラー出力（eprintf, eprintfn）
- StringBuilder（bprintf）
- TextWriter（fprintf, fprintfn）
- 文字列（sprintf）

## 処理フロー

### 処理シーケンス

```
1. 書式文字列の解析
   └─ FormatParser.parseSpecで書式指定子を抽出
2. 書式指定子の検証
   └─ 型文字（d,s,f,x等）とフラグ（幅、精度、左寄せ等）の解析
3. 変換関数の生成
   └─ getValueConverterで型に応じた変換器を取得
4. カリー化された関数の構築
   └─ Specializationsクラスのメソッドで引数キャプチャ関数を生成
5. 引数の収集と変換
   └─ 各引数を順次適用し、文字列に変換
6. 結果の出力
   └─ PrintfEnvのサブクラスで出力先に書き込み
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[書式文字列を受け取る]
    B --> C{書式指定子あり?}
    C -->|Yes| D[書式指定子を解析]
    D --> E[対応する変換関数を取得]
    E --> F[カリー化関数を構築]
    F --> G[引数を待機]
    G --> H{全引数受領?}
    H -->|No| G
    H -->|Yes| I[文字列を構築]
    I --> J[出力先に送出]
    J --> K[終了]
    C -->|No| L[リテラル文字列として出力]
    L --> K
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 型安全性 | 書式指定子と引数の型が一致すること | コンパイル時 |
| BR-02 | 書式指定子構文 | %[flags][width][.precision]type の形式 | 書式文字列内 |
| BR-03 | 幅・精度のスター指定 | *指定時は追加のint引数が必要 | %*d, %.*f等 |

### 計算ロジック

書式指定子の解析:
- `%d`, `%i`: 符号付き整数
- `%u`: 符号なし整数
- `%x`, `%X`: 16進数
- `%o`: 8進数
- `%B`: 2進数
- `%s`: 文字列
- `%c`: 文字
- `%f`, `%F`, `%e`, `%E`, `%g`, `%G`: 浮動小数点数
- `%M`: decimal
- `%b`: bool
- `%O`: ToString()を呼び出し
- `%A`: 構造化された表示
- `%a`: ユーザー定義フォーマッタ
- `%t`: TextWriter操作

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

本機能はデータベースを使用しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | コンパイルエラー | 書式指定子と引数の型不一致 | 正しい型の引数を渡す |
| ArgumentException | 実行時エラー | 不正な書式指定子 | 書式文字列を修正 |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- FormatParserはキャッシュされ、同一書式文字列の再利用時は解析をスキップ
- SmallStringPrintfEnv2/4により、小規模な文字列生成を最適化
- 2つ以下の引数を持つ単純な書式はOneStepWithArg/TwoStepWithArgで高速化

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

- 書式文字列はユーザー入力から構築すべきでない（書式文字列インジェクション防止）
- 機密情報のログ出力時は適切なマスキングを行う

## 備考

F#のprintf系関数は.NETのString.Formatとは異なり、カリー化された関数として実装されており、部分適用が可能である。

---

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

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

### 推奨読解順序

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

書式指定子と変換関数を表現するデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | printf.fs | `src/FSharp.Core/printf.fs` | FormatSpecifier型（93-148行目）で書式指定子の構造を把握 |
| 1-2 | printf.fs | `src/FSharp.Core/printf.fs` | Step型（262-306行目）で処理ステップの種類を確認 |
| 1-3 | printf.fs | `src/FSharp.Core/printf.fs` | PrintfFormat型（19-45行目）で書式文字列の表現を理解 |

**読解のコツ**: FormatSpecifierは書式指定子の全情報（型文字、幅、精度、フラグ）を保持する。Stepは実行時の処理単位を表す。

#### Step 2: エントリーポイントを理解する

Printfモジュールの公開関数がエントリーポイントとなる。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | printf.fs | `src/FSharp.Core/printf.fs` | Printfモジュール（1375-1464行目）でsprintf, printf等の定義を確認 |

**主要処理フロー**:
1. **1408-1420行目**: sprintfの実装。キャッシュから解析済みフォーマッタを取得
2. **1449-1451行目**: printfの実装。Console.Outへの出力
3. **1401-1403行目**: ksprintfによる継続渡し版

#### Step 3: 書式文字列解析を理解する

FormatParserクラスによる書式文字列の解析処理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | printf.fs | `src/FSharp.Core/printf.fs` | FormatStringモジュール（152-260行目）で低レベルなパース処理 |
| 3-2 | printf.fs | `src/FSharp.Core/printf.fs` | FormatParserクラス（1088-1336行目）で書式文字列の解析とカリー化関数生成 |

**主要処理フロー**:
- **162-181行目**: parseFlagsで書式フラグ（0, +, -, 空白）を解析
- **183-202行目**: parseWidth/parsePrecisionで幅・精度を解析
- **232-260行目**: findNextFormatSpecifierで次の書式指定子を検出

#### Step 4: 型変換処理を理解する

各書式指定子に対応する型変換処理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | printf.fs | `src/FSharp.Core/printf.fs` | Integer/FloatAndDecimalモジュール（734-907行目）で数値変換 |
| 4-2 | printf.fs | `src/FSharp.Core/printf.fs` | ObjectPrinter（909-978行目）で汎用オブジェクト変換 |
| 4-3 | printf.fs | `src/FSharp.Core/printf.fs` | getValueConverter（987-1011行目）で型文字から変換器を取得 |

#### Step 5: 出力環境を理解する

出力先に応じた環境クラスを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | printf.fs | `src/FSharp.Core/printf.fs` | PrintfEnv抽象クラス（308-393行目）で出力環境のインターフェース |
| 5-2 | printf.fs | `src/FSharp.Core/printf.fs` | SmallStringPrintfEnv2/4（1042-1064行目）で小規模文字列最適化 |
| 5-3 | printf.fs | `src/FSharp.Core/printf.fs` | TextWriterPrintfEnv（1079-1083行目）でTextWriter出力 |

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

```
sprintf/printf (エントリーポイント)
    │
    ├─ Cache.GetParser
    │      └─ FormatParser (書式文字列解析)
    │             ├─ parseSpec (書式指定子解析)
    │             └─ buildStep (処理ステップ構築)
    │
    ├─ GetCurriedPrinterFactory / GetCurriedStringPrinter
    │      └─ Specializations (カリー化関数生成)
    │             ├─ CaptureFinal1/2/3
    │             ├─ Capture1/2/3
    │             └─ OneStepWithArg/TwoStepWithArg
    │
    └─ PrintfEnv.RunSteps (実行)
           ├─ getValueConverter → ValueConverter (型変換)
           │      ├─ Integer.toString/toFormattedString
           │      ├─ FloatAndDecimal.toFormattedString
           │      └─ ObjectPrinter.GenericToString
           │
           └─ Write/WriteT (出力)
```

### データフロー図

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

書式文字列      ───▶  FormatParser         ───▶  Step[]
"Hello %s"              (解析・キャッシュ)            (処理ステップ配列)
    │
    ▼
引数            ───▶  Specializations      ───▶  カリー化関数
"World"               (関数生成)                   (引数キャプチャ)
    │
    ▼
                ───▶  PrintfEnv.RunSteps   ───▶  結果文字列
                      (ステップ実行)               "Hello World"
                           │
                           ▼
                      出力先 (Console/StringBuilder/TextWriter)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| printf.fs | `src/FSharp.Core/printf.fs` | ソース | printf系関数の主要実装 |
| prim-types.fs | `src/FSharp.Core/prim-types.fs` | ソース | 基本型定義 |
| StructuredFormat.fs | `src/FSharp.Core/StructuredFormat.fs` | ソース | %A用の構造化表示 |
