Skip to content

Commit

Permalink
Added callback for succesfull transition
Browse files Browse the repository at this point in the history
This patch adds a callback for succesfull transitions. This function can
be used to implement a logging service of some sorts for the state
machine.

Signed-off-by: Martin Broers <[email protected]>
  • Loading branch information
Martin Broers committed Nov 24, 2023
1 parent a361028 commit 39a0771
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 2 deletions.
38 changes: 38 additions & 0 deletions examples/transition_callback.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//! An example of using state data to propagate events (See issue-17)

#![deny(missing_docs)]

use std::sync::{Arc, Mutex};

use smlang::statemachine;

statemachine! {
generate_transition_callback: true,
transitions: {
*D0 + ToD1 = D1,
D1 + ToD2 = D2,
},
}

/// Context
pub struct Context {
transition_called: Arc<Mutex<bool>>,
}

impl StateMachineContext for Context {
fn transition_callback(&self, _state: &Option<States>) {
*self.transition_called.lock().unwrap() = true;
}
}

fn main() {
let mut sm = StateMachine::new(Context {
transition_called: Arc::new(Mutex::new(false)),
});

// first event starts the dominos
let _ = sm.process_event(Events::ToD1).unwrap();

assert!(matches!(sm.state(), Ok(&States::D1)));
assert!(*sm.context().transition_called.lock().unwrap());
}
14 changes: 13 additions & 1 deletion macros/src/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ pub fn generate_code(sm: &ParsedStateMachine) -> proc_macro2::TokenStream {
format_ident!("{sm_name}StateMachineContext", span = sm_name_span);

let generate_entry_exit_states = sm.generate_entry_exit_states;
let generate_transition_callback = sm.generate_transition_callback;

// Get only the unique states
let mut state_list: Vec<_> = sm.states.values().collect();
Expand Down Expand Up @@ -254,7 +255,6 @@ pub fn generate_code(sm: &ParsedStateMachine) -> proc_macro2::TokenStream {
// get input state lifetimes
let in_state_lifetimes = sm.state_data.lifetimes.get(&value.in_state.to_string()).cloned().unwrap_or_default();


// get output state lifetimes
let out_state_lifetimes = sm.state_data.lifetimes.get(&value.out_state.to_string()).cloned().unwrap_or_default();

Expand Down Expand Up @@ -494,6 +494,13 @@ pub fn generate_code(sm: &ParsedStateMachine) -> proc_macro2::TokenStream {

let derive_states_list = &sm.derive_states;
let derive_events_list = &sm.derive_events;
let transition_callback = if generate_transition_callback {
quote!(
self.context().transition_callback(&self.state);
)
} else {
quote!()
};
// Build the states and events output
quote! {
/// This trait outlines the guards and actions that need to be implemented for the state
Expand All @@ -504,6 +511,9 @@ pub fn generate_code(sm: &ParsedStateMachine) -> proc_macro2::TokenStream {
#guard_list
#action_list
#entry_list

#[allow(missing_docs)]
fn transition_callback(&self, new_state: &Option<#states_type_name>) {}
}

/// List of auto-generated states.
Expand Down Expand Up @@ -598,6 +608,8 @@ pub fn generate_code(sm: &ParsedStateMachine) -> proc_macro2::TokenStream {
#(#events_type_name::#events => {
#code_blocks

#transition_callback

self.state()
}),*
_ => {
Expand Down
2 changes: 2 additions & 0 deletions macros/src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ pub struct ParsedStateMachine {
pub states_events_mapping: HashMap<String, HashMap<String, EventMapping>>,

pub generate_entry_exit_states: bool,
pub generate_transition_callback: bool,
}

// helper function for adding a transition to a transition event map
Expand Down Expand Up @@ -212,6 +213,7 @@ impl ParsedStateMachine {
event_data,
states_events_mapping,
generate_entry_exit_states: sm.generate_entry_exit_states,
generate_transition_callback: sm.generate_transition_callback,
})
}
}
12 changes: 11 additions & 1 deletion macros/src/parser/state_machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pub struct StateMachine {
pub derive_states: Vec<Ident>,
pub derive_events: Vec<Ident>,
pub generate_entry_exit_states: bool,
pub generate_transition_callback: bool,
}

impl StateMachine {
Expand All @@ -22,6 +23,7 @@ impl StateMachine {
derive_states: Vec::new(),
derive_events: Vec::new(),
generate_entry_exit_states: false,
generate_transition_callback: false,
}
}

Expand Down Expand Up @@ -147,6 +149,13 @@ impl parse::Parse for StateMachine {
statemachine.generate_entry_exit_states = true
}
}
"generate_transition_callback" => {
input.parse::<Token![:]>()?;
let generate_transition_callback: syn::LitBool = input.parse()?;
if generate_transition_callback.value {
statemachine.generate_transition_callback = true
}
}
keyword => {
return Err(parse::Error::new(
input.span(),
Expand All @@ -157,7 +166,8 @@ impl parse::Parse for StateMachine {
\"custom_guard_error\",
\"derive_states\",
\"derive_events\",
\"generate_entry_exit_states\"
\"generate_entry_exit_states\",
\"generate_transition_callback\",
]",
keyword
),
Expand Down

0 comments on commit 39a0771

Please sign in to comment.