/** * This header file contains a library of advanced C Pre-Processor (CPP) macros * which implement various useful functions, such as iteration, in the * pre-processor. */ #ifndef CPPLIB_H #define CPPLIB_H /*#define EXPAND_EXAMPLES */ /** * Macros which expand to common values */ #define EMPTY() #define COMMA() , #define COMMA_IF(cond) COMMA_IF_I(cond) #define COMMA_IF_I(cond) IF_ELSE(cond)(COMMA)(EMPTY)() #define LPAREN() ( #define RPAREN() ) #define PLUS() + #define ZERO() 0 #define ONE() 1 #define STR(n) #n #ifdef __sgi # define EXPAND(a) a # define EAT(x) #else # define EXPAND(...) __VA_ARGS__ # define EAT(x, ...) __VA_ARGS__ #endif /** * Force the pre-processor to expand the macro a large number of times. Usage: * * EVAL(expression) * * This is useful when you have a macro which evaluates to a valid macro * expression which is not subsequently expanded in the same pass. A contrived, * but easy to understand, example of such a macro follows. Note that though * this example is contrived, this behaviour is abused to implement bounded * recursion in macros such as FOR. * * #define A(x) x+1 * #define EMPTY * #define NOT_QUITE_RIGHT(x) A EMPTY (x) * NOT_QUITE_RIGHT(999) * * Here's what happens inside the C preprocessor: * * 1. It sees a macro "NOT_QUITE_RIGHT" and performs a single macro expansion * pass on its arguments. Since the argument is "999" and this isn't a macro, * this is a boring step resulting in no change. * 2. The NOT_QUITE_RIGHT macro is substituted for its definition giving "A * EMPTY() (x)". * 3. The expander moves from left-to-right trying to expand the macro: * The first token, A, cannot be expanded since there are no brackets * immediately following it. The second token EMPTY(), however, can be * expanded (recursively in this manner) and is replaced with "". * 4. Expansion continues from the start of the substituted test (which in this * case is just empty), and sees "(999)" but since no macro name is present, * nothing is done. This results in a final expansion of "A (999)". * * Unfortunately, this doesn't quite meet expectations since you may expect that * "A (999)" would have been expanded into "999+1". Unfortunately this requires * a second expansion pass but luckily we can force the macro processor to make * more passes by abusing the first step of macro expansion: the preprocessor * expands arguments in their own pass. If we define a macro which does nothing * except produce its arguments e.g.: * * #define PASS_THROUGH(...) __VA_ARGS__ * * We can now do "PASS_THROUGH(NOT_QUITE_RIGHT(999))" causing "NOT_QUITE_RIGHT" * to be expanded to "A (999)", as described above, when the arguments are * expanded. Now when the body of PASS_THROUGH is expanded, "A (999)" gets * expanded to "999+1". * * The EVAL defined below is essentially equivalent to a large nesting of * "PASS_THROUGH(PASS_THROUGH(PASS_THROUGH(..." which results in the * preprocessor making a large number of expansion passes over the given * expression. */ #define EVAL(a) EVAL512(EVAL256(EVAL128(EVAL64(EVAL32(EVAL16(EVAL8(EVAL4(EVAL2(EVAL1(a)))))))))) #define EVAL512(a) EVAL256(EVAL128(EVAL64(EVAL32(EVAL16(EVAL8(EVAL4(EVAL2(EVAL1(a))))))))) #define EVAL256(a) EVAL128(EVAL64(EVAL32(EVAL16(EVAL8(EVAL4(EVAL2(EVAL1(a)))))))) #define EVAL128(a) EVAL64(EVAL32(EVAL16(EVAL8(EVAL4(EVAL2(EVAL1(a))))))) #define EVAL64(a) EVAL32(EVAL16(EVAL8(EVAL4(EVAL2(EVAL1(a)))))) #define EVAL32(a) EVAL16(EVAL8(EVAL4(EVAL2(EVAL1(a))))) #define EVAL16(a) EVAL8(EVAL4(EVAL2(EVAL1(a)))) #define EVAL8(a) EVAL4(EVAL2(EVAL1(a))) #define EVAL4(a) EVAL2(EVAL1(a)) #define EVAL2(a) EVAL1(a) #ifdef __sgi # define EVAL1(VA) IF_VA(EXPAND(DEFER(IS_PAREN)(VA)))(DEFER(EXPAND_ARGS_STACK)) VA #else # define EVAL1(...) __VA_ARGS__ #endif /** * Causes a function-style macro to require an additional pass to be expanded. * This is useful, for example, when trying to implement recursion since the * recursive step must not be expanded in a single pass as the pre-processor * will catch it and prevent it. * * Usage: * * DEFER(IN_NEXT_PASS)(args, to, the, macro) * * Blocking a Second time can be done with DEFER2 * * Usage: * * DEFER2(IN_NEXT_NEXT_PASS)(args, to, the, macro) */ /** * As with DEFER1 except here n additional passes are required for DEFERn. * * The mechanism is analogous. */ #define DEFERA1024(a) DEFERA512(DEFERA512(a)) #define DEFERA512(a) DEFERA256(DEFERA256(a)) #define DEFERA256(a) DEFERA128(DEFERA128(a)) #define DEFERA128(a) DEFERA64(DEFERA64(a)) #define DEFERA64(a) DEFERA32(DEFERA32(a)) #define DEFERA32(a) DEFERA16(DEFERA16(a)) #define DEFERA16(a) DEFERA8(DEFERA8(a)) #define DEFERA8(a) DEFERA4(DEFERA4(a)) #define DEFERA4(a) DEFERA2(DEFERA2(a)) #define DEFERA2(a) DEFERA1(DEFERA1(a)) #define DEFERA1(a) EMPTY a #define DEFERB1024(a) DEFERB512(DEFERB512(a)) #define DEFERB512(a) DEFERB256(DEFERB256(a)) #define DEFERB256(a) DEFERB128(DEFERB128(a)) #define DEFERB128(a) DEFERB64(DEFERB64(a)) #define DEFERB64(a) DEFERB32(DEFERB32(a)) #define DEFERB32(a) DEFERB16(DEFERB16(a)) #define DEFERB16(a) DEFERB8(DEFERB8(a)) #define DEFERB8(a) DEFERB4(DEFERB4(a)) #define DEFERB4(a) DEFERB2(DEFERB2(a)) #define DEFERB2(a) DEFERB1(DEFERB1(a)) #define DEFERB1(a) () a #define DEFER1024(id) id DEFERA1024() DEFERB1024() #define DEFER512(id) id DEFERA512() DEFERB512() #define DEFER256(id) id DEFERA256() DEFERB256() #define DEFER128(id) id DEFERA128() DEFERB128() #define DEFER64(id) id DEFERA64() DEFERB64() #define DEFER32(id) id DEFERA32() DEFERB32() #define DEFER16(id) id DEFERA16() DEFERB16() #define DEFER8(id) id DEFERA8() DEFERB8() #define DEFER4(id) id DEFERA4() DEFERB4() #define DEFER3(id) id DEFERA1() DEFERA2() DEFERB2() DEFERB1() #define DEFER2(id) id DEFERA2() DEFERB2() #define DEFER1(id) id DEFERA1() DEFERB1() #define DEFER(id) id DEFERA1() DEFERB1() #define INC(x) CAT(INC_, x) #define INC_0 1 #define INC_1 2 #define INC_2 3 #define INC_3 4 #define INC_4 5 #define INC_5 6 #define INC_6 7 #define INC_7 8 #define INC_8 9 #define INC_9 0 #define DEC(x) CAT(DEC_, x) #define DEC_0 (1/0) #define DEC_1 0 #define DEC_2 1 #define DEC_3 2 #define DEC_4 3 #define DEC_5 4 #define DEC_6 5 #define DEC_7 6 #define DEC_8 7 #define DEC_9 8 /** * Indirection around the standard ## concatenation operator. This simply * ensures that the arguments are expanded (once) before concatenation. * @param a, b * @return Concantinated Token */ #define CAT(a, b) PRIMITIVECAT(a, b) #define PRIMITIVECAT(a, b) a##b #ifdef __sgi /** * Get the first argument and ignore the rest. */ #define FIRST_PRE_VA(a) a #else /** * Get the first argument and ignore the rest. */ # define FIRST_PRE_VA(a,...) a #endif #ifdef __sgi /** * Get the second argument and ignore the rest. */ # define SECOND_PRE_VA(a, b) b #else /** * Get the second argument and ignore the rest. */ # define SECOND_PRE_VA(a, b,...) b #endif /** * Expects a single input (not containing commas). Returns 1 if the input is * PROBE() and otherwise returns 0. * * This can be useful as the basis of a NOT function. * * This macro abuses the fact that PROBE() contains a comma while other valid * inputs must not. */ #ifdef __sgi # define IS_PROBE(a) SECOND_PRE_VA(a, 0) # define PROBE() ~, 1 #else # define IS_PROBE(...) SECOND_PRE_VA(__VA_ARGS__,0) # define PROBE(...) ~, 1, __VA_ARGS__ #endif /** * Detect Parenthesis * @return TRUE/FALSE */ #ifdef __sgi # define IS_PAREN(x) IS_PROBE(IS_PAREN_PROBE x) # define IS_PAREN_PROBE(A) PROBE(~) #else # define IS_PAREN(...) IS_PROBE(IS_PAREN_PROBE __VA_ARGS__) # define IS_PAREN_PROBE(...) PROBE(~) __VA_ARGS__ #endif #ifdef EXPAND_EXAMPLES //IS PAREN IS_PAREN((S)) // IS...((s)) Expands to 1 IS_PAREN(xxx) // IS...(xxx) Expands to 0 #endif /** * Detects if arg or macro is defined as nothing. */ #define IS_EMPTY(x) _IS_EMPTY(x) #define _IS_EMPTY(x) IS_PROBE(CAT(_IS_EMPTY, _##x##_)) #define _IS_EMPTY__ PROBE(~) /*NULL*/ /** * Detects if arg or macro is a Bool (1 or 0). * Use _IS_BOOL to prevent first expansion (TRUE/FALSE macro) * @return TRUE/FALSE */ #define IS_BOOL(x) _IS_BOOL(x) #define _IS_BOOL(x) IS_PROBE(CAT(_IS_BOOL, _##x##_)) #define _IS_BOOL_TRUE_ PROBE(~) #define _IS_BOOL_FALSE_ PROBE(~) #define _IS_BOOL_1_ PROBE(~) #define _IS_BOOL_0_ PROBE(~) /** * Macro version of "defined" however its limited to 1/0/nothing. Any other value * is indistuiguishable from a random name * Certain pre-defined definitions can be "NOTDEFINED" eg THIS. * so checking IF(DEFINED(THIS)) is asking if THIS is NOT defined * @return TRUE/FALSE */ #define DEFINED(x) _DEFINED(x) #define _DEFINED(x) IS_PROBE(CAT(_DEFINED, _##x##_)) #define _DEFINED_0_ PROBE(~) #define _DEFINED_1_ PROBE(~) #define _DEFINED__ PROBE(~) /*The following names are NOT defined and need to be regarded as NOTDEFINED */ #define _DEFINED_THIS_ PROBE(~) #define _DEFINED_SETUPSUBROUTINES(ID) PROBE(~), /** * Logical negation. 0 or nothing is defined as false and everything else as * true. * * When 0, _NOT_0 will be found which evaluates to the PROBE. When 1 (or any * other value) is given, an appropriately named macro won't be found and the * concatenated string will be produced. IS_PROBE then simply checks to see if * the PROBE was returned, cleanly converting the argument into a 1 or 0. * @return TRUE/FALSE */ #define NOT(x) _NOT(x) #define _NOT(x) IS_PROBE(CAT(_NOT, _##x##_)) #define _NOT_0_ PROBE(~) #define _NOT__ PROBE(~) /*NULL*/ #ifdef EXPAND_EXAMPLES //NOT NOT(1) // not 1 NOT(0) // not 0 NOT() // not NOT(NOT(IS_PAREN(()))) // not !1 NOT(NOT(0)) // not !0 NOT(NOT()) // not ! #endif /** * Macro version of C's famous "cast to bool" operator (i.e. !!) which takes * anything and casts it to 0 if it is 0 and 1 otherwise. * @return TRUE/FALSE */ #define BOOL(x) NOT(NOT(x)) /* this little anoying block may look out of place, but it needs to be right here */ /** If Statement (Non-Expanding) @param c: If True, output the contents of parenthises else output nothing. */ #define IF_VA(c) _IF_VA(BOOL(c)) #define _IF_VA(c) CAT(_IF_VA_, c) #define _IF_VA_1(a) a #define _IF_VA_0(a) /** * _VA_ARGS_ for c89 * Allows up to 32 Args on the stack */ #define EXPAND_ARGS_STACK(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,AA,AB,AC,AD,AE,AF,ERROR) \ IF_VA(NOT(IS_EMPTY(A)))/* */(/* */A /* */IF_VA(NOT(IS_EMPTY(B)))/* */(/* */COMMA() B /* */IF_VA(NOT(IS_EMPTY(C)))/* */(/* */COMMA() C /* */IF_VA(NOT(IS_EMPTY(D)))/* */(/* */COMMA() D /* */IF_VA(NOT(IS_EMPTY(E)))/* */(/* */COMMA() E/* */IF_VA(NOT(IS_EMPTY(F)))/* */(/* */COMMA() F /* */IF_VA(NOT(IS_EMPTY(G)))/* */(/* */COMMA() G /* */IF_VA(NOT(IS_EMPTY(H)))/* */(/* */COMMA() H /* */IF_VA(NOT(IS_EMPTY(I)))/* */(/* */COMMA() I /* */IF_VA(NOT(IS_EMPTY(J)))/* */(/* */COMMA() J /* */IF_VA(NOT(IS_EMPTY(K)))/* */(/* */COMMA() K /* */IF_VA(NOT(IS_EMPTY(L)))/* */(/* */COMMA() L /* */IF_VA(NOT(IS_EMPTY(M)))/* */(/* */COMMA() M /* */IF_VA(NOT(IS_EMPTY(N)))/* */(/* */COMMA() N /* */IF_VA(NOT(IS_EMPTY(O)))/* */(/* */COMMA() O /* */IF_VA(NOT(IS_EMPTY(P)))/* */(/* */COMMA() P /* */IF_VA(NOT(IS_EMPTY(Q)))/* */(/* */COMMA() Q /* */IF_VA(NOT(IS_EMPTY(R)))/* */(/* */COMMA() R /* */IF_VA(NOT(IS_EMPTY(S)))/* */(/* */COMMA() S /* */IF_VA(NOT(IS_EMPTY(T)))/* */(/* */COMMA() T /* */IF_VA(NOT(IS_EMPTY(U)))/* */(/* */COMMA() U /* */IF_VA(NOT(IS_EMPTY(V)))/* */(/* */COMMA() V /* */IF_VA(NOT(IS_EMPTY(W)))/* */(/* */COMMA() W /* */IF_VA(NOT(IS_EMPTY(X)))/* */(/* */COMMA() X /* */IF_VA(NOT(IS_EMPTY(Y)))/* */(/* */COMMA() Y /* */IF_VA(NOT(IS_EMPTY(Z)))/* */(/* */COMMA() Z /* */IF_VA(NOT(IS_EMPTY(AA)))/* */(/* */COMMA() AA /* */IF_VA(NOT(IS_EMPTY(AB)))/* */(/* */COMMA() AB /* */IF_VA(NOT(IS_EMPTY(AC)))/* */(/* */COMMA() AC /* */IF_VA(NOT(IS_EMPTY(AD)))/* */(/* */COMMA() AD /* */IF_VA(NOT(IS_EMPTY(AE)))/* */(/* */COMMA() AE /* */IF_VA(NOT(IS_EMPTY(AF)))/* */(/* */COMMA() AF /* */IF_VA(NOT(IS_EMPTY(ERROR)))/* */(/* */COMMA() undefinedlocal = 1/0 "_VA_ARGS Stack full"/* */)/* */) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) /** * Push/Pop VA Args arrays */ #ifdef __sgi # define POP_ARG(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,AA,AB,AC,AD,AE,AF) /* */(IF_VA(IS_PAREN(A))(_POP_ARG A) /* ELSE*/IF_VA(NOT(IS_PAREN(A)))(EXPAND_ARGS_STACK(B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,AA,AB,AC,AD,AE,AF))) # define _POP_ARG(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, AA, AB, AC, AD, AE, AF) EXPAND_ARGS_STACK(B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, AA, AB, AC, AD, AE, AF) #else # define POP_ARG(A, ...) (IF_VA(IS_PAREN(A))(_POP_ARG A) IF_VA(NOT(IS_PAREN(A))) (_POP_ARG(A, __VA_ARGS__)) # define _POP_ARG(A, ...) __VA_ARGS__ #endif # define PUSH_ARG(A,B)(A, TRY_EXPAND(B)) /** * TRY Expand If Array */ #define TRY_EXPAND(c) _TRY_EXPAND(IS_PAREN(c))(c) #define _TRY_EXPAND(c) CAT(__TRY_EXPAND_, c) #ifdef __sgi # define __TRY_EXPAND_1(a) EXPAND_ARGS_STACK a #else # define __TRY_EXPAND_1(A) __TRY_EXPAND_11 A # define __TRY_EXPAND_11(...) __VA_ARGS__ #endif #define __TRY_EXPAND_0(a) a #ifdef __sgi /** * Get the first argument and ignore the rest. */ # define FIRST(a) EXPAND(DEFER(FIRST_PRE_VA)(TRY_EXPAND(a))) /** * Get the second argument and ignore the rest. */ # define SECOND(a, b) EXPAND(DEFER(SECOND_PRE_VA)(TRY_EXPAND(a), b)) #else /** * Get the first argument and ignore the rest. */ # define FIRST(A,...) EXPAND(DEFER(FIRST_PRE_VA)(TRY_EXPAND(a))) /** * Get the second argument and ignore the rest. */ # define SECOND(a, b,...) EXPAND(DEFER(SECOND_PRE_VA)(TRY_EXPAND(a), b)) #endif #ifdef EXPAND_EXAMPLES // POP ARG (THIS, IS, a, TEST, hy) POP_ARG(THIS, IS, a, TEST, hy) // push arg test (this, is, a, test, with, a , is, so, is, a, test, with, a , is, so, is, a, test, with, a , is, so, is, a, test, with, a , is, so) PUSH_ARG(test, (this, is, a, test, with, a2 , is2, so, is3, a3, test2, with2, a3 , is4, so4, is5, a4, test3, with3, a6 , is6, so5, is7, a7, test4, with5, a8 , is8, so8)) #endif /** * Logical OR. Simply performs a lookup. */ #define OR(a, b) CAT(CAT(_OR_, a), b) #define _OR_00 0 #define _OR_01 1 #define _OR_10 1 #define _OR_11 1 /** * Logical XOR. Simply performs a lookup. */ #define XOR(a, b) CAT(CAT(_XOR_, a), b) #define _XOR_00 0 #define _XOR_01 1 #define _XOR_10 1 #define _XOR_11 0 /** * Logical AND. Simply performs a lookup. */ #define AND_CPPLIB(a, b) CAT(CAT(_AND_CPPLIB_, a), b) #define _AND_CPPLIB_00 0 #define _AND_CPPLIB_01 0 #define _AND_CPPLIB_10 0 #define _AND_CPPLIB_11 1 /** * Macro if statement. * Usage: * IF(condition) \ * ( \ * expansion when true \ * ) * @param condition * @return TRUE/FALSE */ #define IF(c) _IF(BOOL(c)) #define _IF(c) CAT(_IF_, c) #define _IF_1(a) TRY_EXPAND(a) #define _IF_0(a) /** * Macro if/else statement. * Usage: * * IF_ELSE(condition) * (( * expansion when true * )) * (( * expansion when false * )) * @param condition * @return TRUE/FALSE */ #define IF_ELSE(c) _IF(CAT(E, BOOL(c))) #define _IF_E1(a) TRY_EXPAND(a) _IF_1_ELSE #define _IF_E0(a) _IF_0_ELSE #define _IF_1_ELSE(a) #define _IF_0_ELSE(a) TRY_EXPAND(a) #ifdef EXPAND_EXAMPLES //if else 220 IF_ELSE(220)((it was, non - zero))(it was zero) // Expands to "it was, non Zero" //if 06 IF(06)(NONZERO) #endif #if 0 /* * When */ #define WHEN(c) IF(c)(EVAL1)(EAT) #endif /** * Macro which checks if it has any arguments. Returns '0' if there are no * arguments, '1' otherwise. * Limitation: HAS_ARGS(,1,2,3) returns 0 -- this check essentially only checks * that the first argument exists. * @return TRUE/FALSE */ #ifdef __sgi # define HAS_ARGS(a) BOOL(EXPAND(_END_OF_ARGUMENTS_ FIRST(a)())) #else # define HAS_ARGS(...) BOOL(FIRST(__VA_ARGS__)) #endif #define _END_OF_ARGUMENTS_() 0 /* for_each(v.begin(), v.end(), [](int &number) { number++; }); */ /** * foreach macro * @param */ #define foreach(var, collection) for (var = *collection; var; var++) #ifdef EXPAND_EXAMPLES //do I have args? //yes HAS_ARGS(a, b, c) HAS_ARGS((a, b, c)) //no HAS_ARGS() HAS_ARGS(()) HAS_ARGS(( ())) //this one has too many parens #endif #if 0 # define test() Im expanded DEFER8(test)() EVAL1(EVAL4(DEFER4(test)())) # define RECURSE(X) FIRST X DEFER(_RECURSE)()(POP_ARG X) # define _RECURSE() RECURSE // RECURSE EVAL16(RECURSE((this, is, a, test, WITH, MANY, ARGS))) #endif #ifdef __sgi #define COUNTPARAMS(X) \ IF_ELSE(IS_PAREN(X)) /* */( /* */EVAL8(COUNTPARAMS_INNER(X, 0)) /* */) /* */( /* */0() /* */) #define COUNTPARAMS_INNER(X, COUNT) \ IF_ELSE(HAS_ARGS(X))/* */( /* */DEFER3(_COUNTPARMS)()(POP_ARG(X), INC(COUNT))/* */) /* */( /* */COUNT /* */) # define _COUNTPARMS() COUNTPARAMS_INNER #else # define ELEVENTH_ARGUMENT(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, ...) a11 # define COUNTPARAMS(...) IF_ELSE(IS_PAREN(__VA_ARGS__))(_COUNTPARAMS __VA_ARGS__)(ELEVENTH_ARGUMENT(dummy, ##__VA_ARGS__, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)) # define _COUNTPARAMS(...) ELEVENTH_ARGUMENT(dummy, ##__VA_ARGS__, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) #endif #ifdef EXPAND_EXAMPLES // COUNTPARAMS - IT WORKS!!!, THIS WILL BE GREAT FOR AI //0 COUNTPARAMS(()) //1 COUNTPARAMS((A)) // 2 COUNTPARAMS((A, B)) // 3 COUNTPARAMS((A, B, C)) // 4 COUNTPARAMS((A, B, C, D)) // 5 COUNTPARAMS((A, B, C, D, E)) // 6 COUNTPARAMS((A, B, C, D, E, F)) // 7 COUNTPARAMS((A, B, C, D, E, F, G)) // 8 COUNTPARAMS((A, B, C, D, E, F, G, H)) // 9 COUNTPARAMS((A, B, C, D, E, F, G, H, I)) #endif #if 0 #define LIST_TO_TUPLE(list) \ IF_ELSE(IS_PAREN(list))\ (\ EVAL16((LIST_TO_TUPLE_INNER(SECOND list, FIRST list)))\ )\ (\ list\ ) #define LIST_TO_TUPLE_INNER(list, listb) \ IF_ELSE(HAS_ARGS(list)) \ (\ EXPAND(DEFER4(_LIST_TO_TUPLE_INNER)()(TRY_EXPAND((POP_ARG list)), PUSH_ARG(FIRST list, listb)))\ )\ (\ 0 listb\ ) #define _LIST_TO_TUPLE_INNER() LIST_TO_TUPLE_INNER // list to tuple LIST_TO_TUPLE((this, (is, (a, (li8st, (lots, (of, (test, (another, ))))))))) //SINGLE LIST_TO_TUPLE((this,(is))) #endif #define REPEAT(count, macro, a) \ IF_ELSE(DEC(count)) \ (DEFER3(REPEAT_INDIRECT)()(DEC(count), macro, a))( \ /* Do nothing, just terminate */) DEFER(macro)(DEC(count), a) #define REPEAT_INDIRECT() REPEAT #ifdef EXPAND_EXAMPLES // An example of repeat 9 # define M(i, _) i EVAL16(REPEAT(9, M, ~)) // 0 1 2 3 4 5 6 7 8 #endif #define WHILE(pred, op, a) \ IF(pred(a)) \ (DEFER2(WHILE_INDIRECT)()(pred, op, op(a)), POP_ARG a) #define WHILE_INDIRECT() WHILE /** * Macro map/list comprehension. Usage: * * MAP(op, sep, ...) * * Produces a 'sep()'-separated list of the result of op(arg) for each arg. * * Example Usage: * * #define MAKE_HAPPY(x) happy_##x * #define COMMA() , * MAP(MAKE_HAPPY, COMMA, 1,2,3) * * Which expands to: * * happy_1 , happy_2 , happy_3 */ #define MAP(op, sep, a) \ IF_ELSE(HAS_ARGS a) \ (EVAL(MAP_INNER(op, sep, a)))(/* Do nothing, just terminate */) #define MAP_INNER(op, sep, a) \ DEFER(op) \ (FIRST a) IF_ELSE(DEFER(HAS_ARGS) POP_ARG a)(EXPAND EMSPTY()( \ sep() OBSTRUCT(_MAP_INNER)()(op, sep, EXPAND(POP_ARG a))))( \ /* Do nothing, just terminate */) #define _MAP_INNER() MAP_INNER /*MAP(MAKE_HAPPY, COMMA, (1,2,3,A))*/ #endif