Skip to content

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

参考:

概要

本稿では、型と値のメタデータを取得するためのリフレクションエントリポイントとして ^^ 演算子の導入を提案する。^^T は型 T の静的メタデータオブジェクトを返し、^^obj は値 obj の動的型メタデータを返す。メタデータオブジェクトは name: String、params: Array(ParamMeta)、fields: Array(FieldMeta) などの情報を持つ通常の 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) ではなく ^^(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 で値の動的型メタデータを取得

詳細設計

型システムへの影響

  • 新規型TypeMetaParamMetaFieldMeta
  • 宇宙レベル^^T が返す型は T より1つ上のレベル
  • ジェネリクス連携^^List^^List(Int) の両方をサポート
  • 関数連携^^add はパラメータと戻り値型を含む関数のメタデータを返す
  • 精化型連携^^Positive は精化式を含む精化型のメタデータを返す

実行時動作

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

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

実行時リフレクション

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

オンデマンド生成 + treeshake

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

コンパイラ変更

  1. 字句解析器^^ を単一のトークンとして認識
  2. 構文解析器^^ 前置式ルールを追加
  3. 型システムTypeMetaParamMetaFieldMeta 型定義を追加
  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/     │
│ (正式設計)  │    │ (元の位置を保持) │
└─────────────┘    └─────────────┘