Add support for global oplist.

Global oplists are global macro defined as M_OPL_##type

Add support of global oplist for macro M_EACH & M_LET.
Partial fix #9
This commit is contained in:
Patrick Pelissier committed 2017-09-10 10:04:39 +02:00
1 parent fc7b1516e2
commit d7c4ca1de5
3 files changed
+71 -21

No files matched your search

+6 -3
View File
@@ -2,11 +2,14 @@
// Let's define an array of 'char *' named 'charp'
ARRAY_DEF (array_charp, char *)
// Let's register globaly the oplist of array_charp
#define M_OPL_array_charp_t() ARRAY_OPLIST(array_charp)
int main(void)
{
// Create an array list 'al'
M_LET (al, ARRAY_OPLIST(array_charp)) {
// Create an array list 'al' of type array_charp_t
M_LET (al, array_charp_t) {
// add elements to the array list
array_charp_push_back (al,"C");
array_charp_push_back (al,"A");
@@ -18,7 +21,7 @@ int main(void)
// Display contents of al
printf("Original contents of al: ");
// For each element of the array al
for M_EACH(element, al, ARRAY_OPLIST(array_charp)) {
for M_EACH(element, al, array_charp_t) {
printf ("%s ", *element);
}
printf("\n");
+58 -17
View File
@@ -67,7 +67,9 @@
/***************************************************************/
/* Maximum number of argument which can be handled by this header.
Can be increased for future release of this header. */
Can be increased for future release of this header.
Some macros have been port to a maximum of 52, but not all.
*/
#define M_MAX_NB_ARGUMENT 26
/* Basic handling of concatenation of symbols:
@@ -151,6 +153,7 @@
M_RET_ARG2
M_RET_ARG3
M_RET_ARG27
M_RET_ARG53
*/
#define M_RETI_ARG1(a, ...) a
#define M_RET_ARG1(...) M_RETI_ARG1(__VA_ARGS__)
@@ -164,6 +167,8 @@
#define M_RETI_ARG27(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, ...) aa
#define M_RET_ARG27(...) M_RETI_ARG27(__VA_ARGS__)
#define M_RETI_ARG53(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,ag,ah,ai,aj,ak,al,am,an,ao,ap,aq,ar,as,at,au,av,aw,ax,ay,az, ba, ...) ba
#define M_RET_ARG53(...) M_RETI_ARG53(__VA_ARGS__)
/* Convert an integer or a symbol into 0 (if 0) or 1 (if not 0).
1 if symbol unknown */
@@ -197,7 +202,7 @@
#define M_IF(c) M_C(M_IFI_, M_BOOL(c))
/* Return 1 if there is a comma inside the argument list, 0 otherwise */
#define M_COMMA_P(...) M_RET_ARG27(__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, useless)
#define M_COMMA_P(...) M_RET_ARG53(__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, useless)
/* Return the string representation of the evaluated x.
NOTE: Need to be used with M_APPLY to defer the evaluation */
@@ -399,7 +404,9 @@
/* M_NARGS: Return number of argument.
(don't work for empty arg) */
#define M_NARGS(...) \
M_RET_ARG27(__VA_ARGS__, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, \
M_RET_ARG53(__VA_ARGS__, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, \
41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, \
26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, \
15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, useless)
/* If the number of arguments is 1 */
@@ -1045,28 +1052,55 @@ m_core_hash (const void *str, size_t length)
} while (0)
/* Test if the argument is a valid oplist.
NOTE: Incomplete test.
NOTE: Imperfect test.
*/
#define M_OPLIST_P(a) \
M_AND(M_AND(M_PARENTHESIS_P(a), M_INV(M_PARENTHESIS_P (M_OPFLAT a))), \
M_EMPTY_P(M_EAT a))
/* Check if a is an oplist, and return a
or if a symbol composed of M_OPL_##a() is defined as an oplist, and returns it
otherwise return a.
In short, if a global oplist is defined for the argument, it returns it
otherwise it returns the argument.
Global oplist is limited to typedef types.
*/
#define M_GLOBAL_OPLIST(a) \
M_IF( M_OPLIST_P(a))(a, M_GLOBALI_OPLIST_ELSE(a))
#define M_GLOBALI_OPLIST_ELSE(a) M_GLOBALI_OPLIST_ELSE2(a, M_C(M_OPL_, a)())
#define M_GLOBALI_OPLIST_ELSE2(a, op) M_IF( M_OPLIST_P (op))(op, a)
/* Check if a a symbol composed of M_OPL_##a() is defined as an oplist, and returns it
otherwise return M_DEFAULT_OPLIST.
In short, if a global oplist is defined for the argument, it returns it
otherwise it returns the argument.
Global oplist is limited to typedef types.
*/
#define M_GLOBAL_OPLIST_OR_DEF(a) \
M_IF( M_PARENTHESIS_P(a))(M_DEFAULT_OPLIST, M_GLOBAL_OPLIST_OR_DEF_ELSE(a))
#define M_GLOBAL_OPLIST_OR_DEF_ELSE(a) M_GLOBAL_OPLIST_OR_DEF_ELSE2(M_C(M_OPL_, a)())
#define M_GLOBAL_OPLIST_OR_DEF_ELSE2(op) M_IF( M_OPLIST_P(op))(op, M_DEFAULT_OPLIST))
/************************************************************/
/******************** Syntax Enhancing **********************/
/************************************************************/
/* Define M_EACH macro allowing to iterate over a container
First argument will be a created pointer to the underlying type.
Example: for M_EACH(item, list, LIST_OPLIST) { action; } */
Third argument can be the oplist of the list or the type of the list if a global
oplist has been recorded.
Example: for M_EACH(item, list, LIST_OPLIST) { action; }
*/
#define M_EACH(item, container, oplist) \
M_IF_METHOD(IT_REF, oplist)( \
M_EACHI(item, container, oplist, \
M_C(local_iterator_, __LINE__), \
M_C(local_cont_, __LINE__)), \
M_EACHI2(item, container, oplist, \
M_C(local_iterator_, __LINE__), \
M_C(local_cont_, __LINE__)) )
M_EACHI_OPLIST(item, container, M_GLOBAL_OPLIST(oplist))
#define M_EACHI_OPLIST(item, container, oplist) \
M_IF_METHOD(IT_REF, oplist)(M_EACHI, M_EACHI_CONST) \
(item, container, oplist, M_C(local_iterator_, __LINE__), \
M_C(local_cont_, __LINE__))
/* Internal for M_EACH with M_GET_IT_REF operator */
#define M_EACHI(item,container,oplist, iterator, cont) \
@@ -1074,16 +1108,18 @@ m_core_hash (const void *str, size_t length)
for(M_GET_SUBTYPE oplist *item; cont ; cont = false) \
for(M_GET_IT_TYPE oplist iterator; cont ; cont = false) \
for(M_GET_IT_FIRST oplist (iterator, container) ; \
!M_GET_IT_END_P oplist (iterator) && (item = M_GET_IT_REF oplist (iterator), true) ; \
!M_GET_IT_END_P oplist (iterator) \
&& (item = M_GET_IT_REF oplist (iterator), true) ; \
M_GET_IT_NEXT oplist (iterator))
/* Internal for M_EACH with M_GET_IT_CREF operator */
#define M_EACHI2(item,container,oplist, iterator, cont) \
#define M_EACHI_CONST(item,container,oplist, iterator, cont) \
(bool cont = true; cont; cont = false) \
for(const M_GET_SUBTYPE oplist *item; cont ; cont = false) \
for(M_GET_IT_TYPE oplist iterator; cont ; cont = false) \
for(M_GET_IT_FIRST oplist (iterator, container) ; \
!M_GET_IT_END_P oplist (iterator) && (item = M_GET_IT_CREF oplist (iterator), true) ; \
!M_GET_IT_END_P oplist (iterator) \
&& (item = M_GET_IT_CREF oplist (iterator), true) ; \
M_GET_IT_NEXT oplist (iterator))
@@ -1094,11 +1130,16 @@ m_core_hash (const void *str, size_t length)
M_LET(a, b, c, STRING_OPLIST) { do something with a, b & c }
NOTE: The user code can not perform a return or a goto within the {}
other wise the clear code of the object won't be called .
Last argument can be the oplist or the type itself if a global
oplist has been recorded for this type.
*/
#define M_LET(...) \
M_ID(M_LETI M_INVERT( __VA_ARGS__, M_C(local_cont_, __LINE__) ))
M_ID(M_LETI1 M_INVERT( __VA_ARGS__, M_C(local_cont_, __LINE__) ))
#define M_LETI(cont, oplist, ...) \
#define M_LETI1(cont, oplist, ...) \
M_LETI2(cont, M_GLOBAL_OPLIST(oplist), __VA_ARGS__)
#define M_LETI2(cont, oplist, ...) \
for(bool cont = true; cont ; /* unused */) \
M_MAP2(M_LETI_SINGLE, (cont, oplist,), __VA_ARGS__)
+7 -1
View File
@@ -230,17 +230,23 @@ static void test_oplist(void)
assert (M_OPLIST_P(()));
assert (M_OPLIST_P((INIT(init))));
assert (M_OPLIST_P((INIT(init),CLEAR(clear))));
assert (M_OPLIST_P((INIT(init),CLEAR(clear),)));
assert (!M_OPLIST_P());
assert (!M_OPLIST_P((())));
assert (!M_OPLIST_P(INIT(init)));
assert (!M_OPLIST_P((INIT(init)) a));
assert (!M_OPLIST_P(f(INIT(init)) a));
assert (!M_OPLIST_P(func(INIT(init)) a));
assert (!M_OPLIST_P(func(INIT(init),) a));
#define a (INIT(0), CLEAR(clear))
assert (M_TEST_DISABLED_METHOD_P(INIT, a));
assert (!M_TEST_DISABLED_METHOD_P(INIT2, a));
assert (!M_TEST_DISABLED_METHOD_P(CLEAR, a));
assert (!M_TEST_DISABLED_METHOD_P(INIT, ()));
#define M_OPL_op() (INIT(1), CLEAR(0))
assert(M_GET_INIT M_GLOBAL_OPLIST(op));
assert(!M_GET_INIT M_GLOBAL_OPLIST(a));
}
static void test_cast(void)