Macro dialectic::Session [−][src]
Session!() { /* proc-macro */ }
The Session!
macro compiles a small domain-specific language for describing session types into
the types themselves. It should be invoked in type position.
The Session!
macro language looks a lot like Rust code: sequential instructions are separated
by semicolons, blocks are delimited with curly braces, etc.
The language defines several keywords, each of which corresponding to the session type of the
same name (except for break
, which is translated by the macro into other constructs):
Additionally, arbitrary session types can be used inline by name, so specifications can be composed.
Examples
In these examples, each example of a session type defined using Session!
is paired with its
equivalent session type written out using the session type constructors in
types
.
You can find further examples of the use of Session!
and its meaning throughout this reference
documentation, the tutorial
, and
in the Dialectic crate’s examples.
In the below examples, all code blocks import:
use static_assertions::assert_type_eq_all as type_eq; use dialectic::prelude::*; // Normally you don't need to import these, because they are only useful // when writing session types directly, not when using the `Session!` macro: use dialectic::types::*;
The send
and recv
keywords
These keywords take the type to be sent or received as an argument, with no parentheses. See
also: the Send
type and send
method, and the Recv
type and recv
method.
type_eq!( Session! { send bool }, Send<bool, Done>, ); type_eq!( Session! { recv bool }, Recv<bool, Done>, );
The offer
and choose
keywords
Using offer
and choose
matches the syntax of the offer!
macro, with each
numerically-labeled branch listed in order, corresponding to the session type to be used in the
case of each potential choice.
See also: the Choose
type and the choose
method, and the Offer
type
and the offer!
macro.
type_eq!( Session! { offer { 0 => {}, 1 => {} } }, Offer<(Done, Done)> ); type_eq!( Session! { choose { 0 => {}, 1 => {} } }, Choose<(Done, Done)> );
The loop
, break
, and continue
keywords
The syntax of loop
, break
and continue
are identical to in Rust syntax, including optional
named labels.
Just like Rust’s loop
keyword, but unlike Dialectic’s Loop
type, when control flow
reaches the end of a loop
in a Session!
, it automatically returns to the head of the loop.
To exit a loop, you must use break
.
type_eq!( Session! { loop { break } }, Loop<Done> ); type_eq!( Session! { loop { send (); } }, Session! { loop { send (); continue; } }, Loop<Send<(), Continue<0>>>, ); type_eq!( Session! { 'outer: loop { loop { break 'outer; } } }, Loop<Loop<Done>> ); type_eq!( Session! { 'outer: loop { send (); loop { continue 'outer; } } }, Loop<Send<(), Loop<Continue<1>>>> );
The call
keyword
The call
keyword either precedes a named session type, or a block. It corresponds to the
Call
session type and the call
method.
type P = Session! { send i64 }; type Q = Session! { call P }; type_eq!(Q, Call<Send<i64, Done>, Done>); type R = Session! { loop { choose { 0 => { send i64; call { continue }; recv i64; }, 1 => break, } } }; type_eq!(R, Loop<Choose<(Send<i64, Call<Continue<0>, Recv<i64, Continue<0>>>>, Done)>>);
The split
keyword
The split
keyword precedes a block with two clauses, indicating two concurrent sessions to be
run, one (marked by ->
) which can only transmit information, and the other (marked by <-
)
which can only receive information. It corresponds to the Split
session type and the split
method.
type P = Session! { split { -> send i64, <- recv bool, }; send String; }; type_eq!(P, Split<Send<i64, Done>, Recv<bool, Done>, Send<String, Done>>);
External session types
Arbitrary session types defined outside the macro invocation can be spliced in as an individual statement, or even used as generic parameters.
type Parity = Session! { send i64; recv bool }; type Twice<T> = Session! { T; T }; type Protocol = Session! { loop { choose { 0 => Twice<Parity>, 1 => break, } } }; type_eq!( Protocol, Loop<Choose<(Send<i64, Recv<bool, Send<i64, Recv<bool, Continue<0>>>>>, Done)>>, );