Skip to content

RFC-033: ^^ Reflection Operator ​

References:

Summary ​

This RFC proposes introducing the ^^ operator as the reflection entry point for obtaining metadata of types and values. ^^T returns the static metadata object of type T, and ^^obj returns the dynamic type metadata of value obj. The metadata object is a regular record type containing information such as name, parameters, and fields, and can be used both at compile-time and runtime.

Motivation ​

Why is this feature needed? ​

  1. Serialization/Deserialization: Needs to access type's field information to automatically generate serialization code
  2. Compile-time metaprogramming: Needs to access type structure at compile-time to generate code or verify constraints
  3. Runtime debugging/tools: Needs to print type information at runtime to assist debugging
  4. Runtime type checking: Needs to determine type relationships at runtime, such as "what type is obj?"

Current Problems ​

Currently, YaoXiang has no reflection mechanism, and it is impossible to access type metadata at compile-time or runtime. If we directly use .name, .fields to access type metadata, it will conflict with user-defined fields:

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

# If Person.name refers to the type metadata name, or the field name?
# This would lead to parsing difficulties and semantic confusion

A syntax that does not intrude into the regular field namespace is needed to access type metadata.

Proposal ​

Core Design ​

Introduce the ^^ operator as the reflection entry point to clearly distinguish regular code from metadata queries.

Two usages:

  1. Static reflection (applies to types): ^^T returns the static metadata object of type T
  2. Dynamic reflection (applies to values): ^^obj returns the dynamic type metadata of value obj

Metadata structure:

yaoxiang
TypeMeta: Type = {
    name: String,
    params: Array(ParamMeta),
    fields: Array(FieldMeta),
    return_type: Type,
    refinement: Option(Expr)  # Some(Expr) at compile-time, None at runtime
}

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

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

Universe levels: If T: Type_n, then ^^T: Type_{n+1}, conforming to standard type-theoretic universe lifting rules.

Precedence: ^^ is a unary prefix operator with the highest precedence. ^^T.name is equivalent to (^^T).name.

Examples ​

Basic Usage ​

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

# Static reflection
meta = ^^Point
print(meta.name)           # "Point"
print(meta.fields.len)     # 2
print(meta.fields[0].name) # "x"
print(fields[0].type)      # Float

# Dynamic reflection (requires runtime reflection to be enabled)
obj = Point(1.0, 2.0)
meta = ^^obj
print(meta.name)           # "Point"

Generic Types ​

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

# Reflect on the generic type itself
meta = ^^List
print(meta.name)           # "List"
print(meta.params)         # [{ name: "T", type: Type }]

# Reflect on a specific instantiation
meta = ^^List(Int)
print(meta.name)           # "List(Int)"
print(meta.params)         # []

Functions ​

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

Refinement Types ​

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

# At compile-time: refinement is Some(Expr)
meta = ^^Positive
print(meta.name)           # "Positive"
print(meta.refinement)     # Some(AST(x > 0))

# At runtime: refinement is None (erased)

Usage in Compile-time Predicates ​

yaoxiang
# Check if a type has fields
HasFields: (T: Type) -> Type = { ^^T.fields.len > 0 }

# Check field types
HasFloatField: (T: Type) -> Type = {
    exists field in ^^T.fields: field.type == Float
}

# Usage
obj: HasFields(Point) = Point(1.0, 2.0)  # ✅ Validation passed
# obj: HasFields(Int) = 42  # ❌ Validation failed

Serialization Example ​

yaoxiang
# Compile-time pure function: generate JSON string
to_json: (T: Type) -> ((obj: T) -> String) = {
    meta = ^^T
    parts: Array(String) = []
    for field in meta.fields {
        # Generate field access code at compile-time
        parts.push("\"${field.name}\": ${obj.${field.name}}")
    }
    return "{" + parts.join(", ") + "}"
}

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

Syntax Changes ​

BeforeAfter
No reflection mechanism^^T to get type metadata
No reflection mechanism^^obj to get value's dynamic type metadata

Detailed Design ​

Type System Impact ​

  • New types: TypeMeta, ParamMeta, FieldMeta
  • Universe levels: The type returned by ^^T is one level higher than T
  • Generic interaction: Both ^^List and ^^List(Int) are supported
  • Function interaction: ^^add returns function metadata (including parameters and return type)
  • Refinement type interaction: ^^Positive returns refinement type metadata (including refinement expression)

Runtime Behavior ​

Compile-time reflection:

  • ^^T is fully evaluated at compile-time, and the result is inlined as a constant
  • Refinement expressions are available at compile-time

Runtime reflection:

  • Disabled by default, zero overhead
  • Enabled via the --enable-runtime-reflection compilation option
  • When enabled, ^^obj returns dynamic type metadata
  • Refinement expressions are erased to None at runtime

On-demand generation + treeshake:

  • Metadata is generated only for types that actually use ^^
  • Types that are not referenced do not generate metadata (treeshake)

Compiler Changes ​

  1. Lexer: Recognize ^^ as a single token
  2. Parser: Add ^^ prefix expression rule
  3. Type system: Add TypeMeta, ParamMeta, FieldMeta type definitions
  4. Type checker: Generate a metadata instance for each type
  5. Compile-time evaluator: Support compile-time evaluation of ^^T
  6. Runtime (optional): Generate RTTI for reflected types

Backward Compatibility ​

  • ✅ No impact on existing syntax: ^^ is a new operator and does not conflict with existing syntax
  • ✅ No impact on existing types: All types automatically support ^^
  • ✅ No impact on existing functions: Functions can use ^^ but are not required to
  • ✅ No impact on compile-time predicates: ^^T behaves the same as regular content in predicates
  • ✅ No impact on runtime: Runtime reflection is disabled by default, zero overhead

Trade-offs ​

Advantages ​

  • Unified treatment: Functions, generics, and refinement types are handled uniformly
  • Zero overhead: Compile-time reflection is completely erased, runtime reflection is optional
  • Integration with existing systems: Seamless integration with compile-time predicates (RFC-027)
  • Concise: ^^ is a pure symbol and does not conflict with user-defined identifiers
  • On-demand generation: treeshake optimization, zero overhead for unused types

Disadvantages ​

  • Learning curve: Need to understand the semantics of ^^ and the metadata structure
  • Runtime overhead: Enabling runtime reflection increases memory overhead (one pointer per instance)
  • Implementation complexity: Multiple compiler components need to be modified

Alternatives ​

AlternativeWhy not chosen
reflect(T) functionWould introduce an extra identifier into the scope, which could be shadowed by users
type_info(T) functionSame as above
Single ^ operatorMay conflict with bitwise operations, and C++26 chose ^^ precisely because of such conflicts
@@, ##, etc. symbolsNo precedent, less intuitive to explain than ^^

Implementation Phases ​

PhaseContentDependencies
Phase 1Compile-time ^^ operator parsingNone
Phase 2TypeMeta data structure definitionPhase 1
Phase 3Compile-time metadata generationPhase 2
Phase 4Runtime reflection support (optional)Phase 3
Phase 5Compile-time predicate integrationPhase 3

Dependency Graph ​

Phase 1 (Parsing)
    ↓
Phase 2 (Data Structures)
    ↓
Phase 3 (Compile-time Metadata)
    ↓
    ├────────────┐
    ↓            ↓
Phase 4        Phase 5
(Runtime Reflection)  (Compile-time Predicates)

Risks ​

  • Parsing conflicts: ^^ may conflict with existing syntax (analysis shows no conflict)
  • Performance impact: Compile-time metadata generation may increase compilation time (can be optimized via treeshake)
  • Runtime overhead: Enabling runtime reflection increases memory overhead (mitigated by on-demand generation)

Open Questions ​

  • [x] ^^ scope: Applies only to types and values, not to expressions
  • [x] Chained access: Supported, metadata objects returned by ^^T can have their properties accessed normally
  • [x] Pattern matching: Supported, TypeMeta is a regular record type and can be pattern-matched normally
  • [x] Comparison: Supported, metadata objects of the same type are equal
  • [x] Memory overhead: On-demand generation + treeshake optimization

Appendix ​

Appendix A: Design Decision Record ​

DecisionDecisionDateRecorder
^^ scopeApplies only to types and values, not expressions2026-06-16Chenxu
Chained accessSupported2026-06-16Chenxu
Pattern matchingSupported2026-06-16Chenxu
ComparisonSupported, same-type metadata is equal2026-06-16Chenxu
Memory overheadOn-demand generation + treeshake2026-06-16Chenxu
Generic interactionBoth ^^List and ^^List(Int) are supported2026-06-16Chenxu
Refinement expression storageAvailable at compile-time, erased to None at runtime2026-06-16Chenxu

Appendix B: Glossary ​

TermDefinition
ReflectionThe ability to access type metadata at runtime or compile-time
MetadataInformation describing a type's structure (name, fields, parameters, etc.)
RTTIRun-Time Type Information
treeshakeCompiler optimization that removes unused code
Refinement typeA type with constraint conditions, e.g., Positive: (x: Int) -> Type = { x > 0 }

References ​


Lifecycle and Destination ​

┌─────────────┐
│   Draft     │  ← Current status
└──────┬──────┘
       │
       ▼
┌─────────────┐
│  Reviewing  │  ← Open community discussion and feedback
└──────┬──────┘
       │
       ├──────────────────┐
       ▼                  ▼
┌─────────────┐    ┌─────────────┐
│  Accepted   │    │  Rejected   │
└──────┬──────┘    └──────┬──────┘
       │                  │
       ▼                  ▼
┌─────────────┐    ┌─────────────┐
│   accepted/ │    │    rfc/     │
│ (Formal Design) │    │ (Retained) │
└─────────────┘    └─────────────┘