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§
- Builtin
Schema - One builtin type: its name, its type parameters, and what may be called on a value of it or on the name of it.
- Case
Schema - One case of a builtin enum.
- Field
Schema - One field of a builtin struct.
- Free
Builtin Schema - One builtin that is called on nothing.
- Method
Schema - One builtin method or associated function.
- Param
Schema - One parameter of a builtin’s signature.
- StdBinding
- A builtin method or associated function whose implementation is Cove source rather than Rust.
Enums§
- Builtin
Type - A type in a builtin’s signature, written in Cove’s source vocabulary.
- Free
Builtin Kind - What a builtin that is called on nothing is.
- StdBinding
Kind - Which of a builtin type’s two call forms a
StdBindingnames.
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 ofOK.- 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 aResult.- 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 onekey/valuepair aMapis built from and iterated as.- MESSAGE_
FIELD message: String, the one field of the builtinErrorstruct.- NONE_
CASE None, the empty case ofOption.- OK
Ok(value: T) -> Result<T, E>.- OK_CASE
Ok(T), the success case of aResult.- OPTION
Option<T>:Some(value)orNone.- RANGE
Range: what0..nand0..=nproduce.- RESULT
Result<T, E>:Ok(value)orErr(error).- SCOPE
Scope: the valuescope 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 anOptioncarries a value in.- STRING
String: an immutable sequence of characters, whoselengthcounts characters rather than bytes — and every other index this type takes or answers, inchars,slice, andindexOf, counts the same way, so an API that mixed characters and bytes never has the chance to become a trap.- TASK
Task<T>: the handlescope.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
namedescribes itself with, if there is one. - builtins
- Every builtin type the language defines.
- declares_
length - Whether the builtin type
namereports how many elements it holds. - enum_
declaring - The builtin enum that declares the case
name, if one does. - free_
builtin - The free builtin
namedescribes itself with, if there is one. - free_
builtins - Every builtin that is called on nothing.
- is_
builtin_ type - Whether
nameis a builtin type a program may write as a namespace, as inVector.of(...). - is_
mutating_ method - Whether
nameis a builtin method that takes avar selfreceiver, 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 ofreceiver, if that method’s body has moved out of Rust. - standard_
library - Every builtin method whose body lives in the standard library.