Skip to content

RFC-033: ^^ リフレクション演算子 ​

参考:

概要 ​

本文書では、型や値のメタデータにアクセスするためのリフレクションエントリポイントとして ^^ 演算子の導入を提案する。^^T は型 T の静的メタデータオブジェクトを返し、^^obj は値 obj の動的型メタデータを返す。メタデータオブジェクトは通常の record type であり、名前、パラメータ、フィールドなどの情報を含み、コンパイル時とランタイムの両方で使用できる。

動機 ​

なぜこの機能が必要なのか? ​

  1. シリアライズ/デシリアライズ:型のフィールド情報にアクセスし、シリアライズコードを自動生成する必要がある
  2. コンパイル時メタプログラミング:コンパイル時に型構造にアクセスし、コード生成や制約検証を行う必要がある
  3. ランタイムデバッグ/ツール:ランタイムで型情報を出力し、デバッグを補助する必要がある
  4. ランタイム型チェック:「obj は何型か?」のような型関係をランタイムで判定する必要がある

現状の問題点 ​

現在の YaoXiang にはリフレクションメカニズムがなく、コンパイル時またはランタイムで型のメタデータにアクセスできない。.name、.fields を直接使用して型メタデータにアクセスすると、ユーザー定義のフィールドと衝突する:

yaoxiang
Person: Type = { name: String, age: Int }

# Person.name は型メタデータの名前か、それともフィールド name か?
# これは解析の困難と意味の混乱を引き起こす

通常のフィールドの名前空間を侵さない型メタデータアクセス構文が必要である。

提案 ​

基本設計 ​

通常のコードとメタデータクエリを明確に区別するリフレクションエントリポイントとして ^^ 演算子を導入する。

2 つの使用方法:

  1. 静的リフレクション(型に作用):^^T は型 T の静的メタデータオブジェクトを返す
  2. 動的リフレクション(値に作用):^^obj は値 obj の動的型メタデータを返す

メタデータ構造:

yaoxiang
TypeMeta: Type = {
    name: String,
    params: Array(ParamMeta),
    fields: Array(FieldMeta),
    return_type: Type,
    refinement: Option(Expr)  # コンパイル時は Some(Expr)、ランタイムは None
}

ParamMeta: Type = {
    name: String,
    type: Type
}

FieldMeta: Type = {
    name: String,
    type: Type
}

宇宙階層:T: Type_n の場合、^^T: Type_{n+1} となり、型論の標準的な宇宙上昇ルールに準拠する。

優先順位:^^ は単項前置演算子であり、優先順位は最高である。^^T.name は (^^T).name と等価である。

例 ​

基本的な使用法 ​

yaoxiang
Point: Type = { x: Float, y: Float }

# 静的リフレクション
meta = ^^Point
print(meta.name)           # "Point"
print(meta.fields.len)     # 2
print(meta.fields[0].name) # "x"
print(fields[0].type)      # Float

# 動的リフレクション(ランタイムリフレクションを有効にする必要がある)
obj = Point(1.0, 2.0)
meta = ^^obj
print(meta.name)           # "Point"

ジェネリクス型 ​

yaoxiang
List: (T: Type) -> Type = { data: Array(T), length: Int }

# ジェネリクス型そのものをリフレクション
meta = ^^List
print(meta.name)           # "List"
print(meta.params)         # [{ name: "T", type: Type }]

# 具体的なインスタンス化型をリフレクション
meta = ^^List(Int)
print(meta.name)           # "List(Int)"
print(meta.params)         # []

関数 ​

yaoxiang
add: (a: Int, b: Int) -> Int = a + b

meta = ^^add
print(meta.name)           # "add"
print(meta.params)         # [{ name: "a", type: Int }, { name: "b", type: Int }]
print(meta.return_type)    # Int

精化型 ​

yaoxiang
Positive: (x: Int) -> Type = { x > 0 }

# コンパイル時:refinement は Some(Expr)
meta = ^^Positive
print(meta.name)           # "Positive"
print(meta.refinement)     # Some(AST(x > 0))

# ランタイム:refinement は None(消去される)

コンパイル時述語での使用 ​

yaoxiang
# 型がフィールドを持つかチェック
HasFields: (T: Type) -> Type = { ^^T.fields.len > 0 }

# フィールド型をチェック
HasFloatField: (T: Type) -> Type = {
    exists field in ^^T.fields: field.type == Float
}

# 使用
obj: HasFields(Point) = Point(1.0, 2.0)  # ✅ 検証成功
# obj: HasFields(Int) = 42  # ❌ 検証失敗

シリアライズの例 ​

yaoxiang
# コンパイル時純粋関数:JSON 文字列を生成
to_json: (T: Type) -> ((obj: T) -> String) = {
    meta = ^^T
    parts: Array(String) = []
    for field in meta.fields {
        # コンパイル時にフィールドアクセスコードを生成
        parts.push("\"${field.name}\": ${obj.${field.name}}")
    }
    return "{" + parts.join(", ") + "}"
}

# 使用
point_to_json = to_json(Point)
print(point_to_json(Point(1.0, 2.0)))  # '{"x": 1.0, "y": 2.0}'

構文の変更 ​

以前変更後
リフレクションメカニズムなし^^T で型メタデータを取得
リフレクションメカニズムなし^^obj で値の動的型メタデータを取得

詳細設計 ​

型システムへの影響 ​

  • 新規型:TypeMeta、ParamMeta、FieldMeta
  • 宇宙階層:^^T の戻り型は T より 1 階層上位
  • ジェネリクスとの相互作用:^^List と ^^List(Int) の両方がサポートされる
  • 関数との相互作用:^^add は関数のメタデータ(引数と戻り型を含む)を返す
  • 精化型との相互作用:^^Positive は精化型のメタデータ(精化式を含む)を返す

ランタイム動作 ​

コンパイル時リフレクション:

  • ^^T はコンパイル時に完全に評価され、結果は定数としてインライン化される
  • 精化式はコンパイル時に利用可能

ランタイムリフレクション:

  • デフォルトでは無効で、ゼロオーバーヘッド
  • --enable-runtime-reflection コンパイルオプションで有効化
  • 有効化後、^^obj は動的型メタデータを返す
  • 精化式はランタイムで None に消去される

オンデマンド生成 + treeshake:

  • ^^ が実際に使用される型のみメタデータが生成される
  • 参照されない型はメタデータが生成されない(treeshake)

コンパイラの修正 ​

  1. 字句解析器:^^ を単一のトークンとして認識
  2. 構文解析器:^^ 前置式のルールを追加
  3. 型システム:TypeMeta、ParamMeta、FieldMeta の型定義を追加
  4. 型検査器:各型に対してメタデータインスタンスを生成
  5. コンパイル時エバリュエータ:^^T のコンパイル時評価をサポート
  6. ランタイム(オプション):リフレクション対象の型に対して RTTI を生成

後方互換性 ​

  • ✅ 既存構文への影響なし:^^ は新演算子であり、既存構文と衝突しない
  • ✅ 既存型への影響なし:すべての型が自動的に ^^ をサポート
  • ✅ 既存関数への影響なし:関数は ^^ を使用できるが、必須ではない
  • ✅ コンパイル時述語への影響なし:^^T は述語内で通常の内容と同様に動作
  • ✅ ランタイムへの影響なし:ランタイムリフレクションはデフォルトで無効、ゼロオーバーヘッド

トレードオフ ​

利点 ​

  • 統一性:関数、ジェネリクス、精化型を統一的に処理
  • ゼロオーバーヘッド:コンパイル時リフレクションは完全に消去され、ランタイムリフレクションはオプション
  • 既存システムとの統合:コンパイル時述語(RFC-027)とシームレスに統合
  • 簡潔さ:^^ は純粋な記号であり、ユーザー定義の識別子と衝突しない
  • オンデマンド生成:treeshake 最適化により、未使用の型はゼロオーバーヘッド

欠点 ​

  • 学習曲線:^^ のセマンティクスとメタデータ構造を理解する必要がある
  • ランタイムオーバーヘッド:ランタイムリフレクションを有効にするとメモリオーバーヘッドが増加(インスタンスごとに 1 ポインタ)
  • 実装の複雑さ:コンパイラの複数のコンポーネントを修正する必要がある

代替案 ​

案採用しない理由
reflect(T) 関数スコープに追加の識別子を導入し、ユーザーがシャドウイングする可能性あり
type_info(T) 関数上に同じ
単一の ^ 演算子ビット演算と衝突する可能性があり、C++26 でも衝突を避けるために ^^ を選択した
@@、## などの記号先例がなく、^^ ほど説明的でない

実装フェーズ ​

フェーズ内容依存関係
Phase 1コンパイル時 ^^ 演算子の解析なし
Phase 2TypeMeta データ構造の定義Phase 1
Phase 3コンパイル時メタデータ生成Phase 2
Phase 4ランタイムリフレクションサポート(オプション)Phase 3
Phase 5コンパイル時述語との統合Phase 3

依存関係図 ​

Phase 1 (解析)
    ↓
Phase 2 (データ構造)
    ↓
Phase 3 (コンパイル時メタデータ)
    ↓
    ├────────────┐
    ↓            ↓
Phase 4        Phase 5
(ランタイムリフレクション)  (コンパイル時述語)

リスク ​

  • 解析の衝突:^^ が既存構文と衝突する可能性(解析の結果、衝突なし)
  • パフォーマンスへの影響:コンパイル時メタデータ生成によりコンパイル時間が増加する可能性あり(treeshake 最適化で緩和可能)
  • ランタイムオーバーヘッド:ランタイムリフレクションを有効にするとメモリオーバーヘッドが増加(オンデマンド生成で緩和)

未解決問題 ​

  • [x] ^^ の作用範囲:型と値にのみ作用し、式には作用しない
  • [x] チェーンアクセス:サポート、^^T が返すメタデータオブジェクトは通常通り属性にアクセス可能
  • [x] パターン照合:サポート、TypeMeta は通常の record type であり、通常通りパターン照合可能
  • [x] 比較:サポート、同型のメタデータオブジェクトは等価
  • [x] メモリオーバーヘッド:オンデマンド生成 + treeshake 最適化

付録 ​

付録A:設計決定記録 ​

決定決定内容日付記録者
^^ の作用範囲型と値にのみ作用し、式には作用しない2026-06-16晨煦
チェーンアクセスサポート2026-06-16晨煦
パターン照合サポート2026-06-16晨煦
比較サポート、同型メタデータは等価2026-06-16晨煦
メモリオーバーヘッドオンデマンド生成 + treeshake2026-06-16晨煦
ジェネリクスとの相互作用^^List と ^^List(Int) の両方をサポート2026-06-16晨煦
精化式の保存コンパイル時に利用可能、ランタイムで None に消去2026-06-16晨煦

付録B:用語集 ​

用語定義
リフレクションランタイムまたはコンパイル時に型メタデータにアクセスする能力
メタデータ型の構造を記述する情報(名前、フィールド、パラメータなど)
RTTIRun-Time Type Information、ランタイム型情報
treeshakeコンパイラ最適化、未使用のコードを削除
精化型制約条件付きの型(例:Positive: (x: Int) -> Type = { x > 0 })

参考文献 ​


ライフサイクルと帰結 ​

┌─────────────┐
│   ドラフト   │  ← 現在の状態
└──────┬──────┘
       │
       ▼
┌─────────────┐
│  レビュー中  │  ← コミュニティの議論とフィードバックを公開
└──────┬──────┘
       │
       ├──────────────────┐
       ▼                  ▼
┌─────────────┐    ┌─────────────┐
│   承認済み   │    │   拒否済み   │
└──────┬──────┘    └──────┬──────┘
       │                  │
       ▼                  ▼
┌─────────────┐    ┌─────────────┐
│   accepted/ │    │    rfc/     │
│ (正式設計)  │    │ (元の場所)   │
└─────────────┘    └─────────────┘