007/include/CPPLib.h

737 lines
22 KiB
C

/**
* 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