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