Under heavy development. This site describes the intended 1.0 language. Current features and performance vary. Development status
Sn50SnThe SnAPI programming language
Snapshot · Oct 24, 2026 · Frozen documentation

Enums

Classifies the semantic shape of a reflected type.

Sn is under heavy development. This reference includes the intended 1.0 design; features may be incomplete in the current compiler. Read the status →

Module std.reflection

import std.reflection;

Public declaration contracts and authored examples. A page can document several related symbols. Implementation bodies are excluded.

TypeKind

pub enum TypeKind

Classifies the semantic shape of a reflected type.

Example

module example.reflection;
from std.reflection import Argument, CopySlot, DestroySlot, Erase,
    EraseForeign, EraseForeignMut, FindType, FindTypeByStableId,
    InvocationFrame, Invoke, MemberQuery, MethodSignature, ParameterMode,
    ParameterSignature, PrivateAccess, ReadField, ReadProperty, RegisteredTypeAt,
    RegisteredTypeCount, ReturnMode, SlotFromStorage, TakeSlot, TypeInfo,
    TypeKind, TypeOf, WriteBorrow, WriteField, WriteProperty;

pub struct Sample {
    pub Value: i32;
    pub Total: i32 { get; set; }

    pub readonly fn Add(Amount: i32) -> i32 {
        return Value + Amount;
    }

    pub fn Reset() -> void {
        Value = 0;
    }
}
pub struct StaticSample { pub static Value: i32; }

fn SameType(Left: TypeInfo, Right: TypeInfo) -> bool {
    let LeftId = Left.StableId;
    let RightId = Right.StableId;
    return LeftId.High == RightId.High && LeftId.Low == RightId.Low;
}

fn Main() -> i32 {
    let Type = TypeOf<Sample>();
    if Type.Kind != .Struct || Type.Name != "Sample" ||
        Type.ModulePath != "example.reflection" || Type.ByteSize == 0 ||
        Type.Alignment == 0 || Type.IsOpaque {
        return 1;
    }
    if Type.BaseCount() != 0 || Type.InterfaceCount() != 0 ||
        Type.GenericArgumentCount() != 0 || Type.AttributeCount() != 0 {
        return 2;
    }
    if Type.BaseAt(0) is .Some { Value = _ } {
        return 3;
    }
    if Type.InterfaceAt(0) is .Some { Value = _ } {
        return 4;
    }
    if Type.GenericArgumentAt(0) is .Some { Value = _ } {
        return 5;
    }
    if Type.AttributeAt(0) is .Some { Value = _ } {
        return 6;
    }

    let StableId = Type.StableId;
    let StableMatch = switch FindTypeByStableId(StableId) {
        case .Ok { Value = Found } => break Found;
        case .Err { Error = _ } => return 7;
    };
    if StableMatch.StableId.High != StableId.High ||
        StableMatch.StableId.Low != StableId.Low {
        return 8;
    }
    let NamedMatch = switch FindType(Type.ModulePath, Type.QualifiedName) {
        case .Ok { Value = Found } => break Found;
        case .Err { Error = _ } => return 9;
    };
    if !SameType(NamedMatch, Type) || RegisteredTypeCount() == 0 {
        return 10;
    }
    if RegisteredTypeAt(RegisteredTypeCount()) is .Some { Value = _ } {
        return 11;
    }

    if Type.FieldCount(.Declared) != 1 ||
        Type.FieldAt(.Declared, 1) is .Some { Value = _ } {
        return 12;
    }
    let Field = switch Type.FindField("Value", .Declared) {
        case .Ok { Value = Found } => break Found;
        case .Err { Error = _ } => return 13;
    };
    if Field.Name != "Value" || !SameType(Field.DeclaringType, Type) ||
        Field.ValueType.Kind != .Integer || Field.Visibility != .Pub ||
        Field.IsStatic || !Field.IsMutable || Field.IsCompilerGenerated ||
        Field.AttributeCount != 0 ||
        Field.AttributeAt(0) is .Some { Value = _ } {
        return 14;
    }
    if Field.AutoProperty is .Some { Value = _ } {
        return 15;
    }

    if Type.PropertyCount(.Declared) != 1 ||
        Type.PropertyAt(.Declared, 1) is .Some { Value = _ } {
        return 16;
    }
    let Property = switch Type.FindProperty("Total", .Declared) {
        case .Ok { Value = Found } => break Found;
        case .Err { Error = _ } => return 17;
    };
    if Property.Name != "Total" ||
        !SameType(Property.DeclaringType, Type) ||
        Property.ValueType.Kind != .Integer ||
        Property.Visibility != .Pub || Property.Getter.IsStatic ||
        Property.IsVirtual || Property.IsOverride ||
        Property.IsSealedOverride || Property.AttributeCount != 0 ||
        Property.AttributeAt(0) is .Some { Value = _ } {
        return 18;
    }
    if (Property.Setter is .None) {
        return 19;
    }
    let BackingField = switch Property.BackingField {
        case .Some { Value = Found } => break Found;
        case .None => return 20;
    };
    if !BackingField.IsCompilerGenerated ||
        BackingField.AutoProperty is .None {
        return 21;
    }

    let ParameterTypes: ParameterSignature[1] = [
        ParameterSignature.Create(TypeOf<i32>(), .Value)
    ];
    let Signature = MethodSignature.Create(
        false,
        ParameterTypes,
        TypeOf<i32>(),
        .Value
    );
    if Signature.IsStatic || Signature.Parameters.Length != 1 ||
        Signature.Parameters[0].Mode != ParameterMode.Value ||
        !SameType(Signature.Parameters[0].Type, TypeOf<i32>()) ||
        !SameType(Signature.ResultType, TypeOf<i32>()) ||
        Signature.ResultMode != ReturnMode.Value {
        return 22;
    }
    let Method = switch Type.FindMethod("Add", Signature, .Declared) {
        case .Ok { Value = Found } => break Found;
        case .Err { Error = _ } => return 23;
    };
    if Method.Name != "Add" || !SameType(Method.DeclaringType, Type) ||
        Method.Visibility != .Pub || Method.IsStatic || Method.IsVirtual ||
        Method.IsOverride || Method.ParameterCount != 1 ||
        Method.AttributeCount != 0 || Method.ResultMode != .Value ||
        !SameType(Method.ResultType, TypeOf<i32>()) ||
        Method.AttributeAt(0) is .Some { Value = _ } {
        return 24;
    }
    let Parameter = switch Method.ParameterAt(0) {
        case .Some { Value = Found } => break Found;
        case .None => return 25;
    };
    if Parameter.Name != "Amount" || Parameter.Position != 0 ||
        Parameter.Mode != .Value ||
        !SameType(Parameter.Type, TypeOf<i32>()) ||
        Parameter.AttributeCount != 0 ||
        Parameter.AttributeAt(0) is .Some { Value = _ } {
        return 26;
    }
    if Method.ParameterAt(1) is .Some { Value = _ } ||
        Type.MethodCount(MemberQuery.Declared) < 2 ||
        Type.MethodAt(.Declared, Type.MethodCount(.Declared))
            is .Some { Value = _ } {
        return 27;
    }

    var Instance: Sample = .{ Value = 7 };
    let InstanceRef = Erase(Instance);
    if InstanceRef.Address == null || InstanceRef.Access != .Write ||
        !SameType(InstanceRef.Type, Type) {
        return 28;
    }
    let SafeRead = switch Field.Read<i32>(Instance) {
        case .Ok { Value = Copied } => break Copied;
        case .Err { Error = _ } => return 53;
    };
    if SafeRead != 7 { return 54; }
    switch Field.Borrow<i32>(Instance) {
        case .Ok { Value = View } => { if View.Get() != 7 { return 201; } }
        case .Err { Error = _ } => return 202;
    }
    var Writable = Field.BorrowMut<i32>(Instance);
    switch Writable {
        case .Ok { Value = View: mut WriteBorrow<i32>& } => { View.Get() = 7; }
        case .Err { Error = _ } => return 203;
    }

    var ResultStorage: i32 = 0;
    var ResultSlot = unsafe {
        // Safety: ResultStorage is live, exact i32 storage for this scope.
        break SlotFromStorage(
            (&ResultStorage) as! mut void*,
            TypeOf<i32>(),
            TypeOf<i32>().ByteSize,
            TypeOf<i32>().Alignment,
            .Live
        );
    };
    if ResultSlot.Address == null || ResultSlot.Capacity == 0 ||
        ResultSlot.Alignment == 0 || ResultSlot.State != .Live ||
        !SameType(ResultSlot.Type, TypeOf<i32>()) {
        DestroySlot(ResultSlot);
        return 29;
    }
    if DestroySlot(ResultSlot) != .Success ||
        ResultSlot.State != .Empty {
        return 29;
    }

    if ReadField(Field, InstanceRef, ResultSlot, .Deny) != .Success {
        return 30;
    }
    let ReadValue = switch CopySlot<i32>(ResultSlot) {
        case .Ok { Value = Value } => break Value;
        case .Err { Error = _ } => {
            DestroySlot(ResultSlot);
            return 31;
        }
    };
    if ReadValue != 7 || ResultSlot.State != .Live {
        DestroySlot(ResultSlot);
        return 32;
    }
    if DestroySlot(ResultSlot) != .Success ||
        ResultSlot.State != .Empty {
        return 32;
    }

    let Replacement: i32 = 11;
    let WriteArgument = Argument.CopyValue(Erase(Replacement));
    if WriteArgument.Mode != .CopyValue ||
        WriteField(Field, InstanceRef, WriteArgument, .Deny) != .Success ||
        Instance.Value != 11 {
        return 33;
    }
    let PublicAccess: PrivateAccess = .Deny;
    switch Field.Write<i32>(Instance, Replacement) {
        case .Ok => {}
        case .Err { Error = _ } => return 55;
    }
    switch Field.Write<i32>(Instance, Replacement, PublicAccess) {
        case .Ok => {}
        case .Err { Error = _ } => return 56;
    }
    if Instance.Value != 11 || Replacement != 11 { return 57; }
    let StaticType = TypeOf<StaticSample>();
    let StaticField = switch StaticType.FindField("Value", .Declared) {
        case .Ok { Value = Found } => break Found;
        case .Err { Error = _ } => return 58;
    };
    switch StaticField.WriteStatic<i32>(Replacement) {
        case .Ok => {}
        case .Err { Error = _ } => return 59;
    }
    switch StaticField.WriteStatic<i32>(Replacement, PublicAccess) {
        case .Ok => {}
        case .Err { Error = _ } => return 60;
    }
    if StaticSample.Value != 11 { return 61; }

    let PropertyValue: i32 = 23;
    let PropertyArgument = Argument.CopyValue(Erase(PropertyValue));
    if WriteProperty(Property, InstanceRef, PropertyArgument, .Deny) !=
        .Success || Instance.Total != 23 {
        return 34;
    }
    if ReadProperty(Property, InstanceRef, ResultSlot, .Deny) != .Success {
        return 35;
    }
    let ReflectedProperty = switch TakeSlot<i32>(ResultSlot) {
        case .Ok { Value = Value } => break Value;
        case .Err { Error = _ } => {
            DestroySlot(ResultSlot);
            return 36;
        }
    };
    if ReflectedProperty != 23 || ResultSlot.State != .Empty {
        return 37;
    }

    let Amount: i32 = 5;
    let Arguments: Argument[1] = [Argument.CopyValue(Erase(Amount))];
    var Frame = InvocationFrame.WithResult(
        InstanceRef,
        Arguments,
        ResultSlot,
        .Deny
    );
    if !Frame.HasResult || Frame.Arguments.Length != 1 ||
        Frame.Access != .Deny || Frame.Instance is .None ||
        Invoke(Method, Frame) != .Success {
        return 38;
    }
    let InvokedValue = switch CopySlot<i32>(ResultSlot) {
        case .Ok { Value = Value } => break Value;
        case .Err { Error = _ } => {
            DestroySlot(ResultSlot);
            return 39;
        }
    };
    if InvokedValue != 16 || ResultSlot.State != .Live {
        DestroySlot(ResultSlot);
        return 40;
    }
    if DestroySlot(ResultSlot) != .Success ||
        ResultSlot.State != .Empty {
        return 40;
    }

    let NoParameters: ParameterSignature[0] = [];
    let ResetSignature = MethodSignature.Create(
        false,
        NoParameters,
        TypeOf<void>(),
        .Void
    );
    let ResetMethod = switch Type.FindMethod(
        "Reset",
        ResetSignature,
        .Declared
    ) {
        case .Ok { Value = Found } => break Found;
        case .Err { Error = _ } => return 41;
    };
    let NoArguments: Argument[0] = [];
    var ResetFrame = InvocationFrame.WithoutResult(
        InstanceRef,
        NoArguments,
        .Deny
    );
    if ResetFrame.HasResult || Invoke(ResetMethod, ResetFrame) != .Success ||
        Instance.Value != 0 {
        return 42;
    }

    var DelayedSource: i32 = 9;
    let MoveArgument = Argument.MoveValue(Erase(DelayedSource));
    let ReadArgument = Argument.RefRead(Erase(Amount));
    let WriteReference = Argument.RefWrite(Erase(DelayedSource));
    let RValueArgument = Argument.RValue(Erase(DelayedSource));
    let OutArgument = Argument.Out(ResultSlot);
    if DelayedSource != 9 || MoveArgument.Mode != .MoveValue ||
        ReadArgument.Mode != .RefRead ||
        WriteReference.Mode != .RefWrite ||
        RValueArgument.Mode != .RValue || OutArgument.Mode != .Out {
        return 43;
    }

    let ForeignRead = unsafe {
        // Safety: Amount is an exact live i32 for the complete view use.
        break EraseForeign((&Amount) as! void*, TypeOf<i32>());
    };
    var ForeignValue: i32 = 3;
    let ForeignWrite = unsafe {
        // Safety: ForeignValue is writable exact i32 storage for this scope.
        break EraseForeignMut(
            (&ForeignValue) as! mut void*,
            TypeOf<i32>()
        );
    };
    if ForeignRead.Access != .Read || ForeignWrite.Access != .Write ||
        ForeignRead.Address == null || ForeignWrite.Address == null {
        return 44;
    }
    if !SameType(TypeOf(Instance), Type) {
        return 45;
    }
    let Pointer: readonly Sample* = unsafe {
        // Safety: Instance remains live throughout the pointer query.
        break (&Instance) as! readonly Sample*;
    };
    let Pointee = unsafe { break TypeOf(Pointer); };
    switch Pointee {
        case .Some { Value = Actual } => {
            if !SameType(Actual, Type) { return 46; }
        }
        case .None => return 47;
    }
    return 0;
}

Visibility

pub enum Visibility

Reports authored member visibility.

MemberQuery

pub enum MemberQuery

Selects declared/inherited and compiler-generated member enumeration.

LookupError

pub enum LookupError

Classifies exact descriptor lookup failure.

AccessMode

pub enum AccessMode

Records erased-place read/write authority.

ParameterMode

pub enum ParameterMode

Records one declared parameter passing mode.

ReturnMode

pub enum ReturnMode

Records one reflected callable result mode.

ValueSlotState

pub enum ValueSlotState

Tracks caller-owned reflected result/output storage lifetime.

ArgumentMode

pub enum ArgumentMode

Selects the delayed operation performed for one invocation argument.

PrivateAccess

pub enum PrivateAccess

Selects explicit private-member operation authority.

InvocationStatus

pub enum InvocationStatus

Reports one complete checked reflection operation outcome.

Documentation snapshot: October 24, 2026 About versions ↗
Searching Development · language & standard library