Add support for given an argument for the initialization of a variable in M_LET

if the variable is within parenthesis:
 M_LET((a,b), string_t)
 ==> It will init a & set it to b.

For the moment, we can only init with value of the same type (through init_set)
This commit is contained in:
Patrick Pelissier committed 2018-08-31 00:02:03 +02:00
1 parent 7ac54c0eb8
commit dbcade3087
2 files changed
+30 -7

No files matched your search

+27 -7
View File
@@ -507,6 +507,10 @@
#define M_RETI_ARG53(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, ...) _53
#define M_RET_ARG53(...) M_RETI_ARG53(__VA_ARGS__)
/* For a pair of argument (arg0, arg1), return either the first or the second.
Needed in case where M_RET_ARGn cannot be used */
#define M_PAIR_1(a,b) a
#define M_PAIR_2(a,b) b
/* Skip the Nth first arguments
Generated by:
@@ -2102,29 +2106,45 @@ m_core_hash (const void *str, size_t length)
Example:
M_LET(a, STRING_OPLIST) { do something with a } or
M_LET(a, b, c, STRING_OPLIST) { do something with a, b & c }
M_LET((a, b), c, STRING_OPLIST) { do something with a(init with 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(a, ...) \
M_ID(M_LETI1 M_INVERT(a, __VA_ARGS__, M_C3(local_cont_, a, __LINE__) ))
M_ID(M_LETI1 M_INVERT(a, __VA_ARGS__, \
M_IF(M_PARENTHESIS_P(a))(M_LETI_VAR_NAME_A, \
M_LETI_VAR_NAME_B)(a) ))
// 1b. Generate a unique name based on the first variable and the line number
#define M_LETI_VAR_NAME_A(var) M_C3(_local_cont_, M_RET_ARG1 var, __LINE__)
#define M_LETI_VAR_NAME_B(var) M_C3(_local_cont_, var, __LINE__)
// 2. Evaluate with or without
#define M_LETI1(cont, oplist, ...) \
M_LETI2(cont, M_GLOBAL_OPLIST(oplist), __VA_ARGS__)
// 3. Map all variables to their own LET
#define M_LETI2(cont, oplist, ...) \
for(bool cont = true; cont ; /* unused */) \
M_MAP2(M_LETI_SINGLE, (cont, oplist,), __VA_ARGS__)
#define M_LETI_SINGLE(data, name) \
M_LETI_SINGLE2(M_RET_ARG1 data, M_RET_ARG2 data, name)
M_MAP2(M_LETI_SINGLE, (cont, oplist), __VA_ARGS__)
// 4. Dispatch the right LET in function of having or not arguments
#define M_LETI_SINGLE(data, name) \
M_IF(M_PARENTHESIS_P(name))( \
M_LETI_SINGLE2_SET(M_PAIR_1 data, M_PAIR_2 data, M_PAIR_1 name, M_PAIR_2 name), \
M_LETI_SINGLE2(M_PAIR_1 data, M_PAIR_2 data, name))
// 5a. Define without argument ==> use INIT
#define M_LETI_SINGLE2(cont, oplist, name) \
for(M_GET_TYPE oplist name; \
cont && (M_GET_INIT oplist (name), true); \
(M_GET_CLEAR oplist (name), cont = false)) \
for(;cont;cont = false)
// 5b. Define with arguments ==> use INIT_SET (INIT_WITH support pending)
#define M_LETI_SINGLE2_SET(cont, oplist, name, val) \
for(M_GET_TYPE oplist name; \
cont && (M_GET_INIT_SET oplist (name, val), true); \
(M_GET_CLEAR oplist (name), cont = false)) \
for(;cont;cont = false)
/* Transform the va list by adding their number as the first argument of
the list.
+3
View File
@@ -173,6 +173,9 @@ static void test_let(void)
{
M_LET(z, M_CLASSIC_OPLIST(testobj)) {
testobj_add(z,z,z);
M_LET((zz,z), M_CLASSIC_OPLIST(testobj)) {
testobj_add(zz,zz,z);
}
break;
assert(0);
}