6 #ifndef METALANG99_AUX_H
7 #define METALANG99_AUX_H
9 #include <metalang99/lang.h>
10 #include <metalang99/priv/compiler_attr.h>
14 * Concatenates @p x with @p y and evaluates the result.
19 * #include <metalang99/aux.h>
21 * #define ABC123 v(Billie Jean)
24 * M_catEval(v(ABC), v(123))
26 * // ERROR: 123ABC is not a valid Metalang99 term.
27 * M_catEval(v(123), v(ABC))
30 #define METALANG99_catEval(x, y) METALANG99_call(METALANG99_catEval, x y)
33 * Concatenates @p x with @p y, leaving the result unevaluated.
38 * #include <metalang99/aux.h>
40 * #define ABC123 Billie Jean
43 * M_cat(v(ABC), v(123))
46 * M_cat(v(123), v(ABC))
49 #define METALANG99_cat(x, y) METALANG99_call(METALANG99_cat, x y)
52 * Stringifies provided arguments.
57 * #include <metalang99/aux.h>
60 * M_stringify(v(Billie Jean))
63 #define METALANG99_stringify(...) METALANG99_call(METALANG99_stringify, __VA_ARGS__)
66 * Evaluates to nothing.
68 #define METALANG99_empty() METALANG99_call(METALANG99_empty, )
71 * Evaluates to its arguments.
76 * #include <metalang99/aux.h>
82 #define METALANG99_id(...) METALANG99_call(METALANG99_id, __VA_ARGS__)
85 * Transforms a sequence of arguments into a parenthesised normal form.
90 * #include <metalang99/aux.h>
93 * M_parenthesiseEval(v(1, 2, 3))
96 #define METALANG99_parenthesiseEval(...) METALANG99_call(METALANG99_parenthesiseEval, __VA_ARGS__)
99 * Parenthesises a sequence of arguments.
104 * #include <metalang99/aux.h>
107 * M_parenthesise(v(1, 2, 3))
110 #define METALANG99_parenthesise(...) METALANG99_call(METALANG99_parenthesise, __VA_ARGS__)
113 * Unparenthesises a sequence of arguments and evaluates the result.
115 * If @p x begins with an opening parenthesis, it must also end with a closing parenthesis, e.g. `()
116 * 123` is disallowed.
121 * #include <metalang99/aux.h>
124 * M_unparenthesiseEval(v((v(1, 2, 3))))
127 #define METALANG99_unparenthesiseEval(x) METALANG99_call(METALANG99_unparenthesiseEval, x)
130 * Unparenthesises a sequence of arguments, leaving the result unevaluated.
132 * If @p x begins with an opening parenthesis, it must also end with a closing parenthesis, e.g. `()
133 * 123` is disallowed.
138 * #include <metalang99/aux.h>
141 * M_unparenthesise(v((1, 2, 3)))
144 #define METALANG99_unparenthesise(x) METALANG99_call(METALANG99_unparenthesise, x)
147 * Tests whether @p x is inside parentheses or not.
149 * If @p x begins with an opening parenthesis, it must also end with a closing parenthesis, e.g. `()
150 * 123` is disallowed.
155 * #include <metalang99/aux.h>
158 * M_isParenthesised(v(123))
161 * M_isParenthesised(v((123)))
164 #define METALANG99_isParenthesised(x) METALANG99_call(METALANG99_isParenthesised, x)
167 * The inverse of #METALANG99_isParenthesised.
169 * If @p x begins with an opening parenthesis, it must also end with a closing parenthesis, e.g. `()
170 * 123` is disallowed.
175 * #include <metalang99/aux.h>
178 * M_isUnparenthesised(v(123))
181 * M_isUnparenthesised(v((123)))
184 #define METALANG99_isUnparenthesised(x) METALANG99_call(METALANG99_isUnparenthesised, x)
187 * Evaluates to @p x, skipping @p a.
192 * #include <metalang99/aux.h>
195 * M_const(v(123), v(5))
198 #define METALANG99_const(x, a) METALANG99_call(METALANG99_const, x a)
201 * Evaluates to @p x, skipping @p a, and @p b.
206 * #include <metalang99/aux.h>
209 * M_const2(v(123), v(5), v(6))
212 #define METALANG99_const2(x, a, b) METALANG99_call(METALANG99_const2, x a b)
215 * Evaluates to @p x, skipping @p a, @p b, and @p c.
220 * #include <metalang99/aux.h>
223 * M_const3(v(123), v(5), v(6), v(7))
226 #define METALANG99_const3(x, a, b, c) METALANG99_call(METALANG99_const3, x a b c)
229 * Reverses the order of arguments of the binary function @p f.
234 * #include <metalang99/aux.h>
237 * M_appl2(M_flip(v(M_catUnevaluated)), v(123), v(ABC))
240 #define METALANG99_flip(f) METALANG99_call(METALANG99_flip, f)
243 * Puts @p x before @p right.
248 * #include <metalang99/aux.h>
251 * M_putBefore(v(0), v(!))
254 #define METALANG99_putBefore(right, x) METALANG99_call(METALANG99_putBefore, right x)
257 * Puts @p x after @p left.
262 * #include <metalang99/aux.h>
265 * M_putAfter(v(!), v(0))
268 #define METALANG99_putAfter(left, x) METALANG99_call(METALANG99_putAfter, left x)
271 * Puts @p x between @p left and @p right.
276 * #include <metalang99/aux.h>
279 * M_putBetween(v(16), v(9), v(+))
282 #define METALANG99_putBetween(left, right, x) METALANG99_call(METALANG99_putBetween, left right x)
285 * Consumes all its arguments and expands to emptiness.
290 * #include <metalang99/aux.h>
293 * M_consume(v(1, 2, 3))
296 #define METALANG99_consume(...) METALANG99_call(METALANG99_consume, __VA_ARGS__)
299 * Puts provided arguments into braces.
301 * Some code formatters behave strangely when encounter braces in macros (in different places) --
302 * this is why this macro exists.
307 * #include <metalang99/aux.h>
309 * // { int a, b, c; }
310 * M_braced(v(int a, b, c;))
313 #define METALANG99_braced(...) METALANG99_call(METALANG99_braced, __VA_ARGS__)
316 * Concatenates @p x with @p y as-is, without expanding them.
321 * #include <metalang99/aux.h>
323 * // This macro will not be expanded.
327 * M_catPrimitive(ABC, 123)
330 * @note This macro does not expand to an Metalang99 term: it is rather an ordinary preprocessor
333 #define METALANG99_catPrimitive(x, y) x##y
336 * Stringifies @p x as-is, without expanding it.
341 * #include <metalang99/aux.h>
343 * // This macro will not be expanded.
347 * M_stringifyPrimitive(ABC)
350 * @note This macro does not expand to an Metalang99 term: it is rather an ordinary preprocessor
353 #define METALANG99_stringifyPrimitive(...) #__VA_ARGS__
356 * Forces to put a semicolon after itself.
361 * #include <metalang99/aux.h>
366 * This macro is often useful when you want a user to put a semicolon after invocation of your
370 * #include <metalang99/aux.h>
372 * #define WHEN(command, handler, ...) \
373 * if (incoming_command == command) { handler(__VA_ARGS__); } M_semicolon()
375 * WHEN(SomeCommand, handler, 1, 2, 3);
378 * @note This macro does not expand to an Metalang99 term: it is rather an ordinary preprocessor
380 * @note This macro can be used both inside and outside of function bodies, in contrast to the `do {
381 * ... } while(0)` idiom. Technically, this macro just expands to an unused static variable
384 #define METALANG99_semicolon() \
385 static const char METALANG99_PRIV_CAT(metalang99_semicolon_, __LINE__) \
386 METALANG99_PRIV_COMPILER_ATTR_UNUSED
389 * The plain version of #METALANG99_cat.
391 #define METALANG99_catPlain(x, y) METALANG99_catPrimitive(x, y)
394 * The plain version of #METALANG99_stringify.
396 #define METALANG99_stringifyPlain(...) METALANG99_stringifyPrimitive(__VA_ARGS__)
399 * The plain version of #METALANG99_empty.
401 #define METALANG99_emptyPlain()
404 * The plain version of #METALANG99_id.
406 #define METALANG99_idPlain(...) __VA_ARGS__
409 * The plain version of #METALANG99_parenthesise.
411 #define METALANG99_parenthesisePlain(...) (__VA_ARGS__)
414 * The plain version of #METALANG99_unparenthesise.
416 #define METALANG99_unparenthesisePlain(x) METALANG99_PRIV_UNPARENTHESISE(x)
419 * The plain version of #METALANG99_isParenthesised.
421 #define METALANG99_isParenthesisedPlain(x) METALANG99_PRIV_IS_PARENTHESISED(x)
424 * The plain version of #METALANG99_isUnparenthesised.
426 #define METALANG99_isUnparenthesisedPlain(x) METALANG99_PRIV_IS_UNPARENTHESISED(x)
429 * The plain version of #METALANG99_consume.
431 #define METALANG99_consumePlain(...)
434 #ifndef DOXYGEN_IGNORE
437 #define METALANG99_catEval_IMPL(x, y) x##y
438 #define METALANG99_cat_IMPL(x, y) v(METALANG99_catPlain(x, y))
439 #define METALANG99_stringify_IMPL(...) v(METALANG99_stringifyPlain(__VA_ARGS__))
440 #define METALANG99_empty_IMPL() v(METALANG99_emptyPlain())
441 #define METALANG99_id_IMPL(...) v(METALANG99_idPlain(__VA_ARGS__))
442 #define METALANG99_parenthesiseEval_IMPL(...) v((v(__VA_ARGS__)))
443 #define METALANG99_parenthesise_IMPL(...) v(METALANG99_parenthesisePlain(__VA_ARGS__))
444 #define METALANG99_unparenthesiseEval_IMPL(x) METALANG99_PRIV_UNPARENTHESISE(x)
445 #define METALANG99_unparenthesise_IMPL(x) v(METALANG99_unparenthesisePlain(x))
446 #define METALANG99_isParenthesised_IMPL(x) v(METALANG99_isParenthesisedPlain(x))
447 #define METALANG99_isUnparenthesised_IMPL(x) v(METALANG99_isUnparenthesisedPlain(x))
448 #define METALANG99_const_IMPL(x, _a) v(x)
449 #define METALANG99_const2_IMPL(x, _a, _b) v(x)
450 #define METALANG99_const3_IMPL(x, _a, _b, _c) v(x)
451 #define METALANG99_flip_IMPL(f) METALANG99_callTrivial(METALANG99_appl, METALANG99_PRIV_flip, f)
452 #define METALANG99_PRIV_flip_IMPL(f, a, b) METALANG99_callTrivial(METALANG99_appl2, f, b, a)
453 #define METALANG99_putBefore_IMPL(right, x) v(x right)
454 #define METALANG99_putAfter_IMPL(left, x) v(left x)
455 #define METALANG99_putBetween_IMPL(left, right, x) v(left x right)
456 #define METALANG99_consume_IMPL(...) v(METALANG99_consumePlain(__VA_ARGS__))
457 #define METALANG99_braced_IMPL(...) v({__VA_ARGS__})
460 // Arity specifiers {
461 #define METALANG99_catEval_ARITY 2
462 #define METALANG99_cat_ARITY 2
463 #define METALANG99_stringify_ARITY 1
464 #define METALANG99_empty_ARITY 1
465 #define METALANG99_id_ARITY 1
466 #define METALANG99_parenthesise_ARITY 1
467 #define METALANG99_unparenthesise_ARITY 1
468 #define METALANG99_unparenthesiseEval_ARITY 1
469 #define METALANG99_parenthesiseEval_ARITY 1
470 #define METALANG99_isUnparenthesised_ARITY 1
471 #define METALANG99_isParenthesised_ARITY 1
472 #define METALANG99_const_ARITY 2
473 #define METALANG99_const2_ARITY 3
474 #define METALANG99_const3_ARITY 4
475 #define METALANG99_flip_ARITY 1
476 #define METALANG99_putBefore_ARITY 2
477 #define METALANG99_putAfter_ARITY 2
478 #define METALANG99_putBetween_ARITY 3
479 #define METALANG99_consume_ARITY 1
480 #define METALANG99_braced_ARITY 1
482 #define METALANG99_PRIV_flip_ARITY 3
486 #ifndef METALANG99_NO_SMALL_PREFIX
488 #define M_catEval METALANG99_catEval
489 #define M_cat METALANG99_cat
490 #define M_stringify METALANG99_stringify
491 #define M_empty METALANG99_empty
492 #define M_id METALANG99_id
493 #define M_parenthesiseEval METALANG99_parenthesiseEval
494 #define M_parenthesise METALANG99_parenthesise
495 #define M_unparenthesiseEval METALANG99_unparenthesiseEval
496 #define M_unparenthesise METALANG99_unparenthesise
497 #define M_isParenthesised METALANG99_isParenthesised
498 #define M_isUnparenthesised METALANG99_isUnparenthesised
499 #define M_const METALANG99_const
500 #define M_const2 METALANG99_const2
501 #define M_const3 METALANG99_const3
502 #define M_flip METALANG99_flip
503 #define M_putBefore METALANG99_putBefore
504 #define M_putAfter METALANG99_putAfter
505 #define M_putBetween METALANG99_putBetween
506 #define M_consume METALANG99_consume
507 #define M_braced METALANG99_braced
508 #define M_catPrimitive METALANG99_catPrimitive
509 #define M_stringifyPrimitive METALANG99_stringifyPrimitive
510 #define M_semicolon METALANG99_semicolon
512 #define M_catPlain METALANG99_catPlain
513 #define M_stringifyPlain METALANG99_stringifyPlain
514 #define M_emptyPlain METALANG99_emptyPlain
515 #define M_idPlain METALANG99_idPlain
516 #define M_parenthesisePlain METALANG99_parenthesisePlain
517 #define M_unparenthesisePlain METALANG99_unparenthesisePlain
518 #define M_isParenthesisedPlain METALANG99_isParenthesisedPlain
519 #define M_isUnparenthesisedPlain METALANG99_isUnparenthesisedPlain
520 #define M_consumePlain METALANG99_consumePlain
522 #endif // METALANG99_NO_SMALL_PREFIX
525 #endif // DOXYGEN_IGNORE
527 #endif // METALANG99_AUX_H