31 std::unordered_set<int> node_refs;
43 static small test(
decltype(&C::toJSON));
48 static const bool value =
sizeof(test<T>(0)) ==
sizeof(
char);
62 enum state_restore_kind { NONE, OBJECT, VECTOR };
63 class state_restore_t {
64 output_state_t prev_state;
66 state_restore_kind kind;
67 friend class JSONGenerator;
69 state_restore_t(JSONGenerator &gen, state_restore_kind kind)
70 : prev_state(gen.output_state), gen(gen), kind(kind) {}
71 state_restore_t(
const state_restore_t &) =
delete;
72 state_restore_t(state_restore_t &&a) : prev_state(a.prev_state), gen(a.gen), kind(a.kind) {
78 if (kind == OBJECT) gen.end_object(*
this);
79 if (kind == VECTOR) gen.end_vector(*
this);
84 explicit JSONGenerator(std::ostream &out,
bool dumpSourceInfo =
false)
85 : out(out), dumpSourceInfo(dumpSourceInfo) {}
87 state_restore_t begin_vector() {
88 if (output_state == OBJ_START) output_state = OBJ_END;
89 BUG_CHECK(output_state != VEC_START,
"invalid json output state in begin_vector");
90 state_restore_t rv(*
this, VECTOR);
91 output_state = VEC_START;
97 void end_vector(state_restore_t &prev) {
98 BUG_CHECK(prev.kind == VECTOR,
"invalid previous state in end_vector");
101 if (output_state == VEC_MID)
102 out << std::endl << indent;
103 else if (output_state != VEC_START)
104 BUG(
"invalid json output state in end_vector");
106 if ((output_state = prev.prev_state) == OBJ_AFTERTAG) output_state = OBJ_MID;
109 state_restore_t begin_object() {
110 BUG_CHECK(output_state != OBJ_START && output_state != OBJ_MID && output_state != OBJ_END,
111 "invalid json output state in begin_object");
112 state_restore_t rv(*
this, OBJECT);
113 output_state = OBJ_START;
117 void end_object(state_restore_t &prev) {
118 BUG_CHECK(prev.kind == OBJECT,
"invalid previous state in end_object");
120 switch (output_state) {
125 out << std::endl << --indent <<
'}';
133 BUG(
"invalid json output state in end_object");
136 if ((output_state = prev.prev_state) == OBJ_AFTERTAG) output_state = OBJ_MID;
139 template <
typename T>
140 void emit(
const T &val) {
141 switch (output_state) {
146 out << std::endl << indent;
147 output_state = VEC_MID;
150 output_state = OBJ_MID;
155 output_state = OBJ_END;
159 BUG(
"invalid json output state for emit(obj)");
162 if (output_state == TOP) out << std::endl;
165 void emit_tag(std::string_view tag) {
166 switch (output_state) {
168 out <<
'{' << std::endl << ++indent;
171 out <<
',' << std::endl << indent;
178 BUG(
"invalid json output state for emit_tag");
181 output_state = OBJ_AFTERTAG;
184 template <
typename T>
185 void emit(std::string_view tag,
const T &val) {
188 output_state = OBJ_MID;
192 template <
typename T>
194 auto t = begin_vector();
195 for (
auto &el : v) emit(el);
199 template <
typename T>
200 void generate(
const std::vector<T> &v) {
201 auto t = begin_vector();
202 for (
auto &el : v) emit(el);
206 template <
typename T,
typename U>
207 void generate(
const std::pair<T, U> &v) {
208 auto t = begin_object();
214 template <
typename T,
typename U>
215 void toJSON(
const std::pair<T, U> &v) {
216 emit(
"first", v.first);
217 emit(
"second", v.second);
221 template <
typename T>
222 void generate(
const std::optional<T> &v) {
223 auto t = begin_object();
225 if (v) emit(
"value", *v);
229 template <
typename T>
230 void generate(
const std::set<T> &v) {
231 auto t = begin_vector();
232 for (
auto &el : v) emit(el);
236 template <
typename T>
238 auto t = begin_vector();
239 for (
auto &el : v) emit(el);
243 template <
typename K,
typename V>
244 void generate(
const std::map<K, V> &v) {
245 auto t = begin_vector();
246 for (
auto &el : v) emit(el);
250 template <
typename K,
typename V>
252 auto t = begin_vector();
253 for (
auto &el : v) emit(el);
257 template <
typename V>
259 auto t = begin_object();
260 for (
auto &el : v) emit(el.first, el.second);
264 template <
class... Types>
265 void generate(
const std::variant<Types...> &v) {
266 auto t = begin_object();
267 emit(
"variant_index", v.index());
268 std::visit([
this](
auto &value) { this->emit(
"value", value); }, v);
272 void generate(
bool v) { out << (v ?
"true" :
"false"); }
273 template <
typename T>
274 std::enable_if_t<std::is_integral_v<T>> generate(T v) {
275 out << std::to_string(v);
277 void generate(
double v) { out << std::to_string(v); }
278 template <
typename T>
279 std::enable_if_t<std::is_same_v<T, big_int>> generate(
const T &v) {
290 template <
typename T>
291 std::enable_if_t<std::is_same_v<T, LTBitMatrix> || std::is_enum_v<T>> generate(T v) {
292 out <<
"\"" << v <<
"\"";
295 void generate(
const bitvec &v) { out <<
"\"" << v <<
"\""; }
297 void generate(
const match_t &v) {
298 auto t = begin_object();
299 emit(
"word0", v.word0);
300 emit(
"word1", v.word1);
304 template <
typename T>
305 std::enable_if_t<has_toJSON<T>::value && !std::is_base_of_v<IR::INode, T>> generate(
307 auto t = begin_object();
313 auto &v = *v_.getNode();
314 auto t = begin_object();
315 if (node_refs.find(v.id) != node_refs.end()) {
316 emit(
"Node_ID", v.id);
318 node_refs.insert(v.id);
320 if (dumpSourceInfo) {
321 v.sourceInfoToJSON(*
this);
329 template <
typename T>
330 void generate(
const T *
const &v) {
337 template <
typename T,
size_t N>
338 void generate(
const T (&v)[N]) {
339 auto t = begin_vector();
340 for (
auto &el : v) emit(el);