Metalang99 1.13.3
Full-blown preprocessor metaprogramming
variadics.h
Go to the documentation of this file.
1
10#ifndef ML99_VARIADICS_H
11#define ML99_VARIADICS_H
12
13#include <metalang99/nat/inc.h>
14#include <metalang99/priv/util.h>
15
16#include <metalang99/lang.h>
17
35#define ML99_variadicsCount(...) ML99_call(ML99_variadicsCount, __VA_ARGS__)
36
52#define ML99_variadicsIsSingle(...) ML99_call(ML99_variadicsIsSingle, __VA_ARGS__)
53
68#define ML99_variadicsGet(i) ML99_PRIV_CAT(ML99_PRIV_variadicsGet_, i)
69
84#define ML99_variadicsTail(...) ML99_call(ML99_variadicsTail, __VA_ARGS__)
85
103#define ML99_variadicsForEach(f, ...) ML99_call(ML99_variadicsForEach, f, __VA_ARGS__)
104
120#define ML99_variadicsForEachI(f, ...) ML99_call(ML99_variadicsForEachI, f, __VA_ARGS__)
121
149#define ML99_OVERLOAD(f, ...) ML99_PRIV_CAT(f, ML99_PRIV_VARIADICS_COUNT(__VA_ARGS__))(__VA_ARGS__)
150
151#define ML99_VARIADICS_COUNT(...) ML99_PRIV_VARIADICS_COUNT(__VA_ARGS__)
152#define ML99_VARIADICS_IS_SINGLE(...) ML99_PRIV_NOT(ML99_PRIV_CONTAINS_COMMA(__VA_ARGS__))
153#define ML99_VARIADICS_GET(i) ML99_PRIV_CAT(ML99_PRIV_VARIADICS_GET_, i)
154#define ML99_VARIADICS_TAIL(...) ML99_PRIV_TAIL(__VA_ARGS__)
155
156#ifndef DOXYGEN_IGNORE
157
158#define ML99_variadicsCount_IMPL(...) v(ML99_VARIADICS_COUNT(__VA_ARGS__))
159#define ML99_variadicsIsSingle_IMPL(...) v(ML99_VARIADICS_IS_SINGLE(__VA_ARGS__))
160
161#define ML99_PRIV_variadicsGet_0(...) ML99_call(ML99_PRIV_variadicsGet_0, __VA_ARGS__)
162#define ML99_PRIV_variadicsGet_1(...) ML99_call(ML99_PRIV_variadicsGet_1, __VA_ARGS__)
163#define ML99_PRIV_variadicsGet_2(...) ML99_call(ML99_PRIV_variadicsGet_2, __VA_ARGS__)
164#define ML99_PRIV_variadicsGet_3(...) ML99_call(ML99_PRIV_variadicsGet_3, __VA_ARGS__)
165#define ML99_PRIV_variadicsGet_4(...) ML99_call(ML99_PRIV_variadicsGet_4, __VA_ARGS__)
166#define ML99_PRIV_variadicsGet_5(...) ML99_call(ML99_PRIV_variadicsGet_5, __VA_ARGS__)
167#define ML99_PRIV_variadicsGet_6(...) ML99_call(ML99_PRIV_variadicsGet_6, __VA_ARGS__)
168#define ML99_PRIV_variadicsGet_7(...) ML99_call(ML99_PRIV_variadicsGet_7, __VA_ARGS__)
169
170#define ML99_PRIV_variadicsGet_0_IMPL(...) v(ML99_VARIADICS_GET(0)(__VA_ARGS__))
171#define ML99_PRIV_variadicsGet_1_IMPL(...) v(ML99_VARIADICS_GET(1)(__VA_ARGS__))
172#define ML99_PRIV_variadicsGet_2_IMPL(...) v(ML99_VARIADICS_GET(2)(__VA_ARGS__))
173#define ML99_PRIV_variadicsGet_3_IMPL(...) v(ML99_VARIADICS_GET(3)(__VA_ARGS__))
174#define ML99_PRIV_variadicsGet_4_IMPL(...) v(ML99_VARIADICS_GET(4)(__VA_ARGS__))
175#define ML99_PRIV_variadicsGet_5_IMPL(...) v(ML99_VARIADICS_GET(5)(__VA_ARGS__))
176#define ML99_PRIV_variadicsGet_6_IMPL(...) v(ML99_VARIADICS_GET(6)(__VA_ARGS__))
177#define ML99_PRIV_variadicsGet_7_IMPL(...) v(ML99_VARIADICS_GET(7)(__VA_ARGS__))
178
179#define ML99_PRIV_VARIADICS_GET_0(...) ML99_PRIV_VARIADICS_GET_AUX_0(__VA_ARGS__, ~)
180#define ML99_PRIV_VARIADICS_GET_1(...) ML99_PRIV_VARIADICS_GET_AUX_1(__VA_ARGS__, ~)
181#define ML99_PRIV_VARIADICS_GET_2(...) ML99_PRIV_VARIADICS_GET_AUX_2(__VA_ARGS__, ~)
182#define ML99_PRIV_VARIADICS_GET_3(...) ML99_PRIV_VARIADICS_GET_AUX_3(__VA_ARGS__, ~)
183#define ML99_PRIV_VARIADICS_GET_4(...) ML99_PRIV_VARIADICS_GET_AUX_4(__VA_ARGS__, ~)
184#define ML99_PRIV_VARIADICS_GET_5(...) ML99_PRIV_VARIADICS_GET_AUX_5(__VA_ARGS__, ~)
185#define ML99_PRIV_VARIADICS_GET_6(...) ML99_PRIV_VARIADICS_GET_AUX_6(__VA_ARGS__, ~)
186#define ML99_PRIV_VARIADICS_GET_7(...) ML99_PRIV_VARIADICS_GET_AUX_7(__VA_ARGS__, ~)
187
188#define ML99_PRIV_VARIADICS_GET_AUX_0(a, ...) a
189#define ML99_PRIV_VARIADICS_GET_AUX_1(_a, b, ...) b
190#define ML99_PRIV_VARIADICS_GET_AUX_2(_a, _b, c, ...) c
191#define ML99_PRIV_VARIADICS_GET_AUX_3(_a, _b, _c, d, ...) d
192#define ML99_PRIV_VARIADICS_GET_AUX_4(_a, _b, _c, _d, e, ...) e
193#define ML99_PRIV_VARIADICS_GET_AUX_5(_a, _b, _c, _d, _e, f, ...) f
194#define ML99_PRIV_VARIADICS_GET_AUX_6(_a, _b, _c, _d, _e, _f, g, ...) g
195#define ML99_PRIV_VARIADICS_GET_AUX_7(_a, _b, _c, _d, _e, _f, _g, h, ...) h
196
197#define ML99_variadicsTail_IMPL(...) v(ML99_VARIADICS_TAIL(__VA_ARGS__))
198
199// ML99_variadicsForEach_IMPL {
200
201#define ML99_variadicsForEach_IMPL(f, ...) \
202 ML99_PRIV_CAT(ML99_PRIV_variadicsForEach_, ML99_VARIADICS_IS_SINGLE(__VA_ARGS__)) \
203 (f, __VA_ARGS__)
204#define ML99_PRIV_variadicsForEach_1(f, x) ML99_appl_IMPL(f, x)
205#define ML99_PRIV_variadicsForEach_0(f, x, ...) \
206 ML99_TERMS(ML99_appl_IMPL(f, x), ML99_callUneval(ML99_variadicsForEach, f, __VA_ARGS__))
207// } (ML99_variadicsForEach_IMPL)
208
209// ML99_variadicsForEachI_IMPL {
210
211#define ML99_variadicsForEachI_IMPL(f, ...) ML99_PRIV_variadicsForEachIAux_IMPL(f, 0, __VA_ARGS__)
212
213#define ML99_PRIV_variadicsForEachIAux_IMPL(f, i, ...) \
214 ML99_PRIV_CAT(ML99_PRIV_variadicsForEachI_, ML99_VARIADICS_IS_SINGLE(__VA_ARGS__)) \
215 (f, i, __VA_ARGS__)
216
217#define ML99_PRIV_variadicsForEachI_1(f, i, x) ML99_appl2_IMPL(f, x, i)
218#define ML99_PRIV_variadicsForEachI_0(f, i, x, ...) \
219 ML99_TERMS( \
220 ML99_appl2_IMPL(f, x, i), \
221 ML99_callUneval(ML99_PRIV_variadicsForEachIAux, f, ML99_PRIV_INC(i), __VA_ARGS__))
222// } (ML99_variadicsForEachI_IMPL)
223
224/*
225 * The StackOverflow solution: <https://stackoverflow.com/a/2124385/13166656>.
226 *
227 * This macro supports at most 63 arguments because C99 allows implementations to handle only 127
228 * parameters/arguments per macro definition/invocation (C99 | 5.2.4 Environmental limits), and
229 * `ML99_PRIV_VARIADICS_COUNT_AUX` already accepts 64 arguments.
230 */
231// clang-format off
232#define ML99_PRIV_VARIADICS_COUNT(...) \
233 ML99_PRIV_VARIADICS_COUNT_AUX( \
234 __VA_ARGS__, \
235 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, \
236 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, \
237 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, \
238 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, \
239 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, \
240 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, \
241 3, 2, 1, ~)
242
243#define ML99_PRIV_VARIADICS_COUNT_AUX( \
244 _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \
245 _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \
246 _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \
247 _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \
248 _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, \
249 _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, \
250 _61, _62, _63, x, ...) \
251 x
252// clang-format on
253
254// Arity specifiers {
255
256#define ML99_variadicsCount_ARITY 1
257#define ML99_variadicsIsSingle_ARITY 1
258#define ML99_variadicsTail_ARITY 1
259#define ML99_variadicsForEach_ARITY 2
260#define ML99_variadicsForEachI_ARITY 2
261
262#define ML99_PRIV_variadicsGet_0_ARITY 1
263#define ML99_PRIV_variadicsGet_1_ARITY 1
264#define ML99_PRIV_variadicsGet_2_ARITY 1
265#define ML99_PRIV_variadicsGet_3_ARITY 1
266#define ML99_PRIV_variadicsGet_4_ARITY 1
267#define ML99_PRIV_variadicsGet_5_ARITY 1
268#define ML99_PRIV_variadicsGet_6_ARITY 1
269#define ML99_PRIV_variadicsGet_7_ARITY 1
270// } (Arity specifiers)
271
272#endif // DOXYGEN_IGNORE
273
274#endif // ML99_VARIADICS_H
The core metalanguage.