2023-07-03 16:47:00 +00:00
|
|
|
|
|
|
|
|
|
|
|
#define PARENS ()
|
|
|
|
|
|
|
|
// Rescan macro tokens 256 times
|
|
|
|
#define EXPAND(...) EXPAND4(EXPAND4(EXPAND4(EXPAND4(__VA_ARGS__))))
|
|
|
|
#define EXPAND4(...) EXPAND3(EXPAND3(EXPAND3(EXPAND3(__VA_ARGS__))))
|
|
|
|
#define EXPAND3(...) EXPAND2(EXPAND2(EXPAND2(EXPAND2(__VA_ARGS__))))
|
|
|
|
#define EXPAND2(...) EXPAND1(EXPAND1(EXPAND1(EXPAND1(__VA_ARGS__))))
|
|
|
|
#define EXPAND1(...) __VA_ARGS__
|
|
|
|
|
|
|
|
#define FOR_EACH(macro, name, ...) \
|
|
|
|
__VA_OPT__(EXPAND(FOR_EACH_HELPER(macro, name, __VA_ARGS__)))
|
|
|
|
#define FOR_EACH_HELPER(macro, name, a1, ...) \
|
|
|
|
macro(name, a1) \
|
|
|
|
__VA_OPT__(FOR_EACH_AGAIN PARENS(macro, name, __VA_ARGS__))
|
|
|
|
#define FOR_EACH_AGAIN() FOR_EACH_HELPER
|
|
|
|
|
|
|
|
#define ENUM_VARIANT0(name, val) name = val,
|
|
|
|
#define ENUM_VARIANT(name, tuple) ENUM_VARIANT0 tuple
|
|
|
|
|
|
|
|
#define TUPLE(x, y) x, y
|
|
|
|
|
|
|
|
#define LPAREN (
|
|
|
|
|
|
|
|
#define TO_STRING_CASE0(type, name, val) \
|
|
|
|
case type::name: \
|
|
|
|
return #name;
|
|
|
|
#define TO_STRING_CASE(type, tuple) TO_STRING_CASE0 LPAREN type, TUPLE tuple)
|
|
|
|
|
|
|
|
#define FROM_INT_CASE0(type, name, val) \
|
|
|
|
case val: \
|
|
|
|
return type::name;
|
|
|
|
#define FROM_INT_CASE(type, tuple) FROM_INT_CASE0 LPAREN type, TUPLE tuple)
|
|
|
|
|
|
|
|
#define ENUM(name, type, ...) \
|
|
|
|
enum class name : type { \
|
|
|
|
FOR_EACH(ENUM_VARIANT, name, __VA_ARGS__) \
|
|
|
|
}; \
|
|
|
|
inline const char* \
|
|
|
|
name##_to_string(name _e) \
|
|
|
|
{ \
|
|
|
|
switch (_e) { \
|
|
|
|
FOR_EACH(TO_STRING_CASE, name, __VA_ARGS__) \
|
|
|
|
default: \
|
|
|
|
return "UNKNOWN"; \
|
|
|
|
} \
|
|
|
|
} \
|
|
|
|
inline name \
|
|
|
|
to_##name(type _t, name _unknown) \
|
|
|
|
{ \
|
|
|
|
switch (_t) { \
|
|
|
|
FOR_EACH(FROM_INT_CASE, name, __VA_ARGS__) \
|
|
|
|
default: \
|
|
|
|
return _unknown; \
|
|
|
|
} \
|
|
|
|
}
|
2024-01-19 23:24:16 +00:00
|
|
|
|
|
|
|
#define SUM_TYPE_UNION_MEMBER0(type, var) type var;
|
|
|
|
#define SUM_TYPE_UNION_MEMBER(name, tuple) SUM_TYPE_UNION_MEMBER0 tuple
|
|
|
|
|
|
|
|
#define SUM_TYPE_ENUM_MEMBER0(type, var) var,
|
|
|
|
#define SUM_TYPE_ENUM_MEMBER(name, tuple) SUM_TYPE_ENUM_MEMBER0 tuple
|
|
|
|
|
|
|
|
#define SUM_TYPE_CONSTRUCTOR0(name, type, val) \
|
|
|
|
name(type&& arg) \
|
|
|
|
: tag(Tag::val) \
|
|
|
|
{ \
|
|
|
|
value.val = std::move(arg); \
|
|
|
|
}
|
|
|
|
#define SUM_TYPE_CONSTRUCTOR(name, tuple) SUM_TYPE_CONSTRUCTOR0 LPAREN name, TUPLE tuple)
|
|
|
|
|
|
|
|
#define SUM_TYPE(name, ...) \
|
|
|
|
class name { \
|
|
|
|
public: \
|
|
|
|
union { \
|
|
|
|
FOR_EACH(SUM_TYPE_UNION_MEMBER, name, __VA_ARGS__) \
|
|
|
|
} value; \
|
|
|
|
enum class Tag { \
|
|
|
|
void_, \
|
|
|
|
FOR_EACH(SUM_TYPE_ENUM_MEMBER, name, __VA_ARGS__) \
|
|
|
|
} tag; \
|
|
|
|
\
|
|
|
|
name() \
|
|
|
|
: tag(Tag::void_) \
|
|
|
|
{ \
|
|
|
|
} \
|
|
|
|
FOR_EACH(SUM_TYPE_CONSTRUCTOR, name, __VA_ARGS__) \
|
|
|
|
};
|