Compile-Time Reflection

@typeof(T)

Returns a TypeInfo compound value at compile time:

tape
@tape fn inspect(T: type) {
    var info = @typeof(T);
    @println("type: {info.name}, size: {info.size}, align: {info.align}");
}

TypeInfo fields:

FieldTypeDescription
namestringType name
kindintType kind (struct, primitive, etc.)
sizeintSize in bytes
alignintAlignment requirement
fieldsarrayArray of field descriptors

Field descriptors

Each element in info.fields is a compound with:

FieldTypeDescription
namestringField name
typetypeField type (as type value)
offsetintByte offset in struct
sizeintField size in bytes
__attrsarrayAttributes applied to this field
tape
@tape fn print_fields(T: type) {
    var info = @typeof(T);
    @println("struct {info.name} (size={info.size}, align={info.align}):");
    for (field in info.fields) {
        @println("  {field.name} : offset={field.offset}, size={field.size}");
    }
}

@sizeof(T)

Returns the size in bytes of a type:

tape
@tape { @assert(@sizeof(u64) == 8); }
@tape { @assert(@sizeof(i32) == 4); }

@alignof(T)

Returns the alignment requirement of a type:

tape
@tape { @assert(@alignof(f64) == 8); }
@tape { @assert(@alignof(u8) == 1); }

@has_field(T, name)

Returns true if the struct type has a field with the given name:

tape
@tape fn maybe_print_name(T: type) {
    comptime if (@has_field(T, "name")) {
        @emit fn print_name(obj: *${T}) {
            io.println(obj.name);
        }
    }
}

@has_method(T, name)

Returns true if a method with the given name exists on the type (checks receiver functions in the current module):

tape
@tape fn gen_print(T: type) {
    comptime if (@has_method(T, "to_string")) {
        @emit fn print_val(v: *${T}) { io.println(v.to_string()); }
    } else {
        @emit fn print_val(v: *${T}) { io.println("<opaque>"); }
    }
}

@field_type(T, name)

Returns the type of a named field as a type value:

tape
@tape fn check_field(T: type) {
    var ft = @field_type(T, "id");
    comptime match(ft) {
        i64 => { @println("id is i64"); }
        _   => { @println("id is something else"); }
    }
}

@field_type returns a comptime type value. It cannot be used directly in type position (e.g., as a return type annotation). Use $ splicing to insert type names into emitted declarations.

@inner_type(T)

Not yet implemented@inner_type is parsed but currently always produces an error. It is intended to extract the inner type from pointers, slices, and optionals.

@assert

Static assertion — produces a compile error if the condition is false:

tape
@tape { @assert(@sizeof(Header) == 64); }
@tape { @assert(@alignof(Vec4) == 16); }

Takes a single boolean expression.

PlannedA second argument for a custom error message (@assert(cond, "message")) is not yet implemented.

@compile_error

Abort compilation with a diagnostic message:

tape
@tape fn require_field(T: type, name: string) {
    comptime if (!@has_field(T, name)) {
        @compile_error("type is missing required field");
    }
}

@embed(path)

Read a file at compile time into a string value:

tape
@tape {
    var shader_src = @embed("shaders/vertex.glsl");
    @emit const VERTEX_SHADER = shader_src;
}

Path is relative to the source file. Maximum file size: 16 MB.

Compile-time output (prints during compilation, not at runtime):

tape
@tape {
    @print("compiling...");
    @println("struct size = {info.size}");
}

Supports string interpolation with {expr} inside the message. Values of type int, string, bool, and type are printed. Type values print their name.

Attribute reflection

Field descriptors carry their __attrs array, accessible via .has_attr() and .attr():

tape
attr serializable;
attr max_length(n: i64);

@tape fn gen_validate(T: type) {
    var info = @typeof(T);
    comptime for (field in info.fields) {
        comptime if (field.has_attr(serializable)) {
            @println("  {field.name} is serializable");
        }
    }
}
MethodReturnsDescription
field.has_attr(attr)boolWhether the field has this attribute
field.attr(attr)compoundThe attribute value (with .value for arguments)

Array operations in comptime

Comptime arrays (like info.fields) support:

  • .len — element count
  • arr[i] — index access
  • for (elem in arr) — iteration
  • for (elem, i in arr) — iteration with index

Last modified: