Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Specialize NameMap::visit_children for ordered_map so that order is … #14

Merged
merged 1 commit into from
Apr 19, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 29 additions & 3 deletions ir/ir-inline.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,35 @@ std::ostream &operator<<(std::ostream &out, const IR::Vector<IR::Expression> &v)
inline std::ostream &operator<<(std::ostream &out, const IR::Vector<IR::Expression> *v) {
return v ? out << *v : out << "<null>"; }

#include "lib/ordered_map.h"
template <class MAP> static inline void
namemap_insert_helper(typename MAP::iterator, typename MAP::key_type k,
typename MAP::mapped_type v, MAP &, MAP &new_symbols) {
new_symbols.emplace(std::move(k), std::move(v));
}

template <class MAP, class InputIterator> static inline void
namemap_insert_helper(typename MAP::iterator, InputIterator b, InputIterator e,
MAP &, MAP &new_symbols) {
new_symbols.insert(b, e);
}

template <class T> static inline void
namemap_insert_helper(typename ordered_map<cstring, T>::iterator it, cstring k, T v,
ordered_map<cstring, T> &symbols, ordered_map<cstring, T> &) {
symbols.emplace_hint(it, std::move(k), std::move(v));
}

template <class T, class InputIterator> static inline void
namemap_insert_helper(typename ordered_map<cstring, T>::iterator it,
InputIterator b, InputIterator e,
ordered_map<cstring, T> &symbols, ordered_map<cstring, T> &) {
symbols.insert(it, b, e);
}

template<class T, template<class K, class V, class COMP, class ALLOC> class MAP /*= std::map */,
class COMP /*= std::less<cstring>*/,
class ALLOC /*= std::allocator<std::pair<cstring, const T*>>*/>
class ALLOC /*= std::allocator<std::pair<const cstring, const T*>>*/>
void IR::NameMap<T, MAP, COMP, ALLOC>::visit_children(Visitor &v) {
map_t new_symbols;
for (auto i = symbols.begin(); i != symbols.end();) {
Expand All @@ -88,14 +114,14 @@ void IR::NameMap<T, MAP, COMP, ALLOC>::visit_children(Visitor &v) {
} else if (n == i->second) {
i++;
} else if (auto m = dynamic_cast<const NameMap *>(n)) {
new_symbols.insert(m->symbols.begin(), m->symbols.end());
namemap_insert_helper(i, m->symbols.begin(), m->symbols.end(), symbols, new_symbols);
i = symbols.erase(i);
} else if (auto s = dynamic_cast<const T *>(n)) {
if (match_name(i->first, s)) {
i->second = s;
i++;
} else {
new_symbols.emplace(obj_name(s), std::move(s));
namemap_insert_helper(i, cstring(obj_name(s)), std::move(s), symbols, new_symbols);
i = symbols.erase(i); }
} else {
BUG("visitor returned invalid type %s for NameMap<%s>",
Expand Down
2 changes: 1 addition & 1 deletion ir/namemap.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace IR {

template<class T, template<class K, class V, class COMP, class ALLOC> class MAP = std::map,
class COMP = std::less<cstring>,
class ALLOC = std::allocator<std::pair<cstring, const T*>>>
class ALLOC = std::allocator<std::pair<const cstring, const T*>>>
class NameMap : public Node {
typedef MAP<cstring, const T *, COMP, ALLOC> map_t;
map_t symbols;
Expand Down
27 changes: 24 additions & 3 deletions lib/ordered_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,22 +130,43 @@ class ordered_map {
if (it == data.end()) throw std::out_of_range("ordered_map");
return it->second; }

std::pair<iterator, bool> emplace(K &&k, V &&v) {
auto it = find(k);
if (it == data.end()) {
it = data.emplace(data.end(), std::move(k), std::move(v));
data_map.emplace(&it->first, it);
return std::make_pair(it, true); }
return std::make_pair(it, false); }
std::pair<iterator, bool> emplace_hint(iterator pos, K &&k, V &&v) {
/* should be const_iterator pos, but glibc++ std::list is broken */
auto it = find(k);
if (it == data.end()) {
it = data.emplace(pos, std::move(k), std::move(v));
data_map.emplace(&it->first, it);
return std::make_pair(it, true); }
return std::make_pair(it, false); }

std::pair<iterator, bool> insert(const value_type &v) {
auto it = find(v.first);
if (it == data.end()) {
it = data.insert(data.end(), v);
data_map.emplace(&it->first, it);
return std::make_pair(it, true); }
return std::make_pair(it, false); }
std::pair<iterator, bool> emplace(K &&k, V &&v) {
auto it = find(k);
std::pair<iterator, bool> insert(iterator pos, const value_type &v) {
/* should be const_iterator pos, but glibc++ std::list is broken */
auto it = find(v.first);
if (it == data.end()) {
it = data.emplace(data.end(), std::move(k), std::move(v));
it = data.insert(pos, v);
data_map.emplace(&it->first, it);
return std::make_pair(it, true); }
return std::make_pair(it, false); }
template<class InputIterator> void insert(InputIterator b, InputIterator e) {
while (b != e) insert(*b++); }
template<class InputIterator>
void insert(iterator pos, InputIterator b, InputIterator e) {
/* should be const_iterator pos, but glibc++ std::list is broken */
while (b != e) insert(pos, *b++); }

/* should be erase(const_iterator), but glibc++ std::list::erase is broken */
iterator erase(iterator pos) {
Expand Down
5 changes: 4 additions & 1 deletion test/Makefile.am
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# Unit tests

check_PROGRAMS = exception_test format_test source_file_test path_test \
enumerator_test default_test unittest_transform1 json_test
enumerator_test default_test unittest_transform1 json_test \
namemap_order_test

default_test_SOURCES = test/unittests/default_test.cpp
default_test_LDADD = libp4ctoolkit.a
Expand All @@ -19,6 +20,8 @@ json_test_SOURCES = test/unittests/json_test.cpp
json_test_LDADD = libp4ctoolkit.a
unittest_transform1_SOURCES = $(ir_SOURCES) test/unittests/transform1.cpp
unittest_transform1_LDADD = libp4ctoolkit.a
namemap_order_test_SOURCES = $(ir_SOURCES) test/unittests/namemap_order_test.cpp
namemap_order_test_LDADD = libp4ctoolkit.a

# Compiler tests

Expand Down
34 changes: 34 additions & 0 deletions test/unittests/namemap_order_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#include "ir/ir.h"
#include "ir/visitor.h"
#include <assert.h>

class TestTrans : public Transform {
IR::Node *preorder(IR::TableProperty *a) override {
if (!a->isConstant)
a->name = "$new$";
return a;
}
IR::Node *postorder(IR::TableProperties *p) override {
int count = 0;
for (auto &prop : p->properties) {
if (prop.first == "$new$")
assert(count == 0);
else
assert(count == 1);
++count; }
return p;
}
};

int main() {
auto tp = new IR::TableProperties();
tp->properties.add("a", new IR::TableProperty(Util::SourceInfo(), "a",
new IR::Annotations(new IR::Vector<IR::Annotation>()),
new IR::Key(Util::SourceInfo(), new IR::Vector<IR::KeyElement>()),
false));
tp->properties.add("b", new IR::TableProperty(Util::SourceInfo(), "b",
new IR::Annotations(new IR::Vector<IR::Annotation>()),
new IR::Key(Util::SourceInfo(), new IR::Vector<IR::KeyElement>()),
true));
tp->apply(TestTrans());
}