What goes where
A Flex file is its module header, then its imports, then a run of global declarations. A position is
a place in that file where the grammar expects a declaration, a statement, or a clause, and most
constructs stand in exactly one. Each table below answers one question — which positions accept a
given construct.
module radar::sensors.tracking
component Radar;
component CommandPost;
message struct TrackReport {
track_id: uint32;
bearing_deg: float32;
}
struct SearchSector {
start_deg: uint16;
end_deg: uint16;
assert end_deg > start_deg;
}
function span_deg(sector: SearchSector) -> uint16 {
let span: uint16 = sector.end_deg - sector.start_deg;
span;
}
const sweep_widths_deg: uint16[] = [w * 2 for w in [10: uint16, 20: uint16]];
local protocol Sweep in Radar {
var sent: uint32 = 0;
send any TrackReport to CommandPost;
set sent = sent + 1;
}
global protocol Report {
exch any TrackReport from Radar to CommandPost;
in CommandPost {
var seen: uint32 = 0;
set seen = seen + 1;
}
}The positions
| Position | Where it is |
|---|---|
| top level | a file's body, after the header and the imports |
| block | a braced statement list: a function or transform body, and a branch of a statement if |
| contract body | inside a contract |
| struct body | inside a struct or a newtype |
| local body | inside a local protocol |
| global body | inside a global protocol |
| comprehension | after the first element of a […] comprehension |
- A
brancharm, alistenarm, aloopbody in a local protocol, and aninblock are all the local body position. - A
choicearm, aparallelbranch, and aloopbody in a global protocol are all the global body position. - An
inblock is therefore the local body position sitting inside a global protocol.
Declarations
The top level is a sequence of global declarations, and no other position accepts any of them:
annotationconstenumfunctiontransformcontractstructnewtypevarianttypecomponentconnectiongroupsystemglobal protocollocal protocol
Most may be preceded by a run of annotation uses. A struct or variant declaration may also carry
leading modifier keywords. The header and the imports precede all of them —
module has the shape of the file itself.
Statements
| Statement | block | contract body | struct body | local body | global body |
|---|---|---|---|---|---|
let | ✓ | ✓ | — | ✓ | — |
assert | ✓ | ✓ | ✓ | — | — |
if | ✓ | ✓ | — | — | — |
var | — | — | — | ✓ | — |
set | — | — | — | ✓ | — |
send | — | — | — | ✓ | — |
recv | — | — | — | ✓ | — |
branch | — | — | — | ✓ | — |
listen | — | — | — | ✓ | — |
exch | — | — | — | — | ✓ |
choice | — | — | — | — | ✓ |
parallel | — | — | — | — | ✓ |
in | — | — | — | — | ✓ |
loop | — | — | — | ✓ | ✓ |
break | — | — | — | ✓ | ✓ |
do | — | — | — | ✓ | ✓ |
| a standalone annotation | — | — | — | ✓ | ✓ |
- No statement stands at the top level, and no declaration stands in any of these positions.
- A block's
letand a local protocol'sletare different statements, and they take different patterns. - A struct body takes its assertions after all of its fields.
varandsetbelong to a local protocol, so aninblock is where a global protocol keeps state.- A
breakmay name aloopthat encloses theinblock it stands in. - An
inblock holds local statements, so it does not accept anotherin. - Every annotation use other than the standalone form attaches to something.
annotationholds the set of targets.
Clauses
| Clause | What takes it |
|---|---|
extends | a struct declaration |
given | a transform declaration |
giving | a call to a transform that declares a given clause |
into let | exch |
where, a predicate | a send or exch payload that binds a name |
assuming | recv, and exch … into |
where, a variable list | a choice naming more than one component |
invariant | a loop in a local protocol, or in an in block |
for, if, let, scan, zip for | a comprehension |
- A
loopin a global protocol takes noinvariant. - The comprehension clauses spelled
ifandletare clauses, not the statements above.
Expressions
An expression stands in all of these slots:
- a
constinitializer - a struct or newtype assertion
- a block's statements and its tail value
- a contract's
assert - a
let,var, orsetvalue - a
sendorrecvpredicate - a
branchorchoiceguard - a
loopinvariant - every clause of a comprehension
Some slots take less than a whole expression:
- An annotation argument is a literal or a reference to a
const. An argument built with an operator is a parse error. - An enum member's value is a literal.
- A
loopinvariant begins with a reference to a bound variable or aletbinding. - A guard of a
choicenaming more than one component reads only the variables itswhereclause defines. ?namestands only in the body of the transform whosegivenclause declares it.
Types
A type stands in all of these slots:
- a struct or newtype field
- a
functionortransformparameter and return type - an
annotationparameter - a
constdeclaration - a
letorvarannotation - an ascription,
expr: Type - the right side of a
typealias - an
Optional<T>argument, an array's element, a tuple's element - the payload of
send,recv, andexch - a
value_casttarget - the type a
matchpattern narrows to
Some slots take only certain types:
- The payload of
send,recv, andexchis a non-abstractmessagestruct or amessagevariant. - A transform's parameter types and return type are non-abstract
messagestructs. - An enum's backing type is a primitive.
Patterns
| Slot | Forms it takes |
|---|---|
a block let | a name, _, a tuple, or pat: Type |
a protocol let or var | one name |
a recv binding | a name, _, a tuple, or pat: Type |
| a comprehension clause's binding | a name, _, a tuple, or pat: Type |
a fold, map, filter, or flatmap binding | a name, _, a tuple, or pat: Type |
a match arm | _, a literal, some, none, a constructor, a tuple, an array, a name, pat as Type, pat : Type |
- A match arm is the only slot that takes the match patterns.
pat as Typeoutside one is a parse error.
References
| Slot | What the path names |
|---|---|
from and to, on send, recv, and exch | a component |
on, on send, recv, and exch | a connection |
from and to, on a connection declaration | a component |
local protocol P in C | a component |
in C { … } | a component |
choice in C | a component |
do in a local protocol | a local protocol of the same component |
do in a global protocol | a global protocol |
a system member | a local protocol |
a group member | a component or a group |
extends | an extensible struct |
| an annotation use | an annotation declaration |
- A
send,recv, orexchneeds a connection clause. A statement carrying none is a parse error. - An
exchneeds afromcomponent, written or implied by anonconnection.
Errors
A declaration inside a protocol
component Radar;
local protocol Sweep in Radar {
const max_range_m: int32 = 40000; // error: unexpected
}A block statement in a global protocol
component Radar;
component CommandPost;
message struct TrackReport {
track_id: uint32;
}
global protocol Report {
let latest: uint32 = 1; // error: unexpected
exch any TrackReport from Radar to CommandPost;
}A field after an assertion
struct SearchSector {
start_deg: uint16;
assert start_deg < 360;
end_deg: uint16; // error: unexpected
}A break with no enclosing loop
component Radar;
local protocol Sweep in Radar {
break; // error: break-outside-loop
}