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