diff --git a/m-core.h b/m-core.h index 652f0757..32163d49 100644 --- a/m-core.h +++ b/m-core.h @@ -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. diff --git a/tests/test-mcore.c b/tests/test-mcore.c index bd4e45b1..09350a76 100644 --- a/tests/test-mcore.c +++ b/tests/test-mcore.c @@ -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); }