Skip to main content

Module builtins

Module builtins 

Source
Expand description

What the builtin types declare about themselves.

Array<T>.get, Vector.of, Shared<T>.lock and their neighbours are the language’s own methods and associated functions rather than a host’s, but they have the Host API schema’s problem exactly: the compiler needs their signatures to check a call, the runtime needs their names to dispatch one, and the two crates cannot see each other. ADR 0004 wrote the table out twice and said so, “until a crate both can depend on exists”. This is that crate, so this is that table, and there is now one of it.

§Why this is not HostType

A Host API operation’s signature is deliberately monomorphic: documents.read(String) -> Result<String, Error> names concrete types because a host is a boundary, and a boundary that took a type parameter would have nothing to instantiate it with. A builtin is the opposite. Array<T>.get answers in the element type of the receiver it was called on, snapshot answers in the receiver’s own type, Shared<T>.lock takes a function and answers in whatever that function produces, and Vector.of(items: T...) binds a parameter of its own. None of that fits HostType, and widening HostType to hold it would put generics into every host signature that has no use for them.

So there are two vocabularies here, on purpose: HostType for what crosses the Host API boundary, and BuiltinType for what the language defines about itself. They overlap in the scalars and diverge exactly where the two kinds of signature differ — BuiltinType has BuiltinType::Param, BuiltinType::SelfType, and BuiltinType::Fn, and HostType has Any, which is a boundary’s way of saying it does not look inside a value and means nothing for a method the language itself defines.

§Two tables, because a builtin is not always called on something

BUILTINS is keyed by a receiver, and most builtins have one: items.length() and Vector.of(1) are both reached through a type. Ok(1), Error("boom"), and assert(true) are not — they are written bare, the way a declared function is — so FREE_BUILTINS is the second table, holding the five constructors and the two assertions with a name, a kind, and a signature each. They were the last builtins written out in both cove-sema and cove-runtime; issue #50 is why they are here.

§What a builtin type is made of, and not only what it answers

A BuiltinSchema began as a name and a list of methods, which was enough for a call and not enough for anything else: Option is Some and None, Result is Ok and Err, an Error carries a message, and a MapEntry carries a key and a value, and none of that is a method. So an entry also declares its cases if it is an enum and its fields if it is a struct, and both ends read them: match exhaustiveness, the type a pattern’s binding gets, the value the interpreter builds, and the field a program reads all come from here. issue #53 is why, and it is the last of the four.

§What is here and what is not

The signatures are here; the implementations are not, and cannot be. A builtin’s body is Rust that reaches into a Value, so it lives in cove_runtime::builtins beside the value model it walks. What this table removes is the second description of those bodies: cove-sema reads every signature from here rather than restating it, and the runtime reads from here every question it can answer from a name alone — which type names are namespaces, which methods take a var self receiver, which names are constructors, which are assertions, how many arguments each takes, which receivers are told that count() is spelled length(), and what each builtin enum’s cases and each builtin struct’s fields are called. crates/cove-runtime/tests/builtin_schema.rs closes the loop by driving every entry in both tables through a real interpreter, so an entry added here with no implementation behind it fails a test rather than a program.

The variants of BuiltinType cover exactly the types the tables below use, on the same rule the host vocabulary follows: add one when a builtin needs it, because an unused variant is a type nobody can produce.

Structs§

BuiltinSchema
One builtin type: its name, its type parameters, and what may be called on a value of it or on the name of it.
CaseSchema
One case of a builtin enum.
FieldSchema
One field of a builtin struct.
FreeBuiltinSchema
One builtin that is called on nothing.
MethodSchema
One builtin method or associated function.
ParamSchema
One parameter of a builtin’s signature.
StdBinding
A builtin method or associated function whose implementation is Cove source rather than Rust.

Enums§

BuiltinType
A type in a builtin’s signature, written in Cove’s source vocabulary.
FreeBuiltinKind
What a builtin that is called on nothing is.
StdBindingKind
Which of a builtin type’s two call forms a StdBinding names.

Constants§

ARRAY
Array<T>: the fixed-length immutable sequence.
ASSERT
assert(condition: Bool) -> Result<Unit, Error>.
ASSERT_EQUAL
assertEqual(actual: T, expected: T) -> Result<Unit, Error>.
BOOL
Bool.
DURATION
Duration: a signed count of nanoseconds.
ERR
Err(error: E) -> Result<T, E>, the mirror of OK.
ERROR
Error, the builtin error struct.
ERROR_OF
Error(message: String) -> Error, the one constructor whose payload has a type of its own rather than one the call site settles.
ERR_CASE
Err(E), the failure case of a Result.
FLOAT
Float: a 64-bit binary floating-point number.
INT
Int: a signed 64-bit integer.
MAP
Map<K, V>: an immutable mapping, kept in ascending key order.
MAP_ENTRY
MapEntry<K, V>: the one key/value pair a Map is built from and iterated as.
MESSAGE_FIELD
message: String, the one field of the builtin Error struct.
NONE_CASE
None, the empty case of Option.
OK
Ok(value: T) -> Result<T, E>.
OK_CASE
Ok(T), the success case of a Result.
OPTION
Option<T>: Some(value) or None.
RANGE
Range: what 0..n and 0..=n produce.
RESULT
Result<T, E>: Ok(value) or Err(error).
SCOPE
Scope: the value scope name { ... } binds.
SET
Set<T>: an immutable set, kept in ascending element order.
SHARED
Shared<T>: mutable state more than one task may reach.
SHARED_OF
Shared(value: T) -> Shared<T>.
SOME
Some(value: T) -> Option<T>.
SOME_CASE
Some(T), the case an Option carries a value in.
STRING
String: an immutable sequence of characters, whose length counts characters rather than bytes — and every other index this type takes or answers, in chars, slice, and indexOf, counts the same way, so an API that mixed characters and bytes never has the chance to become a trap.
TASK
Task<T>: the handle scope.spawn { ... } hands back.
UNIT
Unit, written (): what an expression that produces nothing produces.
VECTOR
Vector<T>: the growable sequence, and the one builtin with a mutable graph of its own.

Statics§

BUILTINS
Every builtin type the language defines.
FREE_BUILTINS
Every builtin that is called on nothing: the constructors, then the assertions.
STANDARD_LIBRARY
Every builtin method whose body has moved out of Rust and into the standard library.

Functions§

builtin
The builtin type name describes itself with, if there is one.
builtins
Every builtin type the language defines.
declares_length
Whether the builtin type name reports how many elements it holds.
enum_declaring
The builtin enum that declares the case name, if one does.
free_builtin
The free builtin name describes itself with, if there is one.
free_builtins
Every builtin that is called on nothing.
is_builtin_type
Whether name is a builtin type a program may write as a namespace, as in Vector.of(...).
is_mutating_method
Whether name is a builtin method that takes a var self receiver, and so needs a mutable place at the call site rather than a value.
standard_associated_binding
The standard-library binding for Receiver.method(...), a call on the type’s own name, if that associated function’s body has moved out of Rust.
standard_binding
The standard-library binding for receiver.method(...), a call on a value of receiver, if that method’s body has moved out of Rust.
standard_library
Every builtin method whose body lives in the standard library.