diff options
author | John Hodge <tpg@mutabah.net> | 2015-03-19 10:49:11 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2015-03-19 10:49:11 +0800 |
commit | 2eb0ef0364591ff9ad30fcefa795bfd8eba17dea (patch) | |
tree | 2e53c6ee1034f90b853f1d194722e268d70dd02f /src/include | |
parent | ca09043bcadaacd7256a9b5d60b2358434743da6 (diff) | |
download | mrust-2eb0ef0364591ff9ad30fcefa795bfd8eba17dea.tar.gz |
EVIL tagged union hackjob
Diffstat (limited to 'src/include')
-rw-r--r-- | src/include/tagged_enum.hpp | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/src/include/tagged_enum.hpp b/src/include/tagged_enum.hpp new file mode 100644 index 00000000..07bd5881 --- /dev/null +++ b/src/include/tagged_enum.hpp @@ -0,0 +1,102 @@ + +#define TE_DATANAME(name) Data_##name +#define ENUM_CONS(__tag, __type) \ + static self_t make_##__tag(__type v) \ + {\ + self_t ret;\ + ret.m_tag = __tag;\ + new (ret.m_data) __type( ::std::move(v) ); \ + return ::std::move(ret); \ + }\ + bool is_##__tag() const { return m_tag == __tag; } \ + const __type& as_##__tag() const { return reinterpret_cast<const __type&>(m_data); } \ + __type& as_##__tag() { return reinterpret_cast<__type&>(m_data); } \ + __type unwrap_##__tag() { return ::std::move(reinterpret_cast<__type&>(m_data)); } \ + +#define TE_CONS(name, _) ENUM_CONS(name, TE_DATANAME(name)) +#define TE_CONS2(a, b) TE_CONS a TE_CONS b +#define TE_CONS3(a, ...) TE_CONS a TE_CONS2(__VA_ARGS__) +#define TE_CONS4(a, ...) TE_CONS a TE_CONS3(__VA_ARGS__) +#define TE_CONS5(a, ...) TE_CONS a TE_CONS4(__VA_ARGS__) +#define TE_CONS6(a, ...) TE_CONS a TE_CONS5(__VA_ARGS__) + +// Sizes of structures +#define TE_SO(name, _) sizeof(TE_DATANAME(name)) +#define MAX2(a, b) (a < b ? b : a) +#define MAXS2(a, b) (TE_SO a < TE_SO b ? TE_SO b : TE_SO a) +#define MAXS3(a, b, c) MAX2(MAXS2(a, b), TE_SO c) +#define MAXS4(a, b, c, d) MAX2(MAXS2(a, b), MAXS2(c, d)) +#define MAXS5(a, b, c, d, e) MAX2(MAXS3(a, b, c), MAXS2(d, e)) +#define MAXS6(a, b, c, d, e, f) MAX2(MAXS3(a, b, c), MAXS3(d, e, f)) + +// Type definitions +#define TE_EXP(...) __VA_ARGS__ +#define TE_TYPEDEF(name, content) struct TE_DATANAME(name) { TE_EXP content }; +#define TE_TYPEDEF2(_1, _2) TE_TYPEDEF _1 TE_TYPEDEF _2 +#define TE_TYPEDEF3(_1, ...) TE_TYPEDEF _1 TE_TYPEDEF2(__VA_ARGS__) +#define TE_TYPEDEF4(_1, ...) TE_TYPEDEF _1 TE_TYPEDEF3(__VA_ARGS__) +#define TE_TYPEDEF5(_1, ...) TE_TYPEDEF _1 TE_TYPEDEF4(__VA_ARGS__) +#define TE_TYPEDEF6(_1, ...) TE_TYPEDEF _1 TE_TYPEDEF5(__VA_ARGS__) + +#define TE_TAG(name, _) name, +#define TE_TAG2(_1,_2) TE_TAG _1 TE_TAG _2 +#define TE_TAG3(_1,...) TE_TAG _1 TE_TAG2(__VA_ARGS__) +#define TE_TAG4(_1,...) TE_TAG _1 TE_TAG3(__VA_ARGS__) +#define TE_TAG5(_1,...) TE_TAG _1 TE_TAG4(__VA_ARGS__) +#define TE_TAG6(_1,...) TE_TAG _1 TE_TAG5(__VA_ARGS__) + +#define TE_DEST_CASE(tag, _) case tag: as_##tag().~TE_DATANAME(tag)(); break; +#define TE_DEST_CASE2(_1,_2) TE_DEST_CASE _1 TE_DEST_CASE _2 +#define TE_DEST_CASE3(_1, ...) TE_DEST_CASE _1 TE_DEST_CASE2(__VA_ARGS__) +#define TE_DEST_CASE4(_1, ...) TE_DEST_CASE _1 TE_DEST_CASE3(__VA_ARGS__) +#define TE_DEST_CASE5(_1, ...) TE_DEST_CASE _1 TE_DEST_CASE4(__VA_ARGS__) +#define TE_DEST_CASE6(_1, ...) TE_DEST_CASE _1 TE_DEST_CASE5(__VA_ARGS__) + +#define TE_MOVE_CASE(tag, _) case tag: new(m_data) TE_DATANAME(tag)(x.unwrap_##tag()); break; +#define TE_MOVE_CASE2(_1,_2) TE_MOVE_CASE _1 TE_MOVE_CASE _2 +#define TE_MOVE_CASE3(_1, ...) TE_MOVE_CASE _1 TE_MOVE_CASE2(__VA_ARGS__) +#define TE_MOVE_CASE4(_1, ...) TE_MOVE_CASE _1 TE_MOVE_CASE3(__VA_ARGS__) +#define TE_MOVE_CASE5(_1, ...) TE_MOVE_CASE _1 TE_MOVE_CASE4(__VA_ARGS__) +#define TE_MOVE_CASE6(_1, ...) TE_MOVE_CASE _1 TE_MOVE_CASE5(__VA_ARGS__) + +// Macro to obtain a numbered macro for argument counts +#define TE_GM(SUF,_1,_2,_3,_4,_5,_6,COUNT,...) SUF##COUNT + +#define MAXS(...) TE_GM(MAXS ,__VA_ARGS__,6,5,4,3,2)(__VA_ARGS__) +#define TE_TYPEDEFS(...) TE_GM(TE_TYPEDEF ,__VA_ARGS__,6,5,4,3,2)(__VA_ARGS__) +#define TE_TAGS(...) TE_GM(TE_TAG ,__VA_ARGS__,6,5,4,3,2)(__VA_ARGS__) +#define TE_DEST_CASES(...) TE_GM(TE_DEST_CASE,__VA_ARGS__,6,5,4,3,2)(__VA_ARGS__) +#define TE_MOVE_CASES(...) TE_GM(TE_MOVE_CASE,__VA_ARGS__,6,5,4,3,2)(__VA_ARGS__) +#define TE_CONSS(...) TE_GM(TE_CONS ,__VA_ARGS__,6,5,4,3,2)(__VA_ARGS__) + +#define TAGGED_ENUM(_name, _def, ...) \ +class _name { \ + typedef _name self_t; \ + TE_TYPEDEFS(__VA_ARGS__) \ + enum Tag { \ + TE_TAGS(__VA_ARGS__)\ + } m_tag; \ + char m_data[MAXS(__VA_ARGS__)]; \ +public:\ + _name(): m_tag(_def) {}\ + _name(_name&& x): m_tag(x.m_tag) { x.m_tag = _def; switch(m_tag) { TE_MOVE_CASES(__VA_ARGS__) } } \ + ~_name() { switch(m_tag) { TE_DEST_CASES(__VA_ARGS__) } } \ + TE_CONSS(__VA_ARGS__) \ +} + +#define ENUM3(_name, _def, _t1, _v1, _t2, _v2, _t3, _v3)\ + TAGGED_ENUM(_name, _def,\ + (_t1, _v1), \ + (_t2, _v2), \ + (_t3, _v3) \ + ) + +/* + ENUM5(Inner, Any, + Any, bool, + Tuple, ::std::vector<Pattern>, + TupleStruct, struct { Path path; ::std::vector<Pattern> sub_patterns; }, + Value, ::std::unique_ptr<ExprNode>, + Range, struct { ::std::unique_ptr<ExprNode> left; ::std::unique_ptr<ExprNode> right; } + ) m_contents; +*/ |