Coverage Report

Created: 2026-10-28 06:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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; } \
hobbes::timeT::name()
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