-
Notifications
You must be signed in to change notification settings - Fork 28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support on_entry and on_exit for states #66
Support on_entry and on_exit for states #66
Conversation
8698944
to
803a5b1
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some general feedback is below. I don't know the state of this or if the intent is to merge it as-is or if it's just inteded to be a starting point.
If this is just a reference implementation for someone else to pick up, can we mark it as a draft? Otherwise, I'm not sure if I should be reviewing or not.
macros/src/codegen.rs
Outdated
@@ -356,6 +370,10 @@ pub fn generate_code(sm: &ParsedStateMachine) -> proc_macro2::TokenStream { | |||
.zip(out_states.iter().zip(guard_action_parameters.iter().zip(guard_action_ref_parameters.iter()))), | |||
) | |||
.map(|(guard, (action, (out_state, (g_a_param, g_a_ref_param))))| { | |||
let out_state_string = &out_state.to_string()[0..out_state.to_string().find('(').unwrap_or_else(|| out_state.to_string().len())]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think a split
is more appropriate and canonical here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed. I think it is now more readable than I had it first, thanks.
macros/src/codegen.rs
Outdated
#entry_list | ||
|
||
#[allow(missing_docs)] | ||
fn transition_callback(&self, new_state: &Option<#states_type_name>) {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why a transition callback when we already have an on_entry and on_exit for all states? Is this basically just intended to be a default function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, understandable. Idea was a generic callback to capture the transition, I use it for bookkeeping in other parts of my application, synchronizing states to my backend. Could your on_entry_[stateA,stateB] and on_exit[stateA,stateB] for this as well, but I'd be duplicating the code for all transitions. So I thought a generic one is better.
Will hide this behind a feature flag as well.
macros/src/codegen.rs
Outdated
self.state = Some(#states_type_name::#out_state); | ||
} | ||
} else { | ||
quote! { | ||
self.state = Some(#states_type_name::#out_state); | ||
self.context_mut().#exit_ident(); | ||
self.context_mut().#entry_ident(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't want to force everyone to implement these if they're not needed. Can we guard these calls based on their existence in the FSM definition?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I have seen other functions to be behind these flags, will update this accordingly (and will put this MR in draft while I haven't done that).
When I have this flag and the other comments fixed, I think it is good to go.
Yes, wasn't totally clear on that. Will work on this to make it final and ping you when I'm happy. Also, open for edits by others if they have time before I do. |
803a5b1
to
eef74ae
Compare
eef74ae
to
39a0771
Compare
I have added two new features, |
macros/src/codegen.rs
Outdated
@@ -19,6 +19,9 @@ 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; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd much rather we generate the calls by the existence of the exit/entry function as specified in the state machine itself.
Like, maybe:
statemachine! {
*Init < enter_init > exit_init + transition / guard_transition => Next,
Next < enter_next > exit_next + transition / guard_transition2 => Init,
}
What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then, if the enter_*
and exit_*
functions don't exist in the UML, we don't generate the respective calls.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or the notation you specified at the end of #60 (comment) would work as well. If we're following Boost SML, that would be preferable.
@ryan-summers : do you know what the state of this PR is? Has it gone stale? |
I haven't seen any response from the author to my review, so I would assume it's been abandoned, but maybe these comments may grab their attention as well :) |
@dgehriger I had it on my list to fix, but got other priorities to work on first. I spent some time to rework the comments, but I failed in properly understanding the macros. Then I got other things on my plate and this got pushed down on my todo list. So, to re-open the issue for myself and start thinking about it again, I have the token parser to parse So, in
which generates an |
Bump. This appears to be one of the more feature-rich state machines in rust that anyone uses. on_enter and on_exit are table stakes for a state machine library. Can we get this feature in here please? |
I have nothing against the implementation @andygikling, but it is not yet done to my knowledge. This, like many open-sourced projects, is maintained primarily through volunteer time. I'm happy to review any proposed changes you may have for the repo, but I don't have significant amounts of time to implement new features unless I need them for specific projects that I'm working on. |
Ok thanks I'll take a closer look and see what's missing! |
3a30100
to
8f3929a
Compare
So, I've finally gotten around to update this PR. I implemented the notation with @ryan-summers pinging for review. |
I see that I initially proposed it, but the Would it make more sense to provide generic This keeps the notation entirely out of the DSL and the compiler can optimize out the empty enter/exit calls if the user doesn't actually need them. It also should make the necessary code changes here pretty simple. |
@ryan-summers Thanks for the feedback. That was my original thought as well. When I read your comment I tried the flag and in rebasing the flag didn't work. So I updated it now and now both ways should work. I kinda like your suggestion with the '<' and '>' as well, so I left them in for now. Updated README and added an example. |
89950ab
to
dc26da7
Compare
I was actually advocating for removing the flag entirely and having the enum States {
Start,
}
trait StateMachineContext {
fn on_entry_start() {
// Default, empty implementation that the user can override in their context definition.
}
fn on_exit_start() {
}
} |
I have removed the flag and let all Thanks for your time. I will have a look at the rebase error and the pipeline failures. Should I also add my example to the tests suite? |
This patch adds functions which are executed when the statemachine transitions from a state A to a state B. First on_exit_state_a is called (which is defined as an empty trait implementation which can be overridden) followed by a call to on_entry_state_b. The on_entry and on_exit functions can be implemented in the Statemachine Context trait implementation or ignored altogether, since the standard implementation is empty. Signed-off-by: Martin Broers <[email protected]>
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]>
By using `>` and `<` we can now define entry functions and exit functions on states. These should be defined once and will apply to all transitions interacting with either entering or exiting the state. Signed-off-by: Martin Broers <[email protected]>
Signed-off-by: Martin Broers <[email protected]>
0df9de1
to
ca4fe43
Compare
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]>
ca4fe43
to
82351af
Compare
@MartinBroers I removed the I think I'd go for the route where it's defined as empty-by-default and the user doesn't need to specify any flags etc. |
Issue #60 describes what I needed. I may have sprinkled a few
Debug
statements here and there which may not have been required, but I am open to suggestions to remove them.I am opening this MR since @pleepleus asked to have a go at it. I don't want him to start from scratch.