-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpreprocessor_tuple.h
More file actions
242 lines (196 loc) · 10.3 KB
/
preprocessor_tuple.h
File metadata and controls
242 lines (196 loc) · 10.3 KB
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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
/*
* CREATED BY SHPEGUN60
*
* TUPLE MACROCES
\**********************************************************************************************************************
* Tuples: `(x, y, z)`.
*
* A tuple is represented as `(x1, ..., xN)`. Tuples are a convenient way to deal with product
* types.
**********************************************************************************************************************
*/
#ifndef __PREPROCESSOR_TUPLE_H__
#define __PREPROCESSOR_TUPLE_H__ 1
/* -- Headers -- */
#ifdef __cplusplus
extern "C" {
#endif
/* -- Macros -- */
/***********************************************************************************************************
* Checks whether x takes the form `(...) (...) ...`.
*
* This often happens when you miss a comma between items:
* - `(1, 2, 3) (4, 5, 6)`
* - etc.
*
* PREPROCESSOR_IS_DOUBLE_TUPLE_BEGINNING() // expands to 0
* PREPROCESSOR_IS_DOUBLE_TUPLE_BEGINNING(2) // expands to 0
* PREPROCESSOR_IS_DOUBLE_TUPLE_BEGINNING((2)) // expands to 0
* PREPROCESSOR_IS_DOUBLE_TUPLE_BEGINNING((2) (3)) // expands to 1
* PREPROCESSOR_IS_DOUBLE_TUPLE_BEGINNING((123) (456)) // expands to 1
* PREPROCESSOR_IS_DOUBLE_TUPLE_BEGINNING((1, 2, 3) (4, 5, 6)) // expands to 1
*/
#define PREPROCESSOR_IS_DOUBLE_TUPLE_BEGINNING(x) \
PREPROCESSOR_ARGS_CONTAINS_COMMA(PREPROCESSOR_EXPAND(PREPROCESSOR_COMMA_VARIADIC PREPROCESSOR_EMPTY_VARIADIC x))
/************************************************************************************************************
* FAST CHECK IF NEXT VALUE IS NOT TUPLE
*
*
* PREPROCESSOR_IS_UNTUPLE_FAST(PREPROCESSOR_TUPLE_MAKE(x, y, z)) // expand to 0
* PREPROCESSOR_IS_UNTUPLE_FAST(x) // expand to 1
* PREPROCESSOR_IS_UNTUPLE_FAST((1,2,3,)) // expand to 0
* PREPROCESSOR_IS_UNTUPLE_FAST(()) // expand to 0
* PREPROCESSOR_IS_UNTUPLE_FAST() // expand to 1
*
* PREPROCESSOR_IS_UNTUPLE the same then PREPROCESSOR_IS_UNTUPLE_FAST, but PREPROCESSOR_IS_UNTUPLE checs if input x takes the form `(...) (...) ...
*
*/
#define PREPROCESSOR_IS_UNTUPLE_FAST(x) PREPROCESSOR_IS_UNTUPLE_FAST_IMPL(x)
#define PREPROCESSOR_IS_UNTUPLE_FAST_IMPL(x) PREPROCESSOR_ARGS_SND(PREPROCESSOR_IS_UNTUPLE_FAST_TEST x, 1)
#define PREPROCESSOR_IS_UNTUPLE_FAST_TEST(...) ~, 0
#define PREPROCESSOR_IS_UNTUPLE(x) \
PREPROCESSOR_IF_ELSE(PREPROCESSOR_IS_DOUBLE_TUPLE_BEGINNING(x)) ( \
PREPROCESSOR_TRUE, \
PREPROCESSOR_IS_UNTUPLE_FAST) \
(x)
/************************************************************************************************************
* FAST CHECK IF NEXT VALUE IS TUPLE
*
*
* PREPROCESSOR_IS_TUPLE_FAST(PREPROCESSOR_TUPLE_MAKE(x, y, z)) // expand to 1
* PREPROCESSOR_IS_TUPLE_FAST(x) // expand to 0
* PREPROCESSOR_IS_TUPLE_FAST((1,2,3,)) // expand to 1
* PREPROCESSOR_IS_TUPLE_FAST(()) // expand to 1
* PREPROCESSOR_IS_TUPLE_FAST() // expand to 0
*
* PREPROCESSOR_IS_TUPLE the same then PREPROCESSOR_IS_TUPLE_FAST, but PREPROCESSOR_IS_TUPLE checs if input x takes the form `(...) (...) ...
*
*/
#define PREPROCESSOR_IS_TUPLE_FAST(x) PREPROCESSOR_NOT(PREPROCESSOR_IS_UNTUPLE_FAST(x))
#define PREPROCESSOR_IS_TUPLE(x) PREPROCESSOR_NOT(PREPROCESSOR_IS_UNTUPLE(x))
/************************************************************************************************************
* TUPLE UNTUPLING
*
* PREPROCESSOR_UNTUPLE((x,y,z)) // expands just to x,y,z (deletes parenthesis)
*/
#define PREPROCESSOR_UNTUPLE(...) PREPROCESSOR_UNTUPLE_IMPL __VA_ARGS__
#define PREPROCESSOR_UNTUPLE_IMPL(...) __VA_ARGS__
/************************************************************************************************************
* TUPLE MAKE
*
* PREPROCESSOR_TUPLE_MAKE(x,y,z) // expands just to (x,y,z) (add parenthesis)
*/
#define PREPROCESSOR_TUPLE_MAKE(...) (PREPROCESSOR_UNTUPLE_IMPL(__VA_ARGS__))
/************************************************************************************************************
* TUPLE EXPANDING SOME MACRO
*/
#define PREPROCESSOR_TUPLE_EXPAND_MACRO(macro, ...) macro __VA_ARGS__
/************************************************************************************************************
* TUPLE PREPEND
*
* PREPROCESSOR_TUPLE_PREPEND(x1, (x, y, z)) // expands to (x1, x, y, z)
*/
#define PREPROCESSOR_TUPLE_PREPEND(expr, tuple) \
PREPROCESSOR_TUPLE_MAKE(expr, PREPROCESSOR_UNTUPLE(tuple))
/************************************************************************************************************
* TUPLE APPEND
*
* PREPROCESSOR_TUPLE_APPEND(x1, (x, y, z)) // expands to (x, y, z, x1)
*/
#define PREPROCESSOR_TUPLE_APPEND(expr, tuple) \
PREPROCESSOR_TUPLE_MAKE(PREPROCESSOR_UNTUPLE(tuple), expr)
/************************************************************************************************************
* TUPLE MERGE
*
* PREPROCESSOR_TUPLE_MERGE((x1, y1, z1), (x, y, z)) // expands to (x1, y1, z1, x, y, z)
* PREPROCESSOR_TUPLE_MERGE_VARIADIC((1,2,3) ,(6,5,4), (3,2,1)) // expands to (1,2,3 , 6,5,4 , 3,2,1)
*/
#define PREPROCESSOR_TUPLE_MERGE(tuple1, tuple2) \
PREPROCESSOR_TUPLE_MAKE(PREPROCESSOR_UNTUPLE(tuple1), PREPROCESSOR_UNTUPLE(tuple2))
#define PREPROCESSOR_TUPLE_MERGE_VARIADIC(...)\
PREPROCESSOR_TUPLE_MAKE(PREPROCESSOR_FOR_EACH(PREPROCESSOR_UNTUPLE, PREPROCESSOR_COMMA, __VA_ARGS__))
/************************************************************************************************************
* TUPLE HEAD / TAIL
*
* PREPROCESSOR_TUPLE_TAIL((x,y,z)) // expands to y,z
* PREPROCESSOR_TUPLE_HEAD((x,y,z)) // expands to x
*/
#define PREPROCESSOR_TUPLE_TAIL(x) PREPROCESSOR_ARGS_TAIL(PREPROCESSOR_UNTUPLE(x))
#define PREPROCESSOR_TUPLE_HEAD(x) PREPROCESSOR_ARGS_HEAD(PREPROCESSOR_UNTUPLE(x))
/************************************************************************************************************
* TUPLE COUNTS OF ARGUMENT
*
* PREPROCESSOR_TUPLE_COUNT((x,y,z, x1)) // expands to 4
*/
#define PREPROCESSOR_TUPLE_COUNT(x) PREPROCESSOR_ARGS_COUNT(PREPROCESSOR_UNTUPLE(x))
/************************************************************************************************************
* TUPLE IS SINGLE OF ARGUMENT
*
* PREPROCESSOR_TUPLE_IS_SINGLE((x,y,z, x1)) // expands to 0
* PREPROCESSOR_TUPLE_IS_SINGLE((x)) // expands to 1
*/
#define PREPROCESSOR_TUPLE_IS_SINGLE(x) PREPROCESSOR_ARGS_IS_SINGLE(PREPROCESSOR_UNTUPLE(x))
/************************************************************************************************************
* TUPLE HAS ARGUMENTS
*
* PREPROCESSOR_TUPLE_IS_NOT_EMPTY((x,y,z)) // expands to 1
* PREPROCESSOR_TUPLE_IS_NOT_EMPTY((x)) // expands to 1
* PREPROCESSOR_TUPLE_IS_NOT_EMPTY(()) // expands to 0
*/
#define PREPROCESSOR_TUPLE_IS_NOT_EMPTY(x) PREPROCESSOR_ARGS_NOT_EMPTY(PREPROCESSOR_UNTUPLE(x))
/************************************************************************************************************
* TUPLE GET / REMOVE
*
*
* PREPROCESSOR_EVAL(PREPROCESSOR_TUPLE_GET(1)PREPROCESSOR_TUPLE_MAKE(x, y, z)) // expands to y
* PREPROCESSOR_TUPLE_GET(1)(x, y, z) // expands to y
*
* PREPROCESSOR_TUPLE_REMOVE(1)(x, y, z) // expands to x , z
* PREPROCESSOR_EVAL(PREPROCESSOR_TUPLE_REMOVE(1)PREPROCESSOR_TUPLE_MAKE(x, y, z)) // expands to x , z
*/
#define PREPROCESSOR_TUPLE_GET(x) PREPROCESSOR_GET_ARG(x)
#define PREPROCESSOR_TUPLE_REMOVE(x) PREPROCESSOR_REMOVE_ARG(x)
/************************************************************************************************************
* TUPLE FOR_EACH
*
* #define TUPLE_FOO(x) printf("%d" x)
* PREPROCESSOR_TUPLE_FOR_EACH_ELEM(TUPLE_FOO, PREPROCESSOR_COMMA_POINT, (1,2,3) ,(6,5,4), (3,2,1))
*
* Which expands to:
* printf("%d" 1) ; printf("%d" 2) ; printf("%d" 3) ; printf("%d" 6) ; printf("%d" 5) ; printf("%d" 4) ; printf("%d" 3) ; printf("%d" 2) ; printf("%d" 1)
*
*
* #define TUPLE_FOO(x) PREPROCESSOR_CONCAT(myFoo, PREPROCESSOR_TUPLE_COUNT(x)) x
* PREPROCESSOR_TUPLE_FOR_EACH(TUPLE_FOO, PREPROCESSOR_COMMA_POINT, (1,2,3,4), (6,5), (3))
*
* Which expands to:
* myFoo4 (1,2,3,4) ; myFoo2 (6,5) ; myFoo1 (3)
*/
#define PREPROCESSOR_TUPLE_FOR_EACH_ELEM(f, sep, ...) \
PREPROCESSOR_FOR_EACH(f, sep, PREPROCESSOR_UNTUPLE(PREPROCESSOR_TUPLE_MERGE_VARIADIC(__VA_ARGS__)))
#define PREPROCESSOR_TUPLE_FOR_EACH(f, sep, ...) \
PREPROCESSOR_FOR_EACH(f, sep, __VA_ARGS__)
/************************************************************************************************************
* TUPLE FOR_EACH with parameter
* the same as PREPROCESSOR_TUPLE_FOR_EACH but contains some user parameter (may be tuple)
*
* #define TUPLE_FOO(par, x) printf(par); PREPROCESSOR_CONCAT(myFoo, PREPROCESSOR_TUPLE_COUNT(x)) x
* PREPROCESSOR_TUPLE_FOR_EACH_PARAMETER("next par------", TUPLE_FOO, PREPROCESSOR_COMMA_POINT, (1,2,3,4), (6,5), (3))
*
* Which expands to:
* printf("next par------");
* myFoo4(1, 2, 3, 4);
* printf("next par------");
* myFoo2(6, 5);
* printf("next par------");
* myFoo1(3)
*
* **** parameters may be tuple -->(2, 3, 4), but progremmer must proceed this
*
*/
#define PREPROCESSOR_TUPLE_FOR_EACH_PARAMETER(par, f, sep, ...) \
PREPROCESSOR_FOR_EACH_PARAMETER(par, f, sep, __VA_ARGS__)
#ifdef __cplusplus
}
#endif
#endif /* __PREPROCESSOR_TUPLE_H__ */