Appendix D — Grammar summary
The normative text is the specification; this appendix is a reference gathering frequently sought shapes. The complete formal grammar is in Annex A (A.10) of the specification.
Clause order of an op head#
[export] [unsafe] [extern] fn|proc <name>
satisfies · lowdoc ① what it is
vector · priority ② character of the whole op
input <name> comptime … ③ translation-time inputs
input <name> cap … · region … ④ capability and region inputs
use <name> <type> . ⑤ allocator drawn from
input <name> <type> . ⑥ data inputs
output <type> . ⑦
effects <atoms…> [via <type>] . ⑧
link "<name>" · variadic · asm <machine> ⑨ joining the outside
access · inplace <written> <read> · invalidates <input> · parallel <name> split · reduce ⑩ how it touches memory · runs split
requires [static|debug|assume] <cond> . ⑪ input conditions
ensures <cond> . ⑫ output promises (ret)
errors <variant> [<cond>] . ⑬ failure
tests … · schedule … ⑭
do
<statements>
end .An extern op whose body is in C holds the same clauses, in the same order, inside do … end — unsafe extern proc <name> do <clause>* end .. Only clauses go in that block.
Declarations#
module <name> .
use <module> [from "<place>"] .
type <name> <type> .
newtype <name> <type> .
struct <name> do [satisfies <trait> .] [layout packed .] [mmio <address> .] <field> <type> [big|little] [rw|ro|wo] . … end .
enum <name> do <variant> [<field> <type>]… . … end .
trait <name> do <op name> <clauses…> . … end .
contract <name> do requires <cond> . … end .
actor <name> do [satisfies …] state do <field> <type> . … end [failure restart max <n> .] [mailbox bounded <n> .] <op>… end .
build profile <name> . build tier t0|t1|t2|t3 . build <mode> .
build option <name> bool|int|choice … default <value>
test <name> [schedule explore_interleavings [limit <n>] .] do expect <cond> . … end .Statements#
Below, <expr>, <value> and <cond> stand for a value with its own stop — a. for a variable, add a. 1 . for a call, 7 for a literal. The . at the end of a line is the stop that closes that statement.
let <name> [use <allocator>. | keep <allocator>.] <type> <expr> [else <leaving statement>] .
var <name> <type> <expr> .
let <name> <type> <expr> else do … end .
let <name> <type> <expr> else error <name> do … end .
set <place> <expr> . (place = <name>. · field … . · idx … .)
if <cond> do … end [else if <cond> do … end]… [else do … end] .
while <cond> do … end .
for <name> [mut] <slice> [if <cond>] do … end .
repeat <name> <type> <count> [if <cond>] do … end .
range <name> <type> <from> <to> [step <stride>] [if <cond>] do … end .
cycle <name> <type> <first> while <cond> next <next value> [if <cond>] do … end .
guard <cond> else <leaving statement> .
match <value> do case <pattern> [when <cond>] do … end . … end .
return [<expr>] . break . continue . panic "<text>" .
drop <name>. .
region <name> stack|frame|arena|static|heap|mmap|disk|device do … end .
task_group [cancel_on_error] do … end .
pipe <source> do <stage> . … <terminal> . end .
spawn send <actor> <message> <value>… . . drain <actor> . schedule .Patterns#
A name in a pattern takes no stop — it is a place where a name is made, not used. The body of a branch is always do … end ..
case _ everything else
case <integer> case <low> to <high>
case <variant> [<name>…] case <pattern> or <pattern>
case some <name> case none case ok <pattern> case error
case <name> when <cond>Expressions#
<op> <args>… . prefix --- a name opens, a stop closes. No precedence
<variable>. a variable follows the same rule (name + stop). Literals, true, false, none take no stop
( <expr> ) parentheses are decoration --- the expression inside closes with its own stop
expr <a> + <b> * <c> . infix island --- * / above + -, comparisons below, and above or
lit <type> do <field> <expr> . … end . <enum>.<variant> <values>… .
lit array <len> <type> <value>… [_] . lit slice <type> <value>… .
field <value> <steps>… . idx <slice> <n> . method <value> <steps>… <name>. <args>… .
some <value> . ok <value> . error <variant> . none
try <expr> [else_none | else_error <variant>] .
comptime <expr> . size_of <type> . config <name> .
spawn actor <type> . send <actor> <message> <values>… . spawn <op> <args>… . await <handle> .
alloc_bytes <root> capacity <n> .
payload <value> <variant> <field> .Opening names and closers#
A form is opened by one name and closed by one closer. The closer is the full stop ., and one stop closes the innermost form that is still open. A variable is a form too — a.. Literals, true, false, none, and names in defining positions (let x, input n, type names, names in patterns) take no stop. do … end is a pair of braces, so end closes only its own do, and a form that owns a block is closed with end .. A chain joined by else is one form, with one stop at the end. A newline is not a closer but whitespace. Parentheses are decoration and cannot cross block boundaries.