41 static small test(
decltype(&C::fromJSON));
46 static const bool value =
sizeof(test<T>(0)) ==
sizeof(
char);
49 std::unordered_map<int, IR::Node *> &node_refs;
50 std::unique_ptr<JsonData> json_root;
53 bool (*errfn)(
const JSONLoader &, std::string_view msg) =
nullptr;
55 JSONLoader(
const JsonData *
json, std::unordered_map<int, IR::Node *> &refs,
57 : node_refs(refs),
json(
json), locinfo(locinfo) {}
61 : node_refs(*(
new std::unordered_map<int, IR::Node *>())), locinfo(li) {
63 json = json_root.get();
66 JSONLoader(
const JSONLoader &unpacker, std::string_view field)
67 : node_refs(unpacker.node_refs),
json(
nullptr), locinfo(unpacker.locinfo) {
68 if (!unpacker)
return;
70 if (
auto it = obj->find(field); it != obj->end()) {
71 json = it->second.get();
76 explicit operator bool()
const {
return json !=
nullptr; }
78 [[nodiscard]]
bool is()
const {
82 [[nodiscard]]
const T &as()
const {
86 std::string locdesc(
const JsonData &d)
const {
87 if (!locinfo)
return "";
88 return locinfo->desc(d);
90 std::string locdesc()
const {
92 return locdesc(*
json);
94 bool error(std::string_view msg)
const {
100 const IR::Node *get_node(NodeFactoryFn factory =
nullptr) {
103 auto success = load(
"Node_ID",
id) || error(
"missing field Node_ID");
104 if (!success)
return nullptr;
106 if (node_refs.find(
id) == node_refs.end()) {
109 auto success = load(
"Node_Type", type) || error(
"missing field Node_Type");
110 if (!success)
return nullptr;
111 factory = get(IR::unpacker_table, type);
114 auto *node = factory(*this)->to<
IR::Node>();
116 node_refs[id] = node;
120 node_refs[id]->sourceInfoFromJSON(*
this);
125 return node_refs[id];
130 template <
typename T>
134 for (
auto &e : as<JsonVector>()) {
140 template <
typename T>
141 void unpack_json(std::set<T> &v) {
144 for (
auto &e : as<JsonVector>()) {
150 template <
typename T>
154 for (
auto &e : as<JsonVector>()) {
160 template <
typename T>
162 v = get_node(NodeFactoryFn(&IR::Vector<T>::fromJSON))->
as<
IR::Vector<T>>();
164 template <
typename T>
166 v = get_node(NodeFactoryFn(&IR::Vector<T>::fromJSON))->checkedTo<
IR::Vector<T>>();
168 template <
typename T>
172 template <
typename T>
174 v = get_node(NodeFactoryFn(&IR::IndexedVector<T>::fromJSON))
177 template <
class T,
template <
class K,
class V,
class COMP,
class ALLOC>
class MAP,
class COMP,
180 m = get_node(NodeFactoryFn(&IR::NameMap<T, MAP, COMP, ALLOC>::fromJSON))
183 template <
class T,
template <
class K,
class V,
class COMP,
class ALLOC>
class MAP,
class COMP,
186 m = get_node(NodeFactoryFn(&IR::NameMap<T, MAP, COMP, ALLOC>::fromJSON))
190 template <
typename K,
typename V>
191 void unpack_json(std::map<K, V> &v) {
192 std::pair<K, V> temp;
194 if (is<JsonVector>()) {
195 for (
auto &e : as<JsonVector>()) {
200 for (
auto &e : as<JsonObject>()) {
202 load(e.second, temp.second);
207 template <
typename K,
typename V>
209 std::pair<K, V> temp;
211 if (is<JsonVector>()) {
212 for (
auto &e : as<JsonVector>()) {
217 for (
auto &e : as<JsonObject>()) {
219 load(e.second, temp.second);
224 template <
typename V>
226 std::pair<cstring, V> temp;
228 for (
auto &e : as<JsonObject>()) {
229 temp.first = e.first;
230 load(e.second, temp.second);
235 template <
typename K,
typename V>
236 void unpack_json(std::multimap<K, V> &v) {
237 std::pair<K, V> temp;
239 if (is<JsonVector>()) {
240 for (
auto &e : as<JsonVector>()) {
245 for (
auto &e : as<JsonObject>()) {
247 load(e.second, temp.second);
253 template <
typename T>
254 void unpack_json(std::vector<T> &v) {
257 for (
auto &e : as<JsonVector>()) {
263 template <
typename T,
typename U>
264 void unpack_json(std::pair<T, U> &v) {
265 load(
"first", v.first) || error(
"missing field first");
266 load(
"second", v.second) || error(
"missing field second");
269 template <
typename T>
270 void unpack_json(std::optional<T> &v) {
271 bool isValid =
false;
272 load(
"valid", isValid) || error(
"missing field valid");
278 auto success = load(
"value", value) || error(
"missing field value");
283 v = std::move(value);
286 template <
int N,
class Variant>
287 std::enable_if_t<N == std::variant_size_v<Variant>> unpack_variant(
int ,
289 BUG(
"Error traversing variant during load");
292 template <
int N,
class Variant>
293 std::enable_if_t<(N < std::variant_size_v<Variant>)> unpack_variant(
int target,
296 variant.template emplace<N>();
297 load(
"value", std::get<N>(variant)) || error(
"missing field value");
299 unpack_variant<N + 1>(target, variant);
302 template <
class... Types>
303 void unpack_json(std::variant<Types...> &v) {
305 load(
"variant_index", index) || error(
"missing field variant_index");
306 unpack_variant<0>(index, v);
309 void unpack_json(
bool &v) { v = as<JsonBoolean>(); }
311 template <
typename T>
312 std::enable_if_t<std::is_integral_v<T>> unpack_json(T &v) {
313 v = as<JsonNumber>();
315 void unpack_json(big_int &v) { v = as<JsonNumber>().val; }
316 void unpack_json(std::string &v) {
317 if (is<JsonString>()) v = as<JsonString>();
320 if (is<JsonString>())
322 else if (is<JsonNull>())
325 void unpack_json(
IR::ID &v) {
333 void unpack_json(
bitvec &v) {
337 template <
typename T>
338 std::enable_if_t<std::is_enum_v<T>> unpack_json(T &v) {
346 template <
typename T>
347 std::enable_if_t<has_fromJSON<T>::value && !std::is_base_of_v<IR::INode, T> &&
348 std::is_pointer_v<decltype(T::fromJSON(std::declval<JSONLoader &>()))>>
350 v = T::fromJSON(*
this);
353 template <
typename T>
354 std::enable_if_t<has_fromJSON<T>::value && !std::is_base_of_v<IR::INode, T> &&
355 std::is_pointer_v<decltype(T::fromJSON(std::declval<JSONLoader &>()))>>
357 v = *(T::fromJSON(*
this));
360 template <
typename T>
361 std::enable_if_t<has_fromJSON<T>::value && !std::is_base_of<IR::INode, T>::value &&
362 !std::is_pointer_v<decltype(T::fromJSON(std::declval<JSONLoader &>()))>>
364 v = T::fromJSON(*
this);
367 template <
typename T>
368 std::enable_if_t<has_fromJSON<T>::value && !std::is_base_of<IR::INode, T>::value &&
369 !std::is_pointer_v<decltype(T::fromJSON(std::declval<JSONLoader &>()))>>
371 v =
new T(T::fromJSON(*
this));
374 template <
typename T>
375 std::enable_if_t<std::is_base_of_v<IR::INode, T>> unpack_json(T &v) {
376 v = get_node()->as<T>();
378 template <
typename T>
379 std::enable_if_t<std::is_base_of_v<IR::INode, T>> unpack_json(
const T *&v) {
380 v = get_node()->checkedTo<T>();
383 template <
typename T,
size_t N>
384 void unpack_json(T (&v)[N]) {
386 for (
size_t i = 0; i < N && i < j->size(); ++i) {
387 load(j->at(i), v[i]);
393 template <
typename T>
395 JSONLoader(&
json, node_refs, locinfo).unpack_json(v);
398 template <
typename T>
399 void load(
const std::unique_ptr<JsonData> &
json, T &v) {
400 JSONLoader(
json.get(), node_refs, locinfo).unpack_json(v);
403 template <
typename T>
404 bool load(std::string_view field, T *&v) {
405 if (
auto loader = JSONLoader(*
this, field)) {
406 loader.unpack_json(v);
414 template <
typename T>
415 bool load(std::string_view field, T &v) {
416 if (
auto loader = JSONLoader(*
this, field)) {
417 loader.unpack_json(v);
423 template <
typename T>
424 JSONLoader &operator>>(T &v) {