@@ -135,13 +135,116 @@ constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, c
135
135
return evaluate (begin, result.position , last, consumed_something (f, sizeof ...(String) > 0 ), captures, ctll::list<Tail...>());
136
136
}
137
137
138
+ template <typename T, typename ... Ts> constexpr auto collides_with (T, ctll::list<Ts...>) noexcept {
139
+ return decltype ((ctll::list<>{} + ... + ctll::item_matcher<Ts>::pick (
140
+ typename std::conditional<collides (calculate_first (sequence<T>{}), calculate_first (sequence<Ts>{})), std::true_type, std::false_type>::type{}
141
+ ))){};
142
+ }
143
+
144
+ template <typename T, typename ... Ts> constexpr auto collides_with_negated (T, ctll::list<Ts...>) noexcept {
145
+ return decltype ((ctll::list<>{} + ... + ctll::item_matcher<Ts>::pick (
146
+ typename std::conditional<collides (ctre::negative_set<decltype (calculate_first (sequence<T>{}))>{}, calculate_first (sequence<Ts>{})), std::true_type, std::false_type>::type{}
147
+ ))){};
148
+ }
149
+
150
+ template <typename T, typename ... Ts> constexpr auto mutually_exclusive_with (T, ctll::list<Ts...>) noexcept {
151
+ return decltype ((ctll::list<>{} + ... + ctll::item_matcher<Ts>::pick (
152
+ typename std::conditional<!collides (calculate_first (sequence<T>{}), calculate_first (sequence<Ts>{})), std::true_type, std::false_type>::type{}
153
+ ))){};
154
+ }
155
+
156
+ namespace detail {
157
+ template <typename ... Content>
158
+ constexpr auto transform_into_set (ctll::list<Content...>) {
159
+ return ctre::set<decltype (Content{})...>{};
160
+ // return ctre::set<decltype(transform_into_set(Content{}))... > {};
161
+ }
162
+
163
+ template <typename T>
164
+ constexpr auto transform_into_set (T) {
165
+ return T{};
166
+ }
167
+
168
+ template <>
169
+ constexpr auto transform_into_set (can_be_anything) {
170
+ return ctre::char_range<std::numeric_limits<int64_t >::min (), std::numeric_limits<int64_t >::max ()>{};
171
+ }
172
+
173
+ template <typename ... Content>
174
+ constexpr auto transform_into_select (ctll::list<Content...>) {
175
+ return ctre::select <decltype (Content{})...>{};
176
+ }
177
+ }
178
+
138
179
// matching select in patterns
139
180
template <typename R, typename Iterator, typename EndIterator, typename HeadOptions, typename ... TailOptions, typename ... Tail>
140
181
constexpr CTRE_FORCE_INLINE R evaluate (const Iterator begin, Iterator current, const EndIterator last, const flags & f, R captures, ctll::list<select<HeadOptions, TailOptions...>, Tail...>) noexcept {
141
- if (auto r = evaluate (begin, current, last, f, captures, ctll::list<HeadOptions, Tail...>())) {
142
- return r;
182
+ if constexpr (sizeof ...(TailOptions) > 1 ) {
183
+ constexpr auto collision_list = collides_with (sequence<HeadOptions, Tail...>{}, ctll::list<
184
+ decltype (sequence<TailOptions, Tail...>{})...
185
+ >{});
186
+
187
+ if constexpr (ctll::empty (collision_list)) {
188
+ using set_type = decltype (detail::transform_into_set (calculate_first (sequence<HeadOptions, Tail...>{})));
189
+ if constexpr (::std::is_same_v<set<>, set_type>) {
190
+ // fail handle as normal
191
+ if (auto r = evaluate (begin, current, last, f, captures, ctll::list<HeadOptions, Tail...>())) {
192
+ return r;
193
+ } else {
194
+ return evaluate (begin, current, last, f, captures, ctll::list<select <TailOptions...>, Tail...>());
195
+ }
196
+ } else {
197
+ // ok optimize into exclusive select
198
+ if (auto r = evaluate (begin, current, last, f, captures, ctll::list<set_type, end_cycle_mark>{})) {
199
+ return evaluate (begin, current, last, f, captures, ctll::list<HeadOptions, Tail...>{});
200
+ } else {
201
+ return evaluate (begin, current, last, f, captures, ctll::list<select <TailOptions...>, Tail...>());
202
+ }
203
+ }
204
+
205
+ return evaluate (begin, current, last, f, captures, ctll::list<HeadOptions, Tail...>());
206
+ } else if constexpr (ctll::size (collision_list) == sizeof ...(TailOptions)) {
207
+ // continue as normal...we collided with everything
208
+ if (auto r = evaluate (begin, current, last, f, captures, ctll::list<HeadOptions, Tail...>())) {
209
+ return r;
210
+ } else {
211
+ return evaluate (begin, current, last, f, captures, ctll::list<select <TailOptions...>, Tail...>());
212
+ }
213
+ } else {
214
+ // we collided with some things, but not others, bifricate on the first character we see
215
+ // may be less computationally expensive to do a set subtraction from the complete list with the collision list, because we're evaluating collisions again
216
+ constexpr auto negated_collision_list = collides_with_negated (sequence<HeadOptions, Tail...>{}, ctll::list<
217
+ decltype (sequence<TailOptions, Tail...>{})...
218
+ >{});
219
+
220
+ using set_type = decltype (detail::transform_into_set (calculate_first (sequence<HeadOptions, Tail...>{})));
221
+ if constexpr (::std::is_same_v<set<>, set_type>) {
222
+ // fail
223
+ if (auto r = evaluate (begin, current, last, f, captures, ctll::list<HeadOptions, Tail...>())) {
224
+ return r;
225
+ } else {
226
+ return evaluate (begin, current, last, f, captures, ctll::list<non_exclusive_select<TailOptions...>, Tail...>());
227
+ }
228
+ } else {
229
+ // ok optimize into a split
230
+ if (auto r = evaluate (begin, current, last, f, captures, ctll::list<set_type, end_cycle_mark>{})) {
231
+ if (auto r2 = evaluate (begin, current, last, f, captures, ctll::list<HeadOptions, Tail...>{})) {
232
+ return r2;
233
+ } else {
234
+ return evaluate (begin, current, last, f, captures, detail::transform_into_select (collision_list));
235
+ }
236
+ } else {
237
+ return evaluate (begin, current, last, f, captures, detail::transform_into_select (negated_collision_list));
238
+ }
239
+ }
240
+ }
143
241
} else {
144
- return evaluate (begin, current, last, f, captures, ctll::list<select <TailOptions...>, Tail...>());
242
+ // simple case, too few branches to pick handle as normal
243
+ if (auto r = evaluate (begin, current, last, f, captures, ctll::list<HeadOptions, Tail...>())) {
244
+ return r;
245
+ } else {
246
+ return evaluate (begin, current, last, f, captures, ctll::list<select <TailOptions...>, Tail...>());
247
+ }
145
248
}
146
249
}
147
250
@@ -151,6 +254,22 @@ constexpr CTRE_FORCE_INLINE R evaluate(const Iterator, Iterator, const EndIterat
151
254
return not_matched;
152
255
}
153
256
257
+ // non exclusive select (assume collisions)
258
+ template <typename R, typename Iterator, typename EndIterator, typename HeadOptions, typename ... TailOptions, typename ... Tail>
259
+ constexpr CTRE_FORCE_INLINE R evaluate (const Iterator begin, Iterator current, const EndIterator last, const flags & f, R captures, ctll::list<non_exclusive_select<HeadOptions, TailOptions...>, Tail...>) noexcept {
260
+ if (auto r = evaluate (begin, current, last, f, captures, ctll::list<HeadOptions, Tail...>())) {
261
+ return r;
262
+ } else {
263
+ return evaluate (begin, current, last, f, captures, ctll::list<non_exclusive_select<TailOptions...>, Tail...>());
264
+ }
265
+ }
266
+
267
+ template <typename R, typename Iterator, typename EndIterator, typename ... Tail>
268
+ constexpr CTRE_FORCE_INLINE R evaluate (const Iterator, Iterator, const EndIterator, flags, R, ctll::list<non_exclusive_select<>, Tail...>) noexcept {
269
+ // no previous option was matched => REJECT
270
+ return not_matched;
271
+ }
272
+
154
273
// matching sequence in patterns
155
274
template <typename R, typename Iterator, typename EndIterator, typename HeadContent, typename ... TailContent, typename ... Tail>
156
275
constexpr CTRE_FORCE_INLINE R evaluate (const Iterator begin, Iterator current, const EndIterator last, const flags & f, R captures, ctll::list<sequence<HeadContent, TailContent...>, Tail...>) noexcept {
0 commit comments