P4C
The P4 Compiler
Loading...
Searching...
No Matches
json_generator.h
1/*
2Copyright 2013-present Barefoot Networks, Inc.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17#ifndef IR_JSON_GENERATOR_H_
18#define IR_JSON_GENERATOR_H_
19
20#include <optional>
21#include <string>
22#include <unordered_set>
23#include <variant>
24
25#include "ir/node.h"
26#include "lib/bitvec.h"
27#include "lib/cstring.h"
28#include "lib/indent.h"
29#include "lib/ltbitmatrix.h"
30#include "lib/match.h"
31#include "lib/ordered_map.h"
32#include "lib/ordered_set.h"
33#include "lib/safe_vector.h"
34
35namespace P4 {
36
38 std::unordered_set<int> node_refs;
39 std::ostream &out;
40 bool dumpSourceInfo;
41
42 template <typename T>
43 class has_toJSON {
44 typedef char small;
45 typedef struct {
46 char c[2];
47 } big;
48
49 template <typename C>
50 static small test(decltype(&C::toJSON));
51 template <typename C>
52 static big test(...);
53
54 public:
55 static const bool value = sizeof(test<T>(0)) == sizeof(char);
56 };
57
58 struct variant_generator {
59 std::ostream &out;
60 JSONGenerator &generator;
61
62 variant_generator(std::ostream &out, JSONGenerator &generator)
63 : out(out), generator(generator) {}
64
65 template <class T>
66 void operator()(const T &value) const {
67 out << R"("value" : )";
68 generator.generate(value);
69 }
70 };
71
72 public:
73 indent_t indent;
74
75 explicit JSONGenerator(std::ostream &out, bool dumpSourceInfo = false)
76 : out(out), dumpSourceInfo(dumpSourceInfo) {}
77
78 template <typename T>
79 void generate(const safe_vector<T> &v) {
80 out << "[";
81 if (v.size() > 0) {
82 out << std::endl << ++indent;
83 generate(v[0]);
84 for (size_t i = 1; i < v.size(); i++) {
85 out << "," << std::endl << indent;
86 generate(v[i]);
87 }
88 out << std::endl << --indent;
89 }
90 out << "]";
91 }
92
93 template <typename T>
94 void generate(const std::vector<T> &v) {
95 out << "[";
96 if (v.size() > 0) {
97 out << std::endl << ++indent;
98 generate(v[0]);
99 for (size_t i = 1; i < v.size(); i++) {
100 out << "," << std::endl << indent;
101 generate(v[i]);
102 }
103 out << std::endl << --indent;
104 }
105 out << "]";
106 }
107
108 template <typename T, typename U>
109 void generate(const std::pair<T, U> &v) {
110 ++indent;
111 out << "{" << std::endl;
112 toJSON(v);
113 out << std::endl << --indent << "}";
114 }
115
116 template <typename T, typename U>
117 void toJSON(const std::pair<T, U> &v) {
118 out << indent << "\"first\" : ";
119 generate(v.first);
120 out << "," << std::endl << indent << "\"second\" : ";
121 generate(v.second);
122 }
123
124 template <typename T>
125 void generate(const std::optional<T> &v) {
126 if (!v) {
127 out << "{ \"valid\" : false }";
128 return;
129 }
130 out << "{" << std::endl << ++indent;
131 out << "\"valid\" : true," << std::endl;
132 out << "\"value\" : ";
133 generate(*v);
134 out << std::endl << --indent << "}";
135 }
136
137 template <typename T>
138 void generate(const std::set<T> &v) {
139 out << "[" << std::endl;
140 if (v.size() > 0) {
141 auto it = v.begin();
142 out << ++indent;
143 generate(*it);
144 for (it++; it != v.end(); ++it) {
145 out << "," << std::endl << indent;
146 generate(*it);
147 }
148 out << std::endl << --indent;
149 }
150 out << "]";
151 }
152
153 template <typename T>
154 void generate(const ordered_set<T> &v) {
155 out << "[" << std::endl;
156 if (v.size() > 0) {
157 auto it = v.begin();
158 out << ++indent;
159 generate(*it);
160 for (it++; it != v.end(); ++it) {
161 out << "," << std::endl << indent;
162 generate(*it);
163 }
164 out << std::endl << --indent;
165 }
166 out << "]";
167 }
168
169 template <typename K, typename V>
170 void generate(const std::map<K, V> &v) {
171 out << "[" << std::endl;
172 if (v.size() > 0) {
173 auto it = v.begin();
174 out << ++indent;
175 generate(*it);
176 for (it++; it != v.end(); ++it) {
177 out << "," << std::endl << indent;
178 generate(*it);
179 }
180 out << std::endl << --indent;
181 }
182 out << "]";
183 }
184
185 template <typename K, typename V>
186 void generate(const ordered_map<K, V> &v) {
187 out << "[" << std::endl;
188 if (v.size() > 0) {
189 auto it = v.begin();
190 out << ++indent;
191 generate(*it);
192 for (it++; it != v.end(); ++it) {
193 out << "," << std::endl << indent;
194 generate(*it);
195 }
196 out << std::endl << --indent;
197 }
198 out << "]";
199 }
200
201 template <class... Types>
202 void generate(const std::variant<Types...> &v) {
203 out << "{" << std::endl << ++indent;
204 out << R"("variant_index" : )" << v.index() << "," << std::endl << indent;
205 variant_generator generator(out, *this);
206 std::visit(generator, v);
207 out << std::endl << --indent << "}";
208 }
209
210 void generate(bool v) { out << (v ? "true" : "false"); }
211 template <typename T>
212 std::enable_if_t<std::is_integral_v<T>> generate(T v) {
213 out << std::to_string(v);
214 }
215 void generate(double v) { out << std::to_string(v); }
216 template <typename T>
217 std::enable_if_t<std::is_same_v<T, big_int>> generate(const T &v) {
218 out << v;
219 }
220
221 void generate(cstring v) {
222 if (v) {
223 out << "\"" << v.escapeJson() << "\"";
224 } else {
225 out << "null";
226 }
227 }
228 template <typename T>
229 std::enable_if_t<std::is_same_v<T, LTBitMatrix> || std::is_enum_v<T>> generate(T v) {
230 out << "\"" << v << "\"";
231 }
232
233 void generate(const bitvec &v) { out << "\"" << v << "\""; }
234
235 void generate(const match_t &v) {
236 out << "{" << std::endl
237 << (indent + 1) << "\"word0\" : " << v.word0 << "," << std::endl
238 << (indent + 1) << "\"word1\" : " << v.word1 << std::endl
239 << indent << "}";
240 }
241
242 template <typename T>
243 std::enable_if_t<has_toJSON<T>::value && !std::is_base_of_v<IR::Node, T>> generate(const T &v) {
244 ++indent;
245 out << "{" << std::endl;
246 v.toJSON(*this);
247 out << std::endl << --indent << "}";
248 }
249
250 void generate(const IR::Node &v) {
251 out << "{" << std::endl;
252 ++indent;
253 if (node_refs.find(v.id) != node_refs.end()) {
254 out << indent << "\"Node_ID\" : " << v.id;
255 } else {
256 node_refs.insert(v.id);
257 v.toJSON(*this);
258 if (dumpSourceInfo) {
259 v.sourceInfoToJSON(*this);
260 }
261 }
262 out << std::endl << --indent << "}";
263 }
264
265 template <typename T>
266 std::enable_if_t<std::is_pointer_v<T> && has_toJSON<std::remove_pointer_t<T>>::value> generate(
267 T v) {
268 if (v)
269 generate(*v);
270 else
271 out << "null";
272 }
273
274 template <typename T, size_t N>
275 void generate(const T (&v)[N]) {
276 out << "[";
277 if (N > 0) {
278 out << std::endl << ++indent;
279 generate(v[0]);
280 for (size_t i = 1; i < N; i++) {
281 out << "," << std::endl << indent;
282 generate(v[i]);
283 }
284 out << std::endl << --indent;
285 }
286 out << "]";
287 }
288
289 JSONGenerator &operator<<(char ch) {
290 out << ch;
291 return *this;
292 }
293 JSONGenerator &operator<<(const char *s) {
294 out << s;
295 return *this;
296 }
297 JSONGenerator &operator<<(indent_t i) {
298 out << i;
299 return *this;
300 }
301 JSONGenerator &operator<<(std::ostream &(*fn)(std::ostream &)) {
302 out << fn;
303 return *this;
304 }
305 template <typename T>
306 JSONGenerator &operator<<(const T &v) {
307 generate(v);
308 return *this;
309 }
310};
311
312} // namespace P4
313
314#endif /* IR_JSON_GENERATOR_H_ */
Definition node.h:94
Definition json_generator.h:37
Definition bitvec.h:120
Definition cstring.h:85
cstring escapeJson() const
Definition cstring.cpp:272
Definition indent.h:26
Definition ordered_map.h:32
Definition ordered_set.h:32
Definition safe_vector.h:27
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:24
Definition match.h:36