40 std::unordered_set<int> node_refs;
52 static small test(
decltype(&C::toJSON));
57 static const bool value =
sizeof(test<T>(0)) ==
sizeof(
char);
71 enum state_restore_kind { NONE, OBJECT, VECTOR };
72 class state_restore_t {
73 output_state_t prev_state;
75 state_restore_kind kind;
76 friend class JSONGenerator;
78 state_restore_t(JSONGenerator &gen, state_restore_kind kind)
79 : prev_state(gen.output_state), gen(gen), kind(kind) {}
80 state_restore_t(
const state_restore_t &) =
delete;
81 state_restore_t(state_restore_t &&a) : prev_state(a.prev_state), gen(a.gen), kind(a.kind) {
87 if (kind == OBJECT) gen.end_object(*
this);
88 if (kind == VECTOR) gen.end_vector(*
this);
93 explicit JSONGenerator(std::ostream &out,
bool dumpSourceInfo =
false)
94 : out(out), dumpSourceInfo(dumpSourceInfo) {}
96 state_restore_t begin_vector() {
97 if (output_state == OBJ_START) output_state = OBJ_END;
98 BUG_CHECK(output_state != VEC_START,
"invalid json output state in begin_vector");
99 state_restore_t rv(*
this, VECTOR);
100 output_state = VEC_START;
106 void end_vector(state_restore_t &prev) {
107 BUG_CHECK(prev.kind == VECTOR,
"invalid previous state in end_vector");
110 if (output_state == VEC_MID)
111 out << std::endl << indent;
112 else if (output_state != VEC_START)
113 BUG(
"invalid json output state in end_vector");
115 if ((output_state = prev.prev_state) == OBJ_AFTERTAG) output_state = OBJ_MID;
118 state_restore_t begin_object() {
119 BUG_CHECK(output_state != OBJ_START && output_state != OBJ_MID && output_state != OBJ_END,
120 "invalid json output state in begin_object");
121 state_restore_t rv(*
this, OBJECT);
122 output_state = OBJ_START;
126 void end_object(state_restore_t &prev) {
127 BUG_CHECK(prev.kind == OBJECT,
"invalid previous state in end_object");
129 switch (output_state) {
134 out << std::endl << --indent <<
'}';
139 BUG(
"invalid json output state in end_object");
142 if ((output_state = prev.prev_state) == OBJ_AFTERTAG) output_state = OBJ_MID;
145 template <
typename T>
146 void emit(
const T &val) {
147 switch (output_state) {
152 out << std::endl << indent;
153 output_state = VEC_MID;
156 output_state = OBJ_MID;
161 output_state = OBJ_END;
165 BUG(
"invalid json output state for emit(obj)");
168 if (output_state == TOP) out << std::endl;
171 void emit_tag(std::string_view tag) {
172 switch (output_state) {
174 out <<
'{' << std::endl << ++indent;
177 out <<
',' << std::endl << indent;
184 BUG(
"invalid json output state for emit_tag");
187 output_state = OBJ_AFTERTAG;
190 template <
typename T>
191 void emit(std::string_view tag,
const T &val) {
194 output_state = OBJ_MID;
198 template <
typename T>
200 auto t = begin_vector();
201 for (
auto &el : v) emit(el);
205 template <
typename T>
206 void generate(
const std::vector<T> &v) {
207 auto t = begin_vector();
208 for (
auto &el : v) emit(el);
212 template <
typename T,
typename U>
213 void generate(
const std::pair<T, U> &v) {
214 auto t = begin_object();
220 template <
typename T,
typename U>
221 void toJSON(
const std::pair<T, U> &v) {
222 emit(
"first", v.first);
223 emit(
"second", v.second);
227 template <
typename T>
228 void generate(
const std::optional<T> &v) {
229 auto t = begin_object();
231 if (v) emit(
"value", *v);
235 template <
typename T>
236 void generate(
const std::set<T> &v) {
237 auto t = begin_vector();
238 for (
auto &el : v) emit(el);
242 template <
typename T>
244 auto t = begin_vector();
245 for (
auto &el : v) emit(el);
249 template <
typename K,
typename V>
250 void generate(
const std::map<K, V> &v) {
251 auto t = begin_vector();
252 for (
auto &el : v) emit(el);
256 template <
typename K,
typename V>
258 auto t = begin_vector();
259 for (
auto &el : v) emit(el);
263 template <
typename V>
265 auto t = begin_object();
266 for (
auto &el : v) emit(el.first, el.second);
270 template <
class... Types>
271 void generate(
const std::variant<Types...> &v) {
272 auto t = begin_object();
273 emit(
"variant_index", v.index());
274 std::visit([
this](
auto &value) { this->emit(
"value", value); }, v);
278 void generate(
bool v) { out << (v ?
"true" :
"false"); }
279 template <
typename T>
280 std::enable_if_t<std::is_integral_v<T>> generate(T v) {
281 out << std::to_string(v);
283 void generate(
double v) { out << std::to_string(v); }
284 template <
typename T>
285 std::enable_if_t<std::is_same_v<T, big_int>> generate(
const T &v) {
296 template <
typename T>
297 std::enable_if_t<std::is_same_v<T, LTBitMatrix> || std::is_enum_v<T>> generate(T v) {
298 out <<
"\"" << v <<
"\"";
301 void generate(
const bitvec &v) { out <<
"\"" << v <<
"\""; }
303 void generate(
const match_t &v) {
304 auto t = begin_object();
305 emit(
"word0", v.word0);
306 emit(
"word1", v.word1);
310 template <
typename T>
311 std::enable_if_t<has_toJSON<T>::value && !std::is_base_of_v<IR::Node, T>> generate(
const T &v) {
312 auto t = begin_object();
318 auto t = begin_object();
319 if (node_refs.find(v.id) != node_refs.end()) {
320 emit(
"Node_ID", v.id);
322 node_refs.insert(v.id);
324 if (dumpSourceInfo) {
325 v.sourceInfoToJSON(*
this);
331 template <
typename T>
332 std::enable_if_t<std::is_pointer_v<T> && has_toJSON<std::remove_pointer_t<T>>::value> generate(
340 template <
typename T,
size_t N>
341 void generate(
const T (&v)[N]) {
342 auto t = begin_vector();
343 for (
auto &el : v) emit(el);