Finite state machines in rust; bendns fork to add types.
Diffstat (limited to 'rust-fsm-dsl/src/variant.rs')
| -rw-r--r-- | rust-fsm-dsl/src/variant.rs | 123 |
1 files changed, 115 insertions, 8 deletions
diff --git a/rust-fsm-dsl/src/variant.rs b/rust-fsm-dsl/src/variant.rs index f9f45f3..a59a5f6 100644 --- a/rust-fsm-dsl/src/variant.rs +++ b/rust-fsm-dsl/src/variant.rs @@ -5,9 +5,8 @@ use syn::{parse::Parse, *}; /// Variant with no discriminator #[derive(Hash, Debug, PartialEq, Eq)] pub struct Variant { - // attrs: Vec<Attribute>, - ident: Ident, - field: Option<(Type, Pat)>, + pub ident: Ident, + field: Option<(Type, Pat, Option<Expr>)>, } impl Parse for Variant { @@ -20,7 +19,15 @@ impl Parse for Variant { parenthesized!(inp in input); let t = inp.parse()?; inp.parse::<Token![=>]>()?; - Some((t, Pat::parse_multi(&inp)?)) + + Some(( + t, + Pat::parse_multi(&inp)?, + inp.lookahead1() + .peek(Token![if]) + .then(|| inp.parse::<Token![if]>().and_then(|_| inp.parse::<Expr>())) + .transpose()?, + )) } else { None }; @@ -46,7 +53,7 @@ impl Ord for Variant { impl ToTokens for Variant { fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { self.ident.to_tokens(tokens); - if let Some((t, _)) = &self.field { + if let Some((t, _, _)) = &self.field { tokens.extend(quote::quote! { (#t) }) } } @@ -56,18 +63,118 @@ impl Variant { pub fn match_on(&self) -> proc_macro2::TokenStream { if let Self { ident, - field: Some((_, p)), + field: Some((_, p, g)), } = self { - quote::quote! { #ident(#p) } + let b = g + .as_ref() + .map_or_else(Default::default, |x| quote::quote! { if #x }); + quote::quote! { #ident(#p) #b } } else { self.ident.to_token_stream() } } + pub fn separate(&self) -> (proc_macro2::TokenStream, proc_macro2::TokenStream) { + if let Self { + ident, + field: Some((_, p, g)), + } = self + { + let b = g + .as_ref() + .map(|x| quote::quote! { if #x }) + .unwrap_or_default(); + (quote::quote! { #ident(#p) }, b) + } else { + (self.ident.to_token_stream(), quote::quote! {}) + } + } } impl Display for Variant { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.match_on()) + write!(f, "{}", self.ident) + } +} +/// type and expression +#[derive(Hash, Debug, PartialEq, Eq, Clone)] +pub struct Final { + pub ident: Ident, + field: Option<(Type, Expr)>, +} + +impl Parse for Final { + fn parse(input: parse::ParseStream) -> Result<Self> { + let ident: Ident = input.parse()?; + let field = if input.peek(token::Paren) { + let inp; + parenthesized!(inp in input); + let t = inp.parse()?; + inp.parse::<Token![=>]>()?; + + Some((t, inp.parse()?)) + } else { + None + }; + Ok(Final { + // attrs, + ident, + field, + }) + } +} + +impl PartialOrd for Final { + fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { + self.ident.partial_cmp(&other.ident) + } +} +impl Ord for Final { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.ident.cmp(&other.ident) + } +} + +impl ToTokens for Final { + fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { + self.ident.to_tokens(tokens); + if let Some((v, _)) = &self.field { + tokens.extend(quote::quote! { (#v) }) + } + } +} + +impl Final { + pub fn reduce(&self) -> proc_macro2::TokenStream { + if let Self { + ident, + field: Some((_, v)), + } = self + { + quote::quote! { #ident ( #v ) } + } else { + self.ident.to_token_stream() + } + } + pub fn variant(self) -> Variant { + Variant { + ident: self.ident, + field: self.field.map(|(x, _)| { + ( + x, + Pat::Wild(PatWild { + attrs: vec![], + underscore_token: Default::default(), + }), + None, + ) + }), + } + } +} + +impl Display for Final { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.ident) } } |