P4C
The P4 Compiler
Loading...
Searching...
No Matches
namemap.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_NAMEMAP_H_
18#define IR_NAMEMAP_H_
19
20#include <map>
21
22#include "ir/node.h"
23#include "lib/cstring.h"
24#include "lib/enumerator.h"
25#include "lib/error.h"
26#include "lib/exceptions.h"
27#include "lib/map.h"
28
29namespace P4 {
30class JSONLoader;
31} // namespace P4
32
33namespace P4::IR {
34
35template <class T, template <class K, class V, class COMP, class ALLOC> class MAP = std::map,
36 class COMP = std::less<cstring>,
37 class ALLOC = std::allocator<std::pair<const cstring, const T *>>>
38class NameMap : public Node {
39 typedef MAP<cstring, const T *, COMP, ALLOC> map_t;
40 map_t symbols;
41 /* if the object has a 'name' field, is it the same as name? */
42 template <class U>
43 auto match_name(cstring name, const U *obj) -> decltype(name == obj->name) {
44 return name == obj->name;
45 }
46 bool match_name(cstring, const void *) { return true; }
47 template <class U>
48 auto obj_name(const U *obj) -> decltype(obj->name) {
49 return obj->name;
50 }
51 cstring obj_name(const void *) { return nullptr; }
52
53 public:
54 NameMap() = default;
55 NameMap(const NameMap &) = default;
56 NameMap(NameMap &&) = default;
57 explicit NameMap(JSONLoader &);
58 NameMap &operator=(const NameMap &) = default;
59 NameMap &operator=(NameMap &&) = default;
60 typedef typename map_t::value_type value_type;
61 typedef typename map_t::iterator iterator;
62 typedef typename map_t::const_iterator const_iterator;
63 typedef typename map_t::reverse_iterator reverse_iterator;
64 typedef typename map_t::const_reverse_iterator const_reverse_iterator;
65
66 private:
67 struct elem_ref {
68 NameMap &self;
69 cstring name;
70 elem_ref(NameMap &s, cstring n) : self(s), name(n) {}
71 const T *operator=(const T *v) const {
72 if (!self.match_name(name, v)) BUG("Inserting into NameMap with incorrect name");
73 return self.symbols[name] = v;
74 }
75 operator const T *() const { return self.count(name) ? self.at(name) : nullptr; }
76 };
77
78 public:
79 const_iterator begin() const { return symbols.begin(); }
80 const_iterator end() const { return symbols.end(); }
81 iterator begin() { return symbols.begin(); }
82 iterator end() { return symbols.end(); }
83 // For multimaps
84 std::pair<const_iterator, const_iterator> equal_range(cstring key) const {
85 return symbols.equal_range(key);
86 }
87 const_reverse_iterator rbegin() const { return symbols.rbegin(); }
88 const_reverse_iterator rend() const { return symbols.rend(); }
89 reverse_iterator rbegin() { return symbols.rbegin(); }
90 reverse_iterator rend() { return symbols.rend(); }
91 size_t count(cstring name) const { return symbols.count(name); }
92 void clear() { symbols.clear(); }
93 size_t size() const { return symbols.size(); }
94 bool empty() const { return symbols.empty(); }
95 size_t erase(cstring n) { return symbols.erase(n); }
96 /* should be erase(const_iterator), but glibc++ std::list::erase is broken */
97 iterator erase(iterator p) { return symbols.erase(p); }
98 iterator erase(iterator f, iterator l) { return symbols.erase(f, l); }
99 const_iterator find(cstring name) const { return symbols.find(name); }
100 template <class U>
101 const U *get(cstring name) const {
102 for (auto it = symbols.find(name); it != symbols.end() && it->first == name; it++)
103 if (auto rv = it->second->template to<U>()) return rv;
104 return nullptr;
105 }
106 void add(cstring name, const T *n) {
107 if (!match_name(name, n)) BUG("Inserting into NameMap with incorrect name");
108 symbols.emplace(std::move(name), std::move(n));
109 }
110 // Expects to have a single node with each name.
111 // Only works for map and unordered_map
112 void addUnique(cstring name, const T *n) {
113 auto prev = symbols.find(name);
114 if (prev != symbols.end())
115 ::P4::error(ErrorType::ERR_DUPLICATE, "%1%: duplicated name (%2% is previous instance)",
116 n, prev->second);
117 symbols.emplace(std::move(name), std::move(n));
118 }
119 // Expects to have a single node with each name.
120 // Only works for map and unordered_map
121 const T *getUnique(cstring name) const {
122 auto it = symbols.find(name);
123 if (it == symbols.end()) return nullptr;
124 return it->second;
125 }
126 elem_ref operator[](cstring name) { return elem_ref(*this, name); }
127 const T *operator[](cstring name) const { return count(name) ? at(name) : nullptr; }
128 const T *&at(cstring name) { return symbols.at(name); }
129 const T *const &at(cstring name) const { return symbols.at(name); }
130 void check_null() const {
131 for (auto &e : symbols) CHECK_NULL(e.second);
132 }
133
134 IRNODE_SUBCLASS(NameMap)
135 bool operator==(const Node &a) const override { return a.operator==(*this); }
136 bool operator==(const NameMap &a) const { return symbols == a.symbols; }
137 bool equiv(const Node &a_) const override {
138 if (static_cast<const Node *>(this) == &a_) return true;
139 if (this->typeId() != a_.typeId()) return false;
140 auto &a = static_cast<const NameMap<T, MAP, COMP, ALLOC> &>(a_);
141 if (size() != a.size()) return false;
142 auto it = a.begin();
143 for (auto &el : *this)
144 if (el.first != it->first || !el.second->equiv(*(it++)->second)) return false;
145 return true;
146 }
147 cstring node_type_name() const override { return "NameMap<" + T::static_type_name() + ">"; }
148 static cstring static_type_name() { return "NameMap<" + T::static_type_name() + ">"; }
149 void visit_children(Visitor &v) override;
150 void visit_children(Visitor &v) const override;
151 void toJSON(JSONGenerator &json) const override;
152 static NameMap<T, MAP, COMP, ALLOC> *fromJSON(JSONLoader &json);
153
154 Util::Enumerator<const T *> *valueEnumerator() const {
155 return Util::enumerate(Values(symbols));
156 }
157 template <typename S>
158 Util::Enumerator<const S *> *only() const {
159 return valueEnumerator()->template as<const S *>()->where(
160 [](const T *d) { return d != nullptr; });
161 }
162
163 DECLARE_TYPEINFO(NameMap, Node);
164};
165
166} // namespace P4::IR
167
168#endif /* IR_NAMEMAP_H_ */
const T & as() const
Tries to convert the class to type T. A BUG occurs if the cast fails.
Definition castable.h:42
Definition namemap.h:38
Definition node.h:95
Definition json_generator.h:36
Definition json_loader.h:38
Type-erased Enumerator interface.
Definition enumerator.h:68
Definition visitor.h:75
Definition cstring.h:85
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:24
void error(const char *format, Args &&...args)
Report an error with the given message.
Definition error.h:51
T * to() noexcept
Definition rtti.h:226
virtual TypeId typeId() const noexcept=0