vision
Install

Concept guide

Generics and monomorphization

A closed type list lets one verb or kind work with a small, named set of types. Vision checks each version at compile time, then emits ordinary C functions and structs.

One program, two generic forms

This program uses the same type list in two places. preserve is a generic verb: it accepts a whole number or text and returns the same concrete type. labeled item is a generic kind: its contents field becomes a whole number in one construction and text in another.

generics.viscompiler checked
kind labeled item, which works on number or text:
    contents
    label is text

to preserve(item), which works on numbers or text:
    answer item

to begin:
    the score is a labeled item of numbers
    score.contents is preserve(42)
    score.label is "points"

    the greeting is a labeled item of text
    greeting.contents is preserve("hello")
    greeting.label is "message"

    say "{score.label}: {score.contents}"
    say "{greeting.label}: {greeting.contents}"
kind labeled item, which works on number or text:
    contents
    label is text

to preserve(item), which works on numbers or text:
    answer item

to begin:
    the score is a labeled item of numbers
    score.contents is preserve(42)
    score.label is "points"

    the greeting is a labeled item of text
    greeting.contents is preserve("hello")
    greeting.label is "message"

    say "{score.label}: {score.contents}"
    say "{greeting.label}: {greeting.contents}"
The build compiles and runs both verb calls and both constructed shapes, then checks the two output lines exactly.

Read which works on as a closed list

which works on numbers or text does not introduce a type named numbers or text. It names two concrete Vision types that this declaration accepts. The list is closed: a decimal, byte, or unrelated kind is not included unless the declaration names it.

At preserve(42), the argument is a whole number, so the call selects the numbers entry. At preserve("hello"), it selects text. There is no abstract T in the source and no runtime value that means β€œone of these types.” The call already has one concrete type when the compiler checks it.

The closed-list signature and compile-time verb specialization are both part of the current surface documented here.

A generic verb becomes concrete verbs

Vision checks preserve's body separately as a number verb and as a text verb. Each version must make sense on its own. A body that adds 1, for example, cannot also claim to work on text just because the number version is valid.

Once a version passes, the compiler emits a concrete C function for that listed type and routes each call straight to the matching function. This is monomorphization. The running program does not inspect a type tag, choose a branch, or box both values behind one shared representation.

A generic kind makes concrete shapes

Generic kinds use the same phrase, but construction chooses the type. a labeled item of numbers makes a shape whose bare contents field is a whole number. a labeled item of text makes a separate shape whose contents field is text.

A bare field follows the type named after of. An explicitly typed field does not: label is text stays text in both shapes. Generic-kind construction and specialization are now part of the language; one concrete C struct is emitted for each kind-and-type pair the program actually constructs.

What changes, and what does not

The source keeps one declaration for preserve and one for labeled item. The generated program has separate concrete functions and shapes. That split happens during compilation, so the output contains no generic dispatch machinery to explain or pay for at runtime.

The ordinary Vision rules still apply inside each version. Text keeps its ownership behavior, numeric operations keep their checked types, and a generic body is not a way around world-touch or failure markers. See Safe by design for those boundaries.

A few current boundaries

A generic verb's body must work for every type it lists. If the verb has several parameters, every argument at one call must resolve to the same concrete type; Vision does not build every possible combination. Call a generic verb directly: it cannot currently be stored as a callable value or exposed as one host function, because there is no single shared function behind its name.

A generic kind must be constructed with of followed by a type, and that type must appear in its own which works on list. The Generics reference will give the full accepted-type and diagnostic rules; these are the limits most likely to matter while following this example.

Add one concrete version

Add decimal to the generic kind's which works on list. Then construct a labeled item of decimals, assign 21.5 directly to its contents, and label it temperature. Predict the third output line before compiling: it should read temperature: 21.5.

For a quick failure check, remove text from preserve without changing the greeting call. The compiler rejects that call because its concrete argument no longer matches the verb's closed list.