50 static small test(
decltype(&C::fromJSON));
55 static const bool value =
sizeof(test<T>(0)) ==
sizeof(
char);
58 std::unordered_map<int, IR::Node *> &node_refs;
59 std::unique_ptr<JsonData> json_root;
62 bool (*errfn)(
const JSONLoader &, std::string_view msg) =
nullptr;
64 JSONLoader(
const JsonData *
json, std::unordered_map<int, IR::Node *> &refs,
66 : node_refs(refs),
json(
json), locinfo(locinfo) {}
70 : node_refs(*(
new std::unordered_map<int, IR::Node *>())), locinfo(li) {
72 json = json_root.get();
75 JSONLoader(
const JSONLoader &unpacker, std::string_view field)
76 : node_refs(unpacker.node_refs),
json(
nullptr), locinfo(unpacker.locinfo) {
77 if (!unpacker)
return;
79 if (
auto it = obj->find(field); it != obj->end()) {
80 json = it->second.get();
85 explicit operator bool()
const {
return json !=
nullptr; }
87 [[nodiscard]]
bool is()
const {
91 [[nodiscard]]
const T &as()
const {
95 std::string locdesc(
const JsonData &d)
const {
96 if (!locinfo)
return "";
97 return locinfo->desc(d);
99 std::string locdesc()
const {
100 if (!
json)
return "";
101 return locdesc(*
json);
103 bool error(std::string_view msg)
const {
109 const IR::Node *get_node(NodeFactoryFn factory =
nullptr) {
112 auto success = load(
"Node_ID",
id) || error(
"missing field Node_ID");
113 if (!success)
return nullptr;
115 if (node_refs.find(
id) == node_refs.end()) {
118 auto success = load(
"Node_Type", type) || error(
"missing field Node_Type");
119 if (!success)
return nullptr;
120 factory = get(IR::unpacker_table, type);
123 auto *node = factory(*this)->to<
IR::Node>();
125 node_refs[id] = node;
129 node_refs[id]->sourceInfoFromJSON(*
this);
134 return node_refs[id];
139 template <
typename T>
143 for (
auto &e : as<JsonVector>()) {
149 template <
typename T>
150 void unpack_json(std::set<T> &v) {
153 for (
auto &e : as<JsonVector>()) {
159 template <
typename T>
163 for (
auto &e : as<JsonVector>()) {
169 template <
typename T>
171 v = get_node(NodeFactoryFn(&IR::Vector<T>::fromJSON))->
as<
IR::Vector<T>>();
173 template <
typename T>
175 v = get_node(NodeFactoryFn(&IR::Vector<T>::fromJSON))->checkedTo<
IR::Vector<T>>();
177 template <
typename T>
181 template <
typename T>
183 v = get_node(NodeFactoryFn(&IR::IndexedVector<T>::fromJSON))
186 template <
class T,
template <
class K,
class V,
class COMP,
class ALLOC>
class MAP,
class COMP,
189 m = get_node(NodeFactoryFn(&IR::NameMap<T, MAP, COMP, ALLOC>::fromJSON))
192 template <
class T,
template <
class K,
class V,
class COMP,
class ALLOC>
class MAP,
class COMP,
195 m = get_node(NodeFactoryFn(&IR::NameMap<T, MAP, COMP, ALLOC>::fromJSON))
199 template <
typename K,
typename V>
200 void unpack_json(std::map<K, V> &v) {
201 std::pair<K, V> temp;
203 if (is<JsonVector>()) {
204 for (
auto &e : as<JsonVector>()) {
209 for (
auto &e : as<JsonObject>()) {
211 load(e.second, temp.second);
216 template <
typename K,
typename V>
218 std::pair<K, V> temp;
220 if (is<JsonVector>()) {
221 for (
auto &e : as<JsonVector>()) {
226 for (
auto &e : as<JsonObject>()) {
228 load(e.second, temp.second);
233 template <
typename V>
235 std::pair<cstring, V> temp;
237 for (
auto &e : as<JsonObject>()) {
238 temp.first = e.first;
239 load(e.second, temp.second);
244 template <
typename K,
typename V>
245 void unpack_json(std::multimap<K, V> &v) {
246 std::pair<K, V> temp;
248 if (is<JsonVector>()) {
249 for (
auto &e : as<JsonVector>()) {
254 for (
auto &e : as<JsonObject>()) {
256 load(e.second, temp.second);
262 template <
typename T>
263 void unpack_json(std::vector<T> &v) {
266 for (
auto &e : as<JsonVector>()) {
272 template <
typename T,
typename U>
273 void unpack_json(std::pair<T, U> &v) {
274 load(
"first", v.first) || error(
"missing field first");
275 load(
"second", v.second) || error(
"missing field second");
278 template <
typename T>
279 void unpack_json(std::optional<T> &v) {
280 bool isValid =
false;
281 load(
"valid", isValid) || error(
"missing field valid");
287 auto success = load(
"value", value) || error(
"missing field value");
292 v = std::move(value);
295 template <
int N,
class Variant>
296 std::enable_if_t<N == std::variant_size_v<Variant>> unpack_variant(
int ,
298 BUG(
"Error traversing variant during load");
301 template <
int N,
class Variant>
302 std::enable_if_t<(N < std::variant_size_v<Variant>)> unpack_variant(
int target,
305 variant.template emplace<N>();
306 load(
"value", std::get<N>(variant)) || error(
"missing field value");
308 unpack_variant<N + 1>(target, variant);
311 template <
class... Types>
312 void unpack_json(std::variant<Types...> &v) {
314 load(
"variant_index", index) || error(
"missing field variant_index");
315 unpack_variant<0>(index, v);
318 void unpack_json(
bool &v) { v = as<JsonBoolean>(); }
320 template <
typename T>
321 std::enable_if_t<std::is_integral_v<T>> unpack_json(T &v) {
322 v = as<JsonNumber>();
324 void unpack_json(big_int &v) { v = as<JsonNumber>().val; }
325 void unpack_json(std::string &v) {
326 if (is<JsonString>()) v = as<JsonString>();
329 if (is<JsonString>())
331 else if (is<JsonNull>())
334 void unpack_json(
IR::ID &v) {
342 void unpack_json(
bitvec &v) {
346 template <
typename T>
347 std::enable_if_t<std::is_enum_v<T>> unpack_json(T &v) {
355 template <
typename T>
356 std::enable_if_t<has_fromJSON<T>::value && !std::is_base_of_v<IR::INode, T> &&
357 std::is_pointer_v<decltype(T::fromJSON(std::declval<JSONLoader &>()))>>
359 v = T::fromJSON(*
this);
362 template <
typename T>
363 std::enable_if_t<has_fromJSON<T>::value && !std::is_base_of_v<IR::INode, T> &&
364 std::is_pointer_v<decltype(T::fromJSON(std::declval<JSONLoader &>()))>>
366 v = *(T::fromJSON(*
this));
369 template <
typename T>
370 std::enable_if_t<has_fromJSON<T>::value && !std::is_base_of<IR::INode, T>::value &&
371 !std::is_pointer_v<decltype(T::fromJSON(std::declval<JSONLoader &>()))>>
373 v = T::fromJSON(*
this);
376 template <
typename T>
377 std::enable_if_t<has_fromJSON<T>::value && !std::is_base_of<IR::INode, T>::value &&
378 !std::is_pointer_v<decltype(T::fromJSON(std::declval<JSONLoader &>()))>>
380 v =
new T(T::fromJSON(*
this));
383 template <
typename T>
384 std::enable_if_t<std::is_base_of_v<IR::INode, T>> unpack_json(T &v) {
385 v = get_node()->as<T>();
387 template <
typename T>
388 std::enable_if_t<std::is_base_of_v<IR::INode, T>> unpack_json(
const T *&v) {
389 v = get_node()->checkedTo<T>();
392 template <
typename T,
size_t N>
393 void unpack_json(T (&v)[N]) {
395 for (
size_t i = 0; i < N && i < j->size(); ++i) {
396 load(j->at(i), v[i]);
402 template <
typename T>
404 JSONLoader(&
json, node_refs, locinfo).unpack_json(v);
407 template <
typename T>
408 void load(
const std::unique_ptr<JsonData> &
json, T &v) {
409 JSONLoader(
json.get(), node_refs, locinfo).unpack_json(v);
412 template <
typename T>
413 bool load(std::string_view field, T *&v) {
414 if (
auto loader = JSONLoader(*
this, field)) {
415 loader.unpack_json(v);
423 template <
typename T>
424 bool load(std::string_view field, T &v) {
425 if (
auto loader = JSONLoader(*
this, field)) {
426 loader.unpack_json(v);
432 template <
typename T>
433 JSONLoader &operator>>(T &v) {