P4C
The P4 Compiler
Loading...
Searching...
No Matches
json_loader.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_LOADER_H_
18#define IR_JSON_LOADER_H_
19
20#include <map>
21#include <optional>
22#include <string>
23#include <string_view>
24#include <unordered_map>
25#include <utility>
26#include <variant>
27
28#include "ir.h"
29#include "json_parser.h"
30#include "lib/bitvec.h"
31#include "lib/cstring.h"
32#include "lib/ltbitmatrix.h"
33#include "lib/match.h"
34#include "lib/ordered_map.h"
35#include "lib/ordered_set.h"
36#include "lib/safe_vector.h"
37
38namespace P4 {
39
40class JSONLoader {
41 template <typename T>
42 class has_fromJSON {
43 typedef char small;
44 typedef struct {
45 char c[2];
46 } big;
47
48 template <typename C>
49 static small test(decltype(&C::fromJSON));
50 template <typename C>
51 static big test(...);
52
53 public:
54 static const bool value = sizeof(test<T>(0)) == sizeof(char);
55 };
56
57 std::unordered_map<int, IR::Node *> &node_refs;
58 std::unique_ptr<JsonData> json_root;
59 const JsonData *json = nullptr;
60
61 JSONLoader(const JsonData *json, std::unordered_map<int, IR::Node *> &refs)
62 : node_refs(refs), json(json) {}
63
64 public:
65 explicit JSONLoader(std::istream &in)
66 : node_refs(*(new std::unordered_map<int, IR::Node *>())) {
67 in >> json_root;
68 json = json_root.get();
69 }
70
71 JSONLoader(const JSONLoader &unpacker, std::string_view field)
72 : node_refs(unpacker.node_refs), json(nullptr) {
73 if (!unpacker) return;
74 if (auto *obj = unpacker.json->to<JsonObject>()) {
75 if (auto it = obj->find(field); it != obj->end()) {
76 json = it->second.get();
77 }
78 }
79 }
80
81 explicit operator bool() const { return json != nullptr; }
82 template <typename T>
83 [[nodiscard]] bool is() const {
84 return json && json->is<T>();
85 }
86 template <typename T>
87 [[nodiscard]] const T &as() const {
88 return json->as<T>();
89 }
90
91 private:
92 const IR::Node *get_node() {
93 if (!json || !json->is<JsonObject>()) return nullptr; // invalid json exception?
94 int id;
95 load("Node_ID", id);
96 if (id >= 0) {
97 if (node_refs.find(id) == node_refs.end()) {
98 cstring type;
99 load("Node_Type", type);
100 if (auto fn = get(IR::unpacker_table, type)) {
101 node_refs[id] = fn(*this);
102 // Creating JsonObject from source_info read from jsonFile
103 // and setting SourceInfo for each node
104 // when "--fromJSON" flag is used
105 node_refs[id]->sourceInfoFromJSON(*this);
106 } else {
107 return nullptr;
108 } // invalid json exception?
109 }
110 return node_refs[id];
111 }
112 return nullptr; // invalid json exception?
113 }
114
115 template <typename T>
116 void unpack_json(safe_vector<T> &v) {
117 T temp;
118 v.clear();
119 for (auto &e : as<JsonVector>()) {
120 load(e, temp);
121 v.push_back(temp);
122 }
123 }
124
125 template <typename T>
126 void unpack_json(std::set<T> &v) {
127 T temp;
128 v.clear();
129 for (auto &e : as<JsonVector>()) {
130 load(e, temp);
131 v.insert(temp);
132 }
133 }
134
135 template <typename T>
136 void unpack_json(ordered_set<T> &v) {
137 T temp;
138 v.clear();
139 for (auto &e : as<JsonVector>()) {
140 load(e, temp);
141 v.insert(temp);
142 }
143 }
144
145 template <typename T>
146 void unpack_json(IR::Vector<T> &v) {
147 v = *IR::Vector<T>::fromJSON(*this);
148 }
149 template <typename T>
150 void unpack_json(const IR::Vector<T> *&v) {
151 v = IR::Vector<T>::fromJSON(*this);
152 }
153 template <typename T>
154 void unpack_json(IR::IndexedVector<T> &v) {
155 v = *IR::IndexedVector<T>::fromJSON(*this);
156 }
157 template <typename T>
158 void unpack_json(const IR::IndexedVector<T> *&v) {
159 v = IR::IndexedVector<T>::fromJSON(*this);
160 }
161 template <class T, template <class K, class V, class COMP, class ALLOC> class MAP, class COMP,
162 class ALLOC>
163 void unpack_json(IR::NameMap<T, MAP, COMP, ALLOC> &m) {
164 m = *IR::NameMap<T, MAP, COMP, ALLOC>::fromJSON(*this);
165 }
166 template <class T, template <class K, class V, class COMP, class ALLOC> class MAP, class COMP,
167 class ALLOC>
168 void unpack_json(const IR::NameMap<T, MAP, COMP, ALLOC> *&m) {
169 m = IR::NameMap<T, MAP, COMP, ALLOC>::fromJSON(*this);
170 }
171
172 template <typename K, typename V>
173 void unpack_json(std::map<K, V> &v) {
174 std::pair<K, V> temp;
175 v.clear();
176 if (is<JsonVector>()) {
177 for (auto &e : as<JsonVector>()) {
178 load(e, temp);
179 v.insert(temp);
180 }
181 } else {
182 for (auto &e : as<JsonObject>()) {
183 load(JsonString(e.first), temp.first);
184 load(e.second, temp.second);
185 v.insert(temp);
186 }
187 }
188 }
189 template <typename K, typename V>
190 void unpack_json(ordered_map<K, V> &v) {
191 std::pair<K, V> temp;
192 v.clear();
193 if (is<JsonVector>()) {
194 for (auto &e : as<JsonVector>()) {
195 load(e, temp);
196 v.insert(temp);
197 }
198 } else {
199 for (auto &e : as<JsonObject>()) {
200 load(JsonString(e.first), temp.first);
201 load(e.second, temp.second);
202 v.insert(temp);
203 }
204 }
205 }
206 template <typename V>
207 void unpack_json(string_map<V> &v) {
208 std::pair<cstring, V> temp;
209 v.clear();
210 for (auto &e : as<JsonObject>()) {
211 temp.first = e.first;
212 load(e.second, temp.second);
213 v.insert(temp);
214 }
215 }
216
217 template <typename K, typename V>
218 void unpack_json(std::multimap<K, V> &v) {
219 std::pair<K, V> temp;
220 v.clear();
221 if (is<JsonVector>()) {
222 for (auto &e : as<JsonVector>()) {
223 load(e, temp);
224 v.insert(temp);
225 }
226 } else {
227 for (auto &e : as<JsonObject>()) {
228 load(JsonString(e.first), temp.first);
229 load(e.second, temp.second);
230 v.insert(temp);
231 }
232 }
233 }
234
235 template <typename T>
236 void unpack_json(std::vector<T> &v) {
237 T temp;
238 v.clear();
239 for (auto &e : as<JsonVector>()) {
240 load(e, temp);
241 v.push_back(temp);
242 }
243 }
244
245 template <typename T, typename U>
246 void unpack_json(std::pair<T, U> &v) {
247 load("first", v.first);
248 load("second", v.second);
249 }
250
251 template <typename T>
252 void unpack_json(std::optional<T> &v) {
253 bool isValid = false;
254 load("valid", isValid);
255 if (!isValid) {
256 v = std::nullopt;
257 return;
258 }
259 T value;
260 load("value", value);
261 v = std::move(value);
262 }
263
264 template <int N, class Variant>
265 std::enable_if_t<N == std::variant_size_v<Variant>> unpack_variant(int /*target*/,
266 Variant & /*variant*/) {
267 BUG("Error traversing variant during load");
268 }
269
270 template <int N, class Variant>
271 std::enable_if_t<(N < std::variant_size_v<Variant>)> unpack_variant(int target,
272 Variant &variant) {
273 if (N == target) {
274 variant.template emplace<N>();
275 load("value", std::get<N>(variant));
276 } else
277 unpack_variant<N + 1>(target, variant);
278 }
279
280 template <class... Types>
281 void unpack_json(std::variant<Types...> &v) {
282 int index = -1;
283 load("variant_index", index);
284 unpack_variant<0>(index, v);
285 }
286
287 void unpack_json(bool &v) { v = as<JsonBoolean>(); }
288
289 template <typename T>
290 std::enable_if_t<std::is_integral_v<T>> unpack_json(T &v) {
291 v = as<JsonNumber>();
292 }
293 void unpack_json(big_int &v) { v = as<JsonNumber>().val; }
294 void unpack_json(std::string &v) {
295 if (is<JsonString>()) v = as<JsonString>();
296 }
297 void unpack_json(cstring &v) {
298 if (is<JsonString>())
299 v = cstring(as<JsonString>());
300 else if (is<JsonNull>())
301 v = cstring();
302 }
303 void unpack_json(IR::ID &v) {
304 if (!json->is<JsonNull>()) v.name = as<JsonString>();
305 }
306
307 void unpack_json(LTBitMatrix &m) {
308 if (auto *s = json->to<JsonString>()) s->c_str() >> m;
309 }
310
311 void unpack_json(bitvec &v) {
312 if (auto *s = json->to<JsonString>()) s->c_str() >> v;
313 }
314
315 template <typename T>
316 std::enable_if_t<std::is_enum_v<T>> unpack_json(T &v) {
317 if (auto *s = json->to<JsonString>()) *s >> v;
318 }
319
320 void unpack_json(match_t &v) {
321 if (auto *s = json->to<JsonString>()) s->c_str() >> v;
322 }
323
324 void unpack_json(UnparsedConstant *&v) {
325 cstring text("");
326 unsigned skip = 0;
327 unsigned base = 0;
328 bool hasWidth = false;
329
330 load("text", text);
331 load("skip", skip);
332 load("base", base);
333 load("hasWidth", hasWidth);
334
335 v = new UnparsedConstant({text, skip, base, hasWidth});
336 }
337
338 template <typename T>
339 std::enable_if_t<has_fromJSON<T>::value && !std::is_base_of_v<IR::Node, T> &&
340 std::is_pointer_v<decltype(T::fromJSON(std::declval<JSONLoader &>()))>>
341 unpack_json(T *&v) {
342 v = T::fromJSON(*this);
343 }
344
345 template <typename T>
346 std::enable_if_t<has_fromJSON<T>::value && !std::is_base_of_v<IR::Node, T> &&
347 std::is_pointer_v<decltype(T::fromJSON(std::declval<JSONLoader &>()))>>
348 unpack_json(T &v) {
349 v = *(T::fromJSON(*this));
350 }
351
352 template <typename T>
353 std::enable_if_t<has_fromJSON<T>::value && !std::is_base_of<IR::Node, T>::value &&
354 !std::is_pointer_v<decltype(T::fromJSON(std::declval<JSONLoader &>()))>>
355 unpack_json(T &v) {
356 v = T::fromJSON(*this);
357 }
358
359 template <typename T>
360 std::enable_if_t<std::is_base_of_v<IR::INode, T>> unpack_json(T &v) {
361 v = get_node()->as<T>();
362 }
363 template <typename T>
364 std::enable_if_t<std::is_base_of_v<IR::INode, T>> unpack_json(const T *&v) {
365 v = get_node()->checkedTo<T>();
366 }
367
368 template <typename T, size_t N>
369 void unpack_json(T (&v)[N]) {
370 if (auto *j = json->to<JsonVector>()) {
371 for (size_t i = 0; i < N && i < j->size(); ++i) {
372 load(j->at(i), v[i]);
373 }
374 }
375 }
376
377 public:
378 template <typename T>
379 void load(const JsonData &json, T &v) {
380 JSONLoader(&json, node_refs).unpack_json(v);
381 }
382
383 template <typename T>
384 void load(const std::unique_ptr<JsonData> &json, T &v) {
385 JSONLoader(json.get(), node_refs).unpack_json(v);
386 }
387
388 template <typename T>
389 bool load(std::string_view field, T *&v) {
390 if (auto loader = JSONLoader(*this, field)) {
391 loader.unpack_json(v);
392 return true;
393 } else {
394 v = nullptr;
395 return false;
396 }
397 }
398
399 template <typename T>
400 bool load(std::string_view field, T &v) {
401 if (auto loader = JSONLoader(*this, field)) {
402 loader.unpack_json(v);
403 return true;
404 } else {
405 return false;
406 }
407 }
408
409 template <typename T>
410 JSONLoader &operator>>(T &v) {
411 unpack_json(v);
412 return *this;
413 }
414};
415
416template <class T>
417IR::Vector<T>::Vector(JSONLoader &json) : VectorBase(json) {
418 json.load("vec", vec);
419}
420template <class T>
421IR::Vector<T> *IR::Vector<T>::fromJSON(JSONLoader &json) {
422 return new Vector<T>(json);
423}
424template <class T>
425IR::IndexedVector<T>::IndexedVector(JSONLoader &json) : Vector<T>(json) {
426 json.load("declarations", declarations);
427}
428template <class T>
429IR::IndexedVector<T> *IR::IndexedVector<T>::fromJSON(JSONLoader &json) {
430 return new IndexedVector<T>(json);
431}
432template <class T, template <class K, class V, class COMP, class ALLOC> class MAP /*= std::map */,
433 class COMP /*= std::less<cstring>*/,
434 class ALLOC /*= std::allocator<std::pair<cstring, const T*>>*/>
435IR::NameMap<T, MAP, COMP, ALLOC>::NameMap(JSONLoader &json) : Node(json) {
436 json.load("symbols", symbols);
437}
438template <class T, template <class K, class V, class COMP, class ALLOC> class MAP /*= std::map */,
439 class COMP /*= std::less<cstring>*/,
440 class ALLOC /*= std::allocator<std::pair<cstring, const T*>>*/>
441IR::NameMap<T, MAP, COMP, ALLOC> *IR::NameMap<T, MAP, COMP, ALLOC>::fromJSON(JSONLoader &json) {
442 return new IR::NameMap<T, MAP, COMP, ALLOC>(json);
443}
444
445} // namespace P4
446
447#endif /* IR_JSON_LOADER_H_ */
Definition indexed_vector.h:40
Definition namemap.h:38
Definition node.h:94
Definition vector.h:59
Definition json_loader.h:40
Definition json_parser.h:17
Definition json_parser.h:84
Definition json_parser.h:73
Definition json_parser.h:49
Definition json_parser.h:62
Definition ltbitmatrix.h:25
Definition bitvec.h:120
Definition cstring.h:85
Definition ordered_map.h:32
Definition ordered_set.h:32
Definition safe_vector.h:27
Definition string_map.h:41
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:24
Definition constantParsing.h:65
Definition id.h:28
T * to() noexcept
Definition rtti.h:226
Definition match.h:36