Keywords and annotations
The closed sets. 32 hard keywords, 18 soft ones, and the six annotations.
Every list on this page is closed and derived from the compiler’s own tables, so it cannot drift from what the language accepts.
Hard keywords
Thirty-two words, reserved everywhere. None of these can be a field, parameter or local name.
| Keyword | |
|---|---|
as |
binds the whole event in an effect arm or a projector handler |
command |
a declaration |
const |
a declaration |
delete |
a projector write |
effect |
a declaration |
else |
with if |
emit |
a command statement |
entity |
inside a projector |
enum |
a declaration, module or projector scoped |
event |
a declaration |
false |
a literal |
fn |
a declaration, module or effect scoped |
fold |
a read declaration |
for |
iteration |
guard |
a declaration, and its use site |
if |
branching |
in |
with for |
invalid |
an outcome |
invoke |
an effect calling a command |
let |
the only binding form |
none |
the absent optional |
on |
an arm, and a fold’s slice |
patch |
a projector write |
projector |
a declaration |
put |
a projector write |
record |
a declaration |
refusal |
a declaration |
reject |
an outcome |
return |
|
test |
a declaration |
true |
a literal |
update |
a projector write |
Soft keywords
Eighteen words claimed only positionally, so each stays usable as an ordinary name
everywhere else. An entity column called given, a parameter called no and a field called
timeout are all legal.
| Keyword | Claimed in |
|---|---|
deliver |
a test action |
erase |
an effect arm |
erased |
a test setup |
expect |
a test expectation |
fail |
an effect arm |
given |
a test log |
http |
an effect arm |
latest |
an effect arm’s delivery |
live |
an effect arm’s delivery |
log |
an effect arm |
no |
a test expectation |
nothing |
a test expectation |
project |
a test action |
respond |
a test setup |
run |
a test action |
secret |
a declaration, and a test setup |
skipped |
a test expectation |
timeout |
a test setup |
There is a third group the tables above deliberately leave out: bare identifiers resolved by
the callable dispatch rather than by the lexer or a positional check. reveal and now,
plus the constructor roots Uuid, Json, Map, Timestamp, Money and Decimal, and the
three rounding words HalfUp, HalfEven and Down. They are builtins, not keywords.
Annotations
Six, and the set is closed. An unrecognised one is unknown-annotation; a recognised one in
the wrong place is bad-annotation.
| Annotation | Legal on | |
|---|---|---|
@subject(field) |
an event field only | seals the value under a key scoped to that subject |
@max(n) |
an event, entity or record field | bounds a String or String? and nothing else |
@no_index |
an event field only | keeps the field out of the tag set, so it is not foldable |
@key |
an entity field, or an effect arm’s trigger destructure | the primary key, or the lane |
@index |
an entity field only | makes the column filterable on the scan route |
@default |
an enum variant only | the zero value, which is what patch materialises |
Two forms behave like annotations without the @:
| Form | Where | |
|---|---|---|
index (a, b) |
entity level | a composite index |
= <literal> |
an entity field | a default for a column a write may omit |
An annotation name may never contain a ..
The subtle rules
@max applies to String and String? and nothing else. @max on an Int, a
container or a record is an error naming the type, because a length there would have nothing
to bound.
@subject on a record field is a dedicated error, not a generic one: a subject-bound
value is recovered from its schema path, and a record reached through a container has no
path to recover it from.
An entity may have at most one @key. A second is bad-annotation.
An effect arm’s @keys are ordered. A composite key is a sequence, so
{ @key a, @key b } and { @key b, @key a } are different lanes.
= none on an optional column is rejected, because an optional is already absent by
default.
Symbols
{ } |
a block, a record literal, a JSON object |
( ) |
grouping, parameters, arguments, a type scale |
[ ] |
a list literal, a comprehension, a test row key |
=> |
a fold arm’s result |
-> |
a fn return type |
? |
an optional type, and an optional secret |
@ |
an event path, and an annotation |
. |
member access, and a projector’s stored value |
= |
binding, and a named argument |
== != < <= > >= |
comparison, non-associative |
+ - * / % |
arithmetic. % is Int only, and there is no + on strings |
&& || ! |
boolean |
, |
separator |
There are no semicolons anywhere in the language, and statements are separated by newlines.
What none of this includes
while, break, continue, match, switch, var, import, module, class,
struct, interface, async, await, try, catch, throw, null, nil, undefined.
None of them is a reserved word, because none of them is a concept the language has. See Containers and control flow for why the loop forms stop where they do.