|
2 | 2 | #ifndef FM_UTIL_H
|
3 | 3 | #define FM_UTIL_H
|
4 | 4 |
|
5 |
| -#define fm_cat_impl(x, y) x##y |
6 |
| -#define fm_cat(x, y) fm_cat_impl(x, y) |
7 |
| -#define fm_cat3_impl(x, y, z) x##y##z |
8 |
| -#define fm_cat3(x, y, z) fm_cat3_impl(x, y, z) |
9 |
| -#define fm_cat4_impl(w, x, y, z) w##x##y##z |
10 |
| -#define fm_cat4(w, x, y, z) fm_cat4_impl(w, x, y, z) |
11 |
| -#define fm_str_impl(...) #__VA_ARGS__ |
12 |
| -#define fm_str(...) fm_str_impl(__VA_ARGS__) |
| 5 | +#define fm_cat(x, y) fm__cat(x, y) |
| 6 | +#define fm__cat(x, y) x##y |
| 7 | +#define fm_cat3(x, y, z) fm__cat3(x, y, z) |
| 8 | +#define fm__cat3(x, y, z) x##y##z |
| 9 | +#define fm_cat4(w, x, y, z) fm__cat4(w, x, y, z) |
| 10 | +#define fm__cat4(w, x, y, z) w##x##y##z |
| 11 | +#define fm_str(...) fm__str(__VA_ARGS__) |
| 12 | +#define fm__str(...) #__VA_ARGS__ |
13 | 13 | #define fm_uniq(x) fm_cat(_##x##_, __COUNTER__)
|
14 | 14 |
|
15 | 15 | #define fm_expand(...) __VA_ARGS__
|
16 | 16 | #define fm_empty(...)
|
17 | 17 |
|
| 18 | +#define fm_comma(...) , |
| 19 | +#define fm__comma , |
| 20 | + |
| 21 | +#define fm_apply(macro, ...) \ |
| 22 | + macro(__VA_ARGS__) |
| 23 | + |
| 24 | +/****************************************/ |
| 25 | +// LOGIC |
| 26 | + |
18 | 27 | #define fm_compl(v) fm_cat(fm_compl_, v)
|
19 | 28 | #define fm_compl_0 1
|
20 | 29 | #define fm_compl_1 0
|
|
54 | 63 | #define fm__iif_1(...) __VA_ARGS__ fm_empty
|
55 | 64 | #define fm__iif_0(...) fm_expand
|
56 | 65 |
|
57 |
| -#define fm_va_comma(...) \ |
58 |
| - fm_cat(fm__va_comma_, fm_va_01(__VA_ARGS__))() |
59 |
| -#define fm__va_comma_0() |
60 |
| -#define fm__va_comma_1() , |
61 |
| - |
62 |
| -#define fm_or_default(...) \ |
63 |
| - fm_iif(fm_va_01(__VA_ARGS__))(__VA_ARGS__) |
| 66 | +/****************************************/ |
| 67 | +// COMPARISON |
64 | 68 |
|
65 |
| -#define fm__primitive_compare(x, y) fm_is_tuple(COMPARE_##x(COMPARE_##y)(())) |
66 |
| -#define fm__is_comparable(x) fm_is_tuple(fm_cat(COMPARE_,x)(())) |
67 |
| -#define fm_not_equal(x, y) \ |
68 |
| - fm_if(fm_and(fm__is_comparable(x),fm__is_comparable(y)), fm__primitive_compare, 1 fm_empty)(x, y) |
69 | 69 | #define fm_equal(x, y) \
|
70 | 70 | fm_compl(fm_not_equal(x, y))
|
| 71 | +#define fm_not_equal(x, y) \ |
| 72 | + fm_if(fm_and(fm__is_comparable(x),fm__is_comparable(y)), fm__primitive_compare, 1 fm_empty)(x, y) |
| 73 | +#define fm__primitive_compare(x, y) fm_is_tuple(COMPARE_##x(COMPARE_##y)(())) |
| 74 | +#define fm__is_comparable(x) fm_is_tuple(fm_cat(COMPARE_,x)(())) |
71 | 75 |
|
72 |
| -#define fm_comma(...) , |
73 |
| -#define fm__comma , |
| 76 | +/****************************************/ |
| 77 | +// __VA_ARGS__ |
| 78 | + |
| 79 | +#define fm_head(...) fm__head(__VA_ARGS__) |
| 80 | +#define fm__head(x, ...) x |
| 81 | +#define fm_tail(...) fm__tail(__VA_ARGS__) |
| 82 | +#define fm__tail(x, ...) __VA_ARGS__ |
| 83 | + |
| 84 | +#define fm_or_default(...) \ |
| 85 | + fm_iif(fm_va_01(__VA_ARGS__))(__VA_ARGS__) |
74 | 86 | #define fm_va_single(...) fm__va_single(__VA_ARGS__, fm__comma)
|
75 | 87 | #define fm_va_many(...) fm__va_many(__VA_ARGS__, fm__comma)
|
76 | 88 | #define fm__va_single(x, y, ...) fm__va_result(y, 1, 0)
|
77 | 89 | #define fm__va_many(x, y, ...) fm__va_result(y, 0, 1)
|
78 | 90 | #define fm__va_result(x, y, res, ...) res
|
79 | 91 |
|
80 |
| -#if !__STRICT_ANSI__ |
81 |
| -#define fm_no_va(...) fm__no_va(__VA_ARGS__) |
82 |
| -#define fm__no_va(...) fm_va_single(~, ##__VA_ARGS__) |
83 |
| -#define fm_va_01(...) fm__va_01(__VA_ARGS__) |
84 |
| -#define fm__va_01(...) fm_va_many(~, ##__VA_ARGS__) |
85 |
| -#else |
86 | 92 | #define fm_no_va fm_is_empty
|
87 | 93 | #define fm_va_01 fm_isnt_empty
|
| 94 | +#define fm_va_01n(...) fm_cat3(fm__va_01n_, fm__isnt_empty(__VA_ARGS__), fm_va_many(__VA_ARGS__)) |
| 95 | +#define fm__va_01n_00 0 |
| 96 | +#define fm__va_01n_10 1 |
| 97 | +#define fm__va_01n_11 n |
| 98 | + |
| 99 | +#if !__STRICT_ANSI__ |
| 100 | +#define fm_is_empty(...) fm__is_empty(__VA_ARGS__) |
| 101 | +#define fm__is_empty(...) fm_va_single(~, ##__VA_ARGS__) |
| 102 | +#define fm_isnt_empty(...) fm__isnt_empty(__VA_ARGS__) |
| 103 | +#define fm__isnt_empty(...) fm_va_many(~, ##__VA_ARGS__) |
| 104 | +#else |
| 105 | +#define fm_is_empty(...) fm_and(fm__is_emptyfirst(__VA_ARGS__), fm_va_single(__VA_ARGS__)) |
| 106 | +#define fm_isnt_empty(...) fm_nand(fm__is_emptyfirst(__VA_ARGS__), fm_va_single(__VA_ARGS__)) |
| 107 | + |
| 108 | +#define fm__is_emptyfirst(x, ...) fm_iif(fm_is_tuple(x))(0)(fm__is_emptyfirst_impl(x)) |
| 109 | +#define fm__is_emptyfirst_impl(x,...) fm_tuple_2((\ |
| 110 | + fm__is_emptyfirst_do1 x (fm__is_emptyfirst_do2), 1, 0)) |
| 111 | +#define fm__is_emptyfirst_do1(F) F() |
| 112 | +#define fm__is_emptyfirst_do2(...) , |
88 | 113 | #endif
|
89 | 114 |
|
| 115 | +#define fm_when_isnt_empty(...) fm_cat(fm__when_, fm__isnt_empty(__VA_ARGS__)) |
| 116 | +#define fm_va_comma(...) \ |
| 117 | + fm_when_isnt_empty(__VA_ARGS__)(fm__comma) |
| 118 | +#define fm_va_comma_fun(...) \ |
| 119 | + fm_if(fm_va_01(__VA_ARGS__), fm_comma, fm_empty) |
| 120 | + |
| 121 | + |
| 122 | +/****************************************/ |
| 123 | +// Tuples |
| 124 | + |
| 125 | +#define fm_is_tuple(x, ...) fm__is_tuple_(fm__is_tuple_help x, 1, 0) |
90 | 126 | #define fm__is_tuple_choose(a,b,x,...) x
|
91 | 127 | #define fm__is_tuple_help(...) ,
|
92 | 128 | #define fm__is_tuple_(...) fm__is_tuple_choose(__VA_ARGS__)
|
93 |
| -#define fm_is_tuple(x, ...) fm__is_tuple_(fm__is_tuple_help x, 1, 0) |
94 |
| - |
95 |
| -#define fm_head(x, ...) x |
96 |
| -#define fm_tail(x, ...) __VA_ARGS__ |
97 |
| - |
98 |
| -#define fm_apply_1(macro, x, ...) \ |
99 |
| - macro(x) |
100 |
| -#define fm_apply_2(macro, x, y, ...) \ |
101 |
| - macro(x, y) |
102 |
| -#define fm_apply_3(macro, x, y, z, ...) \ |
103 |
| - macro(x, y, z) |
104 |
| -#define fm_apply_tuple_1(macro, x, ...) \ |
105 |
| - macro x |
106 |
| -#define fm_apply_tuple_2(macro, x, y, ...) \ |
107 |
| - fm__apply_tuple_2(macro, x, fm_expand y) |
108 |
| -#define fm__apply_tuple_2(macro, x, ...) \ |
109 |
| - macro(x, __VA_ARGS__) |
110 | 129 |
|
111 | 130 | #define fm_tuple_expand(x) fm_expand x
|
112 | 131 | #define fm_tuple_tag(x) fm_head x
|
|
117 | 136 | #define fm_tuple_2(x) fm__tuple_2 x
|
118 | 137 | #define fm__tuple_2(_0, _1, _2, ...) _2
|
119 | 138 |
|
| 139 | +#define fm_tuple_tag_or_0(x) fm__tuple_tag_or_0_(fm__tuple_tag_or_0_help x, 0) |
| 140 | +#define fm__tuple_tag_or_0_(...) fm__tuple_tag_or_0_choose(__VA_ARGS__) |
120 | 141 | #define fm__tuple_tag_or_0_choose(a,x,...) x
|
121 | 142 | #define fm__tuple_tag_or_0_help(tag, ...) , tag
|
122 |
| -#define fm__tuple_tag_or_0_(...) fm__tuple_tag_or_0_choose(__VA_ARGS__) |
123 |
| -#define fm_tuple_tag_or_0(x) fm__tuple_tag_or_0_(fm__tuple_tag_or_0_help x, 0) |
124 | 143 |
|
125 | 144 | #define fm_dispatch_tag_or_0(prefix, x) \
|
126 | 145 | fm_cat(prefix, fm_tuple_tag_or_0(x))
|
127 | 146 |
|
128 |
| -#define fm_va_012(...) \ |
129 |
| - fm_if(fm_no_va(__VA_ARGS__), 0, fm__va_12(__VA_ARGS__)) |
130 |
| -#define fm__va_12(...) \ |
131 |
| - fm_if(fm_va_single(__VA_ARGS__), 1, 2) |
132 |
| - |
133 |
| -// recursion handle |
134 |
| -#define fm_defer(id) id fm_empty() |
135 |
| -#define fm_recurs(id) id fm_empty fm_empty() () |
136 |
| -#define fm_recurs2(a,b) fm_cat fm_empty fm_empty() () (a,b) |
137 |
| - |
138 |
| -#if __STRICT_ANSI__ |
139 |
| -#define fm__is_emptyfirst(x, ...) fm_if(fm_is_tuple(x), 0, fm__is_emptyfirst_impl(x)) |
140 |
| -#define fm__is_emptyfirst_impl(x,...) fm_tuple_2((\ |
141 |
| - fm__is_emptyfirst_do1 x (fm__is_emptyfirst_do2), 1, 0)) |
142 |
| -#define fm__is_emptyfirst_do1(F) F() |
143 |
| -#define fm__is_emptyfirst_do2(...) , |
144 |
| -#define fm_is_empty(...) fm_and(fm__is_emptyfirst(__VA_ARGS__), fm_va_single(__VA_ARGS__)) |
145 |
| -#define fm_isnt_empty(...) fm_nand(fm__is_emptyfirst(__VA_ARGS__), fm_va_single(__VA_ARGS__)) |
146 |
| -#else |
147 |
| -#define fm_is_empty fm_no_va |
148 |
| -#define fm_isnt_empty fm_va_01 |
149 |
| -#endif |
| 147 | +/****************************************/ |
| 148 | +// Iteration |
150 | 149 |
|
| 150 | +/* recursion engine */ |
151 | 151 | #define fm_eval(...) fm__eval_0(__VA_ARGS__)
|
152 | 152 | #ifdef FU_LONG_EVAL
|
153 | 153 | #define fm__eval_0(...) fm__eval_1(fm__eval_1(fm__eval_1(fm__eval_1(__VA_ARGS__))))
|
|
158 | 158 | #define fm__eval_2(...) fm__eval_3(fm__eval_3(__VA_ARGS__))
|
159 | 159 | #define fm__eval_3(...) __VA_ARGS__
|
160 | 160 |
|
161 |
| -#define fm_foreach(macro, ...) \ |
162 |
| - fm_when(fm_va_01(__VA_ARGS__))( \ |
163 |
| - fm_apply_1(macro, __VA_ARGS__) \ |
164 |
| - fm_recurs2(fm_, foreach) (\ |
165 |
| - macro, fm_tail(__VA_ARGS__) \ |
166 |
| - ) \ |
167 |
| - ) |
| 161 | +// recursion handle : delay macro expansion to next recursion iteration |
| 162 | +#define fm_recurs(id) id fm_empty fm_empty() () |
| 163 | +#define fm_recurs2(a,b) fm_cat fm_empty fm_empty() () (a,b) |
| 164 | +#define fm_defer(id) id fm_empty() |
168 | 165 |
|
169 |
| -#define fm_foreach_arg(macro, arg, ...) \ |
170 |
| - fm_when(fm_va_01(__VA_ARGS__))( \ |
171 |
| - fm_apply_2(macro, arg, __VA_ARGS__) \ |
172 |
| - fm_recurs2(fm_, foreach_arg) (\ |
173 |
| - macro, arg, fm_tail(__VA_ARGS__) \ |
174 |
| - ) \ |
175 |
| - ) |
| 166 | +#define fm_foreach_join(join, macro, ...) \ |
| 167 | + fm_foreach_join_(fm_empty, join, macro, __VA_ARGS__) |
| 168 | +#define fm_foreach_join_(join1, join2, macro, ...) \ |
| 169 | + fm_cat(fm_foreach_join_, fm_va_01n(__VA_ARGS__))(join1, join2, macro, __VA_ARGS__) |
| 170 | +#define fm_foreach_join_0(join1, join2, macro, ...) |
| 171 | +#define fm_foreach_join_1(join1, join2, macro, x) \ |
| 172 | + join1() macro(x) |
| 173 | +#define fm_foreach_join_n(join1, join2, macro, x, y, ...) \ |
| 174 | + join1() macro(x) \ |
| 175 | + join2() macro(y) \ |
| 176 | + fm_recurs2(fm_, foreach_join_) (join2, join2, macro, __VA_ARGS__) |
176 | 177 |
|
| 178 | +#define fm_foreach(macro, ...) \ |
| 179 | + fm_foreach_join(fm_empty, macro, __VA_ARGS__) |
177 | 180 | #define fm_foreach_comma(macro, ...) \
|
178 |
| - fm_when(fm_va_01(__VA_ARGS__))( \ |
179 |
| - fm_apply_1(macro, __VA_ARGS__\ |
180 |
| - )fm_if(fm_va_single(__VA_ARGS__), , fm__comma)\ |
181 |
| - fm_recurs2(fm_, foreach_comma) (\ |
182 |
| - macro, fm_tail(__VA_ARGS__) \ |
183 |
| - ) \ |
184 |
| - ) |
| 181 | + fm_foreach_join(fm_comma, macro, __VA_ARGS__) |
| 182 | + |
| 183 | +#define fm_foreach_arg_join(join, macro, arg, ...) \ |
| 184 | + fm_foreach_arg_join_(fm_empty, join, macro, arg, __VA_ARGS__) |
| 185 | +#define fm_foreach_arg_join_(join1, join2, macro, arg, ...) \ |
| 186 | + fm_cat(fm_foreach_arg_join_, fm_va_01n(__VA_ARGS__))(join1, join2, macro, arg, __VA_ARGS__) |
| 187 | +#define fm_foreach_arg_join_0(join1, join2, macro, ...) |
| 188 | +#define fm_foreach_arg_join_1(join1, join2, macro, arg, x) \ |
| 189 | + join1() macro(arg, x) |
| 190 | +#define fm_foreach_arg_join_n(join1, join2, macro, arg, x, y, ...) \ |
| 191 | + join1() macro(arg, x) \ |
| 192 | + join2() macro(arg, y) \ |
| 193 | + fm_recurs2(fm_, foreach_arg_join_) (join2, join2, macro, arg, __VA_ARGS__) |
185 | 194 |
|
| 195 | +#define fm_foreach_arg(macro, arg, ...) \ |
| 196 | + fm_foreach_arg_join(fm_empty, macro, arg, __VA_ARGS__) |
| 197 | +#define fm_foreach_arg_comma(macro, arg, ...) \ |
| 198 | + fm_foreach_arg_join(fm_comma, macro, arg, __VA_ARGS__) |
| 199 | + |
| 200 | +#define fm_foreach_tuple_join(join, macro, ...) \ |
| 201 | + fm_foreach_tuple_join_(fm_empty, join, macro, __VA_ARGS__) |
| 202 | +#define fm_foreach_tuple_join_(join1, join2, macro, ...) \ |
| 203 | + fm_cat(fm_foreach_tuple_join_, fm_va_01n(__VA_ARGS__))(join1, join2, macro, __VA_ARGS__) |
| 204 | +#define fm_foreach_tuple_join_0(join1, join2, macro, ...) |
| 205 | +#define fm_foreach_tuple_join_1(join1, join2, macro, x) \ |
| 206 | + join1() macro x |
| 207 | +#define fm_foreach_tuple_join_n(join1, join2, macro, x, y, ...) \ |
| 208 | + join1() macro x \ |
| 209 | + join2() macro y \ |
| 210 | + fm_recurs2(fm_, foreach_tuple_join_) (join2, join2, macro, __VA_ARGS__) |
186 | 211 |
|
187 | 212 | #define fm_foreach_tuple(macro, ...) \
|
188 |
| - fm_when(fm_va_01(__VA_ARGS__))( \ |
189 |
| - fm_apply_tuple_1(macro, __VA_ARGS__) \ |
190 |
| - fm_recurs2(fm_, foreach_tuple) (\ |
191 |
| - macro, fm_tail(__VA_ARGS__) \ |
192 |
| - ) \ |
193 |
| - ) |
194 |
| - |
195 |
| -#define fm_foreach_tuple_arg(macro, arg, ...) \ |
196 |
| - fm_when(fm_va_01(__VA_ARGS__))( \ |
197 |
| - fm_apply_tuple_2(macro, arg, __VA_ARGS__) \ |
198 |
| - fm_recurs2(fm_, foreach_tuple_arg) (\ |
199 |
| - macro, arg, fm_tail(__VA_ARGS__) \ |
200 |
| - ) \ |
201 |
| - ) |
202 |
| - |
| 213 | + fm_foreach_tuple_join(fm_empty, macro, __VA_ARGS__) |
203 | 214 | #define fm_foreach_tuple_comma(macro, ...) \
|
204 |
| - fm_when(fm_va_01(__VA_ARGS__))( \ |
205 |
| - fm_apply_tuple_1(macro, __VA_ARGS__\ |
206 |
| - )fm_if(fm_va_single(__VA_ARGS__), fm_empty(), fm__comma)\ |
207 |
| - fm_recurs2(fm_, foreach_tuple_comma) (\ |
208 |
| - macro, fm_tail(__VA_ARGS__) \ |
209 |
| - ) \ |
210 |
| - ) |
| 215 | + fm_foreach_tuple_join(fm_comma, macro, __VA_ARGS__) |
| 216 | + |
| 217 | +#define fm_foreach_tuple_arg_join(join, macro, arg, ...) \ |
| 218 | + fm_foreach_tuple_arg_join_(fm_empty, join, macro, arg, __VA_ARGS__) |
| 219 | +#define fm_foreach_tuple_arg_join_(join1, join2, macro, arg, ...) \ |
| 220 | + fm_cat(fm_foreach_tuple_arg_join_, fm_va_01n(__VA_ARGS__))(join1, join2, macro, arg, __VA_ARGS__) |
| 221 | +#define fm_foreach_tuple_arg_join_0(join1, join2, macro, ...) |
| 222 | +#define fm_foreach_tuple_arg_join_1(join1, join2, macro, arg, x) \ |
| 223 | + join1() fm_apply(macro, arg, fm_expand x) |
| 224 | +#define fm_foreach_tuple_arg_join_n(join1, join2, macro, arg, x, y, ...) \ |
| 225 | + join1() fm_apply(macro, arg, fm_expand x) \ |
| 226 | + join2() fm_apply(macro, arg, fm_expand y) \ |
| 227 | + fm_recurs2(fm_, foreach_tuple_arg_join_) (join2, join2, macro, arg, __VA_ARGS__) |
211 | 228 |
|
| 229 | +#define fm_foreach_tuple_arg(macro, arg, ...) \ |
| 230 | + fm_foreach_tuple_arg_join(fm_empty, macro, arg, __VA_ARGS__) |
| 231 | +#define fm_foreach_tuple_arg_comma(macro, arg, ...) \ |
| 232 | + fm_foreach_tuple_arg_join(fm_comma, macro, arg, __VA_ARGS__) |
212 | 233 |
|
213 | 234 | #define fm_eval_foreach(macro, ...) \
|
214 |
| - fm_eval(fm_foreach(macro, __VA_ARGS__)) |
| 235 | + fm_eval(fm_foreach(macro, __VA_ARGS__)) |
215 | 236 |
|
216 | 237 | #define fm_eval_foreach_comma(macro, ...) \
|
217 |
| - fm_eval(fm_foreach_comma(macro, __VA_ARGS__)) |
| 238 | + fm_eval(fm_foreach_comma(macro, __VA_ARGS__)) |
218 | 239 |
|
219 | 240 | #define fm_eval_foreach_arg(macro, arg, ...) \
|
220 |
| - fm_eval(fm_foreach_arg(macro, arg, __VA_ARGS__)) |
| 241 | + fm_eval(fm_foreach_arg(macro, arg, __VA_ARGS__)) |
221 | 242 |
|
222 | 243 | #define fm_eval_tuples(macro, ...) \
|
223 |
| - fm_eval(fm_foreach_tuple(macro, __VA_ARGS__)) |
| 244 | + fm_eval(fm_foreach_tuple(macro, __VA_ARGS__)) |
224 | 245 |
|
225 | 246 | #define fm_eval_tuples_arg(macro, arg, ...) \
|
226 |
| - fm_eval(fm_foreach_tuple_arg(macro, arg, __VA_ARGS__)) |
| 247 | + fm_eval(fm_foreach_tuple_arg(macro, arg, __VA_ARGS__)) |
227 | 248 |
|
228 | 249 | #define fm_eval_tuples_comma(macro, ...) \
|
229 |
| - fm_eval(fm_foreach_tuple_comma(macro, __VA_ARGS__)) |
| 250 | + fm_eval(fm_foreach_tuple_comma(macro, __VA_ARGS__)) |
230 | 251 |
|
231 | 252 | #define fm__dumb_require_semicolon \
|
232 | 253 | struct __dumb_struct_declaration_for_semicolon
|
|
0 commit comments