16 char const* functorOpNameLegacy(
FunctorOp op) {
98 char const* functorOpNameSymbol(
FunctorOp op) {
129 default:
return functorOpNameLegacy(op);
135 #define OP_1(op, t0, tDst) \
136 { functorOpNameSymbol(FOp::op), {TAttr::t0}, TAttr::tDst, FOp::op }
137 #define OP_2(op, t0, t1, tDst, multi) \
138 { functorOpNameSymbol(FOp::op), {TAttr::t0, TAttr::t1}, TAttr::tDst, FOp::op, false, multi }
139 #define OP_3(op, t0, t1, t2, tDst, multi) \
140 { functorOpNameSymbol(FOp::op), {TAttr::t0, TAttr::t1, TAttr::t2}, TAttr::tDst, FOp::op, false, multi }
142 #define OP_1_MONO(op, ty) OP_1(op, ty, ty)
143 #define OP_2_MONO(op, ty, multi) OP_2(op, ty, ty, ty, multi)
144 #define OP_3_MONO(op, ty, multi) OP_3(op, ty, ty, ty, ty, multi)
145 #define OP_1_INTEGRAL(op) OP_1_MONO(op, Signed), OP_1_MONO(U##op, Unsigned)
146 #define OP_2_INTEGRAL_EX(op, multi) OP_2_MONO(op, Signed, multi), OP_2_MONO(U##op, Unsigned, multi)
147 #define OP_3_INTEGRAL_EX(op, multi) OP_3_MONO(op, Signed, multi), OP_3_MONO(U##op, Unsigned, multi)
148 #define OP_2_INTEGRAL(op) OP_2_INTEGRAL_EX(op, false)
149 #define OP_2_NUMERIC(op) OP_2_MONO(F##op, Float, false), OP_2_INTEGRAL(op)
150 #define OP_2_NUMERIC_MULTI(op) OP_2_MONO(F##op, Float, true), OP_2_INTEGRAL_EX(op, true)
151 #define OP_3_NUMERIC_MULTI(op) OP_3_MONO(F##op, Float, true), OP_3_INTEGRAL_EX(op, true)
152 #define VARIADIC(op, ty) \
153 { functorOpNameLegacy(FOp::op), {TAttr::ty}, TAttr::ty, FOp::op, true }
154 #define VARIADIC_ORDERED(op) \
155 VARIADIC(op, Signed), VARIADIC(U##op, Unsigned), VARIADIC(F##op, Float), VARIADIC(S##op, Symbol)
157 const std::vector<IntrinsicFunctorInfo> FUNCTOR_INTRINSICS = {
161 OP_1(F2I, Float, Signed),
162 OP_1(F2S, Float, Symbol),
163 OP_1(F2U, Float, Unsigned),
165 OP_1(I2F, Signed, Float),
166 OP_1(I2S, Signed, Symbol),
167 OP_1(I2U, Signed, Unsigned),
169 OP_1(S2F, Symbol, Float),
170 OP_1(S2I, Symbol, Signed),
171 OP_1(S2U, Symbol, Unsigned),
173 OP_1(U2F, Unsigned, Float),
174 OP_1(U2I, Unsigned, Signed),
175 OP_1(U2S, Unsigned, Symbol),
204 OP_1(ORD, Signed, Signed),
205 OP_1(ORD, Unsigned, Signed),
206 OP_1(ORD, Float, Signed),
207 OP_1(ORD, Symbol, Signed),
208 OP_1(ORD, Record, Signed),
211 OP_1(STRLEN, Symbol, Signed),
212 OP_3(SUBSTR, Symbol, Signed, Signed, Symbol,
false),
215 template <
typename F>
218 for (
auto&& x : FUNCTOR_INTRINSICS)
219 if (f(x)) xs.push_back(x);
225 return pickFunctors([&](
auto&& x) {
return x.op == op; });
229 return pickFunctors([&](
auto&& x) {
return x.symbol == symbol; });
233 return pickFunctors([&](
auto&& x) {
235 x.variadic ?
all_of(params, [&](
auto t) {
return t == x.params[0]; }) : x.params == params;
236 return x.symbol == symbol && paramsOk;
241 return any_of(FUNCTOR_INTRINSICS, [&](
auto&& x) {
242 auto arityOk = x.params.size() == arity || x.variadic;
243 return x.symbol == symbol && arityOk;
249 return xs.front().get().multipleResults;
253 assert(!symbol.empty() &&
"no functors have an empty name");
256 if (symbol ==
"!")
return false;
257 if (symbol ==
"~")
return false;
258 auto alphaUnderscore = symbol ==
"_" || isalpha(symbol.at(0));
259 return !alphaUnderscore;
286 return os << functorOpNameLegacy(op);
292 struct FUNCTOR_INTRINSIC_SANCHECKER {
293 FUNCTOR_INTRINSIC_SANCHECKER() {
294 std::map<FunctorOp, IntrinsicFunctors> byOp;
295 for (
auto&& x : FUNCTOR_INTRINSICS) {
296 byOp[x.op].push_back(x);
297 assert((!x.variadic || x.params.size() == 1) &&
"variadics must have a single parameter");
300 for (
auto&& [_, xs] : byOp) {
301 auto&& multiResult = xs.front().get().multipleResults;
302 auto&& symbol = xs.front().get().symbol;
303 for (
auto&& x : xs) {
306 assert(x.get().multipleResults == multiResult &&
307 "all overloads for op must have same `multipleResults`");
309 assert(x.get().symbol == symbol &&
"all overloads for op must have same `symbol`");
313 } FUNCTOR_INTRINSIC_SANCHECKER;