Skip to content

Commit 3acbb52

Browse files
committed
add runtime_conditional and flow unary operator+
1 parent 6367d04 commit 3acbb52

18 files changed

+681
-261
lines changed

examples/flow_daily_routine/main.cpp

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -95,14 +95,10 @@ struct self_care_component_t {
9595
// Extend flow services
9696
constexpr static auto config = cib::config(
9797

98-
cib::extend<morning_routine_t>(self_care_component_t::WAKE_UP >>
99-
self_care_component_t::EXERCISE >>
100-
self_care_component_t::TAKE_BATH),
98+
cib::extend<morning_routine_t>(+WAKE_UP >> +EXERCISE >> +TAKE_BATH),
10199

102-
cib::extend<evening_routine_t>(self_care_component_t::EXERCISE >>
103-
self_care_component_t::TAKE_BATH >>
104-
self_care_component_t::RELAX >>
105-
self_care_component_t::GO_TO_BED));
100+
cib::extend<evening_routine_t>(+EXERCISE >> +TAKE_BATH >> +RELAX >>
101+
+GO_TO_BED));
106102
};
107103

108104
struct food_component_t {
@@ -119,10 +115,10 @@ struct food_component_t {
119115
constexpr static auto config = cib::config(
120116

121117
cib::extend<morning_routine_t>(self_care_component_t::TAKE_BATH >>
122-
food_component_t::BREAKFAST),
118+
+BREAKFAST),
123119

124120
cib::extend<evening_routine_t>(self_care_component_t::RELAX >>
125-
food_component_t::DINNER >>
121+
+DINNER >>
126122
self_care_component_t::GO_TO_BED));
127123
};
128124

@@ -141,16 +137,13 @@ struct dress_up_component_t {
141137
constexpr static auto config = cib::config(
142138

143139
cib::extend<morning_routine_t>(
144-
self_care_component_t::WAKE_UP >>
145-
dress_up_component_t::GET_READY_FOR_EXERCISE >>
140+
self_care_component_t::WAKE_UP >> +GET_READY_FOR_EXERCISE >>
146141
self_care_component_t::EXERCISE >>
147-
self_care_component_t::TAKE_BATH >>
148-
dress_up_component_t::GET_READY_TO_WORK >>
142+
self_care_component_t::TAKE_BATH >> +GET_READY_TO_WORK >>
149143
food_component_t::BREAKFAST),
150144

151-
cib::extend<evening_routine_t>(
152-
dress_up_component_t::GET_READY_FOR_EXERCISE >>
153-
self_care_component_t::EXERCISE));
145+
cib::extend<evening_routine_t>(+GET_READY_FOR_EXERCISE >>
146+
self_care_component_t::EXERCISE));
154147
};
155148

156149
struct commute_component_t {
@@ -167,11 +160,10 @@ struct commute_component_t {
167160
constexpr static auto config = cib::config(
168161

169162
cib::extend<morning_routine_t>(food_component_t::BREAKFAST >>
170-
commute_component_t::GO_TO_OFFICE),
163+
+GO_TO_OFFICE),
171164

172165
cib::extend<evening_routine_t>(
173-
commute_component_t::RETURN_HOME >>
174-
dress_up_component_t::GET_READY_FOR_EXERCISE));
166+
+RETURN_HOME >> dress_up_component_t::GET_READY_FOR_EXERCISE));
175167
};
176168

177169
struct daily_routine_component_t {
@@ -206,7 +198,7 @@ struct daily_routine_component_t {
206198

207199
// we need to extend the MainLoop as cib::top implements
208200
// MainLoop service
209-
cib::extend<cib::MainLoop>(DAILY_ROUTINES));
201+
cib::extend<cib::MainLoop>(+DAILY_ROUTINES));
210202
};
211203

212204
struct person_routine_proj {

include/cib/config.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <cib/detail/config_item.hpp>
88
#include <cib/detail/exports.hpp>
99
#include <cib/detail/extend.hpp>
10+
#include <cib/detail/runtime_conditional.hpp>
1011

1112
#include <stdx/compiler.hpp>
1213

@@ -22,6 +23,7 @@ namespace cib {
2223
* @see cib::extend
2324
* @see cib::exports
2425
* @see cib::conditional
26+
* @see cib::runtime_conditional
2527
*/
2628
template <typename... Configs>
2729
[[nodiscard]] CONSTEVAL auto config(Configs const &...configs) {
@@ -72,4 +74,10 @@ template <typename Predicate, typename... Configs>
7274
Configs const &...configs) {
7375
return detail::conditional<Predicate, Configs...>{configs...};
7476
}
77+
78+
template <stdx::ct_string Name>
79+
constexpr auto runtime_condition = []<typename P>(P) {
80+
static_assert(std::is_default_constructible_v<P>);
81+
return detail::runtime_condition<Name, P>{};
82+
};
7583
} // namespace cib
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
#pragma once
2+
3+
#include <cib/detail/config_details.hpp>
4+
#include <cib/detail/config_item.hpp>
5+
#include <cib/detail/extend.hpp>
6+
7+
#include <stdx/compiler.hpp>
8+
#include <stdx/ct_format.hpp>
9+
#include <stdx/tuple.hpp>
10+
#include <stdx/tuple_algorithms.hpp>
11+
12+
namespace cib::detail {
13+
template <typename Cond, typename... Configs>
14+
struct runtime_conditional : config_item {
15+
detail::config<Configs...> body;
16+
17+
CONSTEVAL explicit runtime_conditional(Configs const &...configs)
18+
: body{configs...} {}
19+
20+
[[nodiscard]] constexpr auto extends_tuple() const {
21+
return stdx::transform(
22+
[]<typename E>(E e) {
23+
auto args_tuple = stdx::transform(
24+
[]<typename Arg>(Arg) {
25+
return make_runtime_conditional(Cond{}, Arg{});
26+
},
27+
e.args_tuple);
28+
29+
return stdx::apply(
30+
[]<typename... Args>(Args...) {
31+
return extend<typename E::service_type, Args...>{
32+
Args{}...};
33+
},
34+
args_tuple);
35+
},
36+
body.extends_tuple());
37+
}
38+
39+
[[nodiscard]] constexpr auto exports_tuple() const {
40+
return body.exports_tuple();
41+
}
42+
};
43+
44+
template <stdx::ct_string Name, typename... Ps> // FIXME: concept for Ps
45+
struct runtime_condition {
46+
constexpr static auto predicates = stdx::make_tuple(Ps{}...);
47+
48+
constexpr static auto ct_name = Name;
49+
50+
template <typename... Configs>
51+
[[nodiscard]] CONSTEVAL auto operator()(Configs const &...configs) const {
52+
return detail::runtime_conditional<runtime_condition<Name, Ps...>,
53+
Configs...>{configs...};
54+
}
55+
56+
explicit operator bool() const { return (Ps{}() and ...); }
57+
58+
template <stdx::ct_string RhsName, typename... RhsPs>
59+
[[nodiscard]] constexpr auto
60+
operator and(runtime_condition<RhsName, RhsPs...> rhs) const {
61+
if constexpr ((sizeof...(Ps) + sizeof...(RhsPs)) == 0) {
62+
return runtime_condition<"always">{};
63+
64+
} else if constexpr (sizeof...(Ps) == 0) {
65+
return rhs;
66+
67+
} else if constexpr (sizeof...(RhsPs) == 0) {
68+
return *this;
69+
70+
} else {
71+
constexpr auto name =
72+
stdx::ct_format<"{} and {}">(CX_VALUE(Name), CX_VALUE(RhsName));
73+
74+
return runtime_condition<name, Ps..., RhsPs...>{};
75+
}
76+
}
77+
};
78+
79+
using always_condition_t = runtime_condition<"always">;
80+
constexpr auto always_condition = always_condition_t{};
81+
} // namespace cib::detail

include/flow/detail/par.hpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,13 @@ template <node Lhs, node Rhs> struct par {
1111

1212
using is_node = void;
1313

14+
constexpr auto operator+() const {
15+
using lhs_t = decltype(+lhs);
16+
using rhs_t = decltype(+rhs);
17+
18+
return par<lhs_t, rhs_t>{lhs_t{}, rhs_t{}};
19+
}
20+
1421
private:
1522
friend constexpr auto tag_invoke(get_initials_t, par const &p) {
1623
return stdx::tuple_cat(get_initials(p.lhs), get_initials(p.rhs));
@@ -24,6 +31,11 @@ template <node Lhs, node Rhs> struct par {
2431
return stdx::tuple_cat(get_nodes(p.lhs), get_nodes(p.rhs));
2532
}
2633

34+
friend constexpr auto tag_invoke(get_all_mentioned_nodes_t, par const &p) {
35+
return stdx::tuple_cat(get_all_mentioned_nodes(p.lhs),
36+
get_all_mentioned_nodes(p.rhs));
37+
}
38+
2739
friend constexpr auto tag_invoke(get_edges_t, par const &p) {
2840
return stdx::tuple_cat(get_edges(p.lhs), get_edges(p.rhs));
2941
}
@@ -36,3 +48,9 @@ template <flow::dsl::node Lhs, flow::dsl::node Rhs>
3648
[[nodiscard]] constexpr auto operator&&(Lhs const &lhs, Rhs const &rhs) {
3749
return flow::dsl::par{lhs, rhs};
3850
}
51+
52+
template <typename Cond, flow::dsl::node Lhs, flow::dsl::node Rhs>
53+
constexpr auto make_runtime_conditional(Cond, flow::dsl::par<Lhs, Rhs>) {
54+
return flow::dsl::par{make_runtime_conditional(Cond{}, Lhs{}),
55+
make_runtime_conditional(Cond{}, Rhs{})};
56+
}

include/flow/detail/seq.hpp

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,25 @@
11
#pragma once
22

3+
#include <cib/detail/runtime_conditional.hpp>
34
#include <flow/detail/walk.hpp>
45

56
#include <stdx/tuple_algorithms.hpp>
67

78
namespace flow::dsl {
8-
template <node Lhs, node Rhs> struct seq {
9+
template <node Lhs, node Rhs, typename Cond = cib::detail::always_condition_t>
10+
struct seq {
911
Lhs lhs;
1012
Rhs rhs;
1113

1214
using is_node = void;
1315

16+
constexpr auto operator+() const {
17+
using lhs_t = decltype(+lhs);
18+
using rhs_t = decltype(+rhs);
19+
20+
return seq<lhs_t, rhs_t, Cond>{lhs_t{}, rhs_t{}};
21+
}
22+
1423
private:
1524
friend constexpr auto tag_invoke(get_initials_t, seq const &s) {
1625
return get_initials(s.lhs);
@@ -24,6 +33,11 @@ template <node Lhs, node Rhs> struct seq {
2433
return stdx::tuple_cat(get_nodes(s.lhs), get_nodes(s.rhs));
2534
}
2635

36+
friend constexpr auto tag_invoke(get_all_mentioned_nodes_t, seq const &s) {
37+
return stdx::tuple_cat(get_all_mentioned_nodes(s.lhs),
38+
get_all_mentioned_nodes(s.rhs));
39+
}
40+
2741
friend constexpr auto tag_invoke(get_edges_t, seq const &s) {
2842
auto is = get_initials(s.rhs);
2943
auto fs = get_finals(s.lhs);
@@ -33,16 +47,31 @@ template <node Lhs, node Rhs> struct seq {
3347
transform(
3448
[]<typename P>(P const &) {
3549
return edge<stdx::tuple_element_t<0, P>,
36-
stdx::tuple_element_t<1, P>>{};
50+
stdx::tuple_element_t<1, P>, Cond>{};
3751
},
3852
cartesian_product_copy(fs, is)));
3953
}
4054
};
4155

4256
template <node Lhs, node Rhs> seq(Lhs, Rhs) -> seq<Lhs, Rhs>;
57+
4358
} // namespace flow::dsl
4459

4560
template <flow::dsl::node Lhs, flow::dsl::node Rhs>
4661
[[nodiscard]] constexpr auto operator>>(Lhs const &lhs, Rhs const &rhs) {
4762
return flow::dsl::seq{lhs, rhs};
4863
}
64+
65+
template <typename Cond, flow::dsl::node Lhs, flow::dsl::node Rhs,
66+
typename EdgeCond>
67+
constexpr auto make_runtime_conditional(Cond,
68+
flow::dsl::seq<Lhs, Rhs, EdgeCond>) {
69+
auto lhs = make_runtime_conditional(Cond{}, Lhs{});
70+
auto rhs = make_runtime_conditional(Cond{}, Rhs{});
71+
72+
using lhs_t = decltype(lhs);
73+
using rhs_t = decltype(rhs);
74+
using cond_t = decltype(EdgeCond{} and Cond{});
75+
76+
return flow::dsl::seq<lhs_t, rhs_t, cond_t>{lhs, rhs};
77+
}

include/flow/detail/walk.hpp

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ namespace flow::dsl {
1010
template <typename T>
1111
concept node = requires { typename stdx::remove_cvref_t<T>::is_node; };
1212

13-
template <typename Source, typename Dest> struct edge {
13+
template <typename Source, typename Dest, typename Cond> struct edge {
1414
using source_t = Source;
1515
using dest_t = Dest;
1616
};
@@ -47,7 +47,11 @@ constexpr inline class get_finals_t {
4747

4848
constexpr inline class get_nodes_t {
4949
template <node N> friend constexpr auto tag_invoke(get_nodes_t, N &&n) {
50-
return stdx::make_tuple(std::forward<N>(n));
50+
if constexpr (std::remove_cvref_t<N>::is_reference) {
51+
return stdx::tuple{};
52+
} else {
53+
return stdx::make_tuple(std::forward<N>(n));
54+
}
5155
}
5256

5357
public:
@@ -60,6 +64,22 @@ constexpr inline class get_nodes_t {
6064
}
6165
} get_nodes{};
6266

67+
constexpr inline class get_all_mentioned_nodes_t {
68+
template <node N>
69+
friend constexpr auto tag_invoke(get_all_mentioned_nodes_t, N &&n) {
70+
return stdx::make_tuple(std::forward<N>(n));
71+
}
72+
73+
public:
74+
template <typename... Ts>
75+
constexpr auto operator()(Ts &&...ts) const
76+
noexcept(noexcept(tag_invoke(std::declval<get_all_mentioned_nodes_t>(),
77+
std::forward<Ts>(ts)...)))
78+
-> decltype(tag_invoke(*this, std::forward<Ts>(ts)...)) {
79+
return tag_invoke(*this, std::forward<Ts>(ts)...);
80+
}
81+
} get_all_mentioned_nodes{};
82+
6383
constexpr inline class get_edges_t {
6484
friend constexpr auto tag_invoke(get_edges_t, node auto const &) {
6585
return stdx::tuple{};

0 commit comments

Comments
 (0)