nupp.types

Compiler-only type inspection and construction inside @comptime function declarations. Every member is an ordinary checked compile-time value; none has a runtime representation.

Module contents

Functions

FunctionKindDescription
affinecomptime functionAn affine resource over representation: used at most once, and never copied.
argumentscomptime functionThe type arguments a generic declaration was applied to.
arraycomptime functionThe Lua array {element}, with integer keys and no fixed length.
borrowedcomptime functionA borrow of inner, valid for the region that borrows it and not stored.
carraycomptime functionA C array of element, sized when count is given and unsized when it is not.
constofcomptime functioninner behind a const capability, which permits reads and refuses writes.
constructioncomptime functionThe parameters a record or struct is constructed with, as a pack whose slots carry their names.
describecomptime functionEvery fact about one handle at once, as a record whose members are populated according to its kind.
elementscomptime functionThe fixed elements of a composite type, or a pack's fixed head.
errorcomptime functionRejects this type application deliberately, with an authored message.
fieldscomptime functionThe public fields of a shape or of a nominal record, interface, or struct.
formatArgumentscomptime functionComputes the arguments consumed by a literal Lua format string.
function_comptime functionA function type from its parameter and result packs.
indexercomptime functionA type indexed by computed keys rather than by named fields.
intersectioncomptime functionThe intersection of its members, as a set, flattened and deduplicated the way union is.
kindcomptime functionWhat a handle is, as a string, which is the usual way to branch on one.
lengthcomptime functionbase narrowed to the byte lengths from min through max, both included.
literalcomptime functionThe singleton type inhabited by a value.
mapcomptime functionAn indexer whose write side mirrors its read side unless stated otherwise.
nonExhaustivecomptime functionThe member that keeps a union open, so a switch over it stays inexhaustive.
optionalcomptime functioninner | nil.
packcomptime functionA type pack: a fixed head of slots, then an optional tail standing for however many values remain.
parameterscomptime functionThe parameter pack of a function type.
pinnedcomptime functioninner pinned to its address, so the collector may not move it.
pointercomptime functionA pointer to inner.
rangecomptime functionbase narrowed to the values from min through max, both included.
readAtcomptime functionThe type read at a key: the named field when the key is a string literal naming a readable one, and otherwise the...
readKeyscomptime functionEvery key a type can be read at: one string literal per readable field, plus the indexer's read key when it has one.
resultscomptime functionThe result pack of a function type.
sameNominalcomptime functionWhether two types name the same nominal declaration, ignoring its arguments.
shapecomptime functionA structural type with named fields, and optionally an indexer for the keys the names do not cover.
tuplecomptime functionA fixed-length positional type, one slot per element in the order given.
unioncomptime functionThe union of its members, as a set.
writeAtcomptime functionThe type written at a key: the named field when the key is a string literal naming a writable one, and otherwise the...
writeKeyscomptime functionEvery key a type can be written at: one string literal per writable field, plus the indexer's write key when it has one.

Values

ValueKindDescription
anycomptime typeThe dynamic type; compatible with everything, checked at neither end.
booleancomptime typetrue or false.
cdatacomptime typeAny cdata value.
cstringcomptime typeconst char .
floatcomptime typeAn established binary32 Lua number; widens to number.
int16comptime typeSigned physical storage; loads as int32.
int32comptime typeAn established signed 32-bit Lua integer.
int64comptime typeA boxed 64-bit signed cdata integer, as LuaJIT's 1LL.
int8comptime typeSigned physical storage; loads as int32.
integercomptime typeA number known to be integral.
nevercomptime typeThe bottom type; fits everything, nothing fits it.
nil_comptime typeThe nil singleton, spelled nil because nil is a keyword.
numbercomptime typeA LuaJIT double.
stringcomptime typeA Lua string.
table_comptime typeAny table shape, compatible with every table type in both directions, spelled table because table names the standard...
threadcomptime typeA coroutine.
uint16comptime typeUnsigned physical storage; loads as uint32.
uint32comptime typeAn established unsigned 32-bit Lua integer.
uint64comptime typeA boxed 64-bit unsigned cdata integer, as LuaJIT's 1ULL.
uint8comptime typeUnsigned physical storage; loads as uint32.
unknowncomptime typeThe top type; everything fits it, it fits nothing else.
userdatacomptime typeUserdata.
voidptrcomptime typevoid .

Functions#

affinecomptime function#

local affine: @comptime function(representation: type): type
& @comptime function(representation: type, const terminal: function): type
@readonly

An affine resource over representation: used at most once, and never copied.

With a terminal, that const function is the operation consuming the resource, the way close consumes a file. Without one the resource is transfer-only, so ownership may move but nothing ends it.

Arguments

NameTypeDescription
representationtype

the underlying representation type

terminalany

the const-function parameter that consumes it

Returns

TypeDescription
type

the affine type

Raises

TypeCondition
string

when the terminal is not a const-function parameter

argumentscomptime function#

local arguments: @comptime function(value: type): {type}
@readonly

The type arguments a generic declaration was applied to.

Empty for a type that is not a generic application, so a caller may ask without knowing which it has.

Arguments

NameTypeDescription
valuetype

the applied type to inspect

Returns

TypeDescription
{type}

one handle per argument, in declaration order

arraycomptime function#

local array: @comptime function(element: type): type
@readonly

The Lua array {element}, with integer keys and no fixed length.

Arguments

NameTypeDescription
elementtype

the element type

Returns

TypeDescription
type

the array type

borrowedcomptime function#

local borrowed: @comptime function(inner: type): type
@readonly

A borrow of inner, valid for the region that borrows it and not stored.

Arguments

NameTypeDescription
innertype

the owned type being borrowed

Returns

TypeDescription
type

the borrowed type

carraycomptime function#

local carray: @comptime function(element: type, count: integer?): type
@readonly

A C array of element, sized when count is given and unsized when it is not.

Arguments

NameTypeDescription
elementtype

the element type

countinteger?

the fixed length, or nil for an unsized array

Returns

TypeDescription
type

the C array type

Raises

TypeCondition
string

when the count is not a non-negative exact integer

constofcomptime function#

local constof: @comptime function(inner: type): type
@readonly

inner behind a const capability, which permits reads and refuses writes.

Arguments

NameTypeDescription
innertype

the type to make const

Returns

TypeDescription
type

the const type

constructioncomptime function#

local construction: @comptime function(value: type): typepack
@readonly

The parameters a record or struct is constructed with, as a pack whose slots carry their names.

The one declared constructor's parameters, or the stored fields in declaration order when the declaration has no constructor; a field with a default, or one that admits nil, is an optional slot. Written as ...: unpackof nupp.types.construction(E), the pack is a parameter list a call binds by position or by name, the way it would for new E(...).

Arguments

NameTypeDescription
valuetype

the record or struct to inspect

Returns

TypeDescription
typepack

its construction contract

Raises

TypeCondition
string

when the declaration has several constructors, which is no single contract

describecomptime function#

local describe: @comptime function(value: type | typepack): {
    @readonly kind: string,
    @readonly sourceKind: string?,

    --- Reports the nominal declaration category without expanding a reference.
    @readonly declarationKind: string?,
    @readonly name: string?,
    @readonly value: (string | boolean | integer)?,
    @readonly element: type?,
    @readonly members: {type}?,
    @readonly fields: {{
        @readonly name: string,
        @readonly read: type?,
        @readonly write: type?
    }}?,
    @readonly indexer: type?,
    @readonly readKey: type?,
    @readonly readValue: type?,
    @readonly writeKey: type?,
    @readonly writeValue: type?,
    @readonly nominal: boolean?,
    @readonly head: {type}?,
    @readonly tail: type?,
    @readonly modes: {string}?,
    @readonly count: integer?,
    @readonly parameters: typepack?,
    @readonly results: typepack?
}
@readonly

Every fact about one handle at once, as a record whose members are populated according to its kind.

Reach for it when a generator needs several facts about the same handle, or a fact no single accessor exposes, such as a pack's tail or a C array's count. A member that does not apply to the handle's kind is nil.

Arguments

NameTypeDescription
valuetype | typepack

the type or type pack to inspect

Returns

TypeDescription
{ @readonly kind: string, @readonly sourceKind: string?, --- Reports the nominal declaration category without expanding a reference. @readonly declarationKind: string?, @readonly name: string?, @readonly value: (string | boolean | integer)?, @readonly element: type?, @readonly members: {type}?, @readonly fields: {{ @readonly name: string, @readonly read: type?, @readonly write: type? }}?, @readonly indexer: type?, @readonly readKey: type?, @readonly readValue: type?, @readonly writeKey: type?, @readonly writeValue: type?, @readonly nominal: boolean?, @readonly head: {type}?, @readonly tail: type?, @readonly modes: {string}?, @readonly count: integer?, @readonly parameters: typepack?, @readonly results: typepack? }

its descriptor

elementscomptime function#

local elements: @comptime function(value: type | typepack): {type}
@readonly

The fixed elements of a composite type, or a pack's fixed head.

Arguments

NameTypeDescription
valuetype | typepack

the type or type pack to take apart

Returns

TypeDescription
{type}

one handle per element, in declaration order

errorcomptime function#

local error: @comptime function(message: string): never
@readonly

Rejects this type application deliberately, with an authored message.

Distinct from an evaluator crash or a timeout: the message is reported at the application, with a bounded comptime call trace. It returns never, so a generator may call it in a branch that has no type to return.

Arguments

NameTypeDescription
messagestring

what to report at the application

Returns

TypeDescription
never

nothing; the call does not come back

fieldscomptime function#

local fields: @comptime function(value: type): {{
    @readonly name: string,
    @readonly read: type?,
    @readonly write: type?
}}
@readonly

The public fields of a shape or of a nominal record, interface, or struct.

A nominal keeps its declaration identity: reading its fields does not expand it into a structural type. Each descriptor carries a name and whichever of read and write the field has. describe(T).fields reports the same descriptors.

Arguments

NameTypeDescription
valuetype

the shape or nominal type to inspect

Returns

TypeDescription
{{ @readonly name: string, @readonly read: type?, @readonly write: type? }}

one descriptor per field, in declaration order

Raises

TypeCondition
string

when the handle is neither a shape nor a nominal declaration

formatArgumentscomptime function#

local formatArguments: @comptime function(format: type): typepack
@readonly

Computes the arguments consumed by a literal Lua format string.

A broad string produces an open any pack. %? is reserved for compiler-lowered formatting APIs.

Arguments

NameTypeDescription
formattype

the format-string type to inspect

Returns

TypeDescription
typepack

the argument pack consumed by its directives

function_comptime function#

local function_: @comptime function(parameters: typepack, results: typepack): type
@readonly

A function type from its parameter and result packs. Spelled with a trailing underscore because function is a keyword.

Arguments

NameTypeDescription
parameterstypepack

the parameter pack

resultstypepack

the result pack

Returns

TypeDescription
type

the function type

indexercomptime function#

local indexer: @comptime function(
    readKey: type?,
    readValue: type?,
    writeKey: type?,
    writeValue: type?
): type
@readonly

A type indexed by computed keys rather than by named fields.

Each capability is a key/value pair: supply both halves or neither. At least one capability is required, and a read-only or write-only indexer is the point of taking them separately. map is the shorthand for the common case where both sides agree.

Arguments

NameTypeDescription
readKeytype?

the key type reads accept

readValuetype?

the value type reads answer

writeKeytype?

the key type writes accept

writeValuetype?

the value type writes accept

Returns

TypeDescription
type

the indexer type

Raises

TypeCondition
string

when a capability is missing half of its pair, or when neither capability is supplied

intersectioncomptime function#

local intersection: @comptime function(members: {type}): type
@readonly

The intersection of its members, as a set, flattened and deduplicated the way union is. An intersection of function types is an overload set.

Arguments

NameTypeDescription
members{type}

the member types, in any order

Returns

TypeDescription
type

the intersection type

kindcomptime function#

local kind: @comptime function(value: type | typepack): string
@readonly

What a handle is, as a string, which is the usual way to branch on one.

The answer is the handle's own kind, not the builder that made it: map returns "indexer", optional returns "union", pointer returns "ptr", and constof returns "const". A nominal declaration returns "reference", and describe(T).declarationKind says which category it declares.

Arguments

NameTypeDescription
valuetype | typepack

the type or type pack to inspect

Returns

TypeDescription
string

the kind, such as "literal", "array", "shape", or "pack"

lengthcomptime function#

local length: @comptime function(base: type, min: integer, max: integer): type
@readonly

base narrowed to the byte lengths from min through max, both included.

Bytes, matching Nupp's own string length: not code points, not graphemes. An embedded NUL counts like any other byte. The base is string or a constrained alias of it.

Arguments

NameTypeDescription
basetype

the type being narrowed

mininteger

the shortest admitted length in bytes

maxinteger

the longest admitted length in bytes

Returns

TypeDescription
type

the constrained type

Raises

TypeCondition
string

when the base is not a string or the bounds are empty

literalcomptime function#

local literal: @comptime function(value: string | boolean | integer): type
@readonly

The singleton type inhabited by a value.

A number must be an exact integer, since a literal type names a value the checker compares for equality.

Arguments

NameTypeDescription
valuestring | boolean | integer

the inhabitant to lift into type position

Returns

TypeDescription
type

the type whose only value is value

Raises

TypeCondition
string

when the value is not a string, boolean, or exact integer

mapcomptime function#

local map: @comptime function(readKey: type, readValue: type, writeKey: type?, writeValue: type?): type
@readonly

An indexer whose write side mirrors its read side unless stated otherwise.

Equivalent to indexer(readKey, readValue, writeKey or readKey, writeValue or readValue), and it returns a handle of kind "indexer".

Arguments

NameTypeDescription
readKeytype

the key type reads accept

readValuetype

the value type reads answer

writeKeytype?

the key type writes accept, defaulting to readKey

writeValuetype?

the value type writes accept, defaulting to readValue

Returns

TypeDescription
type

the indexer type

nonExhaustivecomptime function#

local nonExhaustive: @comptime function(): type
@readonly

The member that keeps a union open, so a switch over it stays inexhaustive.

No name resolves to this type, so calling for it is the only way to place it in a union. That is what makes a non-exhaustive union a written decision rather than an inferred one. It may be written directly in a type as well as inside a generator.

Returns

TypeDescription
type

the open member

Raises

TypeCondition
string

when given any argument

optionalcomptime function#

local optional: @comptime function(inner: type): type
@readonly

inner | nil.

Built as a union, so it is idempotent: optional(optional(T)) and optional(T) are one handle.

Arguments

NameTypeDescription
innertype

the type to admit nil alongside

Returns

TypeDescription
type

the nilable type

packcomptime function#

local pack: @comptime function(head: {type}, tail: type?, modes: {string}?): typepack
@readonly

A type pack: a fixed head of slots, then an optional tail standing for however many values remain.

modes align with the head one for one and default to "plain"; the others are "affine", "borrowed", "exclusive", and "pinned".

Arguments

NameTypeDescription
head{type}

the fixed slot types, in position order

tailtype?

the type of the remaining values, or nil for a closed pack

modes{string}?

the ownership mode of each fixed slot

Returns

TypeDescription
typepack

the pack

Raises

TypeCondition
string

when there are more modes than slots, or a mode is not one of the five

parameterscomptime function#

local parameters: @comptime function(callable: type): typepack
@readonly

The parameter pack of a function type.

Arguments

NameTypeDescription
callabletype

the function type to inspect

Returns

TypeDescription
typepack

its parameters

Raises

TypeCondition
string

when the handle is not a function type

pinnedcomptime function#

local pinned: @comptime function(inner: type): type
@readonly

inner pinned to its address, so the collector may not move it.

Arguments

NameTypeDescription
innertype

the type to pin

Returns

TypeDescription
type

the pinned type

pointercomptime function#

local pointer: @comptime function(inner: type): type
@readonly

A pointer to inner.

Arguments

NameTypeDescription
innertype

the pointee type

Returns

TypeDescription
type

the pointer type

rangecomptime function#

local range: @comptime function(base: type, min: integer, max: integer): type
@readonly

base narrowed to the values from min through max, both included.

A constrained type is a subtype of its base: it goes wherever the base goes. Entering one is admission rather than subtyping, so a value the checker cannot prove is refused and nupp.admit is how the program says it meant it. A literal is decided here and needs nothing written.

The base is integer, int32, uint32, or a constrained alias of one, which narrows further by intersecting. Representation is unchanged: this converts nothing.

Arguments

NameTypeDescription
basetype

the type being narrowed

mininteger

the lowest admitted value

maxinteger

the highest admitted value

Returns

TypeDescription
type

the constrained type

Raises

TypeCondition
string

when the base is unsupported or the bounds are empty or out of range

readAtcomptime function#

local readAt: @comptime function(value: type, key: type): type
@readonly

The type read at a key: the named field when the key is a string literal naming a readable one, and otherwise the indexer's read value.

Arguments

NameTypeDescription
valuetype

the type to project

keytype

the key to read at

Returns

TypeDescription
type

the value type at that key

Raises

TypeCondition
string

when the type has no read capability there, reported as NUPP2420

readKeyscomptime function#

local readKeys: @comptime function(value: type): {type}
@readonly

Every key a type can be read at: one string literal per readable field, plus the indexer's read key when it has one.

Arguments

NameTypeDescription
valuetype

the shape or indexer to inspect

Returns

TypeDescription
{type}

one handle per readable key

Raises

TypeCondition
string

when the handle is neither a shape nor an indexer

resultscomptime function#

local results: @comptime function(callable: type): typepack
@readonly

The result pack of a function type.

Arguments

NameTypeDescription
callabletype

the function type to inspect

Returns

TypeDescription
typepack

its results

Raises

TypeCondition
string

when the handle is not a function type

sameNominalcomptime function#

local sameNominal: @comptime function(left: type, right: type): boolean
@readonly

Whether two types name the same nominal declaration, ignoring its arguments.

Aliases and ownership wrappers are transparent. Structural types and two different nominal declarations answer false even when their shapes match.

Arguments

NameTypeDescription
lefttype
righttype

Returns

TypeDescription
boolean

shapecomptime function#

local shape: @comptime function(fields: const{{
    @readonly name: string,
    @readonly read: type?,
    @readonly write: type?
}}, indexer: type?): type
@readonly

A structural type with named fields, and optionally an indexer for the keys the names do not cover.

Each descriptor needs a non-empty name unique within the shape, and at least one of read and write: a field with only read is readonly, one with only write is writeonly. Field order does not affect identity, so two shapes with the same fields are one handle however they were listed.

Arguments

NameTypeDescription
fieldsconst{{ @readonly name: string, @readonly read: type?, @readonly write: type? }}

the field descriptors

indexertype?

an indexer handle from nupp.types.indexer or nupp.types.map

Returns

TypeDescription
type

the shape type

Raises

TypeCondition
string

when a name is empty or repeated, when a field declares neither capability, when the indexer did not come from an indexer builder, or when there are more than 1000 fields

tuplecomptime function#

local tuple: @comptime function(elements: {type}): type
@readonly

A fixed-length positional type, one slot per element in the order given.

Arguments

NameTypeDescription
elements{type}

the slot types, in position order

Returns

TypeDescription
type

the tuple type

unioncomptime function#

local union: @comptime function(members: {type}): type
@readonly

The union of its members, as a set.

Nested unions are flattened, duplicates dropped, and the rest ordered canonically, so union{A, union{A, B}} and union{A, B} are one handle.

Arguments

NameTypeDescription
members{type}

the member types, in any order

Returns

TypeDescription
type

the union type

writeAtcomptime function#

local writeAt: @comptime function(value: type, key: type): type
@readonly

The type written at a key: the named field when the key is a string literal naming a writable one, and otherwise the indexer's write value.

Arguments

NameTypeDescription
valuetype

the type to project

keytype

the key to write at

Returns

TypeDescription
type

the value type at that key

Raises

TypeCondition
string

when the type has no write capability there, reported as NUPP2420

writeKeyscomptime function#

local writeKeys: @comptime function(value: type): {type}
@readonly

Every key a type can be written at: one string literal per writable field, plus the indexer's write key when it has one.

Arguments

NameTypeDescription
valuetype

the shape or indexer to inspect

Returns

TypeDescription
{type}

one handle per writable key

Raises

TypeCondition
string

when the handle is neither a shape nor an indexer

Values#

anycomptime type#

local any: @comptime type
@readonly

The dynamic type; compatible with everything, checked at neither end.

booleancomptime type#

local boolean: @comptime type
@readonly

true or false.

cdatacomptime type#

local cdata: @comptime type
@readonly

Any cdata value.

cstringcomptime type#

local cstring: @comptime type
@readonly

const char *.

floatcomptime type#

local float: @comptime type
@readonly

An established binary32 Lua number; widens to number.

int16comptime type#

local int16: @comptime type
@readonly

Signed physical storage; loads as int32.

int32comptime type#

local int32: @comptime type
@readonly

An established signed 32-bit Lua integer.

int64comptime type#

local int64: @comptime type
@readonly

A boxed 64-bit signed cdata integer, as LuaJIT's 1LL.

int8comptime type#

local int8: @comptime type
@readonly

Signed physical storage; loads as int32.

integercomptime type#

local integer: @comptime type
@readonly

A number known to be integral.

nevercomptime type#

local never: @comptime type
@readonly

The bottom type; fits everything, nothing fits it.

nil_comptime type#

local nil_: @comptime type
@readonly

The nil singleton, spelled nil_ because nil is a keyword.

numbercomptime type#

local number: @comptime type
@readonly

A LuaJIT double.

stringcomptime type#

local string: @comptime type
@readonly

A Lua string.

table_comptime type#

local table_: @comptime type
@readonly

Any table shape, compatible with every table type in both directions, spelled table_ because table names the standard library namespace.

threadcomptime type#

local thread: @comptime type
@readonly

A coroutine.

uint16comptime type#

local uint16: @comptime type
@readonly

Unsigned physical storage; loads as uint32.

uint32comptime type#

local uint32: @comptime type
@readonly

An established unsigned 32-bit Lua integer.

uint64comptime type#

local uint64: @comptime type
@readonly

A boxed 64-bit unsigned cdata integer, as LuaJIT's 1ULL.

uint8comptime type#

local uint8: @comptime type
@readonly

Unsigned physical storage; loads as uint32.

unknowncomptime type#

local unknown: @comptime type
@readonly

The top type; everything fits it, it fits nothing else.

userdatacomptime type#

local userdata: @comptime type
@readonly

Userdata.

voidptrcomptime type#

local voidptr: @comptime type
@readonly

void *.