/src/hobbes/include/hobbes/reflect.H
Line | Count | Source |
1 | | /* |
2 | | * reflect : common definitions to help introduce zero-overhead reflective types (consistent with algebraic data types in hobbes) and write their meta-data descriptions |
3 | | * |
4 | | * A macro 'DEFINE_STRUCT(T, (T0, fn0), ... (TN, fnN))' is included to be equivalent to '{fn0:T0, ..., fnN:TN}' |
5 | | * A macro 'DEFINE_VARIANT(T, (cn0, T0), ... (cnN, TN))' is included to be equivalent to '|cn0:T0, ..., cnN:TN|' |
6 | | * A type 'tuple<T0, ..., TN>' is included to be equivalent to '(T0 * ... * TN)' and have standard memory layout |
7 | | * A type 'variant<T0, ..., TN>' is included to be equivalent to '(T0 + ... + TN)' and have standard memory layout |
8 | | * |
9 | | * functions are also included to read and write serialized type descriptions |
10 | | */ |
11 | | |
12 | | #ifndef HOBBES_REFLECT_H_INCLUDED |
13 | | #define HOBBES_REFLECT_H_INCLUDED |
14 | | |
15 | | #include <cassert> |
16 | | #include <cstdint> |
17 | | #include <cstring> |
18 | | #include <cxxabi.h> |
19 | | #include <iostream> |
20 | | #include <map> |
21 | | #include <memory> |
22 | | #include <sstream> |
23 | | #include <stdexcept> |
24 | | #include <string> |
25 | | #include <type_traits> |
26 | | #include <vector> |
27 | | |
28 | | #if defined(__APPLE__) && defined(__MACH__) |
29 | | #include <fcntl.h> |
30 | | #include <unistd.h> |
31 | | |
32 | | // macOS doesn't support fallocate |
33 | | inline int posix_fallocate(int fd, off_t o, off_t dsz) { |
34 | | return ftruncate(fd, o+dsz); |
35 | | } |
36 | | #endif |
37 | | |
38 | | namespace hobbes { |
39 | | |
40 | | // basic string utilities used here |
41 | | namespace string { |
42 | | template <typename T> |
43 | 0 | inline std::string from(const T& x) { |
44 | 0 | std::ostringstream ss; |
45 | 0 | ss << x; |
46 | 0 | return ss.str(); |
47 | 0 | } Unexecuted instantiation: std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > hobbes::string::from<unsigned long>(unsigned long const&) Unexecuted instantiation: std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > hobbes::string::from<unsigned short>(unsigned short const&) |
48 | | |
49 | | // pretty-print C++ type names |
50 | | template <typename T> |
51 | | inline std::string demangle() { |
52 | | if (const char* tn = typeid(T).name()) { |
53 | | int s = 0; |
54 | | if (char* dmn = abi::__cxa_demangle(tn, nullptr, nullptr, &s)) { |
55 | | std::string r(dmn); |
56 | | free(dmn); |
57 | | return r; |
58 | | } else { |
59 | | return std::string(tn); |
60 | | } |
61 | | } else { |
62 | | return ""; |
63 | | } |
64 | | } |
65 | | |
66 | | // tokenize strings |
67 | | using seq = std::vector<std::string>; |
68 | 0 | inline seq csplit(const std::string& str, const std::string& pivot) { |
69 | 0 | using size_type = std::string::size_type; |
70 | 0 | |
71 | 0 | seq ret; |
72 | 0 | size_type mp = 0; |
73 | 0 | |
74 | 0 | while (mp != std::string::npos) { |
75 | 0 | size_type nmp = str.find(pivot, mp); |
76 | 0 | |
77 | 0 | if (nmp == std::string::npos) { |
78 | 0 | ret.push_back(str.substr(mp, str.size() - mp)); |
79 | 0 | mp = nmp; |
80 | 0 | } else { |
81 | 0 | ret.push_back(str.substr(mp, nmp - mp)); |
82 | 0 | mp = nmp + pivot.size(); |
83 | 0 | } |
84 | 0 | } |
85 | 0 | |
86 | 0 | return ret; |
87 | 0 | } |
88 | | |
89 | | using pair = std::pair<std::string, std::string>; |
90 | 0 | inline pair rsplit(const std::string& s, const std::string& ss) { |
91 | 0 | size_t p = s.rfind(ss); |
92 | 0 | if (p == std::string::npos) { |
93 | 0 | return pair("", s); |
94 | 0 | } else { |
95 | 0 | return pair(s.substr(0, p), s.substr(p + ss.size(), s.size())); |
96 | 0 | } |
97 | 0 | } |
98 | | |
99 | 0 | inline std::string cdelim(const seq& ss, const std::string& d) { |
100 | 0 | if (!ss.empty()) { |
101 | 0 | std::ostringstream x; |
102 | 0 | x << ss[0]; |
103 | 0 | for (size_t i = 1; i < ss.size(); ++i) { |
104 | 0 | x << d << ss[i]; |
105 | 0 | } |
106 | 0 | return x.str(); |
107 | 0 | } else { |
108 | 0 | return ""; |
109 | 0 | } |
110 | 0 | } |
111 | | } |
112 | | |
113 | | using int128_t = __int128; |
114 | | |
115 | | // very basic macro metaprogramming |
116 | | #define PRIV_HPPF_FIRST(a, ...) a |
117 | | #define PRIV_HPPF_SECOND(a, b, ...) b |
118 | | #define PRIV_HPPF_JOIN(a,b) a ## b |
119 | | #define PRIV_HPPF_IS_NEGATE(...) PRIV_HPPF_SECOND(__VA_ARGS__, 0) |
120 | | #define PRIV_HPPF_NOT(x) PRIV_HPPF_IS_NEGATE(PRIV_HPPF_JOIN(PRIV_HPPF_SNOT_, x)) |
121 | | #define PRIV_HPPF_SNOT_0 NEGATE, 1 |
122 | | #define PRIV_HPPF_BOOL(x) PRIV_HPPF_NOT(PRIV_HPPF_NOT(x)) |
123 | | #define PRIV_HPPF_IF_ELSE(condition) PRIV_HPPF_SIF_ELSE(PRIV_HPPF_BOOL(condition)) |
124 | | #define PRIV_HPPF_SIF_ELSE(condition) PRIV_HPPF_JOIN(PRIV_HPPF_SIF_, condition) |
125 | | #define PRIV_HPPF_SIF_1(...) __VA_ARGS__ PRIV_HPPF_SIF_1_ELSE |
126 | | #define PRIV_HPPF_SIF_0(...) PRIV_HPPF_SIF_0_ELSE |
127 | | #define PRIV_HPPF_SIF_1_ELSE(...) |
128 | | #define PRIV_HPPF_SIF_0_ELSE(...) __VA_ARGS__ |
129 | | #define PRIV_HPPF_EMPTY() |
130 | 3 | #define PRIV_HPPF_EVAL(...) PRIV_HPPF_EVAL256(__VA_ARGS__) |
131 | 3 | #define PRIV_HPPF_EVAL256(...) PRIV_HPPF_EVAL128(PRIV_HPPF_EVAL128(__VA_ARGS__)) |
132 | 3 | #define PRIV_HPPF_EVAL128(...) PRIV_HPPF_EVAL64(PRIV_HPPF_EVAL64(__VA_ARGS__)) |
133 | 3 | #define PRIV_HPPF_EVAL64(...) PRIV_HPPF_EVAL32(PRIV_HPPF_EVAL32(__VA_ARGS__)) |
134 | 3 | #define PRIV_HPPF_EVAL32(...) PRIV_HPPF_EVAL16(PRIV_HPPF_EVAL16(__VA_ARGS__)) |
135 | 3 | #define PRIV_HPPF_EVAL16(...) PRIV_HPPF_EVAL8(PRIV_HPPF_EVAL8(__VA_ARGS__)) |
136 | 3 | #define PRIV_HPPF_EVAL8(...) PRIV_HPPF_EVAL4(PRIV_HPPF_EVAL4(__VA_ARGS__)) |
137 | 3 | #define PRIV_HPPF_EVAL4(...) PRIV_HPPF_EVAL2(PRIV_HPPF_EVAL2(__VA_ARGS__)) |
138 | 3 | #define PRIV_HPPF_EVAL2(...) PRIV_HPPF_EVAL1(PRIV_HPPF_EVAL1(__VA_ARGS__)) |
139 | 3 | #define PRIV_HPPF_EVAL1(...) __VA_ARGS__ |
140 | | #define PRIV_HPPF_DEFER2(m) m PRIV_HPPF_EMPTY PRIV_HPPF_EMPTY()() |
141 | | #define PRIV_HPPF_HAS_PARGS(...) PRIV_HPPF_BOOL(PRIV_HPPF_FIRST(PRIV_HPPF_SEOAP_ __VA_ARGS__)()) |
142 | | #define PRIV_HPPF_SEOAP_(...) PRIV_HPPF_BOOL(PRIV_HPPF_FIRST(PRIV_HPPF_SEOA_ __VA_ARGS__)()) |
143 | | #define PRIV_HPPF_SEOA_() 0 |
144 | 3 | #define PRIV_HPPF_MAP(f, VS...) PRIV_HPPF_EVAL(PRIV_HPPF_MAPP(f, VS)) |
145 | | #define PRIV_HPPF_MAPP(f, H, T...) \ |
146 | | f H \ |
147 | | PRIV_HPPF_IF_ELSE(PRIV_HPPF_HAS_PARGS(T))( \ |
148 | | PRIV_HPPF_DEFER2(PRIV_HPPF_SMAPP)()(f, T) \ |
149 | | )( \ |
150 | | ) |
151 | | #define PRIV_HPPF_SMAPP() PRIV_HPPF_MAPP |
152 | | #define PRIV_HPPF_MAPL(f, VS...) PRIV_HPPF_EVAL(PRIV_HPPF_MAPLP(f, VS)) |
153 | | #define PRIV_HPPF_MAPLP(f, H, T...) \ |
154 | | f(H) \ |
155 | | PRIV_HPPF_IF_ELSE(PRIV_HPPF_HAS_PARGS(T))( \ |
156 | | PRIV_HPPF_DEFER2(PRIV_HPPF_SMAPLP)()(f, T) \ |
157 | | )( \ |
158 | | ) |
159 | | #define PRIV_HPPF_SMAPLP() PRIV_HPPF_MAPLP |
160 | | |
161 | | // basic compile-time strings |
162 | | template <size_t N> |
163 | | constexpr char at(size_t i, const char (&s)[N]) { |
164 | | return (i < N) ? s[i] : '\0'; |
165 | | } |
166 | | template <size_t N> |
167 | | constexpr size_t at8S(size_t i, size_t k, const char (&s)[N]) { |
168 | | return (k==8) ? 0 : ((static_cast<size_t>(at(i+k,s))<<(8*k))|at8S(i,k+1,s)); |
169 | | } |
170 | | template <size_t N> |
171 | | constexpr size_t at8(size_t i, const char (&s)[N]) { |
172 | | return at8S(i, 0, s); |
173 | | } |
174 | | template <size_t... pcs> |
175 | | struct strpack { |
176 | | static const char* str() { |
177 | | constexpr size_t msg[] = {pcs...}; |
178 | | static_assert(msg[(sizeof(msg)/sizeof(msg[0]))-1] == 0, "compile-time string larger than internal max limit (this limit can be bumped in storage.H)"); |
179 | | |
180 | | static const size_t smsg[] = {pcs...}; |
181 | | return reinterpret_cast<const char*>(smsg); |
182 | | } |
183 | | }; |
184 | | #define PRIV_HPPF_TSTR32(i,s) ::hobbes::at8(i+(8*0),s),::hobbes::at8(i+(8*1),s),::hobbes::at8(i+(8*2),s),::hobbes::at8(i+(8*3),s) |
185 | | #define PRIV_HPPF_TSTR128(i,s) PRIV_HPPF_TSTR32(i+(32*0),s),PRIV_HPPF_TSTR32(i+(32*1),s),PRIV_HPPF_TSTR32(i+(32*2),s),PRIV_HPPF_TSTR32(i+(32*3),s) |
186 | | #define PRIV_HPPF_TSTR512(i,s) PRIV_HPPF_TSTR128(i+(128*0),s),PRIV_HPPF_TSTR128(i+(128*1),s),PRIV_HPPF_TSTR128(i+(128*2),s),PRIV_HPPF_TSTR128(i+(128*3),s) |
187 | | #define PRIV_HPPF_TSTR1024(i,s) PRIV_HPPF_TSTR512(i+(512*0),s),PRIV_HPPF_TSTR512(i+(512*1),s) |
188 | | #define PRIV_HPPF_TSTR(s) ::hobbes::strpack<PRIV_HPPF_TSTR1024(0,s)> |
189 | | |
190 | | // value-level bool -> type-level bool |
191 | | template <bool f> struct tbool { }; |
192 | | template <> struct tbool<true> { using type = void; }; |
193 | | |
194 | | // test to see if a type(s) can be printed |
195 | | template <typename T, class = decltype(std::declval<std::ostream&>() << std::declval<T>())> |
196 | | std::true_type has_shl_ostream_defined(const T&); |
197 | | std::false_type has_shl_ostream_defined(...); |
198 | | |
199 | | template <typename T> |
200 | | struct can_show_type { |
201 | | static const bool value = decltype(has_shl_ostream_defined(std::declval<T>()))::value; |
202 | | }; |
203 | | |
204 | | template <typename ... Ts> |
205 | | struct can_show_types { static const bool value = true; }; |
206 | | template <typename T, typename ... Ts> |
207 | | struct can_show_types<T, Ts...> { static const bool value = can_show_type<T>::value && can_show_types<Ts...>::value; }; |
208 | | |
209 | | // a standard layout tuple type |
210 | 0 | constexpr size_t alignTo(size_t x, size_t a) { |
211 | 0 | return (x % a == 0) ? x : (a * (1 + x/a)); |
212 | 0 | } |
213 | 0 | constexpr size_t szmax(size_t x, size_t y) { |
214 | 0 | return (x > y) ? x : y; |
215 | 0 | } |
216 | | |
217 | | template <size_t index, size_t base, typename ... Fields> |
218 | | struct offsetInfo { |
219 | | static const size_t offset = base; |
220 | | static const size_t maxAlignment = 1; |
221 | | static const size_t size = 0; |
222 | | static const bool packed = true; // but technically unit can't be memcopied |
223 | | |
224 | | static void defInit (uint8_t*) { } |
225 | 0 | static void initFrom(uint8_t*, const Fields&...) { } |
226 | 0 | static void copyFrom(uint8_t*, const uint8_t*) { } |
227 | 0 | static void destroy (uint8_t*) { } |
228 | | static bool eq (const uint8_t*, const uint8_t*) { return true; } // all units are equal |
229 | | }; |
230 | | template <size_t index, size_t base, typename Field, typename ... Fields> |
231 | | struct offsetInfo<index, base, Field, Fields...> { |
232 | | static const size_t offset = alignTo(base, alignof(Field)); |
233 | | |
234 | | using tail = offsetInfo<index + 1, offset + sizeof(Field), Fields...>; |
235 | | |
236 | | static const size_t maxAlignment = szmax(alignof(Field), tail::maxAlignment); |
237 | | static const size_t size = (offset-base) + sizeof(Field) + tail::size; |
238 | | static const bool packed = (offset == base) && tail::packed; |
239 | | |
240 | | static void defInit(uint8_t* b) { |
241 | | new (b+offset) Field(); |
242 | | tail::defInit(b); |
243 | | } |
244 | 0 | static void initFrom(uint8_t* b, const Field& f, const Fields&... fs) { |
245 | 0 | new (b+offset) Field(f); |
246 | 0 | tail::initFrom(b, fs...); |
247 | 0 | } Unexecuted instantiation: hobbes::offsetInfo<0ul, 0ul, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned int, std::shared_ptr<hobbes::ty::D> >::initFrom(unsigned char*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int const&, std::shared_ptr<hobbes::ty::D> const&) Unexecuted instantiation: hobbes::offsetInfo<1ul, 32ul, unsigned int, std::shared_ptr<hobbes::ty::D> >::initFrom(unsigned char*, unsigned int const&, std::shared_ptr<hobbes::ty::D> const&) Unexecuted instantiation: hobbes::offsetInfo<2ul, 36ul, std::shared_ptr<hobbes::ty::D> >::initFrom(unsigned char*, std::shared_ptr<hobbes::ty::D> const&) Unexecuted instantiation: hobbes::offsetInfo<0ul, 0ul, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int, std::shared_ptr<hobbes::ty::D> >::initFrom(unsigned char*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int const&, std::shared_ptr<hobbes::ty::D> const&) Unexecuted instantiation: hobbes::offsetInfo<1ul, 32ul, int, std::shared_ptr<hobbes::ty::D> >::initFrom(unsigned char*, int const&, std::shared_ptr<hobbes::ty::D> const&) |
248 | 0 | static void copyFrom(uint8_t* lhs, const uint8_t* rhs) { |
249 | 0 | new (lhs+offset) Field(*reinterpret_cast<const Field*>(rhs+offset)); |
250 | 0 | tail::copyFrom(lhs, rhs); |
251 | 0 | } Unexecuted instantiation: hobbes::offsetInfo<0ul, 0ul, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned int, std::shared_ptr<hobbes::ty::D> >::copyFrom(unsigned char*, unsigned char const*) Unexecuted instantiation: hobbes::offsetInfo<1ul, 32ul, unsigned int, std::shared_ptr<hobbes::ty::D> >::copyFrom(unsigned char*, unsigned char const*) Unexecuted instantiation: hobbes::offsetInfo<2ul, 36ul, std::shared_ptr<hobbes::ty::D> >::copyFrom(unsigned char*, unsigned char const*) Unexecuted instantiation: hobbes::offsetInfo<0ul, 0ul, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int, std::shared_ptr<hobbes::ty::D> >::copyFrom(unsigned char*, unsigned char const*) Unexecuted instantiation: hobbes::offsetInfo<1ul, 32ul, int, std::shared_ptr<hobbes::ty::D> >::copyFrom(unsigned char*, unsigned char const*) |
252 | 0 | static void destroy(uint8_t* b) { |
253 | 0 | reinterpret_cast<Field*>(b+offset)->~Field(); |
254 | 0 | tail::destroy(b); |
255 | 0 | } Unexecuted instantiation: hobbes::offsetInfo<0ul, 0ul, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned int, std::shared_ptr<hobbes::ty::D> >::destroy(unsigned char*) Unexecuted instantiation: hobbes::offsetInfo<1ul, 32ul, unsigned int, std::shared_ptr<hobbes::ty::D> >::destroy(unsigned char*) Unexecuted instantiation: hobbes::offsetInfo<2ul, 36ul, std::shared_ptr<hobbes::ty::D> >::destroy(unsigned char*) Unexecuted instantiation: hobbes::offsetInfo<0ul, 0ul, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int, std::shared_ptr<hobbes::ty::D> >::destroy(unsigned char*) Unexecuted instantiation: hobbes::offsetInfo<1ul, 32ul, int, std::shared_ptr<hobbes::ty::D> >::destroy(unsigned char*) |
256 | | static bool eq(const uint8_t* lhs, const uint8_t* rhs) { |
257 | | return (*reinterpret_cast<const Field*>(lhs+offset) == *reinterpret_cast<const Field*>(rhs+offset)) ? tail::eq(lhs,rhs) : false; |
258 | | } |
259 | | }; |
260 | | |
261 | | template <size_t n, typename Offs> |
262 | | struct offsetAt : public offsetAt<n-1, typename Offs::tail> { }; |
263 | | template <typename Offs> |
264 | | struct offsetAt<0, Offs> { static const size_t value = Offs::offset; }; |
265 | | |
266 | | template <size_t, typename ... Fields> |
267 | | struct nth { }; |
268 | | template <typename Field, typename ... Fields> |
269 | | struct nth<0, Field, Fields...> { using type = Field; }; |
270 | | template <size_t n, typename Field, typename ... Fields> |
271 | | struct nth<n, Field, Fields...> : nth<n-1, Fields...> { }; |
272 | | |
273 | | template <typename ... Fields> |
274 | | struct tuple { |
275 | | using offs = offsetInfo<0, 0, Fields...>; |
276 | | static const size_t alignment = offs::maxAlignment; |
277 | | static const size_t size = alignTo(offs::size, offs::maxAlignment); |
278 | | static const bool packed = (size == offs::size) && offs::packed; |
279 | | static const size_t count = sizeof...(Fields); |
280 | | uint8_t buffer[size]; |
281 | | |
282 | | tuple() { |
283 | | offs::defInit(this->buffer); |
284 | | } |
285 | | tuple(const Fields&... fs) { |
286 | | offs::initFrom(this->buffer, fs...); |
287 | | } |
288 | | tuple(const tuple<Fields...>& rhs) { |
289 | | offs::copyFrom(this->buffer, rhs.buffer); |
290 | | } |
291 | | ~tuple() { |
292 | | offs::destroy(this->buffer); |
293 | | } |
294 | | tuple<Fields...>& operator=(const tuple<Fields...>& rhs) { |
295 | | if (this != &rhs) { |
296 | | offs::destroy(this->buffer); |
297 | | offs::copyFrom(this->buffer, rhs.buffer); |
298 | | } |
299 | | return *this; |
300 | | } |
301 | | |
302 | | template <size_t k> |
303 | 0 | typename nth<k, Fields...>::type* atP() { |
304 | 0 | return reinterpret_cast<typename nth<k, Fields...>::type*>(this->buffer + offsetAt<k, offs>::value); |
305 | 0 | } Unexecuted instantiation: hobbes::nth<0ul, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int, std::shared_ptr<hobbes::ty::D> >::type* hobbes::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int, std::shared_ptr<hobbes::ty::D> >::atP<0ul>() Unexecuted instantiation: hobbes::nth<2ul, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int, std::shared_ptr<hobbes::ty::D> >::type* hobbes::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int, std::shared_ptr<hobbes::ty::D> >::atP<2ul>() |
306 | | template <size_t k> |
307 | 0 | typename nth<k, Fields...>::type& at() { return *atP<k>(); }Unexecuted instantiation: hobbes::nth<0ul, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int, std::shared_ptr<hobbes::ty::D> >::type& hobbes::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int, std::shared_ptr<hobbes::ty::D> >::at<0ul>() Unexecuted instantiation: hobbes::nth<2ul, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int, std::shared_ptr<hobbes::ty::D> >::type& hobbes::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int, std::shared_ptr<hobbes::ty::D> >::at<2ul>() |
308 | | template <size_t k> |
309 | 0 | const typename nth<k, Fields...>::type* atP() const { |
310 | 0 | return reinterpret_cast<const typename nth<k, Fields...>::type*>(this->buffer + offsetAt<k, offs>::value); |
311 | 0 | } Unexecuted instantiation: hobbes::nth<0ul, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned int, std::shared_ptr<hobbes::ty::D> >::type const* hobbes::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned int, std::shared_ptr<hobbes::ty::D> >::atP<0ul>() const Unexecuted instantiation: hobbes::nth<1ul, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned int, std::shared_ptr<hobbes::ty::D> >::type const* hobbes::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned int, std::shared_ptr<hobbes::ty::D> >::atP<1ul>() const Unexecuted instantiation: hobbes::nth<2ul, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned int, std::shared_ptr<hobbes::ty::D> >::type const* hobbes::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned int, std::shared_ptr<hobbes::ty::D> >::atP<2ul>() const Unexecuted instantiation: hobbes::nth<0ul, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int, std::shared_ptr<hobbes::ty::D> >::type const* hobbes::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int, std::shared_ptr<hobbes::ty::D> >::atP<0ul>() const Unexecuted instantiation: hobbes::nth<2ul, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int, std::shared_ptr<hobbes::ty::D> >::type const* hobbes::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int, std::shared_ptr<hobbes::ty::D> >::atP<2ul>() const Unexecuted instantiation: hobbes::nth<1ul, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int, std::shared_ptr<hobbes::ty::D> >::type const* hobbes::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int, std::shared_ptr<hobbes::ty::D> >::atP<1ul>() const |
312 | | template <size_t k> |
313 | 0 | const typename nth<k, Fields...>::type& at() const { return *atP<k>(); }Unexecuted instantiation: hobbes::nth<0ul, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned int, std::shared_ptr<hobbes::ty::D> >::type const& hobbes::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned int, std::shared_ptr<hobbes::ty::D> >::at<0ul>() const Unexecuted instantiation: hobbes::nth<1ul, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned int, std::shared_ptr<hobbes::ty::D> >::type const& hobbes::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned int, std::shared_ptr<hobbes::ty::D> >::at<1ul>() const Unexecuted instantiation: hobbes::nth<2ul, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned int, std::shared_ptr<hobbes::ty::D> >::type const& hobbes::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned int, std::shared_ptr<hobbes::ty::D> >::at<2ul>() const Unexecuted instantiation: hobbes::nth<0ul, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int, std::shared_ptr<hobbes::ty::D> >::type const& hobbes::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int, std::shared_ptr<hobbes::ty::D> >::at<0ul>() const Unexecuted instantiation: hobbes::nth<2ul, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int, std::shared_ptr<hobbes::ty::D> >::type const& hobbes::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int, std::shared_ptr<hobbes::ty::D> >::at<2ul>() const Unexecuted instantiation: hobbes::nth<1ul, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int, std::shared_ptr<hobbes::ty::D> >::type const& hobbes::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int, std::shared_ptr<hobbes::ty::D> >::at<1ul>() const |
314 | | }; |
315 | | template <> |
316 | | struct tuple<> { |
317 | | static const size_t alignment = 1; |
318 | | static const size_t size = 0; |
319 | | |
320 | | tuple() = default; |
321 | | tuple(const tuple<>&) = default; |
322 | | ~tuple() = default; |
323 | | |
324 | | tuple<>& operator=(const tuple<>&) = default; |
325 | | }; |
326 | | |
327 | | template <typename ... Fields> |
328 | | inline bool operator==(const tuple<Fields...>& lhs, const tuple<Fields...>& rhs) { |
329 | | return offsetInfo<0, 0, Fields...>::eq(lhs.buffer, rhs.buffer); |
330 | | } |
331 | | |
332 | | template <size_t i, typename T> |
333 | | struct tupType { }; |
334 | | template <size_t i, typename ... Ts> |
335 | | struct tupType<i, tuple<Ts...>> { using type = typename nth<i, Ts...>::type; }; |
336 | | |
337 | | // map a function over a tuple's types (useful for structurally-derived types) |
338 | | template <typename ... Ts> |
339 | | struct concatT { }; |
340 | | template <typename ... Ts1, typename ... Ts2, typename ... Rest> |
341 | | struct concatT<tuple<Ts1...>, tuple<Ts2...>, Rest...> { |
342 | | using type = typename concatT<tuple<Ts1..., Ts2...>, Rest...>::type; |
343 | | }; |
344 | | template <typename ... Ts> |
345 | | struct concatT<tuple<Ts...>> { |
346 | | using type = tuple<Ts...>; |
347 | | }; |
348 | | |
349 | | template <template <typename T> class F, typename X> |
350 | | struct fmap { }; |
351 | | template <template <typename T> class F, typename H, typename ... Rest> |
352 | | struct fmap<F, tuple<H, Rest...>> { |
353 | | using type = typename concatT<tuple<typename F<H>::type>, typename fmap<F, tuple<Rest...>>::type>::type; |
354 | | }; |
355 | | template <template <typename T> class F, typename H> |
356 | | struct fmap<F, tuple<H>> { |
357 | | using type = tuple<typename F<H>::type>; |
358 | | }; |
359 | | template <template <typename T> class F> |
360 | | struct fmap<F, tuple<>> { |
361 | | using type = tuple<>; |
362 | | }; |
363 | | |
364 | | // show a tuple iff its fields can be shown |
365 | | template <size_t i, size_t n, typename ... Ts> |
366 | | struct ShowTuple { |
367 | | static void show(std::ostream& o, const tuple<Ts...>& v) { |
368 | | if (i > 0) o << ", "; |
369 | | o << v.template at<i>(); |
370 | | ShowTuple<i+1, n, Ts...>::show(o, v); |
371 | | } |
372 | | }; |
373 | | template <size_t n, typename ... Ts> |
374 | | struct ShowTuple<n, n, Ts...> { |
375 | | static void show(std::ostream&, const tuple<Ts...>&) { } |
376 | | }; |
377 | | |
378 | | template <typename ... Ts> |
379 | | inline typename std::enable_if<can_show_types<Ts...>::value, std::ostream&>::type operator<<(std::ostream& o, const tuple<Ts...>& v) { |
380 | | o << "("; |
381 | | ShowTuple<0, tuple<Ts...>::count, Ts...>::show(o, v); |
382 | | o << ")"; |
383 | | return o; |
384 | | } |
385 | | |
386 | | // the trivially true proposition -- ie: C's "void" with its one value constructible |
387 | | struct unit { |
388 | | unit() = default; |
389 | 0 | bool operator==(const unit&) const { return true; } |
390 | 0 | bool operator< (const unit&) const { return false; } |
391 | | }; |
392 | 0 | inline std::ostream& operator<<(std::ostream& o, const unit&) { o << "()"; return o; } |
393 | | |
394 | | // drop the first type from a sequence to determine a tuple type |
395 | | // (useful with these macro expansions where we can't distinguish first and rest values) |
396 | | template <typename ... Ts> struct tupleTail { }; |
397 | | template <typename T, typename ... Ts> struct tupleTail<T, Ts...> { using type = tuple<Ts...>; }; |
398 | | |
399 | | // reflective structs |
400 | | #define PRIV_HPPF_STRUCT_FIELD(t, n) t n; |
401 | | #define PRIV_HPPF_STRUCT_FIELD_VISIT(t, n) v.template visit<t>(#n); |
402 | | #define PRIV_HPPF_STRUCT_FIELD_EQ(t, n) && this->n == rhs.n |
403 | | #define PRIV_HPPF_STRUCT_FIELD_TYARGL(t, n) , t |
404 | | #define PRIV_HPPF_STRUCT_FIELD_NLOOKUP(t, n) if (o == idx) { return #n; } ++o; |
405 | | #define PRIV_HPPF_STRUCT_FIELD_SHOW(_, n) ss << ", " << #n << "=" << v.n; |
406 | | |
407 | | #define DEFINE_STRUCT(T, FIELDS...) \ |
408 | | struct T { \ |
409 | | PRIV_HPPF_MAP(PRIV_HPPF_STRUCT_FIELD, FIELDS) /* struct fields */ \ |
410 | | static const bool is_hmeta_struct = true; /* identify this type as a struct */ \ |
411 | | typedef typename ::hobbes::tupleTail<int PRIV_HPPF_MAP(PRIV_HPPF_STRUCT_FIELD_TYARGL, FIELDS)>::type as_tuple_type; \ |
412 | 0 | static std::string _hmeta_struct_type_name() { return #T; } \Unexecuted instantiation: hobbes::RegionState::_hmeta_struct_type_name[abi:cxx11]() Unexecuted instantiation: hobbes::CTM::_hmeta_struct_type_name[abi:cxx11]() Unexecuted instantiation: hobbes::fregion::cbatch::_hmeta_struct_type_name[abi:cxx11]() Unexecuted instantiation: hobbes::fregion::cbatchseg::_hmeta_struct_type_name[abi:cxx11]() Unexecuted instantiation: hobbes::DFAStateRep::_hmeta_struct_type_name[abi:cxx11]() |
413 | | template <typename V> \ |
414 | 3 | static void meta(V& v) { \ |
415 | 3 | PRIV_HPPF_MAP(PRIV_HPPF_STRUCT_FIELD_VISIT, FIELDS) \ |
416 | 3 | } \ void hobbes::RegionState::meta<hobbes::inferFieldTypeF>(hobbes::inferFieldTypeF&) Line | Count | Source | 414 | 1 | static void meta(V& v) { \ | 415 | 1 | PRIV_HPPF_MAP(PRIV_HPPF_STRUCT_FIELD_VISIT, FIELDS) \ | 416 | 1 | } \ |
void hobbes::CTM::meta<hobbes::inferFieldTypeF>(hobbes::inferFieldTypeF&) Line | Count | Source | 414 | 2 | static void meta(V& v) { \ | 415 | 2 | PRIV_HPPF_MAP(PRIV_HPPF_STRUCT_FIELD_VISIT, FIELDS) \ | 416 | 2 | } \ |
Unexecuted instantiation: void hobbes::fregion::cbatchseg::meta<hobbes::fregion::defStructF>(hobbes::fregion::defStructF&) Unexecuted instantiation: void hobbes::fregion::cbatch::meta<hobbes::fregion::defStructF>(hobbes::fregion::defStructF&) Unexecuted instantiation: void hobbes::DFAStateRep::meta<hobbes::inferFieldTypeF>(hobbes::inferFieldTypeF&) |
417 | | template <size_t idx> \ |
418 | | static const char* _hmeta_field_name() { \ |
419 | | size_t o = 0; \ |
420 | | PRIV_HPPF_MAP(PRIV_HPPF_STRUCT_FIELD_NLOOKUP, FIELDS) \ |
421 | | return "???"; \ |
422 | | } \ |
423 | | template <typename X> \ |
424 | | inline typename std::enable_if<std::is_base_of<X, T>::value, bool>::type operator==(const X& rhs) const { \ |
425 | | return true PRIV_HPPF_MAP(PRIV_HPPF_STRUCT_FIELD_EQ, FIELDS); \ |
426 | | } \ |
427 | | template <typename X> \ |
428 | | friend inline typename std::enable_if<std::is_base_of<X,T>::value && hobbes::can_show_type<typename T::as_tuple_type>::value,std::ostream&>::type operator<<(std::ostream& o, const X& v) { \ |
429 | | using namespace hobbes; \ |
430 | | std::ostringstream ss; \ |
431 | | PRIV_HPPF_MAP(PRIV_HPPF_STRUCT_FIELD_SHOW, FIELDS); \ |
432 | | o << "{ " << ss.str().substr(2) << " }"; \ |
433 | | return o; \ |
434 | | } \ |
435 | | } |
436 | | |
437 | | // reflective enumerations |
438 | | #define PRIV_HPPF_ENUM_CTOR_DEF(n) n , |
439 | | #define PRIV_HPPF_ENUM_CTOR_CTOR(n) static const SelfT n() { return SelfT(SelfT::Enum::n); } |
440 | | #define PRIV_HPPF_ENUM_META(n) m.push_back(std::pair<std::string,uint32_t>(#n, static_cast<uint32_t>(SelfT::Enum::n))); |
441 | | #define PRIV_HPPF_ENUM_SHOW(n) case SelfT::Enum::n : return "|" #n "|"; |
442 | | #define PRIV_HPPF_ENUM_CTOR_COUNT(n) +1 |
443 | | |
444 | | #define DEFINE_PACKED_ENUM(T, R, CTORS...) \ |
445 | | struct T { \ |
446 | | static const bool is_hmeta_enum = true; \ |
447 | | static const uint32_t ctorCount = 0 PRIV_HPPF_MAP(PRIV_HPPF_ENUM_CTOR_COUNT, CTORS); \ |
448 | | typedef R rep_t; \ |
449 | | enum class Enum : R { \ |
450 | | PRIV_HPPF_MAP(PRIV_HPPF_ENUM_CTOR_DEF, CTORS) \ |
451 | | COUNT \ |
452 | | }; \ |
453 | | Enum value; \ |
454 | | T() : value() { } \ |
455 | | T(Enum v) : value(v) { } \ |
456 | | T& operator=(Enum v) { this->value = v; return *this; } \ |
457 | | operator Enum() const { return this->value; } \ |
458 | | typedef T SelfT; \ |
459 | | PRIV_HPPF_MAP(PRIV_HPPF_ENUM_CTOR_CTOR, CTORS) \ |
460 | | typedef std::vector<std::pair<std::string,R>> MetaSeq; \ |
461 | | static MetaSeq meta() { \ |
462 | | MetaSeq m; \ |
463 | | PRIV_HPPF_MAP(PRIV_HPPF_ENUM_META, CTORS); \ |
464 | | return m; \ |
465 | | } \ |
466 | | bool operator==(const T& rhs) const { return this->value == rhs.value; } \ |
467 | | std::string show() const { switch (this->value) { PRIV_HPPF_MAP(PRIV_HPPF_ENUM_SHOW, CTORS); default: return "?"; } } \ |
468 | | friend inline std::ostream& operator<<(std::ostream& o, const T& v) { o << v.show(); return o; } \ |
469 | | } |
470 | | |
471 | | #define DEFINE_ENUM(T, CTORS...) DEFINE_PACKED_ENUM(T, uint32_t, CTORS) |
472 | | |
473 | | // standard layout sum type with efficient dispatch |
474 | | template <bool f, typename T, typename F> |
475 | | struct TIfF { }; |
476 | | template <typename T, typename F> |
477 | | struct TIfF<true, T, F> { using type = T; }; |
478 | | template <typename T, typename F> |
479 | | struct TIfF<false, T, F> { using type = F; }; |
480 | | template <typename T> |
481 | | struct TSizeOfF { static const size_t value = sizeof(T); }; |
482 | | template <typename T> |
483 | | struct TAlignOfF { static const size_t value = alignof(T); }; |
484 | | template <template <class> class SzP, typename T0, typename ... Ts> |
485 | | struct maximum { static const size_t value = SzP<T0>::value; using type = T0; }; |
486 | | template <template <class> class SzP, typename T0, typename T1, typename ... Ts> |
487 | | struct maximum<SzP, T0, T1, Ts...> : public maximum<SzP, typename TIfF<SzP<T1>::value < SzP<T0>::value, T0, T1>::type, Ts...> { }; |
488 | | |
489 | | template <typename T, typename ... Ctors> |
490 | | struct CtorIndexOf { static const uint32_t value = 0; }; |
491 | | template <typename T, typename ... Ctors> |
492 | | struct CtorIndexOf<T, T, Ctors...> { static const uint32_t value = 0; }; |
493 | | template <typename T, typename Ctor, typename ... Ctors> |
494 | | struct CtorIndexOf<T, Ctor, Ctors...> { static const uint32_t value = 1 + CtorIndexOf<T, Ctors...>::value; }; |
495 | | template <typename T, typename ... Ts> |
496 | | struct First { using type = T; }; |
497 | | |
498 | | template <size_t i, typename R, template <size_t,class,class> class F, typename U, typename A, typename ... Ctors> |
499 | | struct variantAppInit { |
500 | | }; |
501 | | template <size_t i, typename R, template <size_t,class,class> class F, typename U, typename ... Args, typename ... Ctors> |
502 | | struct variantAppInit<i, R, F, U, tuple<Args...>, Ctors...> { |
503 | | using PF = R (*)(void *, Args...); |
504 | 10 | static bool init(PF*) { return true; }hobbes::variantAppInit<2ul, void, hobbes::variantPayloadDtor, void, hobbes::tuple<>>::init(void (**)(void*)) Line | Count | Source | 504 | 5 | static bool init(PF*) { return true; } |
hobbes::variantAppInit<2ul, void, hobbes::variantPayloadCtor, void, hobbes::tuple<void const*>>::init(void (**)(void*, void const*)) Line | Count | Source | 504 | 5 | static bool init(PF*) { return true; } |
|
505 | | }; |
506 | | template <size_t i, typename R, template <size_t,class,class> class F, typename U, typename ... Args, typename Ctor, typename ... Ctors> |
507 | | struct variantAppInit<i, R, F, U, tuple<Args...>, Ctor, Ctors...> { |
508 | | using PF = R (*)(void *, Args...); |
509 | | |
510 | | // Reach the constructor-typed function through a thunk that genuinely has |
511 | | // the erased signature. Casting the function pointer itself and calling |
512 | | // through the mismatched type is undefined behavior even where the ABI |
513 | | // agrees, and -fsanitize=function traps on it. |
514 | | // |
515 | | // The thunk calls fn rather than binding its address, which would accept |
516 | | // implicitly convertible arguments and hide a signature mismatch, so |
517 | | // require the exact signature explicitly -- the check the previous |
518 | | // 'TPF tpf = &F<i, Ctor, U>::fn;' assignment performed implicitly. |
519 | | static_assert( |
520 | | std::is_same<decltype(&F<i, Ctor, U>::fn), R (*)(Ctor *, Args...)>::value, |
521 | | "variant payload function must have signature R(Ctor*, Args...)"); |
522 | | |
523 | 959k | static R thunk(void* p, Args... args) { |
524 | 959k | return F<i, Ctor, U>::fn(reinterpret_cast<Ctor*>(p), args...); |
525 | 959k | } hobbes::variantAppInit<0ul, void, hobbes::variantPayloadDtor, void, hobbes::tuple<>, hobbes::unit, std::shared_ptr<hobbes::TCInstance> >::thunk(void*) Line | Count | Source | 523 | 1.08k | static R thunk(void* p, Args... args) { | 524 | 1.08k | return F<i, Ctor, U>::fn(reinterpret_cast<Ctor*>(p), args...); | 525 | 1.08k | } |
hobbes::variantAppInit<1ul, void, hobbes::variantPayloadDtor, void, hobbes::tuple<>, std::shared_ptr<hobbes::TCInstance> >::thunk(void*) Line | Count | Source | 523 | 866 | static R thunk(void* p, Args... args) { | 524 | 866 | return F<i, Ctor, U>::fn(reinterpret_cast<Ctor*>(p), args...); | 525 | 866 | } |
hobbes::variantAppInit<0ul, void, hobbes::variantPayloadDtor, void, hobbes::tuple<>, hobbes::unit, std::vector<std::shared_ptr<hobbes::TCInstanceFn>, std::allocator<std::shared_ptr<hobbes::TCInstanceFn> > > >::thunk(void*) Line | Count | Source | 523 | 1.73k | static R thunk(void* p, Args... args) { | 524 | 1.73k | return F<i, Ctor, U>::fn(reinterpret_cast<Ctor*>(p), args...); | 525 | 1.73k | } |
hobbes::variantAppInit<1ul, void, hobbes::variantPayloadDtor, void, hobbes::tuple<>, std::vector<std::shared_ptr<hobbes::TCInstanceFn>, std::allocator<std::shared_ptr<hobbes::TCInstanceFn> > > >::thunk(void*) Line | Count | Source | 523 | 1.14k | static R thunk(void* p, Args... args) { | 524 | 1.14k | return F<i, Ctor, U>::fn(reinterpret_cast<Ctor*>(p), args...); | 525 | 1.14k | } |
hobbes::variantAppInit<0ul, void, hobbes::variantPayloadDtor, void, hobbes::tuple<>, hobbes::unit, bool>::thunk(void*) Line | Count | Source | 523 | 9.02k | static R thunk(void* p, Args... args) { | 524 | 9.02k | return F<i, Ctor, U>::fn(reinterpret_cast<Ctor*>(p), args...); | 525 | 9.02k | } |
hobbes::variantAppInit<1ul, void, hobbes::variantPayloadDtor, void, hobbes::tuple<>, bool>::thunk(void*) Line | Count | Source | 523 | 5.74k | static R thunk(void* p, Args... args) { | 524 | 5.74k | return F<i, Ctor, U>::fn(reinterpret_cast<Ctor*>(p), args...); | 525 | 5.74k | } |
Unexecuted instantiation: hobbes::variantAppInit<0ul, void, hobbes::variantPayloadCtor, void, hobbes::tuple<void const*>, hobbes::unit, bool>::thunk(void*, void const*) hobbes::variantAppInit<1ul, void, hobbes::variantPayloadCtor, void, hobbes::tuple<void const*>, bool>::thunk(void*, void const*) Line | Count | Source | 523 | 2.87k | static R thunk(void* p, Args... args) { | 524 | 2.87k | return F<i, Ctor, U>::fn(reinterpret_cast<Ctor*>(p), args...); | 525 | 2.87k | } |
Unexecuted instantiation: hobbes::variantAppInit<0ul, void, hobbes::variantPayloadCtor, void, hobbes::tuple<void const*>, hobbes::unit, std::shared_ptr<hobbes::TCInstance> >::thunk(void*, void const*) hobbes::variantAppInit<1ul, void, hobbes::variantPayloadCtor, void, hobbes::tuple<void const*>, std::shared_ptr<hobbes::TCInstance> >::thunk(void*, void const*) Line | Count | Source | 523 | 433 | static R thunk(void* p, Args... args) { | 524 | 433 | return F<i, Ctor, U>::fn(reinterpret_cast<Ctor*>(p), args...); | 525 | 433 | } |
Unexecuted instantiation: hobbes::variantAppInit<0ul, void, hobbes::variantPayloadCtor, void, hobbes::tuple<void const*>, hobbes::unit, std::vector<std::shared_ptr<hobbes::TCInstanceFn>, std::allocator<std::shared_ptr<hobbes::TCInstanceFn> > > >::thunk(void*, void const*) hobbes::variantAppInit<1ul, void, hobbes::variantPayloadCtor, void, hobbes::tuple<void const*>, std::vector<std::shared_ptr<hobbes::TCInstanceFn>, std::allocator<std::shared_ptr<hobbes::TCInstanceFn> > > >::thunk(void*, void const*) Line | Count | Source | 523 | 572 | static R thunk(void* p, Args... args) { | 524 | 572 | return F<i, Ctor, U>::fn(reinterpret_cast<Ctor*>(p), args...); | 525 | 572 | } |
hobbes::variantAppInit<0ul, void, hobbes::variantPayloadDtor, void, hobbes::tuple<>, hobbes::unit, std::shared_ptr<hobbes::Constraint> >::thunk(void*) Line | Count | Source | 523 | 114k | static R thunk(void* p, Args... args) { | 524 | 114k | return F<i, Ctor, U>::fn(reinterpret_cast<Ctor*>(p), args...); | 525 | 114k | } |
hobbes::variantAppInit<1ul, void, hobbes::variantPayloadDtor, void, hobbes::tuple<>, std::shared_ptr<hobbes::Constraint> >::thunk(void*) Line | Count | Source | 523 | 58.8k | static R thunk(void* p, Args... args) { | 524 | 58.8k | return F<i, Ctor, U>::fn(reinterpret_cast<Ctor*>(p), args...); | 525 | 58.8k | } |
hobbes::variantAppInit<0ul, void, hobbes::variantPayloadCtor, void, hobbes::tuple<void const*>, hobbes::unit, std::shared_ptr<hobbes::MonoType> >::thunk(void*, void const*) Line | Count | Source | 523 | 128k | static R thunk(void* p, Args... args) { | 524 | 128k | return F<i, Ctor, U>::fn(reinterpret_cast<Ctor*>(p), args...); | 525 | 128k | } |
hobbes::variantAppInit<1ul, void, hobbes::variantPayloadCtor, void, hobbes::tuple<void const*>, std::shared_ptr<hobbes::MonoType> >::thunk(void*, void const*) Line | Count | Source | 523 | 170k | static R thunk(void* p, Args... args) { | 524 | 170k | return F<i, Ctor, U>::fn(reinterpret_cast<Ctor*>(p), args...); | 525 | 170k | } |
hobbes::variantAppInit<0ul, void, hobbes::variantPayloadDtor, void, hobbes::tuple<>, hobbes::unit, std::shared_ptr<hobbes::MonoType> >::thunk(void*) Line | Count | Source | 523 | 199k | static R thunk(void* p, Args... args) { | 524 | 199k | return F<i, Ctor, U>::fn(reinterpret_cast<Ctor*>(p), args...); | 525 | 199k | } |
hobbes::variantAppInit<1ul, void, hobbes::variantPayloadDtor, void, hobbes::tuple<>, std::shared_ptr<hobbes::MonoType> >::thunk(void*) Line | Count | Source | 523 | 234k | static R thunk(void* p, Args... args) { | 524 | 234k | return F<i, Ctor, U>::fn(reinterpret_cast<Ctor*>(p), args...); | 525 | 234k | } |
Unexecuted instantiation: hobbes::variantAppInit<0ul, void, hobbes::variantPayloadCtor, void, hobbes::tuple<void const*>, hobbes::unit, std::shared_ptr<hobbes::Constraint> >::thunk(void*, void const*) hobbes::variantAppInit<1ul, void, hobbes::variantPayloadCtor, void, hobbes::tuple<void const*>, std::shared_ptr<hobbes::Constraint> >::thunk(void*, void const*) Line | Count | Source | 523 | 29.4k | static R thunk(void* p, Args... args) { | 524 | 29.4k | return F<i, Ctor, U>::fn(reinterpret_cast<Ctor*>(p), args...); | 525 | 29.4k | } |
Unexecuted instantiation: hobbes::variantAppInit<0ul, void, hobbes::variantPayloadDtor, void, hobbes::tuple<>, int, long>::thunk(void*) Unexecuted instantiation: hobbes::variantAppInit<1ul, void, hobbes::variantPayloadDtor, void, hobbes::tuple<>, long>::thunk(void*) Unexecuted instantiation: hobbes::variantAppInit<0ul, void, hobbes::variantPayloadCtor, void, hobbes::tuple<void const*>, int, long>::thunk(void*, void const*) Unexecuted instantiation: hobbes::variantAppInit<1ul, void, hobbes::variantPayloadCtor, void, hobbes::tuple<void const*>, long>::thunk(void*, void const*) |
526 | | |
527 | 20 | static bool init(PF* pfs) { |
528 | 20 | pfs[i] = &thunk; |
529 | 20 | return variantAppInit<i+1, R, F, U, tuple<Args...>, Ctors...>::init(pfs); |
530 | 20 | } hobbes::variantAppInit<0ul, void, hobbes::variantPayloadDtor, void, hobbes::tuple<>, hobbes::unit, std::shared_ptr<hobbes::TCInstance> >::init(void (**)(void*)) Line | Count | Source | 527 | 1 | static bool init(PF* pfs) { | 528 | 1 | pfs[i] = &thunk; | 529 | 1 | return variantAppInit<i+1, R, F, U, tuple<Args...>, Ctors...>::init(pfs); | 530 | 1 | } |
hobbes::variantAppInit<1ul, void, hobbes::variantPayloadDtor, void, hobbes::tuple<>, std::shared_ptr<hobbes::TCInstance> >::init(void (**)(void*)) Line | Count | Source | 527 | 1 | static bool init(PF* pfs) { | 528 | 1 | pfs[i] = &thunk; | 529 | 1 | return variantAppInit<i+1, R, F, U, tuple<Args...>, Ctors...>::init(pfs); | 530 | 1 | } |
hobbes::variantAppInit<0ul, void, hobbes::variantPayloadDtor, void, hobbes::tuple<>, hobbes::unit, std::vector<std::shared_ptr<hobbes::TCInstanceFn>, std::allocator<std::shared_ptr<hobbes::TCInstanceFn> > > >::init(void (**)(void*)) Line | Count | Source | 527 | 1 | static bool init(PF* pfs) { | 528 | 1 | pfs[i] = &thunk; | 529 | 1 | return variantAppInit<i+1, R, F, U, tuple<Args...>, Ctors...>::init(pfs); | 530 | 1 | } |
hobbes::variantAppInit<1ul, void, hobbes::variantPayloadDtor, void, hobbes::tuple<>, std::vector<std::shared_ptr<hobbes::TCInstanceFn>, std::allocator<std::shared_ptr<hobbes::TCInstanceFn> > > >::init(void (**)(void*)) Line | Count | Source | 527 | 1 | static bool init(PF* pfs) { | 528 | 1 | pfs[i] = &thunk; | 529 | 1 | return variantAppInit<i+1, R, F, U, tuple<Args...>, Ctors...>::init(pfs); | 530 | 1 | } |
hobbes::variantAppInit<0ul, void, hobbes::variantPayloadDtor, void, hobbes::tuple<>, hobbes::unit, bool>::init(void (**)(void*)) Line | Count | Source | 527 | 1 | static bool init(PF* pfs) { | 528 | 1 | pfs[i] = &thunk; | 529 | 1 | return variantAppInit<i+1, R, F, U, tuple<Args...>, Ctors...>::init(pfs); | 530 | 1 | } |
hobbes::variantAppInit<1ul, void, hobbes::variantPayloadDtor, void, hobbes::tuple<>, bool>::init(void (**)(void*)) Line | Count | Source | 527 | 1 | static bool init(PF* pfs) { | 528 | 1 | pfs[i] = &thunk; | 529 | 1 | return variantAppInit<i+1, R, F, U, tuple<Args...>, Ctors...>::init(pfs); | 530 | 1 | } |
hobbes::variantAppInit<0ul, void, hobbes::variantPayloadCtor, void, hobbes::tuple<void const*>, hobbes::unit, bool>::init(void (**)(void*, void const*)) Line | Count | Source | 527 | 1 | static bool init(PF* pfs) { | 528 | 1 | pfs[i] = &thunk; | 529 | 1 | return variantAppInit<i+1, R, F, U, tuple<Args...>, Ctors...>::init(pfs); | 530 | 1 | } |
hobbes::variantAppInit<1ul, void, hobbes::variantPayloadCtor, void, hobbes::tuple<void const*>, bool>::init(void (**)(void*, void const*)) Line | Count | Source | 527 | 1 | static bool init(PF* pfs) { | 528 | 1 | pfs[i] = &thunk; | 529 | 1 | return variantAppInit<i+1, R, F, U, tuple<Args...>, Ctors...>::init(pfs); | 530 | 1 | } |
hobbes::variantAppInit<0ul, void, hobbes::variantPayloadCtor, void, hobbes::tuple<void const*>, hobbes::unit, std::shared_ptr<hobbes::TCInstance> >::init(void (**)(void*, void const*)) Line | Count | Source | 527 | 1 | static bool init(PF* pfs) { | 528 | 1 | pfs[i] = &thunk; | 529 | 1 | return variantAppInit<i+1, R, F, U, tuple<Args...>, Ctors...>::init(pfs); | 530 | 1 | } |
hobbes::variantAppInit<1ul, void, hobbes::variantPayloadCtor, void, hobbes::tuple<void const*>, std::shared_ptr<hobbes::TCInstance> >::init(void (**)(void*, void const*)) Line | Count | Source | 527 | 1 | static bool init(PF* pfs) { | 528 | 1 | pfs[i] = &thunk; | 529 | 1 | return variantAppInit<i+1, R, F, U, tuple<Args...>, Ctors...>::init(pfs); | 530 | 1 | } |
hobbes::variantAppInit<0ul, void, hobbes::variantPayloadCtor, void, hobbes::tuple<void const*>, hobbes::unit, std::vector<std::shared_ptr<hobbes::TCInstanceFn>, std::allocator<std::shared_ptr<hobbes::TCInstanceFn> > > >::init(void (**)(void*, void const*)) Line | Count | Source | 527 | 1 | static bool init(PF* pfs) { | 528 | 1 | pfs[i] = &thunk; | 529 | 1 | return variantAppInit<i+1, R, F, U, tuple<Args...>, Ctors...>::init(pfs); | 530 | 1 | } |
hobbes::variantAppInit<1ul, void, hobbes::variantPayloadCtor, void, hobbes::tuple<void const*>, std::vector<std::shared_ptr<hobbes::TCInstanceFn>, std::allocator<std::shared_ptr<hobbes::TCInstanceFn> > > >::init(void (**)(void*, void const*)) Line | Count | Source | 527 | 1 | static bool init(PF* pfs) { | 528 | 1 | pfs[i] = &thunk; | 529 | 1 | return variantAppInit<i+1, R, F, U, tuple<Args...>, Ctors...>::init(pfs); | 530 | 1 | } |
hobbes::variantAppInit<0ul, void, hobbes::variantPayloadDtor, void, hobbes::tuple<>, hobbes::unit, std::shared_ptr<hobbes::Constraint> >::init(void (**)(void*)) Line | Count | Source | 527 | 1 | static bool init(PF* pfs) { | 528 | 1 | pfs[i] = &thunk; | 529 | 1 | return variantAppInit<i+1, R, F, U, tuple<Args...>, Ctors...>::init(pfs); | 530 | 1 | } |
hobbes::variantAppInit<1ul, void, hobbes::variantPayloadDtor, void, hobbes::tuple<>, std::shared_ptr<hobbes::Constraint> >::init(void (**)(void*)) Line | Count | Source | 527 | 1 | static bool init(PF* pfs) { | 528 | 1 | pfs[i] = &thunk; | 529 | 1 | return variantAppInit<i+1, R, F, U, tuple<Args...>, Ctors...>::init(pfs); | 530 | 1 | } |
hobbes::variantAppInit<0ul, void, hobbes::variantPayloadCtor, void, hobbes::tuple<void const*>, hobbes::unit, std::shared_ptr<hobbes::MonoType> >::init(void (**)(void*, void const*)) Line | Count | Source | 527 | 1 | static bool init(PF* pfs) { | 528 | 1 | pfs[i] = &thunk; | 529 | 1 | return variantAppInit<i+1, R, F, U, tuple<Args...>, Ctors...>::init(pfs); | 530 | 1 | } |
hobbes::variantAppInit<1ul, void, hobbes::variantPayloadCtor, void, hobbes::tuple<void const*>, std::shared_ptr<hobbes::MonoType> >::init(void (**)(void*, void const*)) Line | Count | Source | 527 | 1 | static bool init(PF* pfs) { | 528 | 1 | pfs[i] = &thunk; | 529 | 1 | return variantAppInit<i+1, R, F, U, tuple<Args...>, Ctors...>::init(pfs); | 530 | 1 | } |
hobbes::variantAppInit<0ul, void, hobbes::variantPayloadDtor, void, hobbes::tuple<>, hobbes::unit, std::shared_ptr<hobbes::MonoType> >::init(void (**)(void*)) Line | Count | Source | 527 | 1 | static bool init(PF* pfs) { | 528 | 1 | pfs[i] = &thunk; | 529 | 1 | return variantAppInit<i+1, R, F, U, tuple<Args...>, Ctors...>::init(pfs); | 530 | 1 | } |
hobbes::variantAppInit<1ul, void, hobbes::variantPayloadDtor, void, hobbes::tuple<>, std::shared_ptr<hobbes::MonoType> >::init(void (**)(void*)) Line | Count | Source | 527 | 1 | static bool init(PF* pfs) { | 528 | 1 | pfs[i] = &thunk; | 529 | 1 | return variantAppInit<i+1, R, F, U, tuple<Args...>, Ctors...>::init(pfs); | 530 | 1 | } |
hobbes::variantAppInit<0ul, void, hobbes::variantPayloadCtor, void, hobbes::tuple<void const*>, hobbes::unit, std::shared_ptr<hobbes::Constraint> >::init(void (**)(void*, void const*)) Line | Count | Source | 527 | 1 | static bool init(PF* pfs) { | 528 | 1 | pfs[i] = &thunk; | 529 | 1 | return variantAppInit<i+1, R, F, U, tuple<Args...>, Ctors...>::init(pfs); | 530 | 1 | } |
hobbes::variantAppInit<1ul, void, hobbes::variantPayloadCtor, void, hobbes::tuple<void const*>, std::shared_ptr<hobbes::Constraint> >::init(void (**)(void*, void const*)) Line | Count | Source | 527 | 1 | static bool init(PF* pfs) { | 528 | 1 | pfs[i] = &thunk; | 529 | 1 | return variantAppInit<i+1, R, F, U, tuple<Args...>, Ctors...>::init(pfs); | 530 | 1 | } |
Unexecuted instantiation: hobbes::variantAppInit<0ul, void, hobbes::variantPayloadDtor, void, hobbes::tuple<>, int, long>::init(void (**)(void*)) Unexecuted instantiation: hobbes::variantAppInit<1ul, void, hobbes::variantPayloadDtor, void, hobbes::tuple<>, long>::init(void (**)(void*)) Unexecuted instantiation: hobbes::variantAppInit<0ul, void, hobbes::variantPayloadCtor, void, hobbes::tuple<void const*>, int, long>::init(void (**)(void*, void const*)) Unexecuted instantiation: hobbes::variantAppInit<1ul, void, hobbes::variantPayloadCtor, void, hobbes::tuple<void const*>, long>::init(void (**)(void*, void const*)) |
531 | | }; |
532 | | |
533 | | template <typename R, template <size_t,class,class> class F, typename U, typename V, typename ... Args> |
534 | | struct variantApp { |
535 | | }; |
536 | | // a variant's tag selects the function to call for its payload, out of a |
537 | | // table with one entry per constructor. A tag that arrives from outside the |
538 | | // process -- a peer's reply, decoded by io<variant<...>>::read -- is not |
539 | | // known to name a constructor of the type being read into, and indexing the |
540 | | // table with it read a function pointer from beyond the table and called it. |
541 | 0 | [[noreturn]] inline void raiseBadVariantTag(uint32_t id, size_t ctors) { |
542 | 0 | throw std::runtime_error( |
543 | 0 | "variant tag " + std::to_string(id) + " names no constructor of a variant with " + |
544 | 0 | std::to_string(ctors) + " of them" |
545 | 0 | ); |
546 | 0 | } |
547 | | |
548 | 959k | inline void checkVariantTag(uint32_t id, size_t ctors) { |
549 | 959k | if (id >= ctors) { |
550 | 0 | raiseBadVariantTag(id, ctors); |
551 | 0 | } |
552 | 959k | } |
553 | | |
554 | | template <template <size_t,class,class> class F, typename U, typename ... Ctors, typename ... Args> |
555 | | struct variantApp<void, F, U, tuple<Ctors...>, Args...> { |
556 | | using PF = void (*)(void *, Args...); |
557 | 959k | static PF* fns() { |
558 | 959k | static PF fvec[sizeof...(Ctors)]; |
559 | 959k | static bool init = variantAppInit<0, void, F, U, tuple<Args...>, Ctors...>::init(fvec); |
560 | 959k | return fvec; |
561 | 0 | if (init) return fvec; // <-- pointless, but prevents an unused variable error |
562 | 0 | } hobbes::variantApp<void, hobbes::variantPayloadDtor, void, hobbes::tuple<hobbes::unit, std::shared_ptr<hobbes::TCInstance> >>::fns() Line | Count | Source | 557 | 1.94k | static PF* fns() { | 558 | 1.94k | static PF fvec[sizeof...(Ctors)]; | 559 | 1.94k | static bool init = variantAppInit<0, void, F, U, tuple<Args...>, Ctors...>::init(fvec); | 560 | 1.94k | return fvec; | 561 | 0 | if (init) return fvec; // <-- pointless, but prevents an unused variable error | 562 | 0 | } |
hobbes::variantApp<void, hobbes::variantPayloadDtor, void, hobbes::tuple<hobbes::unit, std::vector<std::shared_ptr<hobbes::TCInstanceFn>, std::allocator<std::shared_ptr<hobbes::TCInstanceFn> > > >>::fns() Line | Count | Source | 557 | 2.87k | static PF* fns() { | 558 | 2.87k | static PF fvec[sizeof...(Ctors)]; | 559 | 2.87k | static bool init = variantAppInit<0, void, F, U, tuple<Args...>, Ctors...>::init(fvec); | 560 | 2.87k | return fvec; | 561 | 0 | if (init) return fvec; // <-- pointless, but prevents an unused variable error | 562 | 0 | } |
hobbes::variantApp<void, hobbes::variantPayloadDtor, void, hobbes::tuple<hobbes::unit, bool>>::fns() Line | Count | Source | 557 | 14.7k | static PF* fns() { | 558 | 14.7k | static PF fvec[sizeof...(Ctors)]; | 559 | 14.7k | static bool init = variantAppInit<0, void, F, U, tuple<Args...>, Ctors...>::init(fvec); | 560 | 14.7k | return fvec; | 561 | 0 | if (init) return fvec; // <-- pointless, but prevents an unused variable error | 562 | 0 | } |
hobbes::variantApp<void, hobbes::variantPayloadCtor, void, hobbes::tuple<hobbes::unit, bool>, void const*>::fns() Line | Count | Source | 557 | 2.87k | static PF* fns() { | 558 | 2.87k | static PF fvec[sizeof...(Ctors)]; | 559 | 2.87k | static bool init = variantAppInit<0, void, F, U, tuple<Args...>, Ctors...>::init(fvec); | 560 | 2.87k | return fvec; | 561 | 0 | if (init) return fvec; // <-- pointless, but prevents an unused variable error | 562 | 0 | } |
hobbes::variantApp<void, hobbes::variantPayloadCtor, void, hobbes::tuple<hobbes::unit, std::shared_ptr<hobbes::TCInstance> >, void const*>::fns() Line | Count | Source | 557 | 433 | static PF* fns() { | 558 | 433 | static PF fvec[sizeof...(Ctors)]; | 559 | 433 | static bool init = variantAppInit<0, void, F, U, tuple<Args...>, Ctors...>::init(fvec); | 560 | 433 | return fvec; | 561 | 0 | if (init) return fvec; // <-- pointless, but prevents an unused variable error | 562 | 0 | } |
hobbes::variantApp<void, hobbes::variantPayloadCtor, void, hobbes::tuple<hobbes::unit, std::vector<std::shared_ptr<hobbes::TCInstanceFn>, std::allocator<std::shared_ptr<hobbes::TCInstanceFn> > > >, void const*>::fns() Line | Count | Source | 557 | 572 | static PF* fns() { | 558 | 572 | static PF fvec[sizeof...(Ctors)]; | 559 | 572 | static bool init = variantAppInit<0, void, F, U, tuple<Args...>, Ctors...>::init(fvec); | 560 | 572 | return fvec; | 561 | 0 | if (init) return fvec; // <-- pointless, but prevents an unused variable error | 562 | 0 | } |
hobbes::variantApp<void, hobbes::variantPayloadDtor, void, hobbes::tuple<hobbes::unit, std::shared_ptr<hobbes::Constraint> >>::fns() Line | Count | Source | 557 | 173k | static PF* fns() { | 558 | 173k | static PF fvec[sizeof...(Ctors)]; | 559 | 173k | static bool init = variantAppInit<0, void, F, U, tuple<Args...>, Ctors...>::init(fvec); | 560 | 173k | return fvec; | 561 | 0 | if (init) return fvec; // <-- pointless, but prevents an unused variable error | 562 | 0 | } |
hobbes::variantApp<void, hobbes::variantPayloadCtor, void, hobbes::tuple<hobbes::unit, std::shared_ptr<hobbes::MonoType> >, void const*>::fns() Line | Count | Source | 557 | 298k | static PF* fns() { | 558 | 298k | static PF fvec[sizeof...(Ctors)]; | 559 | 298k | static bool init = variantAppInit<0, void, F, U, tuple<Args...>, Ctors...>::init(fvec); | 560 | 298k | return fvec; | 561 | 0 | if (init) return fvec; // <-- pointless, but prevents an unused variable error | 562 | 0 | } |
hobbes::variantApp<void, hobbes::variantPayloadDtor, void, hobbes::tuple<hobbes::unit, std::shared_ptr<hobbes::MonoType> >>::fns() Line | Count | Source | 557 | 433k | static PF* fns() { | 558 | 433k | static PF fvec[sizeof...(Ctors)]; | 559 | 433k | static bool init = variantAppInit<0, void, F, U, tuple<Args...>, Ctors...>::init(fvec); | 560 | 433k | return fvec; | 561 | 0 | if (init) return fvec; // <-- pointless, but prevents an unused variable error | 562 | 0 | } |
hobbes::variantApp<void, hobbes::variantPayloadCtor, void, hobbes::tuple<hobbes::unit, std::shared_ptr<hobbes::Constraint> >, void const*>::fns() Line | Count | Source | 557 | 29.4k | static PF* fns() { | 558 | 29.4k | static PF fvec[sizeof...(Ctors)]; | 559 | 29.4k | static bool init = variantAppInit<0, void, F, U, tuple<Args...>, Ctors...>::init(fvec); | 560 | 29.4k | return fvec; | 561 | 0 | if (init) return fvec; // <-- pointless, but prevents an unused variable error | 562 | 0 | } |
Unexecuted instantiation: hobbes::variantApp<void, hobbes::variantPayloadDtor, void, hobbes::tuple<int, long>>::fns() Unexecuted instantiation: hobbes::variantApp<void, hobbes::variantPayloadCtor, void, hobbes::tuple<int, long>, void const*>::fns() |
563 | | |
564 | 959k | static void apply(uint32_t id, void* payload, Args... args) { |
565 | 959k | checkVariantTag(id, sizeof...(Ctors)); |
566 | 959k | fns()[id](payload, args...); |
567 | 959k | } hobbes::variantApp<void, hobbes::variantPayloadDtor, void, hobbes::tuple<hobbes::unit, std::shared_ptr<hobbes::TCInstance> >>::apply(unsigned int, void*) Line | Count | Source | 564 | 1.94k | static void apply(uint32_t id, void* payload, Args... args) { | 565 | 1.94k | checkVariantTag(id, sizeof...(Ctors)); | 566 | 1.94k | fns()[id](payload, args...); | 567 | 1.94k | } |
hobbes::variantApp<void, hobbes::variantPayloadDtor, void, hobbes::tuple<hobbes::unit, std::vector<std::shared_ptr<hobbes::TCInstanceFn>, std::allocator<std::shared_ptr<hobbes::TCInstanceFn> > > >>::apply(unsigned int, void*) Line | Count | Source | 564 | 2.87k | static void apply(uint32_t id, void* payload, Args... args) { | 565 | 2.87k | checkVariantTag(id, sizeof...(Ctors)); | 566 | 2.87k | fns()[id](payload, args...); | 567 | 2.87k | } |
hobbes::variantApp<void, hobbes::variantPayloadDtor, void, hobbes::tuple<hobbes::unit, bool>>::apply(unsigned int, void*) Line | Count | Source | 564 | 14.7k | static void apply(uint32_t id, void* payload, Args... args) { | 565 | 14.7k | checkVariantTag(id, sizeof...(Ctors)); | 566 | 14.7k | fns()[id](payload, args...); | 567 | 14.7k | } |
hobbes::variantApp<void, hobbes::variantPayloadCtor, void, hobbes::tuple<hobbes::unit, bool>, void const*>::apply(unsigned int, void*, void const*) Line | Count | Source | 564 | 2.87k | static void apply(uint32_t id, void* payload, Args... args) { | 565 | 2.87k | checkVariantTag(id, sizeof...(Ctors)); | 566 | 2.87k | fns()[id](payload, args...); | 567 | 2.87k | } |
hobbes::variantApp<void, hobbes::variantPayloadCtor, void, hobbes::tuple<hobbes::unit, std::shared_ptr<hobbes::TCInstance> >, void const*>::apply(unsigned int, void*, void const*) Line | Count | Source | 564 | 433 | static void apply(uint32_t id, void* payload, Args... args) { | 565 | 433 | checkVariantTag(id, sizeof...(Ctors)); | 566 | 433 | fns()[id](payload, args...); | 567 | 433 | } |
hobbes::variantApp<void, hobbes::variantPayloadCtor, void, hobbes::tuple<hobbes::unit, std::vector<std::shared_ptr<hobbes::TCInstanceFn>, std::allocator<std::shared_ptr<hobbes::TCInstanceFn> > > >, void const*>::apply(unsigned int, void*, void const*) Line | Count | Source | 564 | 572 | static void apply(uint32_t id, void* payload, Args... args) { | 565 | 572 | checkVariantTag(id, sizeof...(Ctors)); | 566 | 572 | fns()[id](payload, args...); | 567 | 572 | } |
hobbes::variantApp<void, hobbes::variantPayloadDtor, void, hobbes::tuple<hobbes::unit, std::shared_ptr<hobbes::Constraint> >>::apply(unsigned int, void*) Line | Count | Source | 564 | 173k | static void apply(uint32_t id, void* payload, Args... args) { | 565 | 173k | checkVariantTag(id, sizeof...(Ctors)); | 566 | 173k | fns()[id](payload, args...); | 567 | 173k | } |
hobbes::variantApp<void, hobbes::variantPayloadCtor, void, hobbes::tuple<hobbes::unit, std::shared_ptr<hobbes::MonoType> >, void const*>::apply(unsigned int, void*, void const*) Line | Count | Source | 564 | 298k | static void apply(uint32_t id, void* payload, Args... args) { | 565 | 298k | checkVariantTag(id, sizeof...(Ctors)); | 566 | 298k | fns()[id](payload, args...); | 567 | 298k | } |
hobbes::variantApp<void, hobbes::variantPayloadDtor, void, hobbes::tuple<hobbes::unit, std::shared_ptr<hobbes::MonoType> >>::apply(unsigned int, void*) Line | Count | Source | 564 | 433k | static void apply(uint32_t id, void* payload, Args... args) { | 565 | 433k | checkVariantTag(id, sizeof...(Ctors)); | 566 | 433k | fns()[id](payload, args...); | 567 | 433k | } |
hobbes::variantApp<void, hobbes::variantPayloadCtor, void, hobbes::tuple<hobbes::unit, std::shared_ptr<hobbes::Constraint> >, void const*>::apply(unsigned int, void*, void const*) Line | Count | Source | 564 | 29.4k | static void apply(uint32_t id, void* payload, Args... args) { | 565 | 29.4k | checkVariantTag(id, sizeof...(Ctors)); | 566 | 29.4k | fns()[id](payload, args...); | 567 | 29.4k | } |
Unexecuted instantiation: hobbes::variantApp<void, hobbes::variantPayloadDtor, void, hobbes::tuple<int, long>>::apply(unsigned int, void*) Unexecuted instantiation: hobbes::variantApp<void, hobbes::variantPayloadCtor, void, hobbes::tuple<int, long>, void const*>::apply(unsigned int, void*, void const*) |
568 | | }; |
569 | | |
570 | | template <typename R, template <size_t,class,class> class F, typename U, typename ... Ctors, typename ... Args> |
571 | | struct variantApp<R, F, U, tuple<Ctors...>, Args...> { |
572 | | using PF = R (*)(void *, Args...); |
573 | | static PF* fns() { |
574 | | static PF fvec[sizeof...(Ctors)]; |
575 | | static bool init = variantAppInit<0, R, F, U, tuple<Args...>, Ctors...>::init(fvec); |
576 | | return fvec; |
577 | | if (init) return fvec; // <-- pointless, but prevents an unused variable error |
578 | | } |
579 | | |
580 | | static R apply(uint32_t id, void* payload, Args... args) { |
581 | | checkVariantTag(id, sizeof...(Ctors)); |
582 | | return fns()[id](payload, args...); |
583 | | } |
584 | | }; |
585 | | |
586 | | template <size_t, typename T, typename U> |
587 | | struct variantPayloadCtor { |
588 | 332k | static void fn(T* p, const void* rhsp) { |
589 | 332k | new (p) T(*reinterpret_cast<const T*>(rhsp)); |
590 | 332k | } hobbes::variantPayloadCtor<0ul, hobbes::unit, void>::fn(hobbes::unit*, void const*) Line | Count | Source | 588 | 128k | static void fn(T* p, const void* rhsp) { | 589 | 128k | new (p) T(*reinterpret_cast<const T*>(rhsp)); | 590 | 128k | } |
hobbes::variantPayloadCtor<1ul, bool, void>::fn(bool*, void const*) Line | Count | Source | 588 | 2.87k | static void fn(T* p, const void* rhsp) { | 589 | 2.87k | new (p) T(*reinterpret_cast<const T*>(rhsp)); | 590 | 2.87k | } |
hobbes::variantPayloadCtor<1ul, std::shared_ptr<hobbes::TCInstance>, void>::fn(std::shared_ptr<hobbes::TCInstance>*, void const*) Line | Count | Source | 588 | 433 | static void fn(T* p, const void* rhsp) { | 589 | 433 | new (p) T(*reinterpret_cast<const T*>(rhsp)); | 590 | 433 | } |
hobbes::variantPayloadCtor<1ul, std::vector<std::shared_ptr<hobbes::TCInstanceFn>, std::allocator<std::shared_ptr<hobbes::TCInstanceFn> > >, void>::fn(std::vector<std::shared_ptr<hobbes::TCInstanceFn>, std::allocator<std::shared_ptr<hobbes::TCInstanceFn> > >*, void const*) Line | Count | Source | 588 | 572 | static void fn(T* p, const void* rhsp) { | 589 | 572 | new (p) T(*reinterpret_cast<const T*>(rhsp)); | 590 | 572 | } |
hobbes::variantPayloadCtor<1ul, std::shared_ptr<hobbes::MonoType>, void>::fn(std::shared_ptr<hobbes::MonoType>*, void const*) Line | Count | Source | 588 | 170k | static void fn(T* p, const void* rhsp) { | 589 | 170k | new (p) T(*reinterpret_cast<const T*>(rhsp)); | 590 | 170k | } |
hobbes::variantPayloadCtor<1ul, std::shared_ptr<hobbes::Constraint>, void>::fn(std::shared_ptr<hobbes::Constraint>*, void const*) Line | Count | Source | 588 | 29.4k | static void fn(T* p, const void* rhsp) { | 589 | 29.4k | new (p) T(*reinterpret_cast<const T*>(rhsp)); | 590 | 29.4k | } |
Unexecuted instantiation: hobbes::variantPayloadCtor<0ul, int, void>::fn(int*, void const*) Unexecuted instantiation: hobbes::variantPayloadCtor<1ul, long, void>::fn(long*, void const*) |
591 | | }; |
592 | | |
593 | | template <size_t, typename T, typename U> |
594 | | struct variantPayloadDtor { |
595 | 627k | static void fn(T* p) { |
596 | 627k | p->~T(); |
597 | 627k | } hobbes::variantPayloadDtor<0ul, hobbes::unit, void>::fn(hobbes::unit*) Line | Count | Source | 595 | 326k | static void fn(T* p) { | 596 | 326k | p->~T(); | 597 | 326k | } |
hobbes::variantPayloadDtor<1ul, std::shared_ptr<hobbes::TCInstance>, void>::fn(std::shared_ptr<hobbes::TCInstance>*) Line | Count | Source | 595 | 866 | static void fn(T* p) { | 596 | 866 | p->~T(); | 597 | 866 | } |
hobbes::variantPayloadDtor<1ul, std::vector<std::shared_ptr<hobbes::TCInstanceFn>, std::allocator<std::shared_ptr<hobbes::TCInstanceFn> > >, void>::fn(std::vector<std::shared_ptr<hobbes::TCInstanceFn>, std::allocator<std::shared_ptr<hobbes::TCInstanceFn> > >*) Line | Count | Source | 595 | 1.14k | static void fn(T* p) { | 596 | 1.14k | p->~T(); | 597 | 1.14k | } |
hobbes::variantPayloadDtor<1ul, bool, void>::fn(bool*) Line | Count | Source | 595 | 5.74k | static void fn(T* p) { | 596 | 5.74k | p->~T(); | 597 | 5.74k | } |
hobbes::variantPayloadDtor<1ul, std::shared_ptr<hobbes::Constraint>, void>::fn(std::shared_ptr<hobbes::Constraint>*) Line | Count | Source | 595 | 58.8k | static void fn(T* p) { | 596 | 58.8k | p->~T(); | 597 | 58.8k | } |
hobbes::variantPayloadDtor<1ul, std::shared_ptr<hobbes::MonoType>, void>::fn(std::shared_ptr<hobbes::MonoType>*) Line | Count | Source | 595 | 234k | static void fn(T* p) { | 596 | 234k | p->~T(); | 597 | 234k | } |
Unexecuted instantiation: hobbes::variantPayloadDtor<0ul, int, void>::fn(int*) Unexecuted instantiation: hobbes::variantPayloadDtor<1ul, long, void>::fn(long*) |
598 | | }; |
599 | | |
600 | | template <size_t, typename T, typename U> |
601 | | struct variantPayloadEq { |
602 | | static bool fn(T* lhs, const void* rhs) { |
603 | | return *lhs == *reinterpret_cast<const T*>(rhs); |
604 | | } |
605 | | }; |
606 | | |
607 | | namespace detail { |
608 | | template <typename Fn, typename... Ts> struct variantVisitorByTag { |
609 | | static void visit(std::size_t, std::size_t, Fn &&, void *) {} |
610 | | }; |
611 | | |
612 | | template <typename Fn, typename T, typename... Ts> |
613 | | struct variantVisitorByTag<Fn, T, Ts...> { |
614 | | static void visit(std::size_t count, std::size_t tag, Fn &&fn, |
615 | | void *storage) { |
616 | | if (tag == (count - sizeof...(Ts) - 1)) { |
617 | | std::forward<Fn>(fn)(storage); |
618 | | } else { |
619 | | variantVisitorByTag<Fn, Ts...>::visit(count, tag, fn, storage); |
620 | | } |
621 | | } |
622 | | }; |
623 | | |
624 | | template <typename T, typename... Ts> struct CountType { |
625 | | static constexpr std::size_t value = 0; |
626 | | }; |
627 | | |
628 | | template <typename T, typename U, typename... Ts> |
629 | | struct CountType<T, U, Ts...> { |
630 | | static constexpr std::size_t value = |
631 | | (std::is_same<T, U>::value ? 1 : 0) + CountType<T, Ts...>::value; |
632 | | }; |
633 | | } // namespace detail |
634 | | |
635 | | template <typename ... Ctors> |
636 | | class variant { |
637 | | public: |
638 | | static const size_t count = sizeof...(Ctors); |
639 | | static_assert(count > 0, "Empty variants are impossible to construct"); |
640 | | |
641 | | using VCCtor = variantApp<void, variantPayloadCtor, void, tuple<Ctors...>, const void *>; |
642 | | using VDtor = variantApp<void, variantPayloadDtor, void, tuple<Ctors...>>; |
643 | | |
644 | 197k | variant() : tag(0) { |
645 | 197k | new (this->storage) typename First<Ctors...>::type(); |
646 | 197k | } hobbes::variant<hobbes::unit, std::shared_ptr<hobbes::TCInstance> >::variant() Line | Count | Source | 644 | 1.08k | variant() : tag(0) { | 645 | 1.08k | new (this->storage) typename First<Ctors...>::type(); | 646 | 1.08k | } |
hobbes::variant<hobbes::unit, std::vector<std::shared_ptr<hobbes::TCInstanceFn>, std::allocator<std::shared_ptr<hobbes::TCInstanceFn> > > >::variant() Line | Count | Source | 644 | 1.73k | variant() : tag(0) { | 645 | 1.73k | new (this->storage) typename First<Ctors...>::type(); | 646 | 1.73k | } |
hobbes::variant<hobbes::unit, bool>::variant() Line | Count | Source | 644 | 9.02k | variant() : tag(0) { | 645 | 9.02k | new (this->storage) typename First<Ctors...>::type(); | 646 | 9.02k | } |
hobbes::variant<hobbes::unit, std::shared_ptr<hobbes::Constraint> >::variant() Line | Count | Source | 644 | 114k | variant() : tag(0) { | 645 | 114k | new (this->storage) typename First<Ctors...>::type(); | 646 | 114k | } |
hobbes::variant<hobbes::unit, std::shared_ptr<hobbes::MonoType> >::variant() Line | Count | Source | 644 | 71.0k | variant() : tag(0) { | 645 | 71.0k | new (this->storage) typename First<Ctors...>::type(); | 646 | 71.0k | } |
Unexecuted instantiation: hobbes::variant<int, long>::variant() |
647 | | template <typename T> |
648 | 97.1k | variant(const T& t) : tag(CtorIndexOf<T, Ctors...>::value) { |
649 | 97.1k | static_assert(CtorIndexOf<T, Ctors...>::value < sizeof...(Ctors), "Constructor type isn't part of variant"); |
650 | 97.1k | new (this->storage) T(t); |
651 | 97.1k | } Unexecuted instantiation: hobbes::variant<hobbes::unit, char>::variant<char>(char const&) Unexecuted instantiation: hobbes::variant<hobbes::unit, char>::variant<hobbes::unit>(hobbes::unit const&) Unexecuted instantiation: hobbes::variant<hobbes::unit, unsigned char>::variant<unsigned char>(unsigned char const&) Unexecuted instantiation: hobbes::variant<hobbes::unit, unsigned char>::variant<hobbes::unit>(hobbes::unit const&) Unexecuted instantiation: hobbes::variant<hobbes::unit, __int128>::variant<__int128>(__int128 const&) Unexecuted instantiation: hobbes::variant<hobbes::unit, __int128>::variant<hobbes::unit>(hobbes::unit const&) Unexecuted instantiation: hobbes::variant<hobbes::unit, short>::variant<short>(short const&) Unexecuted instantiation: hobbes::variant<hobbes::unit, short>::variant<hobbes::unit>(hobbes::unit const&) Unexecuted instantiation: hobbes::variant<hobbes::unit, int>::variant<int>(int const&) Unexecuted instantiation: hobbes::variant<hobbes::unit, int>::variant<hobbes::unit>(hobbes::unit const&) Unexecuted instantiation: hobbes::variant<hobbes::unit, long>::variant<long>(long const&) Unexecuted instantiation: hobbes::variant<hobbes::unit, long>::variant<hobbes::unit>(hobbes::unit const&) Unexecuted instantiation: hobbes::variant<hobbes::unit, float>::variant<float>(float const&) Unexecuted instantiation: hobbes::variant<hobbes::unit, float>::variant<hobbes::unit>(hobbes::unit const&) Unexecuted instantiation: hobbes::variant<hobbes::unit, double>::variant<double>(double const&) Unexecuted instantiation: hobbes::variant<hobbes::unit, double>::variant<hobbes::unit>(hobbes::unit const&) hobbes::variant<hobbes::unit, bool>::variant<bool>(bool const&) Line | Count | Source | 648 | 2.87k | variant(const T& t) : tag(CtorIndexOf<T, Ctors...>::value) { | 649 | 2.87k | static_assert(CtorIndexOf<T, Ctors...>::value < sizeof...(Ctors), "Constructor type isn't part of variant"); | 650 | 2.87k | new (this->storage) T(t); | 651 | 2.87k | } |
hobbes::variant<hobbes::unit, std::shared_ptr<hobbes::TCInstance> >::variant<std::shared_ptr<hobbes::TCInstance> >(std::shared_ptr<hobbes::TCInstance> const&) Line | Count | Source | 648 | 433 | variant(const T& t) : tag(CtorIndexOf<T, Ctors...>::value) { | 649 | 433 | static_assert(CtorIndexOf<T, Ctors...>::value < sizeof...(Ctors), "Constructor type isn't part of variant"); | 650 | 433 | new (this->storage) T(t); | 651 | 433 | } |
hobbes::variant<hobbes::unit, std::vector<std::shared_ptr<hobbes::TCInstanceFn>, std::allocator<std::shared_ptr<hobbes::TCInstanceFn> > > >::variant<std::vector<std::shared_ptr<hobbes::TCInstanceFn>, std::allocator<std::shared_ptr<hobbes::TCInstanceFn> > > >(std::vector<std::shared_ptr<hobbes::TCInstanceFn>, std::allocator<std::shared_ptr<hobbes::TCInstanceFn> > > const&) Line | Count | Source | 648 | 572 | variant(const T& t) : tag(CtorIndexOf<T, Ctors...>::value) { | 649 | 572 | static_assert(CtorIndexOf<T, Ctors...>::value < sizeof...(Ctors), "Constructor type isn't part of variant"); | 650 | 572 | new (this->storage) T(t); | 651 | 572 | } |
hobbes::variant<hobbes::unit, std::shared_ptr<hobbes::MonoType> >::variant<std::shared_ptr<hobbes::MonoType> >(std::shared_ptr<hobbes::MonoType> const&) Line | Count | Source | 648 | 63.8k | variant(const T& t) : tag(CtorIndexOf<T, Ctors...>::value) { | 649 | 63.8k | static_assert(CtorIndexOf<T, Ctors...>::value < sizeof...(Ctors), "Constructor type isn't part of variant"); | 650 | 63.8k | new (this->storage) T(t); | 651 | 63.8k | } |
hobbes::variant<hobbes::unit, std::shared_ptr<hobbes::Constraint> >::variant<std::shared_ptr<hobbes::Constraint> >(std::shared_ptr<hobbes::Constraint> const&) Line | Count | Source | 648 | 29.4k | variant(const T& t) : tag(CtorIndexOf<T, Ctors...>::value) { | 649 | 29.4k | static_assert(CtorIndexOf<T, Ctors...>::value < sizeof...(Ctors), "Constructor type isn't part of variant"); | 650 | 29.4k | new (this->storage) T(t); | 651 | 29.4k | } |
Unexecuted instantiation: hobbes::variant<int, long>::variant<int>(int const&) Unexecuted instantiation: hobbes::variant<int, long>::variant<long>(long const&) |
652 | 298k | variant(const variant<Ctors...>& rhs) : tag(rhs.tag) { |
653 | 298k | VCCtor::apply(this->tag, this->storage, rhs.storage); |
654 | 298k | } |
655 | 593k | ~variant() { |
656 | 593k | VDtor::apply(this->tag, this->storage); |
657 | 593k | } hobbes::variant<hobbes::unit, bool>::~variant() Line | Count | Source | 655 | 11.8k | ~variant() { | 656 | 11.8k | VDtor::apply(this->tag, this->storage); | 657 | 11.8k | } |
hobbes::variant<hobbes::unit, std::vector<std::shared_ptr<hobbes::TCInstanceFn>, std::allocator<std::shared_ptr<hobbes::TCInstanceFn> > > >::~variant() Line | Count | Source | 655 | 2.30k | ~variant() { | 656 | 2.30k | VDtor::apply(this->tag, this->storage); | 657 | 2.30k | } |
hobbes::variant<hobbes::unit, std::shared_ptr<hobbes::TCInstance> >::~variant() Line | Count | Source | 655 | 1.51k | ~variant() { | 656 | 1.51k | VDtor::apply(this->tag, this->storage); | 657 | 1.51k | } |
hobbes::variant<hobbes::unit, std::shared_ptr<hobbes::Constraint> >::~variant() Line | Count | Source | 655 | 144k | ~variant() { | 656 | 144k | VDtor::apply(this->tag, this->storage); | 657 | 144k | } |
hobbes::variant<hobbes::unit, std::shared_ptr<hobbes::MonoType> >::~variant() Line | Count | Source | 655 | 433k | ~variant() { | 656 | 433k | VDtor::apply(this->tag, this->storage); | 657 | 433k | } |
Unexecuted instantiation: hobbes::variant<int, long>::~variant() |
658 | 33.2k | variant<Ctors...>& operator=(const variant<Ctors...>& rhs) { |
659 | 33.2k | if (this != &rhs) { |
660 | 33.2k | VDtor::apply(this->tag, this->storage); |
661 | 33.2k | this->tag = rhs.tag; |
662 | 33.2k | VCCtor::apply(this->tag, this->storage, rhs.storage); |
663 | 33.2k | } |
664 | 33.2k | return *this; |
665 | 33.2k | } hobbes::variant<hobbes::unit, bool>::operator=(hobbes::variant<hobbes::unit, bool> const&) Line | Count | Source | 658 | 2.87k | variant<Ctors...>& operator=(const variant<Ctors...>& rhs) { | 659 | 2.87k | if (this != &rhs) { | 660 | 2.87k | VDtor::apply(this->tag, this->storage); | 661 | 2.87k | this->tag = rhs.tag; | 662 | 2.87k | VCCtor::apply(this->tag, this->storage, rhs.storage); | 663 | 2.87k | } | 664 | 2.87k | return *this; | 665 | 2.87k | } |
hobbes::variant<hobbes::unit, std::shared_ptr<hobbes::TCInstance> >::operator=(hobbes::variant<hobbes::unit, std::shared_ptr<hobbes::TCInstance> > const&) Line | Count | Source | 658 | 433 | variant<Ctors...>& operator=(const variant<Ctors...>& rhs) { | 659 | 433 | if (this != &rhs) { | 660 | 433 | VDtor::apply(this->tag, this->storage); | 661 | 433 | this->tag = rhs.tag; | 662 | 433 | VCCtor::apply(this->tag, this->storage, rhs.storage); | 663 | 433 | } | 664 | 433 | return *this; | 665 | 433 | } |
hobbes::variant<hobbes::unit, std::vector<std::shared_ptr<hobbes::TCInstanceFn>, std::allocator<std::shared_ptr<hobbes::TCInstanceFn> > > >::operator=(hobbes::variant<hobbes::unit, std::vector<std::shared_ptr<hobbes::TCInstanceFn>, std::allocator<std::shared_ptr<hobbes::TCInstanceFn> > > > const&) Line | Count | Source | 658 | 572 | variant<Ctors...>& operator=(const variant<Ctors...>& rhs) { | 659 | 572 | if (this != &rhs) { | 660 | 572 | VDtor::apply(this->tag, this->storage); | 661 | 572 | this->tag = rhs.tag; | 662 | 572 | VCCtor::apply(this->tag, this->storage, rhs.storage); | 663 | 572 | } | 664 | 572 | return *this; | 665 | 572 | } |
hobbes::variant<hobbes::unit, std::shared_ptr<hobbes::Constraint> >::operator=(hobbes::variant<hobbes::unit, std::shared_ptr<hobbes::Constraint> > const&) Line | Count | Source | 658 | 29.4k | variant<Ctors...>& operator=(const variant<Ctors...>& rhs) { | 659 | 29.4k | if (this != &rhs) { | 660 | 29.4k | VDtor::apply(this->tag, this->storage); | 661 | 29.4k | this->tag = rhs.tag; | 662 | 29.4k | VCCtor::apply(this->tag, this->storage, rhs.storage); | 663 | 29.4k | } | 664 | 29.4k | return *this; | 665 | 29.4k | } |
Unexecuted instantiation: hobbes::variant<int, long>::operator=(hobbes::variant<int, long> const&) |
666 | | |
667 | | // This function is only instantiated when T is unique in Ctors |
668 | | template <typename T, typename = std::enable_if_t<detail::CountType<T, Ctors...>::value == 1>> |
669 | 3.24k | T* get() { return findByCtor<T>(); }std::vector<std::shared_ptr<hobbes::TCInstanceFn>, std::allocator<std::shared_ptr<hobbes::TCInstanceFn> > >* hobbes::variant<hobbes::unit, std::vector<std::shared_ptr<hobbes::TCInstanceFn>, std::allocator<std::shared_ptr<hobbes::TCInstanceFn> > > >::get<std::vector<std::shared_ptr<hobbes::TCInstanceFn>, std::allocator<std::shared_ptr<hobbes::TCInstanceFn> > >, void>() Line | Count | Source | 669 | 218 | T* get() { return findByCtor<T>(); } |
std::shared_ptr<hobbes::TCInstance>* hobbes::variant<hobbes::unit, std::shared_ptr<hobbes::TCInstance> >::get<std::shared_ptr<hobbes::TCInstance>, void>() Line | Count | Source | 669 | 2.26k | T* get() { return findByCtor<T>(); } |
std::shared_ptr<hobbes::Constraint>* hobbes::variant<hobbes::unit, std::shared_ptr<hobbes::Constraint> >::get<std::shared_ptr<hobbes::Constraint>, void>() Line | Count | Source | 669 | 762 | T* get() { return findByCtor<T>(); } |
|
670 | | template <typename T, typename = std::enable_if_t<detail::CountType<T, Ctors...>::value == 1>> |
671 | 198k | const T* get() const { return findByCtor<T>(); }std::vector<std::shared_ptr<hobbes::TCInstanceFn>, std::allocator<std::shared_ptr<hobbes::TCInstanceFn> > > const* hobbes::variant<hobbes::unit, std::vector<std::shared_ptr<hobbes::TCInstanceFn>, std::allocator<std::shared_ptr<hobbes::TCInstanceFn> > > >::get<std::vector<std::shared_ptr<hobbes::TCInstanceFn>, std::allocator<std::shared_ptr<hobbes::TCInstanceFn> > >, void>() const Line | Count | Source | 671 | 65 | const T* get() const { return findByCtor<T>(); } |
bool const* hobbes::variant<hobbes::unit, bool>::get<bool, void>() const Line | Count | Source | 671 | 5.60k | const T* get() const { return findByCtor<T>(); } |
std::shared_ptr<hobbes::TCInstance> const* hobbes::variant<hobbes::unit, std::shared_ptr<hobbes::TCInstance> >::get<std::shared_ptr<hobbes::TCInstance>, void>() const Line | Count | Source | 671 | 36.5k | const T* get() const { return findByCtor<T>(); } |
std::shared_ptr<hobbes::Constraint> const* hobbes::variant<hobbes::unit, std::shared_ptr<hobbes::Constraint> >::get<std::shared_ptr<hobbes::Constraint>, void>() const Line | Count | Source | 671 | 117k | const T* get() const { return findByCtor<T>(); } |
std::shared_ptr<hobbes::MonoType> const* hobbes::variant<hobbes::unit, std::shared_ptr<hobbes::MonoType> >::get<std::shared_ptr<hobbes::MonoType>, void>() const Line | Count | Source | 671 | 39.3k | const T* get() const { return findByCtor<T>(); } |
|
672 | | |
673 | | // This function is only instantiated in case of having a type like variant<char, int, char> |
674 | | // and tring to access the char |
675 | | // |
676 | | // \p fn should be void(void*) alike |
677 | | template <typename T, typename Fn, |
678 | | std::enable_if_t<(detail::CountType<T, Ctors...>::value > 1)>> |
679 | | void get(uint32_t t, Fn &&fn) { |
680 | | detail::variantVisitorByTag<Fn, Ctors...>::visit( |
681 | | count, t, std::forward<Fn>(fn), this->storage); |
682 | | } |
683 | | |
684 | | template <typename R, template <size_t,class,class> class F, typename U, typename ... Args> |
685 | | R apply(Args... args) { |
686 | | return variantApp<R, F, U, tuple<Ctors...>, Args...>::apply(this->tag, this->storage, args...); |
687 | | } |
688 | | template <typename R, template <size_t,class,class> class F, typename U, typename ... Args> |
689 | | R apply(Args... args) const { |
690 | | return variantApp<R, F, U, tuple<Ctors...>, Args...>::apply(this->tag, const_cast<void*>(reinterpret_cast<const void*>(this->storage)), args...); |
691 | | } |
692 | | public: |
693 | | const uint32_t& unsafeTag() const { return this->tag; } |
694 | | uint32_t& unsafeTag() { return this->tag; } |
695 | | const void* unsafePayload() const { return this->storage; } |
696 | | void* unsafePayload() { return this->storage; } |
697 | | private: |
698 | | uint32_t tag; |
699 | | union { |
700 | | char storage[maximum<TSizeOfF, Ctors...>::value]; |
701 | | typename maximum<TAlignOfF, Ctors...>::type maxAlignedT; |
702 | | }; |
703 | | |
704 | | template <typename T, typename = std::enable_if_t<detail::CountType<T, Ctors...>::value == 1>> |
705 | 202k | T* findByCtor() const { |
706 | 202k | if (this->tag == CtorIndexOf<T, Ctors...>::value) { |
707 | 89.0k | return const_cast<T*>(reinterpret_cast<const T*>(this->storage)); |
708 | 113k | } else { |
709 | 113k | return nullptr; |
710 | 113k | } |
711 | 202k | } std::vector<std::shared_ptr<hobbes::TCInstanceFn>, std::allocator<std::shared_ptr<hobbes::TCInstanceFn> > >* hobbes::variant<hobbes::unit, std::vector<std::shared_ptr<hobbes::TCInstanceFn>, std::allocator<std::shared_ptr<hobbes::TCInstanceFn> > > >::findByCtor<std::vector<std::shared_ptr<hobbes::TCInstanceFn>, std::allocator<std::shared_ptr<hobbes::TCInstanceFn> > >, void>() const Line | Count | Source | 705 | 283 | T* findByCtor() const { | 706 | 283 | if (this->tag == CtorIndexOf<T, Ctors...>::value) { | 707 | 283 | return const_cast<T*>(reinterpret_cast<const T*>(this->storage)); | 708 | 283 | } else { | 709 | 0 | return nullptr; | 710 | 0 | } | 711 | 283 | } |
std::shared_ptr<hobbes::TCInstance>* hobbes::variant<hobbes::unit, std::shared_ptr<hobbes::TCInstance> >::findByCtor<std::shared_ptr<hobbes::TCInstance>, void>() const Line | Count | Source | 705 | 38.7k | T* findByCtor() const { | 706 | 38.7k | if (this->tag == CtorIndexOf<T, Ctors...>::value) { | 707 | 18.0k | return const_cast<T*>(reinterpret_cast<const T*>(this->storage)); | 708 | 20.7k | } else { | 709 | 20.7k | return nullptr; | 710 | 20.7k | } | 711 | 38.7k | } |
bool* hobbes::variant<hobbes::unit, bool>::findByCtor<bool, void>() const Line | Count | Source | 705 | 5.60k | T* findByCtor() const { | 706 | 5.60k | if (this->tag == CtorIndexOf<T, Ctors...>::value) { | 707 | 5.60k | return const_cast<T*>(reinterpret_cast<const T*>(this->storage)); | 708 | 5.60k | } else { | 709 | 0 | return nullptr; | 710 | 0 | } | 711 | 5.60k | } |
std::shared_ptr<hobbes::Constraint>* hobbes::variant<hobbes::unit, std::shared_ptr<hobbes::Constraint> >::findByCtor<std::shared_ptr<hobbes::Constraint>, void>() const Line | Count | Source | 705 | 118k | T* findByCtor() const { | 706 | 118k | if (this->tag == CtorIndexOf<T, Ctors...>::value) { | 707 | 32.5k | return const_cast<T*>(reinterpret_cast<const T*>(this->storage)); | 708 | 85.5k | } else { | 709 | 85.5k | return nullptr; | 710 | 85.5k | } | 711 | 118k | } |
std::shared_ptr<hobbes::MonoType>* hobbes::variant<hobbes::unit, std::shared_ptr<hobbes::MonoType> >::findByCtor<std::shared_ptr<hobbes::MonoType>, void>() const Line | Count | Source | 705 | 39.3k | T* findByCtor() const { | 706 | 39.3k | if (this->tag == CtorIndexOf<T, Ctors...>::value) { | 707 | 32.5k | return const_cast<T*>(reinterpret_cast<const T*>(this->storage)); | 708 | 32.5k | } else { | 709 | 6.81k | return nullptr; | 710 | 6.81k | } | 711 | 39.3k | } |
|
712 | | }; |
713 | | template <typename ... Ctors> |
714 | | inline bool operator==(const variant<Ctors...>& lhs, const variant<Ctors...>& rhs) { |
715 | | return lhs.unsafeTag() == rhs.unsafeTag() && |
716 | | variantApp<bool, variantPayloadEq, void, tuple<Ctors...>, const void*>::apply(lhs.unsafeTag(), const_cast<void*>(reinterpret_cast<const void*>(lhs.unsafePayload())), reinterpret_cast<const void*>(rhs.unsafePayload())); |
717 | | } |
718 | | template <typename T, typename ... Ctors, typename = std::enable_if_t<detail::CountType<T, Ctors...>::value == 1>> |
719 | 3.24k | T* get(variant<Ctors...>& v) { |
720 | 3.24k | return v.template get<T>(); |
721 | 3.24k | } std::vector<std::shared_ptr<hobbes::TCInstanceFn>, std::allocator<std::shared_ptr<hobbes::TCInstanceFn> > >* hobbes::get<std::vector<std::shared_ptr<hobbes::TCInstanceFn>, std::allocator<std::shared_ptr<hobbes::TCInstanceFn> > >, hobbes::unit, std::vector<std::shared_ptr<hobbes::TCInstanceFn>, std::allocator<std::shared_ptr<hobbes::TCInstanceFn> > >, void>(hobbes::variant<hobbes::unit, std::vector<std::shared_ptr<hobbes::TCInstanceFn>, std::allocator<std::shared_ptr<hobbes::TCInstanceFn> > > >&) Line | Count | Source | 719 | 218 | T* get(variant<Ctors...>& v) { | 720 | 218 | return v.template get<T>(); | 721 | 218 | } |
std::shared_ptr<hobbes::TCInstance>* hobbes::get<std::shared_ptr<hobbes::TCInstance>, hobbes::unit, std::shared_ptr<hobbes::TCInstance>, void>(hobbes::variant<hobbes::unit, std::shared_ptr<hobbes::TCInstance> >&) Line | Count | Source | 719 | 2.26k | T* get(variant<Ctors...>& v) { | 720 | 2.26k | return v.template get<T>(); | 721 | 2.26k | } |
std::shared_ptr<hobbes::Constraint>* hobbes::get<std::shared_ptr<hobbes::Constraint>, hobbes::unit, std::shared_ptr<hobbes::Constraint>, void>(hobbes::variant<hobbes::unit, std::shared_ptr<hobbes::Constraint> >&) Line | Count | Source | 719 | 762 | T* get(variant<Ctors...>& v) { | 720 | 762 | return v.template get<T>(); | 721 | 762 | } |
|
722 | | template <typename T, typename ... Ctors, typename = std::enable_if_t<detail::CountType<T, Ctors...>::value == 1>> |
723 | 198k | const T* get(const variant<Ctors...>& v) { |
724 | 198k | return v.template get<T>(); |
725 | 198k | } std::vector<std::shared_ptr<hobbes::TCInstanceFn>, std::allocator<std::shared_ptr<hobbes::TCInstanceFn> > > const* hobbes::get<std::vector<std::shared_ptr<hobbes::TCInstanceFn>, std::allocator<std::shared_ptr<hobbes::TCInstanceFn> > >, hobbes::unit, std::vector<std::shared_ptr<hobbes::TCInstanceFn>, std::allocator<std::shared_ptr<hobbes::TCInstanceFn> > >, void>(hobbes::variant<hobbes::unit, std::vector<std::shared_ptr<hobbes::TCInstanceFn>, std::allocator<std::shared_ptr<hobbes::TCInstanceFn> > > > const&) Line | Count | Source | 723 | 65 | const T* get(const variant<Ctors...>& v) { | 724 | 65 | return v.template get<T>(); | 725 | 65 | } |
bool const* hobbes::get<bool, hobbes::unit, bool, void>(hobbes::variant<hobbes::unit, bool> const&) Line | Count | Source | 723 | 5.60k | const T* get(const variant<Ctors...>& v) { | 724 | 5.60k | return v.template get<T>(); | 725 | 5.60k | } |
std::shared_ptr<hobbes::TCInstance> const* hobbes::get<std::shared_ptr<hobbes::TCInstance>, hobbes::unit, std::shared_ptr<hobbes::TCInstance>, void>(hobbes::variant<hobbes::unit, std::shared_ptr<hobbes::TCInstance> > const&) Line | Count | Source | 723 | 36.5k | const T* get(const variant<Ctors...>& v) { | 724 | 36.5k | return v.template get<T>(); | 725 | 36.5k | } |
std::shared_ptr<hobbes::Constraint> const* hobbes::get<std::shared_ptr<hobbes::Constraint>, hobbes::unit, std::shared_ptr<hobbes::Constraint>, void>(hobbes::variant<hobbes::unit, std::shared_ptr<hobbes::Constraint> > const&) Line | Count | Source | 723 | 117k | const T* get(const variant<Ctors...>& v) { | 724 | 117k | return v.template get<T>(); | 725 | 117k | } |
std::shared_ptr<hobbes::MonoType> const* hobbes::get<std::shared_ptr<hobbes::MonoType>, hobbes::unit, std::shared_ptr<hobbes::MonoType>, void>(hobbes::variant<hobbes::unit, std::shared_ptr<hobbes::MonoType> > const&) Line | Count | Source | 723 | 39.3k | const T* get(const variant<Ctors...>& v) { | 724 | 39.3k | return v.template get<T>(); | 725 | 39.3k | } |
|
726 | | |
727 | | template <typename ... Ts> struct variantTail { }; |
728 | | template <typename T, typename ... Ts> struct variantTail<T, Ts...> { using type = variant<Ts...>; }; |
729 | | |
730 | | template <typename T> |
731 | | struct toVariant { }; |
732 | | template <typename ... Ts> |
733 | | struct toVariant<tuple<Ts...>> { using type = variant<Ts...>; }; |
734 | | |
735 | | // show a variant iff its constructors can be shown |
736 | | template <size_t, typename T, typename U> |
737 | | struct ShowVariantPayload { |
738 | | static void fn(T* x, std::ostream* out) { |
739 | | *out << *x; |
740 | | } |
741 | | }; |
742 | | |
743 | | template <typename ... Ts> |
744 | | inline typename std::enable_if<0<sizeof...(Ts) && can_show_types<Ts...>::value, std::ostream&>::type operator<<(std::ostream& o, const variant<Ts...>& cv) { |
745 | | variant<Ts...>& v = *const_cast<variant<Ts...>*>(&cv); |
746 | | o << "|" << v.unsafeTag() << "="; |
747 | | variantApp<void, ShowVariantPayload, void, tuple<Ts...>, std::ostream*>::apply(v.unsafeTag(), const_cast<void*>(reinterpret_cast<const void*>(v.unsafePayload())), &o); |
748 | | o << "|"; |
749 | | return o; |
750 | | } |
751 | | |
752 | | // reflective variants |
753 | | #define PRIV_HPPF_VARIANT_TYARGL(_, t) , t |
754 | | #define PRIV_HPPF_VARIANT_CTOR(n, t) static SelfT n(const t & x) { SelfT r; r.tag = Enum::tag_##n; new (&r.n##_data) t(x); return r; } |
755 | | #define PRIV_HPPF_VARIANT_PCOPY(n, t) case Enum::tag_##n: new (&this->n##_data) t(rhs.n##_data); break; |
756 | | #define PRIV_HPPF_VARIANT_GINIT(n, t) case Enum::tag_##n: new (&this->n##_data) t(); v.template init<t>(&this->n##_data); break; |
757 | | #define PRIV_HPPF_VARIANT_PDESTROY(n, t) case Enum::tag_##n: { typedef t PRIV_DT; reinterpret_cast<PRIV_DT*>(&this->n##_data)->~PRIV_DT(); } break; |
758 | | #define PRIV_HPPF_VARIANT_CTOR_TAG(n, t) tag_##n, |
759 | | #define PRIV_HPPF_VARIANT_CTOR_DATA(n, t) t n##_data; |
760 | | #define PRIV_HPPF_VARIANT_CTOR_COUNT(_,__) +1 |
761 | | #define PRIV_HPPF_VARIANT_EQCASE(n, _) case Enum::tag_##n: return (this->n##_data == rhs.n##_data); |
762 | | #define PRIV_HPPF_VARIANT_META(n, t) v.template ctor<t>(#n, static_cast<uint32_t>(Enum::tag_##n)); |
763 | | #define PRIV_HPPF_VARIANT_VDECL(n, t) virtual R n(const t & x) const = 0; |
764 | | #define PRIV_HPPF_VARIANT_VCASE(n, _) case Enum::tag_##n: return v. n (this->n##_data); |
765 | | #define PRIV_HPPF_VARIANT_GVCASE(n, t) case Enum::tag_##n: return v.template visit<t>(#n, static_cast<uint32_t>(Enum::tag_##n), this->n##_data); |
766 | | #define PRIV_HPPF_VARIANT_SHOW(n, t) case X::Enum::tag_##n: o << "|" << #n << "=" << v.n##_data << "|"; break; |
767 | | #define PRIV_HPPF_VARIANT_HMCTOR_NAME(n, _) case Enum::tag_##n: return #n; |
768 | | |
769 | | #define DEFINE_VARIANT(T, CTORS...) \ |
770 | | template <typename R> \ |
771 | | struct T##Visitor { \ |
772 | | PRIV_HPPF_MAP(PRIV_HPPF_VARIANT_VDECL, CTORS) \ |
773 | | }; \ |
774 | | struct T { \ |
775 | | static const bool is_hmeta_variant = true; \ |
776 | | typedef T SelfT; \ |
777 | | static const uint32_t ctorCount = 0 PRIV_HPPF_MAP(PRIV_HPPF_VARIANT_CTOR_COUNT, CTORS); \ |
778 | | typedef typename ::hobbes::variantTail<int PRIV_HPPF_MAP(PRIV_HPPF_VARIANT_TYARGL, CTORS)>::type as_variant_type; \ |
779 | | T() : tag(Enum::COUNT) { } \ |
780 | | PRIV_HPPF_MAP(PRIV_HPPF_VARIANT_CTOR, CTORS) \ |
781 | | T(const T& rhs) : tag(rhs.tag) { \ |
782 | | switch (this->tag) { \ |
783 | | PRIV_HPPF_MAP(PRIV_HPPF_VARIANT_PCOPY, CTORS) \ |
784 | | default: break; \ |
785 | | } \ |
786 | | } \ |
787 | | ~T() { \ |
788 | | switch (this->tag) { \ |
789 | | PRIV_HPPF_MAP(PRIV_HPPF_VARIANT_PDESTROY, CTORS) \ |
790 | | default: break; \ |
791 | | } \ |
792 | | } \ |
793 | | T& operator=(const T& rhs) { \ |
794 | | if (this == &rhs) return *this; \ |
795 | | switch (this->tag) { \ |
796 | | PRIV_HPPF_MAP(PRIV_HPPF_VARIANT_PDESTROY, CTORS) \ |
797 | | default: break; \ |
798 | | } \ |
799 | | this->tag = rhs.tag; \ |
800 | | switch (this->tag) { \ |
801 | | PRIV_HPPF_MAP(PRIV_HPPF_VARIANT_PCOPY, CTORS) \ |
802 | | default: break; \ |
803 | | } \ |
804 | | return *this; \ |
805 | | } \ |
806 | | template <typename V> \ |
807 | | static void meta(V& v) { \ |
808 | | PRIV_HPPF_MAP(PRIV_HPPF_VARIANT_META, CTORS) \ |
809 | | } \ |
810 | | template <typename R> \ |
811 | | R visit(const T##Visitor<R>& v) const { \ |
812 | | switch (this->tag) { \ |
813 | | PRIV_HPPF_MAP(PRIV_HPPF_VARIANT_VCASE, CTORS) \ |
814 | | default: throw std::runtime_error("while deconstructing the " #T " variant, cannot decide payload type because tag is invalid"); \ |
815 | | } \ |
816 | | } \ |
817 | | template <typename V> \ |
818 | | void gvisit(V& v) const { \ |
819 | | switch (this->tag) { \ |
820 | | PRIV_HPPF_MAP(PRIV_HPPF_VARIANT_GVCASE, CTORS) \ |
821 | | default: break; \ |
822 | | } \ |
823 | | } \ |
824 | | template <typename V> \ |
825 | | void ginit(uint32_t t, V& v) { \ |
826 | | switch (this->tag) { \ |
827 | | PRIV_HPPF_MAP(PRIV_HPPF_VARIANT_PDESTROY, CTORS) \ |
828 | | default: break; \ |
829 | | } \ |
830 | | this->tag = static_cast<Enum>(t); \ |
831 | | switch (this->tag) { \ |
832 | | PRIV_HPPF_MAP(PRIV_HPPF_VARIANT_GINIT, CTORS) \ |
833 | | default: break; \ |
834 | | } \ |
835 | | } \ |
836 | | template <size_t i> \ |
837 | | static const char* _hmeta_ctor_name() { \ |
838 | | static_assert(i < as_variant_type::count, "Invalid constructor index in variant"); \ |
839 | | switch (static_cast<Enum>(i)) { \ |
840 | | PRIV_HPPF_MAP(PRIV_HPPF_VARIANT_HMCTOR_NAME, CTORS) \ |
841 | | default: return "impossible"; \ |
842 | | } \ |
843 | | } \ |
844 | | template <size_t i> \ |
845 | | static uint32_t _hmeta_ctor_id() { \ |
846 | | static_assert(i < as_variant_type::count, "Invalid constructor index in variant"); \ |
847 | | return static_cast<uint32_t>(i); \ |
848 | | } \ |
849 | | template <typename X> \ |
850 | | inline typename std::enable_if<std::is_base_of<X, T>::value, bool>::type operator==(const X& rhs) const { \ |
851 | | if (this->tag != rhs.tag) { \ |
852 | | return false; \ |
853 | | } else { \ |
854 | | switch (this->tag) { \ |
855 | | PRIV_HPPF_MAP(PRIV_HPPF_VARIANT_EQCASE, CTORS) \ |
856 | | default: return false; \ |
857 | | } \ |
858 | | } \ |
859 | | } \ |
860 | | private: \ |
861 | | enum class Enum : uint32_t { \ |
862 | | PRIV_HPPF_MAP(PRIV_HPPF_VARIANT_CTOR_TAG, CTORS) \ |
863 | | COUNT \ |
864 | | }; \ |
865 | | Enum tag; \ |
866 | | union { \ |
867 | | char data[1]; \ |
868 | | PRIV_HPPF_MAP(PRIV_HPPF_VARIANT_CTOR_DATA, CTORS) \ |
869 | | }; \ |
870 | | public: \ |
871 | | template <typename X> \ |
872 | | friend inline typename std::enable_if<std::is_base_of<X,T>::value && ::hobbes::can_show_type<T::as_variant_type>::value,std::ostream&>::type operator<<(std::ostream& o, const X& v) { \ |
873 | | switch (v.tag) { \ |
874 | | PRIV_HPPF_MAP(PRIV_HPPF_VARIANT_SHOW, CTORS) \ |
875 | | default: o << "?"; break; \ |
876 | | } \ |
877 | | return o; \ |
878 | | } \ |
879 | | } |
880 | | |
881 | | // reflective variants with explicit constructor names |
882 | | #define PRIV_HPPF_LBLVARIANT_TYARGL(n, lbl, t) , t |
883 | | #define PRIV_HPPF_LBLVARIANT_CTOR(n, lbl, t) static SelfT n(const t & x) { SelfT r; r.tag = Enum::tag_##n; new (&r.n##_data) t(x); return r; } |
884 | | #define PRIV_HPPF_LBLVARIANT_PCOPY(n, lbl, t) case Enum::tag_##n: new (&this->n##_data) t(rhs.n##_data); break; |
885 | | #define PRIV_HPPF_LBLVARIANT_GINIT(n, lbl, t) case Enum::tag_##n: new (&this->n##_data) t(); v.template init<t>(&this->n##_data); break; |
886 | | #define PRIV_HPPF_LBLVARIANT_PDESTROY(n, lbl, t) case Enum::tag_##n: { typedef t PRIV_DT; reinterpret_cast<PRIV_DT*>(&this->n##_data)->~PRIV_DT(); } break; |
887 | | #define PRIV_HPPF_LBLVARIANT_CTOR_TAG(n, lbl, t) tag_##n, |
888 | | #define PRIV_HPPF_LBLVARIANT_CTOR_DATA(n, lbl, t) t n##_data; |
889 | | #define PRIV_HPPF_LBLVARIANT_CTOR_COUNT(n, lbl, t) +1 |
890 | | #define PRIV_HPPF_LBLVARIANT_EQCASE(n, lbl, t) case Enum::tag_##n: return (this->n##_data == rhs.n##_data); |
891 | | #define PRIV_HPPF_LBLVARIANT_META(n, lbl, t) v.template ctor<t>(#lbl, static_cast<uint32_t>(Enum::tag_##n)); |
892 | | #define PRIV_HPPF_LBLVARIANT_VDECL(n, lbl, t) virtual R n(const t & x) const = 0; |
893 | | #define PRIV_HPPF_LBLVARIANT_VCASE(n, lbl, t) case Enum::tag_##n: return v. n (this->n##_data); |
894 | | #define PRIV_HPPF_LBLVARIANT_GVCASE(n, lbl, t) case Enum::tag_##n: return v.template visit<t>(#lbl, static_cast<uint32_t>(Enum::tag_##n), this->n##_data); |
895 | | #define PRIV_HPPF_LBLVARIANT_SHOW(n, lbl, t) case Enum::tag_##n: o << "|" << #lbl << "=" << v.n##_data << "|"; break; |
896 | | |
897 | | #define DEFINE_VARIANT_WITH_LABELS(T, CTORS...) \ |
898 | | template <typename R> \ |
899 | | struct T##Visitor { \ |
900 | | PRIV_HPPF_MAP(PRIV_HPPF_LBLVARIANT_VDECL, CTORS) \ |
901 | | }; \ |
902 | | struct T { \ |
903 | | static const bool is_hmeta_variant = true; \ |
904 | | typedef T SelfT; \ |
905 | | static const uint32_t ctorCount = 0 PRIV_HPPF_MAP(PRIV_HPPF_LBLVARIANT_CTOR_COUNT, CTORS); \ |
906 | | typedef typename ::hobbes::variantTail<int PRIV_HPPF_MAP(PRIV_HPPF_LBLVARIANT_TYARGL, CTORS)>::type as_variant_type; \ |
907 | | T() : tag(Enum::COUNT) { } \ |
908 | | PRIV_HPPF_MAP(PRIV_HPPF_LBLVARIANT_CTOR, CTORS) \ |
909 | | T(const T& rhs) : tag(rhs.tag) { \ |
910 | | switch (this->tag) { \ |
911 | | PRIV_HPPF_MAP(PRIV_HPPF_LBLVARIANT_PCOPY, CTORS) \ |
912 | | default: break; \ |
913 | | } \ |
914 | | } \ |
915 | | ~T() { \ |
916 | | switch (this->tag) { \ |
917 | | PRIV_HPPF_MAP(PRIV_HPPF_LBLVARIANT_PDESTROY, CTORS) \ |
918 | | default: break; \ |
919 | | } \ |
920 | | } \ |
921 | | T& operator=(const T& rhs) { \ |
922 | | if (this == &rhs) return *this; \ |
923 | | switch (this->tag) { \ |
924 | | PRIV_HPPF_MAP(PRIV_HPPF_LBLVARIANT_PDESTROY, CTORS) \ |
925 | | default: break; \ |
926 | | } \ |
927 | | this->tag = rhs.tag; \ |
928 | | switch (this->tag) { \ |
929 | | PRIV_HPPF_MAP(PRIV_HPPF_LBLVARIANT_PCOPY, CTORS) \ |
930 | | default: break; \ |
931 | | } \ |
932 | | return *this; \ |
933 | | } \ |
934 | | template <typename V> \ |
935 | | static void meta(V& v) { \ |
936 | | PRIV_HPPF_MAP(PRIV_HPPF_LBLVARIANT_META, CTORS) \ |
937 | | } \ |
938 | | template <typename R> \ |
939 | | R visit(const T##Visitor<R>& v) const { \ |
940 | | switch (this->tag) { \ |
941 | | PRIV_HPPF_MAP(PRIV_HPPF_LBLVARIANT_VCASE, CTORS) \ |
942 | | default: throw std::runtime_error("while deconstructing the " #T " variant, cannot decide payload type because tag is invalid"); \ |
943 | | } \ |
944 | | } \ |
945 | | template <typename V> \ |
946 | | void gvisit(V& v) const { \ |
947 | | switch (this->tag) { \ |
948 | | PRIV_HPPF_MAP(PRIV_HPPF_LBLVARIANT_GVCASE, CTORS) \ |
949 | | default: break; \ |
950 | | } \ |
951 | | } \ |
952 | | template <typename V> \ |
953 | | void ginit(uint32_t t, V& v) { \ |
954 | | switch (this->tag) { \ |
955 | | PRIV_HPPF_MAP(PRIV_HPPF_LBLVARIANT_PDESTROY, CTORS) \ |
956 | | default: break; \ |
957 | | } \ |
958 | | this->tag = static_cast<Enum>(t); \ |
959 | | switch (this->tag) { \ |
960 | | PRIV_HPPF_MAP(PRIV_HPPF_LBLVARIANT_GINIT, CTORS) \ |
961 | | default: break; \ |
962 | | } \ |
963 | | } \ |
964 | | template <typename X> \ |
965 | | inline typename std::enable_if<std::is_base_of<X, T>::value, bool>::type operator==(const X& rhs) const { \ |
966 | | if (this->tag != rhs.tag) { \ |
967 | | return false; \ |
968 | | } else { \ |
969 | | switch (this->tag) { \ |
970 | | PRIV_HPPF_MAP(PRIV_HPPF_LBLVARIANT_EQCASE, CTORS) \ |
971 | | default: return false; \ |
972 | | } \ |
973 | | } \ |
974 | | } \ |
975 | | private: \ |
976 | | enum class Enum : uint32_t { \ |
977 | | PRIV_HPPF_MAP(PRIV_HPPF_LBLVARIANT_CTOR_TAG, CTORS) \ |
978 | | COUNT \ |
979 | | }; \ |
980 | | Enum tag; \ |
981 | | union { \ |
982 | | char data[1]; \ |
983 | | PRIV_HPPF_MAP(PRIV_HPPF_LBLVARIANT_CTOR_DATA, CTORS) \ |
984 | | }; \ |
985 | | public: \ |
986 | | template <typename X> \ |
987 | | friend inline typename std::enable_if<std::is_base_of<X,T>::value && ::hobbes::can_show_type<T::as_variant_type>::value,std::ostream&>::type operator<<(std::ostream& o, const X& v) { \ |
988 | | switch (v.tag) { \ |
989 | | PRIV_HPPF_MAP(PRIV_HPPF_LBLVARIANT_SHOW, CTORS) \ |
990 | | default: o << "?"; break; \ |
991 | | } \ |
992 | | return o; \ |
993 | | } \ |
994 | | } |
995 | | |
996 | | // arrays with dynamically-determined length |
997 | | template <typename T> |
998 | | struct array { |
999 | | using ptr = array<T> *; |
1000 | | |
1001 | | size_t size; |
1002 | | T data[1]; // unknown length, bytes inline with this structure |
1003 | | |
1004 | | const T& operator[](size_t i) const { return this->data[i]; } |
1005 | | T& operator[](size_t i) { return this->data[i]; } |
1006 | | }; |
1007 | | template <typename T> const T* begin(const array<T>* d) { return d->data; } |
1008 | | template <typename T> const T* end (const array<T>* d) { return d->data + d->size; } |
1009 | | template <typename T> T* begin( array<T>* d) { return d->data; } |
1010 | | template <typename T> T* end ( array<T>* d) { return d->data + d->size; } |
1011 | | |
1012 | | template <typename T> const T* begin(const array<T>& d) { return d.data; } |
1013 | | template <typename T> const T* end (const array<T>& d) { return d.data + d.size; } |
1014 | | template <typename T> T* begin( array<T>& d) { return d.data; } |
1015 | | template <typename T> T* end ( array<T>& d) { return d.data + d.size; } |
1016 | | |
1017 | | // arrays with dynamically-determined length but with a fixed-capacity |
1018 | | template <typename T, size_t N> |
1019 | | struct carray { |
1020 | | size_t size; |
1021 | | T data[N]; |
1022 | | |
1023 | | const T& operator[](size_t i) const { return this->data[i]; } |
1024 | | T& operator[](size_t i) { return this->data[i]; } |
1025 | | }; |
1026 | | template <size_t N> |
1027 | | struct carray<char,N> { |
1028 | | size_t size; |
1029 | | char data[N]; |
1030 | | |
1031 | | const char& operator[](size_t i) const { return this->data[i]; } |
1032 | | char& operator[](size_t i) { return this->data[i]; } |
1033 | | |
1034 | | carray<char,N>& operator=(const char* s) { |
1035 | | size_t n = std::min<size_t>(N, strlen(s)); |
1036 | | memcpy(this->data, s, n); |
1037 | | this->size = n; |
1038 | | return *this; |
1039 | | } |
1040 | | }; |
1041 | | |
1042 | | template <typename T, size_t N> const T* begin(const carray<T,N>* d) { return d->data; } |
1043 | | template <typename T, size_t N> const T* end (const carray<T,N>* d) { return d->data + d->size; } |
1044 | | template <typename T, size_t N> T* begin( carray<T,N>* d) { return d->data; } |
1045 | | template <typename T, size_t N> T* end ( carray<T,N>* d) { return d->data + d->size; } |
1046 | | |
1047 | | template <typename T, size_t N> const T* begin(const carray<T,N>& d) { return d.data; } |
1048 | | template <typename T, size_t N> const T* end (const carray<T,N>& d) { return d.data + d.size; } |
1049 | | template <typename T, size_t N> T* begin( carray<T,N>& d) { return d.data; } |
1050 | | template <typename T, size_t N> T* end ( carray<T,N>& d) { return d.data + d.size; } |
1051 | | |
1052 | | // define opaque type aliases (inherit from 'alias', add a static 'name()' function) |
1053 | | template <typename RepTy> |
1054 | | struct alias { |
1055 | | static const bool is_hmeta_alias = true; |
1056 | | using type = RepTy; |
1057 | | RepTy value; |
1058 | | |
1059 | | alias() : value() { } |
1060 | 0 | alias(const RepTy& x) : value(x) { } |
1061 | | constexpr alias(const alias<RepTy>&) = default; |
1062 | | alias& operator=(const alias<RepTy>&) = default; |
1063 | | }; |
1064 | | |
1065 | | #define DEFINE_TYPE_ALIAS_AS(PRIV_ATY, N, PRIV_REPTY) \ |
1066 | | struct PRIV_ATY : public ::hobbes::alias<PRIV_REPTY> { \ |
1067 | | using ::hobbes::alias<PRIV_REPTY>::alias; \ |
1068 | 17 | static const char* name() { return #N; } \hobbes::timespanT::name() Line | Count | Source | 1068 | 3 | static const char* name() { return #N; } \ |
Line | Count | Source | 1068 | 3 | static const char* name() { return #N; } \ |
hobbes::datetimeT::name() Line | Count | Source | 1068 | 11 | static const char* name() { return #N; } \ |
|
1069 | | } |
1070 | | |
1071 | | #define DEFINE_TYPE_ALIAS(PRIV_ATY, PRIV_REPTY) DEFINE_TYPE_ALIAS_AS(PRIV_ATY, PRIV_ATY, PRIV_REPTY) |
1072 | | |
1073 | | /*************************************************** |
1074 | | * |
1075 | | * type description/encoding |
1076 | | * |
1077 | | ***************************************************/ |
1078 | | |
1079 | | namespace ty { |
1080 | | |
1081 | | using bytes = std::vector<uint8_t>; |
1082 | | |
1083 | | // type encoding logic |
1084 | | #define PRIV_HPPF_TYCTOR_PRIM (static_cast<uint32_t>(0)) |
1085 | | #define PRIV_HPPF_TYCTOR_TVAR (static_cast<uint32_t>(2)) |
1086 | | #define PRIV_HPPF_TYCTOR_FIXEDARR (static_cast<uint32_t>(4)) |
1087 | | #define PRIV_HPPF_TYCTOR_ARR (static_cast<uint32_t>(5)) |
1088 | | #define PRIV_HPPF_TYCTOR_VARIANT (static_cast<uint32_t>(6)) |
1089 | | #define PRIV_HPPF_TYCTOR_STRUCT (static_cast<uint32_t>(7)) |
1090 | | #define PRIV_HPPF_TYCTOR_SIZE (static_cast<uint32_t>(11)) |
1091 | | #define PRIV_HPPF_TYCTOR_TAPP (static_cast<uint32_t>(12)) |
1092 | | #define PRIV_HPPF_TYCTOR_RECURSIVE (static_cast<uint32_t>(13)) |
1093 | | #define PRIV_HPPF_TYCTOR_TABS (static_cast<uint32_t>(15)) |
1094 | | |
1095 | 0 | struct D { uint32_t tid; D(uint32_t tid) : tid(tid) { } }; |
1096 | | using desc = std::shared_ptr<D>; |
1097 | | |
1098 | | struct Nat : public D { |
1099 | 0 | Nat(size_t x) : D(PRIV_HPPF_TYCTOR_SIZE), x(x) { } |
1100 | | |
1101 | | size_t x; |
1102 | | }; |
1103 | 0 | inline desc nat(size_t x) { return desc(new Nat(x)); } |
1104 | | |
1105 | | struct Prim : public D { |
1106 | 0 | Prim(const std::string& n, const desc& rep) : D(PRIV_HPPF_TYCTOR_PRIM), n(n), rep(rep) { } |
1107 | | |
1108 | | std::string n; // the name of this type, assumed primitive |
1109 | | desc rep; // may be null if not an opaque type alias |
1110 | | }; |
1111 | 0 | inline desc prim(const std::string& n, const desc& rep = desc()) { return desc(new Prim(n, rep)); } |
1112 | | |
1113 | | struct Var : public D { |
1114 | 0 | Var(const std::string& n) : D(PRIV_HPPF_TYCTOR_TVAR), n(n) { } |
1115 | | std::string n; |
1116 | | }; |
1117 | 0 | inline desc var(const std::string& n) { return desc(new Var(n)); } |
1118 | | |
1119 | | struct FArr : public D { |
1120 | 0 | FArr(const desc& t, const desc& len) : D(PRIV_HPPF_TYCTOR_FIXEDARR), t(t), len(len) { } |
1121 | | desc t; |
1122 | | desc len; |
1123 | | }; |
1124 | 0 | inline desc array(const desc& t, const desc& len) { return desc(new FArr(t, len)); } |
1125 | | |
1126 | | struct Arr : public D { |
1127 | 0 | Arr(const desc& t) : D(PRIV_HPPF_TYCTOR_ARR), t(t) { } |
1128 | | desc t; |
1129 | | }; |
1130 | 0 | inline desc array(const desc& t) { return desc(new Arr(t)); } |
1131 | | |
1132 | | struct Variant : public D { |
1133 | | using Ctor = tuple<std::string, uint32_t, desc>; |
1134 | | using Ctors = std::vector<Ctor>; |
1135 | | |
1136 | 0 | Variant(const Ctors& ctors) : D(PRIV_HPPF_TYCTOR_VARIANT), ctors(ctors) { } |
1137 | | |
1138 | | Ctors ctors; |
1139 | | }; |
1140 | 0 | inline desc variant(const Variant::Ctors& ctors) { return desc(new Variant(ctors)); } |
1141 | | |
1142 | | template <typename ... Tys> |
1143 | 0 | struct sumAcc { static void acc(std::vector<desc>*, const Tys& ...) { } }; |
1144 | | template <typename ... Tys> |
1145 | 0 | struct sumAcc<desc, Tys...> { static void acc(std::vector<desc>* ts, const desc& t, const Tys& ... tt) { ts->push_back(t); sumAcc<Tys...>::acc(ts, tt...); } };Unexecuted instantiation: hobbes::ty::sumAcc<std::shared_ptr<hobbes::ty::D>, std::shared_ptr<hobbes::ty::D> >::acc(std::vector<std::shared_ptr<hobbes::ty::D>, std::allocator<std::shared_ptr<hobbes::ty::D> > >*, std::shared_ptr<hobbes::ty::D> const&, std::shared_ptr<hobbes::ty::D> const&) Unexecuted instantiation: hobbes::ty::sumAcc<std::shared_ptr<hobbes::ty::D> >::acc(std::vector<std::shared_ptr<hobbes::ty::D>, std::allocator<std::shared_ptr<hobbes::ty::D> > >*, std::shared_ptr<hobbes::ty::D> const&) |
1146 | | |
1147 | | template <typename ... Tys> |
1148 | 0 | inline desc sum(const Tys&... tt) { |
1149 | 0 | std::vector<desc> ts; |
1150 | 0 | sumAcc<Tys...>::acc(&ts, tt...); |
1151 | 0 | |
1152 | 0 | Variant::Ctors cs; |
1153 | 0 | for (size_t i = 0; i < ts.size(); ++i) { |
1154 | 0 | std::ostringstream n; |
1155 | 0 | n << ".f" << i; |
1156 | 0 | cs.push_back(Variant::Ctor(n.str(), static_cast<uint32_t>(i), ts[i])); |
1157 | 0 | } |
1158 | 0 | return variant(cs); |
1159 | 0 | } |
1160 | | |
1161 | | struct Struct : public D { |
1162 | | using Field = tuple<std::string, int, desc>; |
1163 | | using Fields = std::vector<Field>; |
1164 | | |
1165 | 0 | Struct(const Fields& fields) : D(PRIV_HPPF_TYCTOR_STRUCT), fields(fields) { } |
1166 | | |
1167 | | Fields fields; |
1168 | | }; |
1169 | 0 | inline desc record(const Struct::Fields& fields) { return fields.empty() ? prim("unit") : desc(new Struct(fields)); } |
1170 | | |
1171 | | template <typename ... Tys> |
1172 | 0 | struct tupAcc { static void acc(Struct::Fields*) { } }; |
1173 | | template <typename ... Tys> |
1174 | 0 | struct tupAcc<int, desc, Tys...> { static void acc(Struct::Fields* fs, const int& o, const desc& t, const Tys& ... tt) { fs->push_back(Struct::Field("", o, t)); tupAcc<Tys...>::acc(fs, tt...); } }; |
1175 | | template <typename ... Tys> |
1176 | 0 | struct tupAcc<size_t, desc, Tys...> { static void acc(Struct::Fields* fs, const size_t& o, const desc& t, const Tys& ... tt) { fs->push_back(Struct::Field("", o, t)); tupAcc<Tys...>::acc(fs, tt...); } }; |
1177 | | template <typename ... Tys> |
1178 | 0 | desc tup(const Tys& ... tt) { |
1179 | 0 | Struct::Fields fs; |
1180 | 0 | tupAcc<Tys...>::acc(&fs, tt...); |
1181 | 0 | for (size_t i = 0; i < fs.size(); ++i) { |
1182 | 0 | std::ostringstream n; |
1183 | 0 | n << ".f" << i; |
1184 | 0 | fs[i].at<0>() = n.str(); |
1185 | 0 | } |
1186 | 0 | return record(fs); |
1187 | 0 | } |
1188 | | |
1189 | | template <typename ... Tys> |
1190 | 0 | struct recAcc { static void acc(Struct::Fields*) { } }; |
1191 | | template <size_t N, typename ... Tys> |
1192 | 0 | struct recAcc<char[N], int, desc, Tys...> { static void acc(Struct::Fields* fs, const char (&n)[N], const int& o, const desc& t, const Tys& ... tt) { fs->push_back(Struct::Field(n, o, t)); recAcc<Tys...>::acc(fs, tt...); } }; |
1193 | | template <size_t N, typename ... Tys> |
1194 | 0 | struct recAcc<char[N], size_t, desc, Tys...> { static void acc(Struct::Fields* fs, const char (&n)[N], const size_t& o, const desc& t, const Tys& ... tt) { fs->push_back(Struct::Field(n, o, t)); recAcc<Tys...>::acc(fs, tt...); } }; |
1195 | | template <typename ... Tys> |
1196 | 0 | desc rec(const Tys& ... tt) { |
1197 | 0 | Struct::Fields fs; |
1198 | 0 | recAcc<Tys...>::acc(&fs, tt...); |
1199 | 0 | return record(fs); |
1200 | 0 | } |
1201 | | |
1202 | | struct Recursive : public D { |
1203 | 0 | Recursive(const std::string& x, const desc& t) : D(PRIV_HPPF_TYCTOR_RECURSIVE), x(x), t(t) { } |
1204 | | |
1205 | | std::string x; |
1206 | | desc t; |
1207 | | }; |
1208 | 0 | inline desc recursive(const std::string& x, const desc& t) { return desc(new Recursive(x, t)); } |
1209 | | |
1210 | | struct Fn : public D { |
1211 | | using Args = std::vector<std::string>; |
1212 | 0 | Fn(const Args& args, const desc& t) : D(PRIV_HPPF_TYCTOR_TABS), args(args), t(t) { } |
1213 | | |
1214 | | Args args; |
1215 | | desc t; |
1216 | | }; |
1217 | 0 | inline desc fnc(const Fn::Args& args, const desc& t) { return desc(new Fn(args, t)); } |
1218 | | |
1219 | | template <typename ... Tys> |
1220 | | struct fnAcc { static desc acc(Fn::Args*) { assert(false && "fn must define arg list and body"); return desc(); } }; |
1221 | | template <> |
1222 | 0 | struct fnAcc<desc> { static desc acc(Fn::Args* args, const desc& t) { return fnc(*args, t); } }; |
1223 | | template <size_t N, typename ... Tys> |
1224 | 0 | struct fnAcc<char[N], Tys...> { static desc acc(Fn::Args* args, const char (&n)[N], const Tys& ... tt) { args->push_back(n); return fnAcc<Tys...>::acc(args, tt...); } };Unexecuted instantiation: hobbes::ty::fnAcc<char [2], std::shared_ptr<hobbes::ty::D> >::acc(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >*, char const (&) [2], std::shared_ptr<hobbes::ty::D> const&) Unexecuted instantiation: hobbes::ty::fnAcc<char [2], char [2], std::shared_ptr<hobbes::ty::D> >::acc(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >*, char const (&) [2], char const (&) [2], std::shared_ptr<hobbes::ty::D> const&) Unexecuted instantiation: hobbes::ty::fnAcc<char [2], char [2], char [2], std::shared_ptr<hobbes::ty::D> >::acc(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >*, char const (&) [2], char const (&) [2], char const (&) [2], std::shared_ptr<hobbes::ty::D> const&) |
1225 | | |
1226 | | template <typename ... Tys> |
1227 | 0 | inline desc fn(const Tys& ... tt) { Fn::Args args; return fnAcc<Tys...>::acc(&args, tt...); }Unexecuted instantiation: std::shared_ptr<hobbes::ty::D> hobbes::ty::fn<char [2], std::shared_ptr<hobbes::ty::D> >(char const (&) [2], std::shared_ptr<hobbes::ty::D> const&) Unexecuted instantiation: std::shared_ptr<hobbes::ty::D> hobbes::ty::fn<char [2], char [2], std::shared_ptr<hobbes::ty::D> >(char const (&) [2], char const (&) [2], std::shared_ptr<hobbes::ty::D> const&) Unexecuted instantiation: std::shared_ptr<hobbes::ty::D> hobbes::ty::fn<char [2], char [2], char [2], std::shared_ptr<hobbes::ty::D> >(char const (&) [2], char const (&) [2], char const (&) [2], std::shared_ptr<hobbes::ty::D> const&) |
1228 | | |
1229 | | struct App : public D { |
1230 | | using Args = std::vector<desc>; |
1231 | | |
1232 | 0 | App(const desc& f, const Args& args) : D(PRIV_HPPF_TYCTOR_TAPP), f(f), args(args) { } |
1233 | | |
1234 | | desc f; |
1235 | | Args args; |
1236 | | }; |
1237 | 0 | inline desc appc(const desc& f, const App::Args& args) { return desc(new App(f, args)); } |
1238 | | |
1239 | | template <typename ... Tys> |
1240 | 0 | struct appAcc { static void acc(std::vector<desc>*) { } }; |
1241 | | template <typename ... Tys> |
1242 | 0 | struct appAcc<desc, Tys...> { static void acc(std::vector<desc>* ds, const desc& d, const Tys& ... tt) { ds->push_back(d); appAcc<Tys...>::acc(ds, tt...); } };Unexecuted instantiation: hobbes::ty::appAcc<std::shared_ptr<hobbes::ty::D> >::acc(std::vector<std::shared_ptr<hobbes::ty::D>, std::allocator<std::shared_ptr<hobbes::ty::D> > >*, std::shared_ptr<hobbes::ty::D> const&) Unexecuted instantiation: hobbes::ty::appAcc<std::shared_ptr<hobbes::ty::D>, std::shared_ptr<hobbes::ty::D> >::acc(std::vector<std::shared_ptr<hobbes::ty::D>, std::allocator<std::shared_ptr<hobbes::ty::D> > >*, std::shared_ptr<hobbes::ty::D> const&, std::shared_ptr<hobbes::ty::D> const&) Unexecuted instantiation: hobbes::ty::appAcc<std::shared_ptr<hobbes::ty::D>, std::shared_ptr<hobbes::ty::D>, std::shared_ptr<hobbes::ty::D> >::acc(std::vector<std::shared_ptr<hobbes::ty::D>, std::allocator<std::shared_ptr<hobbes::ty::D> > >*, std::shared_ptr<hobbes::ty::D> const&, std::shared_ptr<hobbes::ty::D> const&, std::shared_ptr<hobbes::ty::D> const&) |
1243 | | |
1244 | | template <typename ... Tys> |
1245 | 0 | inline desc app(const desc& f, const Tys& ... tt) { |
1246 | 0 | std::vector<desc> ds; |
1247 | 0 | appAcc<Tys...>::acc(&ds, tt...); |
1248 | 0 | return appc(f, ds); |
1249 | 0 | } Unexecuted instantiation: std::shared_ptr<hobbes::ty::D> hobbes::ty::app<std::shared_ptr<hobbes::ty::D> >(std::shared_ptr<hobbes::ty::D> const&, std::shared_ptr<hobbes::ty::D> const&) Unexecuted instantiation: std::shared_ptr<hobbes::ty::D> hobbes::ty::app<std::shared_ptr<hobbes::ty::D>, std::shared_ptr<hobbes::ty::D> >(std::shared_ptr<hobbes::ty::D> const&, std::shared_ptr<hobbes::ty::D> const&, std::shared_ptr<hobbes::ty::D> const&) Unexecuted instantiation: std::shared_ptr<hobbes::ty::D> hobbes::ty::app<std::shared_ptr<hobbes::ty::D>, std::shared_ptr<hobbes::ty::D>, std::shared_ptr<hobbes::ty::D> >(std::shared_ptr<hobbes::ty::D> const&, std::shared_ptr<hobbes::ty::D> const&, std::shared_ptr<hobbes::ty::D> const&, std::shared_ptr<hobbes::ty::D> const&) |
1250 | | |
1251 | | template <typename R> |
1252 | | inline desc enumdef(const desc& rep, const std::vector<std::pair<std::string, R>>& eds) { |
1253 | | Variant::Ctors ctors; |
1254 | | for (const auto& ed : eds) { |
1255 | | ctors.push_back(Variant::Ctor(ed.first, ed.second, prim("unit"))); |
1256 | | } |
1257 | | if (sizeof(R) == sizeof(uint32_t)) { |
1258 | | return variant(ctors); |
1259 | | } else { |
1260 | | return app(prim("penum", fn("r", "v", var("r"))), rep, variant(ctors)); |
1261 | | } |
1262 | | } |
1263 | | |
1264 | 0 | inline desc fileRef(const desc& t) { |
1265 | 0 | return app(prim("fileref", fn("x", prim("long"))), t); |
1266 | 0 | } |
1267 | | |
1268 | | // remove file ref types (recursively) |
1269 | | // (this reverses the storage view of all types) |
1270 | 0 | inline desc elimFileRefs(const desc& t) { |
1271 | 0 | const D* pd = t.get(); |
1272 | 0 | const FArr* pfa = reinterpret_cast<const FArr*>(pd); |
1273 | 0 | const Arr* pa = reinterpret_cast<const Arr*>(pd); |
1274 | 0 | const auto* pv = reinterpret_cast<const Variant*>(pd); |
1275 | 0 | const auto* ps = reinterpret_cast<const Struct*>(pd); |
1276 | 0 | const auto* pr = reinterpret_cast<const Recursive*>(pd); |
1277 | 0 | const Fn* pfn = reinterpret_cast<const Fn*>(pd); |
1278 | 0 | const App* papp = reinterpret_cast<const App*>(pd); |
1279 | 0 |
|
1280 | 0 | switch (t->tid) { |
1281 | 0 | default: |
1282 | 0 | return t; |
1283 | 0 | case PRIV_HPPF_TYCTOR_FIXEDARR: |
1284 | 0 | return array(elimFileRefs(pfa->t), elimFileRefs(pfa->len)); |
1285 | 0 | case PRIV_HPPF_TYCTOR_ARR: |
1286 | 0 | return array(elimFileRefs(pa->t)); |
1287 | 0 | case PRIV_HPPF_TYCTOR_VARIANT: |
1288 | 0 | { |
1289 | 0 | Variant::Ctors ctors; |
1290 | 0 | for (const auto& ctor : pv->ctors) { |
1291 | 0 | ctors.push_back(Variant::Ctor(ctor.at<0>(), ctor.at<1>(), elimFileRefs(ctor.at<2>()))); |
1292 | 0 | } |
1293 | 0 | return variant(ctors); |
1294 | 0 | } |
1295 | 0 | case PRIV_HPPF_TYCTOR_STRUCT: |
1296 | 0 | { |
1297 | 0 | Struct::Fields fs; |
1298 | 0 | for (const auto& field : ps->fields) { |
1299 | 0 | fs.push_back(Struct::Field(field.at<0>(), -1, elimFileRefs(field.at<2>()))); |
1300 | 0 | } |
1301 | 0 | return record(fs); |
1302 | 0 | } |
1303 | 0 | case PRIV_HPPF_TYCTOR_TAPP: |
1304 | 0 | { |
1305 | 0 | if (papp->f->tid == PRIV_HPPF_TYCTOR_PRIM) { |
1306 | 0 | if (reinterpret_cast<const Prim*>(papp->f.get())->n == "fileref") { |
1307 | 0 | if (!papp->args.empty()) { |
1308 | 0 | return elimFileRefs(papp->args[0]); |
1309 | 0 | } |
1310 | 0 | } |
1311 | 0 | } |
1312 | 0 |
|
1313 | 0 | // default translation |
1314 | 0 | App::Args args; |
1315 | 0 | for (const auto& arg : papp->args) { |
1316 | 0 | args.push_back(elimFileRefs(arg)); |
1317 | 0 | } |
1318 | 0 | return appc(elimFileRefs(papp->f), args); |
1319 | 0 | } |
1320 | 0 | case PRIV_HPPF_TYCTOR_RECURSIVE: |
1321 | 0 | return recursive(pr->x, elimFileRefs(pr->t)); |
1322 | 0 | case PRIV_HPPF_TYCTOR_TABS: |
1323 | 0 | return fnc(pfn->args, elimFileRefs(pfn->t)); |
1324 | 0 | } |
1325 | 0 | } |
1326 | | |
1327 | | // encode a type description as a byte array (for storage/transmission) |
1328 | | template <typename T> |
1329 | 0 | void w(const T& x, bytes* out) { |
1330 | 0 | out->insert(out->end(), reinterpret_cast<const uint8_t*>(&x), reinterpret_cast<const uint8_t*>(&x) + sizeof(x)); |
1331 | 0 | } Unexecuted instantiation: void hobbes::ty::w<unsigned long>(unsigned long const&, std::vector<unsigned char, std::allocator<unsigned char> >*) Unexecuted instantiation: void hobbes::ty::w<unsigned int>(unsigned int const&, std::vector<unsigned char, std::allocator<unsigned char> >*) Unexecuted instantiation: void hobbes::ty::w<bool>(bool const&, std::vector<unsigned char, std::allocator<unsigned char> >*) |
1332 | 0 | inline void ws(const char* x, bytes* out) { |
1333 | 0 | size_t n = strlen(x); |
1334 | 0 | w(n, out); |
1335 | 0 | out->insert(out->end(), x, x + n); |
1336 | 0 | } |
1337 | 0 | inline void ws(const std::string& x, bytes* out) { |
1338 | 0 | w(static_cast<size_t>(x.size()), out); |
1339 | 0 | out->insert(out->end(), x.begin(), x.end()); |
1340 | 0 | } |
1341 | 0 | inline void ws(const bytes& x, bytes* out) { |
1342 | 0 | w(static_cast<size_t>(x.size()), out); |
1343 | 0 | out->insert(out->end(), x.begin(), x.end()); |
1344 | 0 | } |
1345 | | |
1346 | 0 | inline void encode(const desc& t, bytes* o) { |
1347 | 0 | const D* pd = t.get(); |
1348 | 0 | const Prim* pt = reinterpret_cast<const Prim*>(pd); |
1349 | 0 | const Var* pvn = reinterpret_cast<const Var*>(pd); |
1350 | 0 | const FArr* pfa = reinterpret_cast<const FArr*>(pd); |
1351 | 0 | const Arr* pa = reinterpret_cast<const Arr*>(pd); |
1352 | 0 | const auto* pv = reinterpret_cast<const Variant*>(pd); |
1353 | 0 | const auto* ps = reinterpret_cast<const Struct*>(pd); |
1354 | 0 | const auto* pr = reinterpret_cast<const Recursive*>(pd); |
1355 | 0 | const Fn* pfn = reinterpret_cast<const Fn*>(pd); |
1356 | 0 | const App* papp = reinterpret_cast<const App*>(pd); |
1357 | 0 | const Nat* pn = reinterpret_cast<const Nat*>(pd); |
1358 | 0 |
|
1359 | 0 | w(t->tid, o); |
1360 | 0 | switch (t->tid) { |
1361 | 0 | case PRIV_HPPF_TYCTOR_PRIM: |
1362 | 0 | ws(pt->n, o); |
1363 | 0 | if (pt->rep) { |
1364 | 0 | w(true, o); |
1365 | 0 | encode(pt->rep, o); |
1366 | 0 | } else { |
1367 | 0 | w(false, o); |
1368 | 0 | } |
1369 | 0 | break; |
1370 | 0 | case PRIV_HPPF_TYCTOR_TVAR: |
1371 | 0 | ws(pvn->n, o); |
1372 | 0 | break; |
1373 | 0 | case PRIV_HPPF_TYCTOR_FIXEDARR: |
1374 | 0 | encode(pfa->t, o); |
1375 | 0 | encode(pfa->len, o); |
1376 | 0 | break; |
1377 | 0 | case PRIV_HPPF_TYCTOR_ARR: |
1378 | 0 | encode(pa->t, o); |
1379 | 0 | break; |
1380 | 0 | case PRIV_HPPF_TYCTOR_VARIANT: |
1381 | 0 | w(static_cast<size_t>(pv->ctors.size()), o); |
1382 | 0 | for (const auto& ctor : pv->ctors) { |
1383 | 0 | ws(ctor.at<0>(), o); |
1384 | 0 | w(static_cast<uint32_t>(ctor.at<1>()), o); |
1385 | 0 | encode(ctor.at<2>(), o); |
1386 | 0 | } |
1387 | 0 | break; |
1388 | 0 | case PRIV_HPPF_TYCTOR_STRUCT: |
1389 | 0 | w(static_cast<size_t>(ps->fields.size()), o); |
1390 | 0 | for (const auto& field : ps->fields) { |
1391 | 0 | ws(field.at<0>(), o); |
1392 | 0 | w(static_cast<uint32_t>(field.at<1>()), o); |
1393 | 0 | encode(field.at<2>(), o); |
1394 | 0 | } |
1395 | 0 | break; |
1396 | 0 | case PRIV_HPPF_TYCTOR_SIZE: |
1397 | 0 | w(pn->x, o); |
1398 | 0 | break; |
1399 | 0 | case PRIV_HPPF_TYCTOR_TAPP: |
1400 | 0 | encode(papp->f, o); |
1401 | 0 | w(static_cast<size_t>(papp->args.size()), o); |
1402 | 0 | for (const auto& arg : papp->args) { |
1403 | 0 | encode(arg, o); |
1404 | 0 | } |
1405 | 0 | break; |
1406 | 0 | case PRIV_HPPF_TYCTOR_RECURSIVE: |
1407 | 0 | ws(pr->x, o); |
1408 | 0 | encode(pr->t, o); |
1409 | 0 | break; |
1410 | 0 | case PRIV_HPPF_TYCTOR_TABS: |
1411 | 0 | w(static_cast<size_t>(pfn->args.size()), o); |
1412 | 0 | for (const auto& arg : pfn->args) { |
1413 | 0 | ws(arg, o); |
1414 | 0 | } |
1415 | 0 | encode(pfn->t, o); |
1416 | 0 | break; |
1417 | 0 | default: |
1418 | 0 | assert(false && "Invalid type description, internal error"); |
1419 | 0 | break; |
1420 | 0 | } |
1421 | 0 | } |
1422 | | |
1423 | 0 | inline bytes encoding(const desc& t) { |
1424 | 0 | bytes r; |
1425 | 0 | encode(t, &r); |
1426 | 0 | return r; |
1427 | 0 | } |
1428 | | |
1429 | 0 | inline bool operator==(const desc& t0, const desc& t1) { |
1430 | 0 | return encoding(t0) == encoding(t1); |
1431 | 0 | } |
1432 | 0 | inline bool operator!=(const desc& t0, const desc& t1) { |
1433 | 0 | return !(t0 == t1); |
1434 | 0 | } |
1435 | | |
1436 | | // decode a type description from a byte array generated by 'encode' |
1437 | | template <typename T> |
1438 | 0 | T readValue(const bytes& bs, size_t* i) { |
1439 | 0 | assert((bs.size() >= (*i + sizeof(T))) && "Invalid type encoding, expected data not available"); |
1440 | 0 | T result; |
1441 | 0 | std::memcpy(&result, &bs[*i], sizeof(T)); |
1442 | 0 | *i += sizeof(T); |
1443 | 0 | return result; |
1444 | 0 | } Unexecuted instantiation: unsigned long hobbes::ty::readValue<unsigned long>(std::vector<unsigned char, std::allocator<unsigned char> > const&, unsigned long*) Unexecuted instantiation: unsigned int hobbes::ty::readValue<unsigned int>(std::vector<unsigned char, std::allocator<unsigned char> > const&, unsigned long*) Unexecuted instantiation: bool hobbes::ty::readValue<bool>(std::vector<unsigned char, std::allocator<unsigned char> > const&, unsigned long*) Unexecuted instantiation: int hobbes::ty::readValue<int>(std::vector<unsigned char, std::allocator<unsigned char> > const&, unsigned long*) |
1445 | 0 | inline std::string readString(const bytes& bs, size_t* i) { |
1446 | 0 | auto sz = readValue<size_t>(bs, i); |
1447 | 0 | assert((bs.size() >= (*i + sz)) && "Invalid type encoding, expected string data not available"); |
1448 | 0 | const char* s = reinterpret_cast<const char*>(&bs[*i]); |
1449 | 0 | std::string result(s, s + sz); |
1450 | 0 | *i += sz; |
1451 | 0 | return result; |
1452 | 0 | } |
1453 | | |
1454 | 0 | inline desc decodeFrom(const bytes& bs, size_t* i) { |
1455 | 0 | switch (readValue<uint32_t>(bs, i)) { |
1456 | 0 | case PRIV_HPPF_TYCTOR_PRIM: { |
1457 | 0 | std::string n = readString(bs, i); |
1458 | 0 | desc rep; |
1459 | 0 | if (readValue<bool>(bs, i)) { |
1460 | 0 | rep = decodeFrom(bs, i); |
1461 | 0 | } |
1462 | 0 | return prim(n, rep); |
1463 | 0 | } |
1464 | 0 |
|
1465 | 0 | case PRIV_HPPF_TYCTOR_TVAR: { |
1466 | 0 | std::string n = readString(bs, i); |
1467 | 0 | return var(n); |
1468 | 0 | } |
1469 | 0 |
|
1470 | 0 | case PRIV_HPPF_TYCTOR_FIXEDARR: { |
1471 | 0 | desc t = decodeFrom(bs, i); |
1472 | 0 | desc n = decodeFrom(bs, i); |
1473 | 0 | return array(t, n); |
1474 | 0 | } |
1475 | 0 |
|
1476 | 0 | case PRIV_HPPF_TYCTOR_ARR: { |
1477 | 0 | return array(decodeFrom(bs, i)); |
1478 | 0 | } |
1479 | 0 |
|
1480 | 0 | case PRIV_HPPF_TYCTOR_VARIANT: { |
1481 | 0 | auto n = readValue<size_t>(bs, i); |
1482 | 0 | Variant::Ctors cs; |
1483 | 0 | for (size_t k = 0; k < n; ++k) { |
1484 | 0 | std::string n = readString(bs, i); |
1485 | 0 | int id = readValue<int>(bs, i); |
1486 | 0 | desc t = decodeFrom(bs, i); |
1487 | 0 |
|
1488 | 0 | cs.push_back(Variant::Ctor(n, id, t)); |
1489 | 0 | } |
1490 | 0 | return variant(cs); |
1491 | 0 | } |
1492 | 0 |
|
1493 | 0 | case PRIV_HPPF_TYCTOR_STRUCT: { |
1494 | 0 | auto count = readValue<size_t>(bs, i); |
1495 | 0 | Struct::Fields fs; |
1496 | 0 | for (size_t k = 0; k < count; ++k) { |
1497 | 0 | std::string n = readString(bs, i); |
1498 | 0 | int o = readValue<int>(bs, i); |
1499 | 0 | desc t = decodeFrom(bs, i); |
1500 | 0 |
|
1501 | 0 | fs.push_back(Struct::Field(n, o, t)); |
1502 | 0 | } |
1503 | 0 | return record(fs); |
1504 | 0 | } |
1505 | 0 |
|
1506 | 0 | case PRIV_HPPF_TYCTOR_SIZE: { |
1507 | 0 | return nat(readValue<size_t>(bs, i)); |
1508 | 0 | } |
1509 | 0 |
|
1510 | 0 | case PRIV_HPPF_TYCTOR_TAPP: { |
1511 | 0 | desc f = decodeFrom(bs, i); |
1512 | 0 | auto n = readValue<size_t>(bs, i); |
1513 | 0 |
|
1514 | 0 | App::Args args; |
1515 | 0 | for (size_t k = 0; k < n; ++k) { |
1516 | 0 | args.push_back(decodeFrom(bs, i)); |
1517 | 0 | } |
1518 | 0 |
|
1519 | 0 | return appc(f, args); |
1520 | 0 | } |
1521 | 0 |
|
1522 | 0 | case PRIV_HPPF_TYCTOR_RECURSIVE: { |
1523 | 0 | std::string n = readString(bs, i); |
1524 | 0 | desc t = decodeFrom(bs, i); |
1525 | 0 |
|
1526 | 0 | return recursive(n, t); |
1527 | 0 | } |
1528 | 0 |
|
1529 | 0 | case PRIV_HPPF_TYCTOR_TABS: { |
1530 | 0 | auto n = readValue<size_t>(bs, i); |
1531 | 0 | Fn::Args args; |
1532 | 0 | for (size_t k = 0; k < n; ++k) { |
1533 | 0 | args.push_back(readString(bs, i)); |
1534 | 0 | } |
1535 | 0 | desc t = decodeFrom(bs, i); |
1536 | 0 |
|
1537 | 0 | return fnc(args, t); |
1538 | 0 | } |
1539 | 0 |
|
1540 | 0 | default: |
1541 | 0 | assert(false && "Invalid type description, internal error"); |
1542 | 0 | throw std::runtime_error("Invalid type description"); |
1543 | 0 | } |
1544 | 0 | } |
1545 | | |
1546 | 0 | inline desc decode(const bytes& bs) { |
1547 | 0 | size_t i = 0; |
1548 | 0 | return decodeFrom(bs, &i); |
1549 | 0 | } |
1550 | | |
1551 | 0 | inline void print(std::ostream& o, const bytes& bs) { |
1552 | 0 | o << "0x"; |
1553 | 0 | for (auto b : bs) { |
1554 | 0 | static const char nybs[] = "0123456789abcdef"; |
1555 | 0 | o << nybs[(b>>4)%16]; |
1556 | 0 | o << nybs[(b&0x0f)%16]; |
1557 | 0 | } |
1558 | 0 | } |
1559 | | |
1560 | | // describe a type description for human consumption |
1561 | 0 | inline void describe(const desc& t, std::ostream& o) { |
1562 | 0 | const D* pd = t.get(); |
1563 | 0 | const Prim* pt = reinterpret_cast<const Prim*>(pd); |
1564 | 0 | const Var* pvn = reinterpret_cast<const Var*>(pd); |
1565 | 0 | const FArr* pfa = reinterpret_cast<const FArr*>(pd); |
1566 | 0 | const Arr* pa = reinterpret_cast<const Arr*>(pd); |
1567 | 0 | const auto* pv = reinterpret_cast<const Variant*>(pd); |
1568 | 0 | const auto* ps = reinterpret_cast<const Struct*>(pd); |
1569 | 0 | const auto* pr = reinterpret_cast<const Recursive*>(pd); |
1570 | 0 | const Fn* pfn = reinterpret_cast<const Fn*>(pd); |
1571 | 0 | const App* papp = reinterpret_cast<const App*>(pd); |
1572 | 0 | const Nat* pn = reinterpret_cast<const Nat*>(pd); |
1573 | 0 |
|
1574 | 0 | switch (t->tid) { |
1575 | 0 | case PRIV_HPPF_TYCTOR_PRIM: |
1576 | 0 | if (pt->n == "unit") { |
1577 | 0 | o << "()"; |
1578 | 0 | } else { |
1579 | 0 | o << pt->n; |
1580 | 0 | } |
1581 | 0 | break; |
1582 | 0 | case PRIV_HPPF_TYCTOR_TVAR: |
1583 | 0 | o << pvn->n; |
1584 | 0 | break; |
1585 | 0 | case PRIV_HPPF_TYCTOR_FIXEDARR: |
1586 | 0 | o << "[:"; |
1587 | 0 | describe(pfa->t, o); |
1588 | 0 | o << "|"; |
1589 | 0 | describe(pfa->len, o); |
1590 | 0 | o << ":]"; |
1591 | 0 | break; |
1592 | 0 | case PRIV_HPPF_TYCTOR_ARR: |
1593 | 0 | o << "["; |
1594 | 0 | describe(pa->t, o); |
1595 | 0 | o << "]"; |
1596 | 0 | break; |
1597 | 0 | case PRIV_HPPF_TYCTOR_VARIANT: |
1598 | 0 | if (pv->ctors.empty()) { |
1599 | 0 | o << "void"; |
1600 | 0 | } else { |
1601 | 0 | // show as sum or variant |
1602 | 0 | if (pv->ctors[0].at<0>().substr(0,1) == ".") { |
1603 | 0 | o << "("; |
1604 | 0 | describe(pv->ctors[0].at<2>(), o); |
1605 | 0 | for (size_t i = 1; i < pv->ctors.size(); ++i) { |
1606 | 0 | o << "+"; |
1607 | 0 | describe(pv->ctors[i].at<2>(), o); |
1608 | 0 | } |
1609 | 0 | o << ")"; |
1610 | 0 | } else { |
1611 | 0 | o << "|" << pv->ctors[0].at<0>() << ":"; |
1612 | 0 | describe(pv->ctors[0].at<2>(), o); |
1613 | 0 | for (size_t i = 1; i < pv->ctors.size(); ++i) { |
1614 | 0 | o << ", " << pv->ctors[i].at<0>() << ":"; |
1615 | 0 | describe(pv->ctors[i].at<2>(), o); |
1616 | 0 | } |
1617 | 0 | o << "|"; |
1618 | 0 | } |
1619 | 0 | } |
1620 | 0 | break; |
1621 | 0 | case PRIV_HPPF_TYCTOR_STRUCT: |
1622 | 0 | if (ps->fields.empty()) { |
1623 | 0 | o << "()"; |
1624 | 0 | } else { |
1625 | 0 | // show as product or record |
1626 | 0 | if (ps->fields[0].at<0>().substr(0,1) == ".") { |
1627 | 0 | o << "("; |
1628 | 0 | describe(ps->fields[0].at<2>(), o); |
1629 | 0 | for (size_t i = 1; i < ps->fields.size(); ++i) { |
1630 | 0 | o << "*"; |
1631 | 0 | describe(ps->fields[i].at<2>(), o); |
1632 | 0 | } |
1633 | 0 | o << ")"; |
1634 | 0 | } else { |
1635 | 0 | o << "{" << ps->fields[0].at<0>() << ":"; |
1636 | 0 | describe(ps->fields[0].at<2>(), o); |
1637 | 0 | for (size_t i = 1; i < ps->fields.size(); ++i) { |
1638 | 0 | o << ", " << ps->fields[i].at<0>() << ":"; |
1639 | 0 | describe(ps->fields[i].at<2>(), o); |
1640 | 0 | } |
1641 | 0 | o << "}"; |
1642 | 0 | } |
1643 | 0 | } |
1644 | 0 | break; |
1645 | 0 | case PRIV_HPPF_TYCTOR_SIZE: |
1646 | 0 | o << pn->x; |
1647 | 0 | break; |
1648 | 0 | case PRIV_HPPF_TYCTOR_TAPP: |
1649 | 0 | if (!papp->args.empty() && papp->f->tid == PRIV_HPPF_TYCTOR_PRIM && reinterpret_cast<const ty::Prim*>(papp->f.get())->n == "fileref") { |
1650 | 0 | describe(papp->args[0], o); |
1651 | 0 | o << "@?"; |
1652 | 0 | } else { |
1653 | 0 | describe(papp->f, o); |
1654 | 0 | o << "("; |
1655 | 0 | if (!papp->args.empty()) { |
1656 | 0 | describe(papp->args[0], o); |
1657 | 0 | for (size_t i = 1; i < papp->args.size(); ++i) { |
1658 | 0 | o << ", "; |
1659 | 0 | describe(papp->args[i], o); |
1660 | 0 | } |
1661 | 0 | } |
1662 | 0 | o << ")"; |
1663 | 0 | } |
1664 | 0 | break; |
1665 | 0 | case PRIV_HPPF_TYCTOR_RECURSIVE: |
1666 | 0 | o << "^" << pr->x << "."; |
1667 | 0 | describe(pr->t, o); |
1668 | 0 | break; |
1669 | 0 | case PRIV_HPPF_TYCTOR_TABS: |
1670 | 0 | o << "\\"; |
1671 | 0 | if (!pfn->args.empty()) { |
1672 | 0 | o << pfn->args[0]; |
1673 | 0 | for (size_t i = 1; i < pfn->args.size(); ++i) { |
1674 | 0 | o << " " << pfn->args[i]; |
1675 | 0 | } |
1676 | 0 | o << "."; |
1677 | 0 | describe(pfn->t, o); |
1678 | 0 | } |
1679 | 0 | break; |
1680 | 0 | default: |
1681 | 0 | assert(false && "Invalid type description, internal error"); |
1682 | 0 | break; |
1683 | 0 | } |
1684 | 0 | } |
1685 | | |
1686 | 0 | inline std::string show(const desc& t) { |
1687 | 0 | std::ostringstream ss; |
1688 | 0 | describe(t, ss); |
1689 | 0 | return ss.str(); |
1690 | 0 | } |
1691 | | |
1692 | | // type description equivalence modulo offset in record types (allows undefined offsets) |
1693 | 0 | inline bool equivModOffset(const desc& t0, const desc& t1) { |
1694 | 0 | if (t0->tid != t1->tid) { |
1695 | 0 | return false; |
1696 | 0 | } |
1697 | 0 |
|
1698 | 0 | const D* pd0 = t0.get(); |
1699 | 0 | const D* pd1 = t1.get(); |
1700 | 0 |
|
1701 | 0 | switch (t0->tid) { |
1702 | 0 | case PRIV_HPPF_TYCTOR_PRIM: |
1703 | 0 | return reinterpret_cast<const Prim*>(pd0)->n == reinterpret_cast<const Prim*>(pd1)->n; |
1704 | 0 | case PRIV_HPPF_TYCTOR_TVAR: |
1705 | 0 | return reinterpret_cast<const Var*>(pd0)->n == reinterpret_cast<const Var*>(pd1)->n; |
1706 | 0 | case PRIV_HPPF_TYCTOR_FIXEDARR: |
1707 | 0 | return equivModOffset(reinterpret_cast<const FArr*>(pd0)->t, reinterpret_cast<const FArr*>(pd1)->t) && |
1708 | 0 | equivModOffset(reinterpret_cast<const FArr*>(pd0)->len, reinterpret_cast<const FArr*>(pd1)->len); |
1709 | 0 | case PRIV_HPPF_TYCTOR_ARR: |
1710 | 0 | return equivModOffset(reinterpret_cast<const Arr*>(pd0)->t, reinterpret_cast<const Arr*>(pd1)->t); |
1711 | 0 | case PRIV_HPPF_TYCTOR_VARIANT: { |
1712 | 0 | const auto* pv0 = reinterpret_cast<const Variant*>(pd0); |
1713 | 0 | const auto* pv1 = reinterpret_cast<const Variant*>(pd1); |
1714 | 0 |
|
1715 | 0 | if (pv0->ctors.size() != pv1->ctors.size()) { |
1716 | 0 | return false; |
1717 | 0 | } else { |
1718 | 0 | for (size_t i = 0; i < pv0->ctors.size(); ++i) { |
1719 | 0 | if (pv0->ctors[i].at<0>() != pv1->ctors[i].at<0>() || |
1720 | 0 | pv0->ctors[i].at<1>() != pv1->ctors[i].at<1>() || |
1721 | 0 | !equivModOffset(pv0->ctors[i].at<2>(), pv1->ctors[i].at<2>())) { |
1722 | 0 | return false; |
1723 | 0 | } |
1724 | 0 | } |
1725 | 0 | return true; |
1726 | 0 | } |
1727 | 0 | } |
1728 | 0 | case PRIV_HPPF_TYCTOR_STRUCT: { |
1729 | 0 | const auto* pr0 = reinterpret_cast<const Struct*>(pd0); |
1730 | 0 | const auto* pr1 = reinterpret_cast<const Struct*>(pd1); |
1731 | 0 |
|
1732 | 0 | if (pr0->fields.size() != pr1->fields.size()) { |
1733 | 0 | return false; |
1734 | 0 | } else { |
1735 | 0 | for (size_t i = 0; i < pr0->fields.size(); ++i) { |
1736 | 0 | if (pr0->fields[i].at<0>() != pr1->fields[i].at<0>() || |
1737 | 0 | !equivModOffset(pr0->fields[i].at<2>(), pr1->fields[i].at<2>())) { |
1738 | 0 | return false; |
1739 | 0 | } |
1740 | 0 | } |
1741 | 0 | return true; |
1742 | 0 | } |
1743 | 0 | } |
1744 | 0 | case PRIV_HPPF_TYCTOR_SIZE: |
1745 | 0 | return reinterpret_cast<const Nat*>(pd0)->x == reinterpret_cast<const Nat*>(pd1)->x; |
1746 | 0 | case PRIV_HPPF_TYCTOR_TAPP: { |
1747 | 0 | const App* papp0 = reinterpret_cast<const App*>(pd0); |
1748 | 0 | const App* papp1 = reinterpret_cast<const App*>(pd1); |
1749 | 0 |
|
1750 | 0 | if (!equivModOffset(papp0->f, papp1->f)) { |
1751 | 0 | return false; |
1752 | 0 | } else if (papp0->args.size() != papp1->args.size()) { |
1753 | 0 | return false; |
1754 | 0 | } else { |
1755 | 0 | for (size_t i = 0; i < papp0->args.size(); ++i) { |
1756 | 0 | if (!equivModOffset(papp0->args[i], papp1->args[i])) { |
1757 | 0 | return false; |
1758 | 0 | } |
1759 | 0 | } |
1760 | 0 | return true; |
1761 | 0 | } |
1762 | 0 | } |
1763 | 0 | case PRIV_HPPF_TYCTOR_RECURSIVE: |
1764 | 0 | return equivModOffset(reinterpret_cast<const Recursive*>(pd0)->t, reinterpret_cast<const Recursive*>(pd1)->t); |
1765 | 0 | case PRIV_HPPF_TYCTOR_TABS: { |
1766 | 0 | const Fn* fn0 = reinterpret_cast<const Fn*>(pd0); |
1767 | 0 | const Fn* fn1 = reinterpret_cast<const Fn*>(pd1); |
1768 | 0 | return fn0->args.size() == fn1->args.size() && equivModOffset(fn0->t, fn1->t); |
1769 | 0 | } |
1770 | 0 | default: |
1771 | 0 | assert(false && "Invalid type description, internal error"); |
1772 | 0 | return false; |
1773 | 0 | } |
1774 | 0 | } |
1775 | | |
1776 | | // standard memory layout |
1777 | 0 | inline size_t alignOf(const desc& t) { |
1778 | 0 | const D* pd = t.get(); |
1779 | 0 | const Prim* pt = reinterpret_cast<const Prim*>(pd); |
1780 | 0 | const Var* pvn = reinterpret_cast<const Var*>(pd); |
1781 | 0 | const FArr* pfa = reinterpret_cast<const FArr*>(pd); |
1782 | 0 | const auto* pv = reinterpret_cast<const Variant*>(pd); |
1783 | 0 | const auto* ps = reinterpret_cast<const Struct*>(pd); |
1784 | 0 |
|
1785 | 0 | switch (t->tid) { |
1786 | 0 | case PRIV_HPPF_TYCTOR_PRIM: |
1787 | 0 | if (pt->rep) { |
1788 | 0 | return alignOf(pt->rep); |
1789 | 0 | } else { |
1790 | 0 | static std::map<std::string, size_t> paligns = { |
1791 | 0 | { "unit", 1 }, { "bool", 1 }, { "char", 1 }, { "byte", 1 }, |
1792 | 0 | { "short", 2 }, { "int", 4 }, { "long", 8 }, { "float", 4 }, |
1793 | 0 | { "double", 8 } |
1794 | 0 | }; |
1795 | 0 | auto pa = paligns.find(pt->n); |
1796 | 0 | if (pa != paligns.end()) { |
1797 | 0 | return pa->second; |
1798 | 0 | } else { |
1799 | 0 | throw std::runtime_error("Can't determine alignment of unknown primitive type: " + pt->n); |
1800 | 0 | } |
1801 | 0 | } |
1802 | 0 |
|
1803 | 0 | case PRIV_HPPF_TYCTOR_TVAR: |
1804 | 0 | throw std::runtime_error("Can't determine alignment of type variable: " + pvn->n); |
1805 | 0 |
|
1806 | 0 | case PRIV_HPPF_TYCTOR_FIXEDARR: |
1807 | 0 | return alignOf(pfa->t); |
1808 | 0 |
|
1809 | 0 | case PRIV_HPPF_TYCTOR_ARR: |
1810 | 0 | throw std::runtime_error("Can't determine alignment of variable-length array type: " + show(t)); |
1811 | 0 |
|
1812 | 0 | case PRIV_HPPF_TYCTOR_VARIANT: |
1813 | 0 | if (pv->ctors.empty()) { |
1814 | 0 | return 1; |
1815 | 0 | } else { |
1816 | 0 | size_t maxAlign = 4; // the variant tag is an int |
1817 | 0 | for (const auto& ctor : pv->ctors) { |
1818 | 0 | maxAlign = std::max<size_t>(maxAlign, alignOf(ctor.at<2>())); |
1819 | 0 | } |
1820 | 0 | return maxAlign; |
1821 | 0 | } |
1822 | 0 |
|
1823 | 0 | case PRIV_HPPF_TYCTOR_STRUCT: |
1824 | 0 | if (ps->fields.empty()) { |
1825 | 0 | return 1; |
1826 | 0 | } else { |
1827 | 0 | size_t maxAlign = 1; |
1828 | 0 | for (const auto& field : ps->fields) { |
1829 | 0 | maxAlign = std::max<size_t>(maxAlign, alignOf(field.at<2>())); |
1830 | 0 | } |
1831 | 0 | return maxAlign; |
1832 | 0 | } |
1833 | 0 |
|
1834 | 0 | case PRIV_HPPF_TYCTOR_SIZE: |
1835 | 0 | throw std::runtime_error("Can't determine alignment of type-level number: " + show(t)); |
1836 | 0 |
|
1837 | 0 | case PRIV_HPPF_TYCTOR_TAPP: |
1838 | 0 | throw std::runtime_error("nyi, alignment of " + show(t)); |
1839 | 0 |
|
1840 | 0 | case PRIV_HPPF_TYCTOR_RECURSIVE: |
1841 | 0 | return alignof(void*); |
1842 | 0 |
|
1843 | 0 | case PRIV_HPPF_TYCTOR_TABS: |
1844 | 0 | throw std::runtime_error("Can't decide alignment of type abstraction: " + show(t)); |
1845 | 0 |
|
1846 | 0 | default: |
1847 | 0 | throw std::runtime_error("Invalid type description to alignOf, internal error"); |
1848 | 0 | } |
1849 | 0 | } |
1850 | | |
1851 | 0 | inline size_t sizeOf(const desc& t) { |
1852 | 0 | const D* pd = t.get(); |
1853 | 0 | const Prim* pt = reinterpret_cast<const Prim*>(pd); |
1854 | 0 | const Var* pvn = reinterpret_cast<const Var*>(pd); |
1855 | 0 | const FArr* pfa = reinterpret_cast<const FArr*>(pd); |
1856 | 0 | const auto* pv = reinterpret_cast<const Variant*>(pd); |
1857 | 0 | const auto* ps = reinterpret_cast<const Struct*>(pd); |
1858 | 0 |
|
1859 | 0 | switch (t->tid) { |
1860 | 0 | case PRIV_HPPF_TYCTOR_PRIM: |
1861 | 0 | if (pt->rep) { |
1862 | 0 | return sizeOf(pt->rep); |
1863 | 0 | } else if (pt->n == "unit") { |
1864 | 0 | return 0; |
1865 | 0 | } else { |
1866 | 0 | return alignOf(t); |
1867 | 0 | } |
1868 | 0 |
|
1869 | 0 | case PRIV_HPPF_TYCTOR_TVAR: |
1870 | 0 | throw std::runtime_error("Can't determine size of type variable: " + pvn->n); |
1871 | 0 |
|
1872 | 0 | case PRIV_HPPF_TYCTOR_FIXEDARR: |
1873 | 0 | if (pfa->len->tid == PRIV_HPPF_TYCTOR_SIZE) { |
1874 | 0 | return sizeOf(pfa->t) * reinterpret_cast<const Nat*>(pfa->len.get())->x; |
1875 | 0 | } else { |
1876 | 0 | throw std::runtime_error("Can't determine size of fixed array: " + show(t)); |
1877 | 0 | } |
1878 | 0 |
|
1879 | 0 | case PRIV_HPPF_TYCTOR_ARR: |
1880 | 0 | throw std::runtime_error("Can't determine size of variable-length array type: " + show(t)); |
1881 | 0 |
|
1882 | 0 | case PRIV_HPPF_TYCTOR_VARIANT: |
1883 | 0 | if (pv->ctors.empty()) { |
1884 | 0 | return 4; |
1885 | 0 | } else { |
1886 | 0 | size_t maxSize = 4; // the variant tag is an int |
1887 | 0 | size_t maxAlign = 4; |
1888 | 0 | for (const auto& ctor : pv->ctors) { |
1889 | 0 | maxSize = std::max<size_t>(maxSize, sizeOf(ctor.at<2>())); |
1890 | 0 | maxAlign = std::max<size_t>(maxAlign, alignOf(ctor.at<2>())); |
1891 | 0 | } |
1892 | 0 | return alignTo(alignTo(4, maxAlign) + maxSize, maxAlign); |
1893 | 0 | } |
1894 | 0 |
|
1895 | 0 | case PRIV_HPPF_TYCTOR_STRUCT: |
1896 | 0 | if (ps->fields.empty()) { |
1897 | 0 | return 1; |
1898 | 0 | } else { |
1899 | 0 | size_t maxAlign = 1; |
1900 | 0 | size_t offset = 0; |
1901 | 0 | for (const auto& field : ps->fields) { |
1902 | 0 | maxAlign = std::max<size_t>(maxAlign, alignOf(field.at<2>())); |
1903 | 0 | offset = alignTo(offset, alignOf(field.at<2>())) + sizeOf(field.at<2>()); |
1904 | 0 | } |
1905 | 0 | return alignTo(offset, maxAlign); |
1906 | 0 | } |
1907 | 0 |
|
1908 | 0 | case PRIV_HPPF_TYCTOR_SIZE: |
1909 | 0 | throw std::runtime_error("Can't determine size of type-level number: " + show(t)); |
1910 | 0 |
|
1911 | 0 | case PRIV_HPPF_TYCTOR_TAPP: |
1912 | 0 | throw std::runtime_error("nyi, size of " + show(t)); |
1913 | 0 |
|
1914 | 0 | case PRIV_HPPF_TYCTOR_RECURSIVE: |
1915 | 0 | return sizeof(void*); |
1916 | 0 |
|
1917 | 0 | case PRIV_HPPF_TYCTOR_TABS: |
1918 | 0 | throw std::runtime_error("Can't decide size of type abstraction: " + show(t)); |
1919 | 0 |
|
1920 | 0 | default: |
1921 | 0 | throw std::runtime_error("Invalid type description for sizeOf, internal error"); |
1922 | 0 | } |
1923 | 0 | } |
1924 | | |
1925 | | } |
1926 | | } |
1927 | | |
1928 | | #endif |
1929 | | |