Skip to content

Commit

Permalink
Removed on_entry flag
Browse files Browse the repository at this point in the history
Also the parse will not parse ">" and "<" states anymore, since all
on_entry and on_exit functions will be autogenerated.

Signed-off-by: Martin Broers <[email protected]>
  • Loading branch information
Martin Broers committed Jun 27, 2024
1 parent a127650 commit ca4fe43
Show file tree
Hide file tree
Showing 7 changed files with 24 additions and 227 deletions.
24 changes: 2 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -262,28 +262,8 @@ This example is available in `ex3.rs`.

### Using entry and exit functions in transitions

DSL implementation:

```rust
statemachine!{
transitions: {
*State1 + Event1 = State2,
State2 < exit_state_2 + Event2 = State1,
State1 > enter_state_3 + Event3 = State3,
State2 + Event3 = State3,
}
}
```
For all transitions entering State3, the function `enter_state_3` will be
called. For all transitions exiting State2, the function `exit_state_2` will be
called, in the right order, so first the `exit` function prior to the `entry`
function.

An example is available in `on_entry_on_exit`.

There is also a generic flag available, `generate_on_entry_on_exit`, which will
generate for all states in the statemachine an entry and an exit function. If
they are not used, they will be optimized away by the compiler. An example be
The statemachine will create for all states an `on_entry_` and `on_exit_` function.
If the are not used, they will be optimized away by the compiler. An example be
found in `on_entry_on_exit_generic`.

## Helpers
Expand Down
70 changes: 0 additions & 70 deletions examples/on_entry_on_exit.rs

This file was deleted.

3 changes: 1 addition & 2 deletions examples/on_entry_on_exit_generic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@ use smlang::statemachine;

statemachine! {
name: OnEntryExample,
generate_entry_exit_states: true,
transitions: {
*D0 < exit_d0 + ToD1 = D1,
*D0 + ToD1 = D1,
D0 + ToD3 = D3,
D1 + ToD2 = D2,
D2 + ToD1 = D1,
Expand Down
59 changes: 19 additions & 40 deletions macros/src/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,8 @@ pub fn generate_code(sm: &ParsedStateMachine) -> proc_macro2::TokenStream {
let state_machine_context_type_name =
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;

let mut entry_fns = sm.entry_functions.clone();
let mut exit_fns = sm.exit_functions.clone();

// Get only the unique states
let mut state_list: Vec<_> = sm.states.values().collect();
state_list.sort_by_key(|state| state.to_string());
Expand Down Expand Up @@ -255,18 +251,6 @@ pub fn generate_code(sm: &ParsedStateMachine) -> proc_macro2::TokenStream {
let mut action_list = proc_macro2::TokenStream::new();

let mut entries_exits = proc_macro2::TokenStream::new();
for ident in entry_fns.values() {
entries_exits.extend(quote! {
#[allow(missing_docs)]
fn #ident(&mut self){}
});
}
for ident in exit_fns.values() {
entries_exits.extend(quote! {
#[allow(missing_docs)]
fn #ident(&mut self){}
});
}

for (state, event_mappings) in transitions.iter() {
// create the state data token stream
Expand All @@ -275,20 +259,17 @@ pub fn generate_code(sm: &ParsedStateMachine) -> proc_macro2::TokenStream {
Some(st) => quote! { state_data: &#st, },
None => quote! {},
};
if generate_entry_exit_states {
let entry_ident = format_ident!("on_entry_{}", string_morph::to_snake_case(state));
entries_exits.extend(quote! {
#[allow(missing_docs)]
fn #entry_ident(&mut self){}
});
entry_fns.insert(format_ident!("{}", state), entry_ident);
let exit_ident = format_ident!("on_exit_{}", string_morph::to_snake_case(state));
entries_exits.extend(quote! {
#[allow(missing_docs)]
fn #exit_ident(&mut self){}
});
exit_fns.insert(format_ident!("{}", state), exit_ident);
};

let entry_ident = format_ident!("on_entry_{}", string_morph::to_snake_case(state));
entries_exits.extend(quote! {
#[allow(missing_docs)]
fn #entry_ident(&mut self){}
});
let exit_ident = format_ident!("on_exit_{}", string_morph::to_snake_case(state));
entries_exits.extend(quote! {
#[allow(missing_docs)]
fn #exit_ident(&mut self){}
});

for (event, event_mapping) in event_mappings {
for transition in &event_mapping.transitions {
Expand Down Expand Up @@ -446,19 +427,17 @@ pub fn generate_code(sm: &ParsedStateMachine) -> proc_macro2::TokenStream {

let binding = out_state.to_string();
let out_state_string = &binding.split('(').collect::<Vec<_>>()[0];
let entry_ident = format_ident!("on_entry_{}",string_morph::to_snake_case(out_state_string ));
let binding = in_state.to_string();
let in_state_string = &binding.split('(').collect::<Vec<_>>()[0];
let exit_ident = format_ident!("on_exit_{}",string_morph::to_snake_case(in_state_string));
let entry_exit_states = if generate_entry_exit_states {
quote! {
self.context_mut().#exit_ident();
self.context_mut().#entry_ident();
}
} else {
quote! { }
};

let entry_ident = format_ident!("on_entry_{}", string_morph::to_snake_case(out_state_string));
let exit_ident = format_ident!("on_exit_{}", string_morph::to_snake_case(in_state_string));

let entry_exit_states =
quote! {
self.context_mut().#exit_ident();
self.context_mut().#entry_ident();
};
let (is_async_action,action_code) = generate_action(action, &temporary_context_call, g_a_param);
is_async_state_machine |= is_async_action;
if let Some(expr) = guard { // Guarded transition
Expand Down
37 changes: 0 additions & 37 deletions macros/src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,6 @@ use syn::{parse, Ident, Type};
use transition::StateTransition;
pub type TransitionMap = HashMap<String, HashMap<String, EventMapping>>;

#[derive(Debug, Clone)]
pub struct EntryIdent {
pub ident: Ident,
pub state: Vec<InputState>,
pub is_async: bool,
}

#[derive(Debug, Clone)]
pub struct AsyncIdent {
pub ident: Ident,
Expand Down Expand Up @@ -64,10 +57,7 @@ pub struct ParsedStateMachine {
pub event_data: DataDefinitions,
pub states_events_mapping: HashMap<String, HashMap<String, EventMapping>>,

pub generate_entry_exit_states: bool,
pub generate_transition_callback: bool,
pub entry_functions: HashMap<Ident, Ident>,
pub exit_functions: HashMap<Ident, Ident>,
}

// helper function for adding a transition to a transition event map
Expand Down Expand Up @@ -147,29 +137,6 @@ impl ParsedStateMachine {
let mut event_data = DataDefinitions::new();
let mut states_events_mapping = TransitionMap::new();

let mut states_with_exit_function = HashMap::new();
let mut states_with_entry_function = HashMap::new();

fn add_entry(map: &mut HashMap<Ident, Ident>, vec: &Vec<EntryIdent>) -> parse::Result<()> {
for identifier in vec {
for input_state in &identifier.state {
if let Some(existing_identifier) =
map.insert(input_state.ident.clone(), identifier.ident.clone())
{
if identifier.ident != existing_identifier {
return Err(parse::Error::new(
Span::call_site(),
"Different entry or exit functions defined for state",
));
}
}
}
}
Ok(())
}
add_entry(&mut states_with_entry_function, &sm.entries)?;
add_entry(&mut states_with_exit_function, &sm.exits)?;

for transition in sm.transitions.iter() {
// Collect states
let in_state_name = transition.in_state.ident.to_string();
Expand Down Expand Up @@ -265,11 +232,7 @@ impl ParsedStateMachine {
events,
event_data,
states_events_mapping,
generate_entry_exit_states: sm.generate_entry_exit_states,
generate_transition_callback: sm.generate_transition_callback,

entry_functions: states_with_entry_function,
exit_functions: states_with_exit_function,
})
}
}
25 changes: 1 addition & 24 deletions macros/src/parser/state_machine.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
use super::{
transition::{StateTransition, StateTransitions},
EntryIdent,
};
use super::transition::{StateTransition, StateTransitions};
use syn::{braced, bracketed, parse, spanned::Spanned, token, Ident, Token, Type};

#[derive(Debug)]
Expand All @@ -12,10 +9,7 @@ pub struct StateMachine {
pub name: Option<Ident>,
pub derive_states: Vec<Ident>,
pub derive_events: Vec<Ident>,
pub generate_entry_exit_states: bool,
pub generate_transition_callback: bool,
pub entries: Vec<EntryIdent>,
pub exits: Vec<EntryIdent>,
}

impl StateMachine {
Expand All @@ -27,10 +21,7 @@ impl StateMachine {
name: None,
derive_states: Vec::new(),
derive_events: Vec::new(),
generate_entry_exit_states: false,
generate_transition_callback: false,
entries: Vec::new(),
exits: Vec::new(),
}
}

Expand All @@ -45,12 +36,6 @@ impl StateMachine {
};
self.transitions.push(transition);
}
if let Some(entry) = transitions.entry {
self.entries.push(entry);
}
if let Some(exit) = transitions.exit {
self.exits.push(exit);
}
}
}

Expand Down Expand Up @@ -155,13 +140,6 @@ impl parse::Parse for StateMachine {
};
}
}
"generate_entry_exit_states" => {
input.parse::<Token![:]>()?;
let generate_entry_exit_states: syn::LitBool = input.parse()?;
if generate_entry_exit_states.value {
statemachine.generate_entry_exit_states = true
}
}
"generate_transition_callback" => {
input.parse::<Token![:]>()?;
let generate_transition_callback: syn::LitBool = input.parse()?;
Expand All @@ -179,7 +157,6 @@ impl parse::Parse for StateMachine {
\"custom_guard_error\",
\"derive_states\",
\"derive_events\",
\"generate_entry_exit_states\",
\"generate_transition_callback\",
]",
keyword
Expand Down
33 changes: 1 addition & 32 deletions macros/src/parser/transition.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use super::event::Event;
use super::input_state::InputState;
use super::output_state::OutputState;
use super::AsyncIdent;
use super::{event::Event, EntryIdent};
use proc_macro2::TokenStream;
use quote::quote;
use std::fmt;
Expand All @@ -22,8 +22,6 @@ pub struct StateTransitions {
pub event: Event,
pub guard: Option<GuardExpression>,
pub action: Option<AsyncIdent>,
pub entry: Option<EntryIdent>,
pub exit: Option<EntryIdent>,
pub out_state: OutputState,
}

Expand All @@ -50,33 +48,6 @@ impl parse::Parse for StateTransitions {
}
}
}

// Possible extry function
let entry = if input.parse::<Token![<]>().is_ok() {
let is_async = input.parse::<token::Async>().is_ok();
let entry_function: Ident = input.parse()?;
Some(EntryIdent {
ident: entry_function,
state: in_states.clone(),
is_async,
})
} else {
None
};
let exit = if input.parse::<Token![>]>().is_ok() {
let is_async = input.parse::<token::Async>().is_ok();
let exit_function: Ident = match input.parse() {
Ok(v) => v,
Err(e) => panic!("Could not parse exit token: {:?}", e),
};
Some(EntryIdent {
ident: exit_function,
state: in_states.clone(),
is_async,
})
} else {
None
};
// Event
let event: Event = input.parse()?;

Expand Down Expand Up @@ -109,8 +80,6 @@ impl parse::Parse for StateTransitions {
guard,
action,
out_state,
entry,
exit,
})
}
}
Expand Down

0 comments on commit ca4fe43

Please sign in to comment.