Maki
Loading...
Searching...
No Matches
transition_table.hpp
1//Copyright Florian Goujeon 2021 - 2026.
2//Distributed under the Boost Software License, Version 1.0.
3//(See accompanying file LICENSE or copy at
4//https://www.boost.org/LICENSE_1_0.txt)
5//Official repository: https://github.com/fgoujeon/maki
6
11
12#ifndef MAKI_TRANSITION_TABLE_HPP
13#define MAKI_TRANSITION_TABLE_HPP
14
15#include "action.hpp"
16#include "guard.hpp"
17#include "event_set.hpp"
18#include "event.hpp"
19#include "state_set.hpp"
20#include "state_mold.hpp"
21#include "states.hpp"
22#include "ini.hpp"
23#include "fin.hpp"
24#include "null.hpp"
25#include "detail/tlu/left_fold.hpp"
26#include "detail/type_set.hpp"
27#include "detail/friendly_impl.hpp"
28#include "detail/tuple.hpp"
29
30namespace maki
31{
32
33#ifdef MAKI_DETAIL_DOXYGEN
53template<class Impl = IMPLEMENTATION_DETAIL>
55#else
56template<class Impl = detail::tuple<>>
58#endif
59
60namespace detail
61{
62 template
63 <
64 class SourceStateMold,
65 class TargetStateMold,
66 class Event,
67 action_signature ActionSignature,
68 class ActionCallable,
69 guard_signature GuardSignature,
70 class GuardCallable
71 >
72 struct transition
73 {
74 using event_type = Event;
75
76 SourceStateMold source_state_mold;
77 TargetStateMold target_state_mold;
78 Event evt;
79 action<ActionSignature, ActionCallable> act;
80 guard<GuardSignature, GuardCallable> grd;
81
82 [[nodiscard]]
83 static constexpr bool can_process_completion_event()
84 {
85 return is_null_v<Event>;
86 }
87 };
88
89 template
90 <
91 class SourceStateMold,
92 class TargetStateMold,
93 class Event,
94 action_signature ActionSignature,
95 class ActionCallable,
96 guard_signature GuardSignature,
97 class GuardCallable
98 >
99 transition
100 (
101 SourceStateMold,
102 TargetStateMold,
103 Event,
104 action<ActionSignature, ActionCallable>,
105 guard<GuardSignature, GuardCallable>
106 ) -> transition
107 <
108 SourceStateMold,
109 TargetStateMold,
110 Event,
111 ActionSignature,
112 ActionCallable,
113 GuardSignature,
114 GuardCallable
115 >;
116
117 template<class TransitionEvent>
118 struct transition_event_event_type_set;
119
120 template<class Event>
121 struct transition_event_event_type_set<event_t<Event>>
122 {
123 using type = type_set_item<Event>;
124 };
125
126 template<class EventSetImpl>
127 struct transition_event_event_type_set<event_set<EventSetImpl>>
128 {
129 using type = EventSetImpl;
130 };
131
132 template<>
133 struct transition_event_event_type_set<null_t>
134 {
135 using type = empty_type_set_t;
136 };
137
138 template<class TransitionEvent>
139 using transition_event_event_type_set_t = typename transition_event_event_type_set<TransitionEvent>::type;
140
141 template<class Transition>
142 using transition_event_type_set_t = transition_event_event_type_set_t<typename Transition::event_type>;
143
144 template<class... Transitions>
145 constexpr auto make_transition_table(const tuple<Transitions...>& transitions)
146 {
147 return transition_table<tuple<Transitions...>>{transitions};
148 }
149
150 template<class T>
151 constexpr decltype(auto) store_state_mold(T&& obj)
152 {
153 return std::forward<T>(obj);
154 }
155
156 //Store a pointer in this case
157 constexpr auto store_state_mold(ini_t /*ini*/)
158 {
159 return &detail::state_molds::null;
160 }
161
162 //Store a pointer in this case
163 constexpr auto store_state_mold(fin_t /*fin*/)
164 {
165 return &detail::state_molds::fin;
166 }
167
168 //Store a pointer in this case
169 template<class OptionSet>
170 constexpr auto store_state_mold(const state_mold<OptionSet>& mold)
171 {
172 return &mold;
173 }
174}
175
176template<class Impl>
178{
179public:
183 constexpr transition_table() = default;
184
188 constexpr transition_table(const transition_table&) = default;
189
194
195 ~transition_table() = default;
196
201
206
216 template
217 <
218 class Source,
219 class Target,
220 class Event = null_t,
221 class ActionOrNull = null_t,
222 class GuardOrNull = null_t
223 >
224 constexpr auto operator()
225 (
226 const Source& source_state_mold,
227 const Target& target_state_mold,
228 const Event& evt = null,
229 const ActionOrNull& action = null,
230 const GuardOrNull& guard = null
231 )
232 {
233 //Check source
234 if constexpr(Impl::size == 0)
235 {
236 static_assert
237 (
238 detail::is_ini_v<Source>,
239 "Source (1st argument) of first transition must be `maki::ini`. (Note: Composite state regions without initial pseudostate are not implemented yet.)"
240 );
241 }
242 else
243 {
244 static_assert
245 (
246 detail::is_state_mold_v<Source> || detail::is_state_set_v<Source>,
247 "Source (1st argument) must be an instance of `maki::state_mold` or an instance of `maki::state_set`"
248 );
249 }
250
251 //Check target
252 if constexpr(detail::is_ini_v<Source>)
253 {
254 static_assert
255 (
256 detail::is_state_mold_v<Target>,
257 "Target (2nd argument) of transition from initial pseudostate must be an instance of `maki::state_mold`."
258 );
259 }
260 else
261 {
262 static_assert
263 (
264 detail::is_state_mold_v<Target> || detail::is_null_v<Target> || detail::is_fin_v<Target>,
265 "Target (2nd argument) must be an instance of `maki::state_mold`, `maki::null` or `maki::fin`."
266 );
267 }
268
269 //Check event
270 if constexpr(detail::is_ini_v<Source>)
271 {
272 static_assert
273 (
274 detail::is_null_v<Event>,
275 "Event (3rd argument) of transition from initial pseudostate must be `maki::null`"
276 );
277 }
278 else
279 {
280 static_assert
281 (
282 detail::is_event_v<Event> || detail::is_event_set_v<Event> || detail::is_null_v<Event>,
283 "Event (3rd argument) must be an instance of `maki::event_t`, an instance of `maki::event_set`, or `maki::null`"
284 );
285 }
286
287 //Check action
288 static_assert
289 (
290 detail::is_action_v<ActionOrNull> || detail::is_null_v<ActionOrNull>,
291 "Action (4th argument) must be an instance of `maki::action` or `maki::null`."
292 );
293
294 //Check guard
295 if constexpr(detail::is_ini_v<Source>)
296 {
297 static_assert
298 (
299 detail::is_null_v<GuardOrNull>,
300 "Guard (5th argument) of transition from initial pseudostate must be `maki::null`."
301 );
302 }
303 else
304 {
305 static_assert
306 (
307 detail::is_guard_v<GuardOrNull> || detail::is_null_v<GuardOrNull>,
308 "Guard (5th argument) must be an instance of `maki::guard` or `maki::null`."
309 );
310 }
311
312 return detail::make_transition_table
313 (
314 impl_.append
315 (
316 detail::transition
317 {
318 detail::store_state_mold(source_state_mold),
319 detail::store_state_mold(target_state_mold),
320 evt,
321 detail::to_action(action),
322 detail::to_guard(guard)
323 }
324 )
325 );
326 }
327
328private:
329 MAKI_DETAIL_FRIENDLY_IMPL
330
331 using impl_type = Impl;
332
333#ifndef MAKI_DETAIL_DOXYGEN
334 template<class... Transitions>
335 friend constexpr auto detail::make_transition_table(const detail::tuple<Transitions...>&);
336#endif
337
338 constexpr explicit transition_table(const Impl& impl):
339 impl_{impl}
340 {
341 }
342
343 impl_type impl_;
344};
345
346namespace detail
347{
348 template<class EventTypeSet, class Transition>
349 using transition_table_event_type_set_fold_operation_t = type_set_union_t
350 <
351 EventTypeSet,
352 transition_event_type_set_t<Transition>
353 >;
354
355 template<class TransitionTable>
356 using transition_table_event_type_set_t = tlu::left_fold_t
357 <
358 impl_of_t<TransitionTable>,
359 transition_table_event_type_set_fold_operation_t,
360 empty_type_set_t
361 >;
362}
363
364} //namespace
365
366#endif
event_set(event_t< Event >) -> event_set< IMPLEMENTATION_DETAIL >
Class template argument deduction guide for maki::event_set.
Represents a transition table.
Definition transition_table.hpp:178
constexpr transition_table(const transition_table &)=default
Copy constructor.
transition_table & operator=(transition_table &&)=delete
Deleted move operator.
transition_table(transition_table &&)=delete
Deleted move constructor.
transition_table & operator=(const transition_table &)=delete
Deleted assignment operator.
constexpr transition_table()=default
Default constructor.
The Maki library.
IMPLEMENTATION_DETAIL null_t
The type of maki::null.
Definition null.hpp:26
IMPLEMENTATION_DETAIL ini_t
The type of maki::ini.
Definition ini.hpp:19
guard_signature
The set of arguments taken by a guard callable.
Definition guard.hpp:26
action_signature
The set of arguments taken by an action callable.
Definition action.hpp:26
IMPLEMENTATION_DETAIL fin_t
The type of maki::fin.
Definition fin.hpp:19
Represents an action to be given to maki::transition_table.
Definition action.hpp:60
Represents a guard to be given to maki::transition_table. Use the builder functions (maki::guard_v() ...
Definition guard.hpp:86