From eaa48b58ba070a05ec59e57338bacf7c84cc5363 Mon Sep 17 00:00:00 2001 From: Dmitriy Kumshayev Date: Tue, 4 Jun 2024 12:20:59 +0100 Subject: [PATCH] return error if none of the transitions failed --- examples/event_with_data.rs | 2 +- examples/event_with_reference_data.rs | 4 ++-- examples/ex3.rs | 2 +- examples/guard_custom_error.rs | 2 +- examples/named_ex3.rs | 2 +- macros/src/codegen.rs | 31 +++++++++++++++------------ 6 files changed, 23 insertions(+), 20 deletions(-) diff --git a/examples/event_with_data.rs b/examples/event_with_data.rs index 2fe7897..00e5aff 100644 --- a/examples/event_with_data.rs +++ b/examples/event_with_data.rs @@ -34,7 +34,7 @@ fn main() { let mut sm = StateMachine::new(Context); let result = sm.process_event(Events::Event1(MyEventData(1))); // Guard will fail - assert!(matches!(result, Err(Error::GuardFailed(())))); + assert!(matches!(result, Err(Error::TransitionsFailed))); let result = sm.process_event(Events::Event1(MyEventData(42))); // Guard will pass diff --git a/examples/event_with_reference_data.rs b/examples/event_with_reference_data.rs index 51533d7..c80f530 100644 --- a/examples/event_with_reference_data.rs +++ b/examples/event_with_reference_data.rs @@ -43,13 +43,13 @@ fn main() { let mut sm = StateMachine::new(Context); let result = sm.process_event(Events::Event1(&[])); // Guard will fail - assert!(matches!(result, Err(Error::GuardFailed(())))); + assert!(matches!(result, Err(Error::TransitionsFailed))); let result = sm.process_event(Events::Event1(&[1, 2, 3])); // Guard will pass assert!(matches!(result, Ok(&States::State2))); let r = 42; let result = sm.process_event(Events::Event2(MyReferenceWrapper(&r))); // Guard will fail - assert!(matches!(result, Err(Error::GuardFailed(())))); + assert!(matches!(result, Err(Error::TransitionsFailed))); let r = 9001; let result = sm.process_event(Events::Event2(MyReferenceWrapper(&r))); // Guard will pass diff --git a/examples/ex3.rs b/examples/ex3.rs index c1c7173..0552336 100644 --- a/examples/ex3.rs +++ b/examples/ex3.rs @@ -53,7 +53,7 @@ fn main() { // The action will never run as the guard will fail let r = sm.process_event(Events::Event2); - assert!(matches!(r, Err(Error::GuardFailed(())))); + assert!(matches!(r, Err(Error::TransitionsFailed))); println!("After action 2"); diff --git a/examples/guard_custom_error.rs b/examples/guard_custom_error.rs index b282314..8b7ad95 100644 --- a/examples/guard_custom_error.rs +++ b/examples/guard_custom_error.rs @@ -60,5 +60,5 @@ fn main() { let r = sm.process_event(Events::Event1(MyEventData(1))); - assert!(matches!(r, Err(Error::GuardFailed(())))); + assert!(matches!(r, Err(Error::TransitionsFailed))); } diff --git a/examples/named_ex3.rs b/examples/named_ex3.rs index 93759e5..8015931 100644 --- a/examples/named_ex3.rs +++ b/examples/named_ex3.rs @@ -54,7 +54,7 @@ fn main() { // The action will never run as the guard will fail let r = sm.process_event(LoopingWithGuardsEvents::Event2); - assert!(matches!(r, Err(LoopingWithGuardsError::GuardFailed(())))); + assert!(matches!(r, Err(LoopingWithGuardsError::TransitionsFailed))); println!("After action 2"); diff --git a/macros/src/codegen.rs b/macros/src/codegen.rs index ad5d033..23141ef 100644 --- a/macros/src/codegen.rs +++ b/macros/src/codegen.rs @@ -381,7 +381,7 @@ pub fn generate_code(sm: &ParsedStateMachine) -> proc_macro2::TokenStream { let streams: Vec = guard.iter() .zip(action.iter().zip(out_state)).map(|(guard, (action,out_state))| - if let Some(AsyncIdent {ident: g, is_async: is_g_async}) = guard { + if let Some(AsyncIdent {ident: guard_ident, is_async: is_g_async}) = guard { let guard_await = match is_g_async { true => { sm_is_async = true; quote! { .await } }, false => quote! { }, @@ -392,8 +392,8 @@ pub fn generate_code(sm: &ParsedStateMachine) -> proc_macro2::TokenStream { false => quote! { }, }; quote! { - let guard_result = self.context.#g(#temporary_context_call #g_a_ref_param) #guard_await; - self.context.log_guard(stringify!(#g), &guard_result); + let guard_result = self.context.#guard_ident(#temporary_context_call #g_a_ref_param) #guard_await; + self.context.log_guard(stringify!(#guard_ident), &guard_result); match guard_result { true => { let _data = self.context.#a(#temporary_context_call #g_a_param) #action_await; @@ -409,8 +409,8 @@ pub fn generate_code(sm: &ParsedStateMachine) -> proc_macro2::TokenStream { } } else { quote! { - let guard_result = self.context.#g(#temporary_context_call #g_a_ref_param); - self.context.log_guard(stringify!(#g), &guard_result); + let guard_result = self.context.#guard_ident(#temporary_context_call #g_a_ref_param); + self.context.log_guard(stringify!(#guard_ident), &guard_result); match guard_result { true => { let out_state = #states_type_name::#out_state; @@ -422,14 +422,14 @@ pub fn generate_code(sm: &ParsedStateMachine) -> proc_macro2::TokenStream { } } } - } else if let Some(AsyncIdent {ident: a, is_async: is_a_async}) = action { + } else if let Some(AsyncIdent {ident: action_ident, is_async: is_a_async}) = action { let action_await = match is_a_async { true => { sm_is_async = true; quote! { .await } }, false => quote! { }, }; quote! { - let _data = self.context.#a(#temporary_context_call #g_a_param) #action_await ; - self.context.log_action(stringify!(#a)); + let _data = self.context.#action_ident(#temporary_context_call #g_a_param) #action_await ; + self.context.log_action(stringify!(#action_ident)); let out_state = #states_type_name::#out_state; self.context.log_state_change(&out_state); self.state = Some(out_state); @@ -552,11 +552,11 @@ pub fn generate_code(sm: &ParsedStateMachine) -> proc_macro2::TokenStream { /// List of possible errors #[derive(Debug)] - pub enum #error_type_name { + pub enum #error_type_name { /// When an event is processed which should not come in the current state. InvalidEvent, - /// When an event is processed whose guard did not return `true`. - GuardFailed(T), + /// When an event is processed and not of the transitions happened. + TransitionsFailed, /// When the state has an unexpected value. /// /// This can happen if there is a bug in the code generated by smlang, @@ -617,10 +617,13 @@ pub fn generate_code(sm: &ParsedStateMachine) -> proc_macro2::TokenStream { #(#states_type_name::#in_states => match event { #(#events_type_name::#events => { #code_blocks - - // all guards disabled #[allow(unreachable_code)] - self.state() + { + // none of the guarded or non-guarded transitions occurred, + // therefore return an error, + self.state = Some(#states_type_name::#in_states); + Err(#error_type_name ::TransitionsFailed) + } }),* #[allow(unreachable_patterns)] _ => {