From 95b104ee48aa216f6589bf592099a801a4bfaaf7 Mon Sep 17 00:00:00 2001 From: Patrick Pelissier Date: Fri, 6 May 2022 01:10:31 +0200 Subject: [PATCH] Issue in generation of functions: if the method in the oplist uses API_* transformation, if this method is a macro itself, it may delay the expansion too much and the macro may not be expanded at all in the final code generation. Fix issue by adding a supplementary evaluation in the macro expansion. Add test cases --- m-array.h | 8 ++++++-- m-bptree.h | 2 +- m-buffer.h | 6 +++--- m-concurrent.h | 4 ++-- m-deque.h | 2 +- m-dict.h | 10 +++++----- m-i-list.h | 4 ++-- m-i-shared.h | 2 +- m-list.h | 4 ++-- m-prioqueue.h | 2 +- m-rbtree.h | 2 +- m-shared.h | 4 ++-- m-snapshot.h | 6 +++--- m-tuple.h | 2 +- m-variant.h | 2 +- tests/test-mbuffer.c | 5 +++++ tests/test-obj.h | 6 +++++- 17 files changed, 42 insertions(+), 29 deletions(-) diff --git a/m-array.h b/m-array.h index 25f59ccc..d4cc5157 100644 --- a/m-array.h +++ b/m-array.h @@ -144,8 +144,12 @@ } while (0) /* Deferred evaluation for the array definition, - so that all arguments are evaluated before further expansion */ -#define M_ARRA4_DEF_P1(arg) M_ARRA4_DEF_P2 arg + so that all arguments are fully evaluated before further expansion + (ensuring good performance) + and performed a final step evaluation of the returning expansion + (ensuring delayed evaluation are still expanded) +*/ +#define M_ARRA4_DEF_P1(arg) M_ID( M_ARRA4_DEF_P2 arg ) /* Validate the oplist before going further */ #define M_ARRA4_DEF_P2(name, type, oplist, array_t, it_t) \ diff --git a/m-bptree.h b/m-bptree.h index 4d7e63c5..15c7dafa 100644 --- a/m-bptree.h +++ b/m-bptree.h @@ -304,7 +304,7 @@ /* Deferred evaluation for the b+tree definition, so that all arguments are evaluated before further expansion */ -#define M_BPTR33_DEF_P1(arg) M_BPTR33_DEF_P2 arg +#define M_BPTR33_DEF_P1(arg) M_ID( M_BPTR33_DEF_P2 arg ) /* Validate the key oplist before going further */ #define M_BPTR33_DEF_P2(name, N, key_t, key_oplist, value_t, value_oplist, isMap, isMulti, tree_t, node_t, pit_t, it_t, subtype_t) \ diff --git a/m-buffer.h b/m-buffer.h index 799f9fc9..baaa9ebb 100644 --- a/m-buffer.h +++ b/m-buffer.h @@ -235,7 +235,7 @@ m_buff3r_number_dec(m_buff3r_number_ct n, unsigned int policy) /* Deferred evaluation for the definition, so that all arguments are evaluated before further expansion */ -#define M_BUFF3R_DEF_P1(arg) M_BUFF3R_DEF_P2 arg +#define M_BUFF3R_DEF_P1(arg) M_ID( M_BUFF3R_DEF_P2 arg ) /* Validate the value oplist before going further */ #define M_BUFF3R_DEF_P2(name, type, m_size, policy, oplist, buffer_t) \ @@ -752,7 +752,7 @@ M_C(name, _init)(buffer_t v, size_t size) \ /* Deferred evaluation for the definition, so that all arguments are evaluated before further expansion */ -#define M_QU3UE_MPMC_DEF_P1(arg) M_QU3UE_MPMC_DEF_P2 arg +#define M_QU3UE_MPMC_DEF_P1(arg) M_ID( M_QU3UE_MPMC_DEF_P2 arg ) /* Validate the value oplist before going further */ #define M_QU3UE_MPMC_DEF_P2(name, type, policy, oplist, buffer_t) \ @@ -974,7 +974,7 @@ M_C(name, _init)(buffer_t v, size_t size) \ /* Deferred evaluation for the definition, so that all arguments are evaluated before further expansion */ -#define M_QU3UE_SPSC_DEF_P1(arg) M_QU3UE_SPSC_DEF_P2 arg +#define M_QU3UE_SPSC_DEF_P1(arg) M_ID( M_QU3UE_SPSC_DEF_P2 arg ) /* Validate the value oplist before going further */ #define M_QU3UE_SPSC_DEF_P2(name, type, policy, oplist, buffer_t) \ diff --git a/m-concurrent.h b/m-concurrent.h index 1bd5f807..335a7d3e 100644 --- a/m-concurrent.h +++ b/m-concurrent.h @@ -143,7 +143,7 @@ /* Deferred evaluation for the concurrent definition, so that all arguments are evaluated before further expansion */ -#define M_C0NCURRENT_DEF_P1(arg) M_C0NCURRENT_DEF_P2 arg +#define M_C0NCURRENT_DEF_P1(arg) M_ID( M_C0NCURRENT_DEF_P2 arg ) /* Validate the value oplist before going further */ #define M_C0NCURRENT_DEF_P2(name, type, oplist, concurrent_t) \ @@ -740,7 +740,7 @@ /* Deferred evaluation for the RP concurrent definition, so that all arguments are evaluated before further expansion */ -#define M_C0NCURRENT_RP_DEF_P1(arg) M_C0NCURRENT_RP_DEF_P2 arg +#define M_C0NCURRENT_RP_DEF_P1(arg) M_ID( M_C0NCURRENT_RP_DEF_P2 arg ) /* Validate the value oplist before going further */ #define M_C0NCURRENT_RP_DEF_P2(name, type, oplist, concurrent_t) \ diff --git a/m-deque.h b/m-deque.h index d4b6ad70..08af36d7 100644 --- a/m-deque.h +++ b/m-deque.h @@ -74,7 +74,7 @@ /* Deferred evaluation for the deque definition, so that all arguments are evaluated before further expansion */ -#define M_D3QU3_DEF_P1(arg) M_D3QU3_DEF_P2 arg +#define M_D3QU3_DEF_P1(arg) M_ID( M_D3QU3_DEF_P2 arg ) /* Validate the oplist before going further */ #define M_D3QU3_DEF_P2(name, type, oplist, deque_t, it_t, node_t) \ diff --git a/m-dict.h b/m-dict.h index 85f58bea..d6de7406 100644 --- a/m-dict.h +++ b/m-dict.h @@ -186,7 +186,7 @@ current array size). */ /* Deferred evaluation for arg */ -#define M_D1CT_DEF2_P1(arg) M_D1CT_DEF2_P2 arg +#define M_D1CT_DEF2_P1(arg) M_ID( M_D1CT_DEF2_P2 arg ) /* Validate the key oplist before going further */ #define M_D1CT_DEF2_P2(name, key_type, key_oplist, value_type, value_oplist, dict_t, dict_it_t, it_deref_t) \ @@ -218,7 +218,7 @@ representing a bucket). */ /* Defered evaluation for arg */ -#define M_D1CT_SHASH_DEF2_P1(arg) M_D1CT_SHASH_DEF2_P2 arg +#define M_D1CT_SHASH_DEF2_P1(arg) M_ID( M_D1CT_SHASH_DEF2_P2 arg ) /* Validate the key oplist before going further */ #define M_D1CT_SHASH_DEF2_P2(name, key_type, key_oplist, value_type, value_oplist, dict_t, dict_it_t, it_deref_t) \ @@ -248,7 +248,7 @@ It is defined as an array of singly linked list (each list representing a bucket). */ -#define M_D1CT_SET_DEF_P1(arg) M_D1CT_SET_DEF_P2 arg +#define M_D1CT_SET_DEF_P1(arg) M_ID( M_D1CT_SET_DEF_P2 arg ) /* Validate the key oplist before going further */ #define M_D1CT_SET_DEF_P2(name, key_type, key_oplist, dict_t, dict_it_t, it_deref_t) \ @@ -1215,7 +1215,7 @@ enum m_d1ct_oa_element_e { M_ASSERT( (dict)->upper_limit <= (dict)->mask+1); \ } while (0) -#define M_D1CT_OA_DEF_P1(args) M_D1CT_OA_DEF_P2 args +#define M_D1CT_OA_DEF_P1(args) M_ID( M_D1CT_OA_DEF_P2 args ) /* Validate the key oplist before going further */ #define M_D1CT_OA_DEF_P2(name, key_type, key_oplist, value_type, value_oplist, dict_t, dict_it_t, it_deref_t) \ @@ -1234,7 +1234,7 @@ enum m_d1ct_oa_element_e { M_D1CT_OA_LOWER_BOUND, M_D1CT_OA_UPPER_BOUND, \ dict_t, dict_it_t, it_deref_t) -#define M_D1CT_OASET_DEF_P1(args) M_D1CT_OASET_DEF_P2 args +#define M_D1CT_OASET_DEF_P1(args) M_ID( M_D1CT_OASET_DEF_P2 args ) /* Validate the value oplist before going further */ #define M_D1CT_OASET_DEF_P2(name, key_type, key_oplist, dict_t, dict_it_t, it_deref_t) \ diff --git a/m-i-list.h b/m-i-list.h index dc69645f..3eef0868 100644 --- a/m-i-list.h +++ b/m-i-list.h @@ -140,8 +140,8 @@ typedef struct m_il1st_head_s { M_ASSERT((node)->prev->next == node); \ } while (0) -/* Indirection call to allow expanding all arguments (TBC) */ -#define M_IL1ST_DEF_P1(arg) M_IL1ST_DEF_P2 arg +/* Indirection call to allow expanding all arguments */ +#define M_IL1ST_DEF_P1(arg) M_ID( M_IL1ST_DEF_P2 arg ) /* Validate the oplist before going further */ #define M_IL1ST_DEF_P2(name, type, oplist, list_t, it_t) \ diff --git a/m-i-shared.h b/m-i-shared.h index 53a17a65..3f393fa6 100644 --- a/m-i-shared.h +++ b/m-i-shared.h @@ -102,7 +102,7 @@ M_BEGIN_PROTECTED_CODE ) // Deferred evaluatioin -#define M_ISHAR3D_PTR_DEF_P1(arg) M_ISHAR3D_PTR_DEF_P2 arg +#define M_ISHAR3D_PTR_DEF_P1(arg) M_ID( M_ISHAR3D_PTR_DEF_P2 arg ) /* Validate the oplist before going further */ #define M_ISHAR3D_PTR_DEF_P2(name, type, oplist, shared_t) \ diff --git a/m-list.h b/m-list.h index 64824878..4ae9b195 100644 --- a/m-list.h +++ b/m-list.h @@ -148,7 +148,7 @@ /* Deferred evaluation for the list definition, so that all arguments are evaluated before further expansion */ -#define M_L1ST_DEF_P1(arg) M_L1ST_DEF_P2 arg +#define M_L1ST_DEF_P1(arg) M_ID( M_L1ST_DEF_P2 arg ) /* Validate the oplist before going further */ #define M_L1ST_DEF_P2(name, type, oplist, list_t, it_t) \ @@ -913,7 +913,7 @@ /* Deferred evaluation for the dual-push list definition, so that all arguments are evaluated before further expansion */ -#define M_L1ST_DUAL_PUSH_DEF_P1(arg) M_L1ST_DUAL_PUSH_DEF_P2 arg +#define M_L1ST_DUAL_PUSH_DEF_P1(arg) M_ID( M_L1ST_DUAL_PUSH_DEF_P2 arg ) /* Validate the oplist before going further */ #define M_L1ST_DUAL_PUSH_DEF_P2(name, type, oplist, list_t, it_t) \ diff --git a/m-prioqueue.h b/m-prioqueue.h index 58ed3cfb..41d6f027 100644 --- a/m-prioqueue.h +++ b/m-prioqueue.h @@ -103,7 +103,7 @@ /* Deferred evaluation for the definition, so that all arguments are evaluated before further expansion */ -#define M_PR1OQUEUE_DEF_P1(arg) M_PR1OQUEUE_DEF_P2 arg +#define M_PR1OQUEUE_DEF_P1(arg) M_ID( M_PR1OQUEUE_DEF_P2 arg ) /* Validate the oplist before going further */ #define M_PR1OQUEUE_DEF_P2(name, type, oplist, prioqueue_t, it_t) \ diff --git a/m-rbtree.h b/m-rbtree.h index fc08774e..e8c39c1c 100644 --- a/m-rbtree.h +++ b/m-rbtree.h @@ -156,7 +156,7 @@ typedef enum { /* Deferred evaluation for the rbtree definition, so that all arguments are evaluated before further expansion */ -#define M_RBTR33_DEF_P1(arg) M_RBTR33_DEF_P2 arg +#define M_RBTR33_DEF_P1(arg) M_ID( M_RBTR33_DEF_P2 arg ) /* Validate the oplist before going further */ #define M_RBTR33_DEF_P2(name, type, oplist, tree_t, node_t, it_t) \ diff --git a/m-shared.h b/m-shared.h index 07f27732..cbbebe50 100644 --- a/m-shared.h +++ b/m-shared.h @@ -149,7 +149,7 @@ static inline int m_shar3d_integer_cref(int *p) { return *p; } } while (0) // deferred evaluation -#define M_SHAR3D_PTR_DEF_P1(arg) M_SHAR3D_PTR_DEF_P2 arg +#define M_SHAR3D_PTR_DEF_P1(arg) M_ID( M_SHAR3D_PTR_DEF_P2 arg ) /* Validate the oplist before going further */ #define M_SHAR3D_PTR_DEF_P2(name, type, oplist, cpt_oplist, shared_t) \ @@ -360,7 +360,7 @@ static inline int m_shar3d_integer_cref(int *p) { return *p; } } while (0) // deferred -#define M_SHAR3D_RESOURCE_DEF_P1(arg) M_SHAR3D_RESOURCE_DEF_P2 arg +#define M_SHAR3D_RESOURCE_DEF_P1(arg) M_ID( M_SHAR3D_RESOURCE_DEF_P2 arg ) /* Validate the oplist before going further */ #define M_SHAR3D_RESOURCE_DEF_P2(name, type, oplist, shared_t, it_t) \ diff --git a/m-snapshot.h b/m-snapshot.h index 40c663db..a4598ee3 100644 --- a/m-snapshot.h +++ b/m-snapshot.h @@ -156,7 +156,7 @@ M_BEGIN_PROTECTED_CODE #define M_SNAPSH0T_SPSC_MAX_BUFFER 3 // Defered evaluation of the arguments. -#define M_SNAPSH0T_SPSC_DEF_P1(arg) M_SNAPSH0T_SPSC_DEF_P2 arg +#define M_SNAPSH0T_SPSC_DEF_P1(arg) M_ID( M_SNAPSH0T_SPSC_DEF_P2 arg ) /* Validate the oplist before going further */ #define M_SNAPSH0T_SPSC_DEF_P2(name, type, oplist, snapshot_t) \ @@ -591,7 +591,7 @@ m_snapsh0t_mrsw_read_end(m_snapsh0t_mrsw_ct s, unsigned int idx) // Defered evaluation -#define M_SNAPSH0T_SPMC_DEF_P1(arg) M_SNAPSH0T_SPMC_DEF_P2 arg +#define M_SNAPSH0T_SPMC_DEF_P1(arg) M_ID( M_SNAPSH0T_SPMC_DEF_P2 arg ) /* Validate the oplist before going further */ #define M_SNAPSH0T_SPMC_DEF_P2(name, type, oplist, snapshot_t) \ @@ -700,7 +700,7 @@ m_snapsh0t_mrsw_read_end(m_snapsh0t_mrsw_ct s, unsigned int idx) // MPMC is built upon SPMC // Defered evaluation -#define M_SNAPSH0T_MPMC_DEF_P1(arg) M_SNAPSH0T_MPMC_DEF_P2 arg +#define M_SNAPSH0T_MPMC_DEF_P1(arg) M_ID( M_SNAPSH0T_MPMC_DEF_P2 arg ) /* Validate the oplist before going further */ #define M_SNAPSH0T_MPMC_DEF_P2(name, type, oplist, snapshot_t) \ diff --git a/m-tuple.h b/m-tuple.h index f1f8f35e..e2311d07 100644 --- a/m-tuple.h +++ b/m-tuple.h @@ -103,7 +103,7 @@ namespace m_lib { M_IF_NARGS_EQ1(__VA_ARGS__)( (f, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)()), (f, __VA_ARGS__) ) // Deferred evaluation -#define M_TUPL3_DEF2_P1(...) M_TUPL3_DEF2_P2 __VA_ARGS__ +#define M_TUPL3_DEF2_P1(...) M_ID( M_TUPL3_DEF2_P2 __VA_ARGS__ ) // Test if all third argument of all arguments is an oplist #define M_TUPL3_IF_ALL_OPLIST(...) \ diff --git a/m-variant.h b/m-variant.h index 4a514fe2..a92b2c3d 100644 --- a/m-variant.h +++ b/m-variant.h @@ -79,7 +79,7 @@ M_IF_NARGS_EQ1(__VA_ARGS__)( (f, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)()), (f, __VA_ARGS__) ) // Deferred evaluation -#define M_VAR1ANT_DEF2_P1(...) M_VAR1ANT_DEF2_P2 __VA_ARGS__ +#define M_VAR1ANT_DEF2_P1(...) M_ID( M_VAR1ANT_DEF2_P2 __VA_ARGS__ ) // Test if all third argument of all arguments is an oplist #define M_VAR1ANT_IF_ALL_OPLIST(...) \ diff --git a/tests/test-mbuffer.c b/tests/test-mbuffer.c index 492a670c..56746f53 100644 --- a/tests/test-mbuffer.c +++ b/tests/test-mbuffer.c @@ -53,6 +53,11 @@ QUEUE_SPSC_DEF_AS(BufferDouble3, BufferDouble3, double, BUFFER_QUEUE) #define M_OPL_BufferDouble2() BUFFER_OPLIST(BufferDouble2, M_BASIC_OPLIST) #define M_OPL_BufferDouble3() BUFFER_OPLIST(BufferDouble3, M_BASIC_OPLIST) +// Define buffer with ENUM oplist (with API_1 usage) +typedef enum { OK, KO } state_t; +#define M_OPL_state_t() M_ENUM_OPLIST(state_t, OK) +BUFFER_DEF(array_state, state_t, M_BUFFER_QUEUE, 0) + buffer_uint_t g_buff; buffer_uint_t g_buffB; diff --git a/tests/test-obj.h b/tests/test-obj.h index 83dae724..fd07ebdd 100644 --- a/tests/test-obj.h +++ b/tests/test-obj.h @@ -163,11 +163,15 @@ static inline void testobj_str(string_t str, const testobj_t z, bool append) else string_printf (str, "%u", z->ptr[0]); } +// Go through a macro that forward to the right function. +// This enables testing good macro expansion in OPLIST usage +#define testobj_clear_indirect(op, x) testobj_clear(x) + #define TESTOBJ_OPLIST \ (INIT(testobj_init), \ INIT_SET(testobj_init_set), \ SET(testobj_set), \ - CLEAR(testobj_clear), \ + CLEAR(API_1(testobj_clear_indirect)), \ TYPE(testobj_t), \ OUT_STR(testobj_out_str), \ IN_STR(testobj_in_str), \