Hi Nick,
1) You may consider unioning or intersecting talk_sm with a machine
( any | anytime_events )*
A union will prevent the talk_sm machine from ever failing, so
intersection may be what you need.
2) The ragel equivalent is called conditions. Note I am currently
re-implementing the condition feature for ragel 7. If you're using the
master branch then conditions will be broken for a little while longer.
3) You can change the first transition of 'hungry' to
put_food_in_mouth eating -> hungry |
where 'eating' is complete machine definition with start state and final
states. The Final states of 'eating' will receive epsilon transitions to
'hungry'.
4) It's unimplemented. It requires passing any existing labels through
the NFA -> DFA alg and adding them to the output.
Regards,
Adrian
On 12-10-11 03:30 PM, Nick Parker wrote:
Hello, I'm on a project at work which has been using Boost's Meta State Machine
(boost::msm) library in a couple places. A major downside for us is that our
state machines are apparently quite large by boost::msm standards (on the order
of 50-80 transitions), resulting in very resource intensive builds which need a
couple minutes and several GB of ram to complete. Long story short, I figured
this would be a good opportunity to learn Ragel. I've made pretty good progress
in writing Ragelized versions of our current machines, but have encountered
some corner cases where I wasn't able to think up an obvious Ragel equivalent
to a boost::msm feature:
1) Let some events be considered valid during any state. In boost::msm, we've
been handling this via a secondary orthogonal state[1] dedicated to handling
those events, leaving the main state unchanged. The best Ragel equivalent I
found was to do something like this, where a no-op submachine containing those
events would be manually added to each state:
anytime_events = (
e_sneeze @a_sneeze_from_any_to_same |
e_laugh @a_laugh_from_any_to_same
);
talk_sm = (
start: (
e_hello @a_hello_from_start_to_hello -> hello |
e_goodbye @a_goodbye_from_start_to_final -> final |
anytime_events -> start
),
hello: (
e_convo @a_convo_from_hello_to_conversation -> conversation |
e_nevermind @a_nevermind_from_hello_to_final -> final |
anytime_events -> hello
),
conversation: (
e_talk @a_talk_from_conversation_to_conversation -> conversation |
e_goodbye @a_goodbye_from_conversation_to_final -> final |
anytime_events -> conversation
)
);
This solution works fine and is also fairly intuitive, but it felt a little
clunky adding this thing to every state. Is there a more direct alternative
that I missed?
2) boost::msm has a feature called "Guards"[2], which are user-defined functions that get called
before a transition completes and determine whether the transition should be aborted. Would a reasonable
Ragel-based implementation of this be an action which calls "fgoto *fcurs" or similar when a
condition fails? Assuming it's not too cumbersome to do so, it'd be nice if this could be done
"natively" without the fgoto, if only so that the guard failure case appears as a transition in
graphviz exports, but this isn't a big deal.
3) In one case, there's a heirarchical machine with submachines that
effectively act as modes of operation within a larger state. The tricky part is
that these submachines have multiple exit states into the parent machine,
depending on what happened within the submachine. This feels like a common
scenario, but I couldn't really think of a good equivalent in Ragel for this.
Syntactically, I think it'd look something like this:
eat_sm = (
start: (
pick_up_fork -> hungry
),
hungry: (
put_food_in_mouth -> eating |
die_of_starvation -> final
),
not_hungry: (
put_down_fork -> final
),
eating: (
start: [] -> chewing,
chewing: (
chew -> chewing |
spit_out -> hungry | #exit to parent's "hungry" state
swallow -> swallowing
),
swallowing: (
cough_up -> chewing |
swallowed -> not_hungry #exit to parent's "not_hungry" state
)
)
)
The best solution I could think of was to move all the submachine content to
the parent machine, which wouldn't be so bad in the above example. However, the
real-world case I'm trying to solve has 4 of these submachines, each with 4-5
states, so it'd start to look pretty messy if all of these were all merged into
one big list, and the explicit partitioning of these modes into submachines
would be nice to keep as well.
4) Unrelated to boost::msm: I've been making very good use of the graphviz
export feature. One thing I've found to be missing is that the state circles
are only labeled with a seemingly arbitrary integer (1,2,3,...) instead of the
state label (state_x,state_y,state_z,...). As a result, I end up needing to go
by the transition action labels to figure out which graphviz circles correspond
to which states. This can rapidly get cumbersome when the machine is large. Is
this a limitation of the dot file format itself or just an unimplemented
feature in Ragel? I'm using Ragel 6.7 from Debian unstable, and xdot to view
the graphviz output.
[1] "Submachines, orthogonal regions, pseudostates"
http://www.boost.org/doc/libs/1_51_0/libs/msm/doc/HTML/ch02s02.html#d0e151
[2] "the guard is a Boolean operation executed [before the transition] which can
prevent the transition from firing by returning false"
www.boost.org/doc/libs/1_51_0/libs/msm/doc/HTML/ch02s02.html#d0e121
_______________________________________________
ragel-users mailing list
ragel-users@complang.org
http://www.complang.org/mailman/listinfo/ragel-users
_______________________________________________
ragel-users mailing list
ragel-users@complang.org
http://www.complang.org/mailman/listinfo/ragel-users