Skip to content

Recursive protocols without Rec and Var #32

Description

@ebfull

Associated types are powerful enough to avoid needing an environment stack or recursive session types.

pubtraitHasDual{typeDual:SessionType;}pubtraitAlias{typeId:HasDual;}pubstructGoto<A:Alias>(PhantomData<A>);pubstructGotoDual<A:Alias>(PhantomData<A>);impl<A:Alias>HasDualforGoto<A>{typeDual = GotoDual<A>;}impl<A:Alias>HasDualforGotoDual<A>{typeDual = Goto<A>;}

Cool, but it requires ugly struct definitions and impls at every depth. I think this downside is mentioned throughout session type literature. It's not practical, they said. Just use recursive session types, they said.

But wait, there's macros!

proto!(Atm = {RecvString,AtmMenu = Accept{AtmDeposit = {Recvu64,Sendu64,GotoAtmMenu},AtmWithdraw = {Recvu64,Sendbool,GotoAtmMenu},AtmGetBalance = {Sendu64,GotoAtmMenu},End}});

Unfortunately the macro necessary to expand such a construct is ridiculously complex (and this is after omitting recursion, choose/offer, etc.):

#[macro_export]macro_rules! proto((@form_ty End) => (End);(@form_ty Goto $t:ty) => (Goto<$t>);(@form_ty Recv $t:ty, $($rest:tt)*) => (Recv<$t, proto!(@form_ty $($rest)*)>);(@form_ty Send $t:ty, $($rest:tt)*) => (Send<$t, proto!(@form_ty $($rest)*)>);(@form_ty {$($stuff:tt)*}) => (proto!(@form_ty $($stuff)*));(@form_ty $i:ty = {$($stuff:tt)*}) => (<$i asAlias>::Id);(@form_ty $i:ty = $t:ident {$($stuff:tt)*}) => (<$i asAlias>::Id);(@new_aliases () $($others:tt)*) => (
proto!(@construct_alias $($others)*););(@new_aliases ({$($some:tt)*}$($rest:tt)*) $($others:tt)*) => (
proto!(@new_aliases ($($some)* $($rest)*) $($others)*););(@new_aliases (, $($rest:tt)*) $($others:tt)*) => (
proto!(@new_aliases ($($rest)*) $($others)*););(@new_aliases ($alias:ident = {$($astuff:tt)*} $($lol:tt)*) $($others:tt)*) => (
proto!(@new_aliases ($($lol)*)($alias = {$($astuff)*}) $($others)*););(@new_aliases ($alias:ident = $t:ident {$($astuff:tt)*} $($lol:tt)*) $($others:tt)*) => (
proto!(@new_aliases ($($lol)*)($alias = {$t {$($astuff)*}}) $($others)*););(@new_aliases ($x:ident $($rest:tt)*) $($others:tt)*) => (
proto!(@new_aliases ($($rest)*) $($others)*););(@construct_final ($alias:ident, $($arest:tt)*)) => (
#[allow(dead_code)]struct $alias;implAliasfor $alias {typeId = proto!(@form_ty $($arest)*);});(@construct_final ($alias:ident, $($arest:tt)*) $($rest:tt)*) => (
proto!(@construct_final ($alias, $($arest)*));
proto!(@construct_final $($rest)*););(@construct_alias @eps $($rest:tt)*) => (
proto!(@construct_final $($rest)*););(@construct_alias ($alias:ident = {$($rest:tt)*}) $($others:tt)*) => (
proto!(@new_aliases ($($rest)*) $($others)*($alias, $($rest)*)););($start:ident = {$($rest:tt)*}) => (
proto!(@construct_alias ($start = {$($rest)*}) @eps);););

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions