Finite state machines in rust; bendns fork to add types.
i have ideas
| -rw-r--r-- | doc-example/src/lib.rs | 2 | ||||
| -rw-r--r-- | rust-fsm-dsl/src/lib.rs | 26 | ||||
| -rw-r--r-- | rust-fsm-dsl/src/parser.rs | 40 | ||||
| -rw-r--r-- | rust-fsm/src/lib.rs | 9 | ||||
| -rw-r--r-- | rust-fsm/tests/circuit_breaker_dsl.rs | 4 | ||||
| -rw-r--r-- | rust-fsm/tests/simple.rs | 4 |
6 files changed, 39 insertions, 46 deletions
diff --git a/doc-example/src/lib.rs b/doc-example/src/lib.rs index c34c52e..e6621c3 100644 --- a/doc-example/src/lib.rs +++ b/doc-example/src/lib.rs @@ -4,7 +4,7 @@ state_machine! { /// A dummy implementation of the Circuit Breaker pattern to demonstrate /// capabilities of its library DSL for defining finite state machines. /// https://martinfowler.com/bliki/CircuitBreaker.html - pub CircuitBreaker => Result => Action + pub CircuitBreaker => pub Result => pub Action Closed => Unsuccessful => Open [SetupTimer], Open => TimerTriggered => HalfOpen, diff --git a/rust-fsm-dsl/src/lib.rs b/rust-fsm-dsl/src/lib.rs index 1c9fe36..094e3b2 100644 --- a/rust-fsm-dsl/src/lib.rs +++ b/rust-fsm-dsl/src/lib.rs @@ -32,16 +32,13 @@ fn attrs_to_token_stream(attrs: Vec<Attribute>) -> proc_macro2::TokenStream { pub fn state_machine(tokens: TokenStream) -> TokenStream { let StateMachineDef { doc, - visibility, - state_name, - input_name, - output_name, + state_name: (state_attrs, state_visibility, state_name), + input_name: (input_attrs, input_visibility, input_name), + output_name: (output_attrs, output_visibility, output_name), transitions, - attributes, } = parse_macro_input!(tokens as parser::StateMachineDef); let doc = attrs_to_token_stream(doc); - let attrs = attrs_to_token_stream(attributes); if transitions.is_empty() { let output = quote! { @@ -168,10 +165,11 @@ pub fn state_machine(tokens: TokenStream) -> TokenStream { .unwrap(); let input_generics = input_name.g(); let input_impl = variant::tokenize(&inputs, |x| { + let attrs = attrs_to_token_stream(input_attrs); input_name.tokenize(|f| { quote! { #attrs - #visibility enum #f #input_generics { + #input_visibility enum #f #input_generics { #(#x),* } } @@ -179,10 +177,11 @@ pub fn state_machine(tokens: TokenStream) -> TokenStream { }); let input_name = input_name.path(); let state_impl = variant::tokenize(&states, |x| { + let attrs = attrs_to_token_stream(state_attrs.clone()); state_name.tokenize(|f| { quote! { #attrs - #visibility enum #f { + #state_visibility enum #f { #(#x),* } } @@ -191,18 +190,11 @@ pub fn state_machine(tokens: TokenStream) -> TokenStream { let state_name = state_name.path(); let output_generics = output_name.g(); let output_impl = variant::tokenize(&outputs, |outputs| { + let attrs = attrs_to_token_stream(output_attrs); output_name.tokenize(|output_name| { - // Many attrs and derives may work incorrectly (or simply not work) for empty enums, so we just skip them - // altogether if the output alphabet is empty. - let attrs = if outputs.is_empty() { - quote!() - } else { - attrs.clone() - }; - quote! { #attrs - #visibility enum #output_name #output_generics { + #output_visibility enum #output_name #output_generics { #(#outputs),* } } diff --git a/rust-fsm-dsl/src/parser.rs b/rust-fsm-dsl/src/parser.rs index 7a25efe..aabdf88 100644 --- a/rust-fsm-dsl/src/parser.rs +++ b/rust-fsm-dsl/src/parser.rs @@ -117,13 +117,11 @@ impl Parse for TransitionDef { /// ``` pub struct StateMachineDef { pub doc: Vec<Attribute>, - /// The visibility modifier (applies to all generated items) - pub visibility: Visibility, - pub state_name: ImplementationRequired, - pub input_name: ImplementationRequired, - pub output_name: ImplementationRequired, + + pub state_name: (Vec<Attribute>, Visibility, ImplementationRequired), + pub input_name: (Vec<Attribute>, Visibility, ImplementationRequired), + pub output_name: (Vec<Attribute>, Visibility, ImplementationRequired), pub transitions: Vec<TransitionDef>, - pub attributes: Vec<Attribute>, } pub enum ImplementationRequired { @@ -155,20 +153,20 @@ impl ImplementationRequired { impl Parse for StateMachineDef { fn parse(input: ParseStream) -> Result<Self> { let mut doc = Vec::new(); - let attributes = Attribute::parse_outer(input)? - .into_iter() - .filter_map(|attribute| { - if attribute.path().is_ident("doc") { - doc.push(attribute); - None - } else { - Some(attribute) - } - }) - .collect(); + let mut i = || { + let attributes = Attribute::parse_outer(input)? + .into_iter() + .filter_map(|attribute| { + if attribute.path().is_ident("doc") { + doc.push(attribute); + None + } else { + Some(attribute) + } + }) + .collect(); + let visibility = input.parse()?; - let visibility = input.parse()?; - let i = || { input .peek(Token![::]) .then(|| { @@ -182,7 +180,9 @@ impl Parse for StateMachineDef { let g = input.parse::<Generics>()?; Ok(ImplementationRequired::Yes(t, g)) }) + .map(|x| (attributes, visibility, x)) }; + let state_name = i()?; input.parse::<Token![=>]>()?; let input_name = i()?; @@ -196,12 +196,10 @@ impl Parse for StateMachineDef { Ok(Self { doc, - visibility, state_name, input_name, output_name, transitions, - attributes, }) } } diff --git a/rust-fsm/src/lib.rs b/rust-fsm/src/lib.rs index ae43bcd..4f1bbaa 100644 --- a/rust-fsm/src/lib.rs +++ b/rust-fsm/src/lib.rs @@ -56,10 +56,13 @@ The DSL is parsed by the `state_machine` macro. Here is a little example. use rust_fsm::*; state_machine! { - #[derive(Debug)] - #[repr(C)] + #[derive(Debug)] #[repr(C)] /// A Circuit Breaker state machine. - CircuitBreaker => Result => Action + CircuitBreaker => + #[derive(Debug)] #[repr(C)] + Result => + #[derive(Debug)] #[repr(C)] + Action Closed => Unsuccessful => Open [SetupTimer], Open => TimerTriggered => HalfOpen, diff --git a/rust-fsm/tests/circuit_breaker_dsl.rs b/rust-fsm/tests/circuit_breaker_dsl.rs index 8d5e0f3..12da2cd 100644 --- a/rust-fsm/tests/circuit_breaker_dsl.rs +++ b/rust-fsm/tests/circuit_breaker_dsl.rs @@ -10,7 +10,9 @@ state_machine! { /// capabilities of its library DSL for defining finite state machines. /// https://martinfowler.com/bliki/CircuitBreaker.html #[derive(Debug)] - pub CircuitBreaker => Result => Action + pub CircuitBreaker => + #[derive(Debug)] pub Result => + #[derive(Debug)] pub Action Closed => Unsuccessful => Open [SetupTimer], Open => TimerTriggered => HalfOpen, diff --git a/rust-fsm/tests/simple.rs b/rust-fsm/tests/simple.rs index 3810dcf..b85440e 100644 --- a/rust-fsm/tests/simple.rs +++ b/rust-fsm/tests/simple.rs @@ -1,9 +1,7 @@ use rust_fsm::*; state_machine! { - #[derive(Debug)] - #[repr(C)] - Door => Action => __ + #[derive(Debug)] #[repr(C)] Door => #[derive(Debug)] #[repr(C)] Action => __ Open => Key => Closed, Closed => Key => Open, |