1 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ 2 3 /* 4 * Main authors: 5 * Guido Tack <guido.tack@monash.edu> 6 */ 7 8 /* This Source Code Form is subject to the terms of the Mozilla Public 9 * License, v. 2.0. If a copy of the MPL was not distributed with this 10 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 11 12 #pragma once 13 14 #include <minizinc/ast.hh> 15 #include <minizinc/exception.hh> 16 17 #include <unordered_map> 18 #include <unordered_set> 19 20 namespace MiniZinc { 21 22 /// Hash class for expressions 23 struct ExpressionHash { operator ()MiniZinc::ExpressionHash24 size_t operator()(const Expression* e) const { return Expression::hash(e); } 25 }; 26 27 /// Equality test for expressions 28 struct ExpressionEq { operator ()MiniZinc::ExpressionEq29 bool operator()(const Expression* e0, const Expression* e1) const { 30 return Expression::equal(e0, e1); 31 } 32 }; 33 34 /// Hash map from expression to \a T 35 template <class T> 36 class ExpressionMap { 37 protected: 38 /// The underlying map implementation 39 std::unordered_map<Expression*, T, ExpressionHash, ExpressionEq> _m; 40 41 public: 42 /// Iterator type 43 typedef 44 typename std::unordered_map<Expression*, T, ExpressionHash, ExpressionEq>::iterator iterator; 45 /// Insert mapping from \a e to \a t insert(Expression * e,const T & t)46 iterator insert(Expression* e, const T& t) { 47 assert(e != nullptr); 48 return _m.insert(std::pair<Expression*, T>(e, t)).first; 49 } 50 /// Find \a e in map find(Expression * e)51 iterator find(Expression* e) { return _m.find(e); } 52 /// Begin of iterator begin()53 iterator begin() { return _m.begin(); } 54 /// End of iterator end()55 iterator end() { return _m.end(); } 56 /// Remove binding of \a e from map remove(Expression * e)57 void remove(Expression* e) { _m.erase(e); } 58 /// Remove all elements from the map clear()59 void clear() { _m.clear(); } 60 }; 61 62 /// Equality test for identifiers 63 struct IdEq { operator ()MiniZinc::IdEq64 bool operator()(const Id* e0, const Id* e1) const { 65 if (e0->idn() == e1->idn()) { 66 if (e0->idn() == -1) { 67 return e0->v() == e1->v(); 68 } 69 return true; 70 } 71 return false; 72 } 73 }; 74 75 /// Hash map from identifier to \a T 76 template <class T> 77 class IdMap { 78 protected: 79 /// The underlying map implementation 80 std::unordered_map<Id*, T, ExpressionHash, IdEq> _m; 81 82 public: 83 /// Iterator type 84 typedef typename std::unordered_map<Id*, T, ExpressionHash, IdEq>::iterator iterator; 85 /// Insert mapping from \a e to \a t insert(Id * e,const T & t)86 void insert(Id* e, const T& t) { 87 assert(e != nullptr); 88 _m.insert(std::pair<Id*, T>(e, t)); 89 } 90 /// Find \a e in map find(Id * e)91 iterator find(Id* e) { return _m.find(e); } 92 /// Begin of iterator begin()93 iterator begin() { return _m.begin(); } 94 /// End of iterator end()95 iterator end() { return _m.end(); } 96 /// Remove binding of \a e from map remove(Id * e)97 void remove(Id* e) { _m.erase(e); } 98 /// Return number of elements in the map size() const99 int size() const { return _m.size(); } 100 /// Remove all elements from the map clear()101 void clear() { _m.clear(); } get(Id * ident)102 T& get(Id* ident) { 103 auto it = find(ident); 104 // assert(it != _m.end()); 105 if (_m.end() == it) { // Changing so it stays in Release version 106 std::string msg = "Id "; 107 // if (ident) // could be a segfault... 108 // msg += ident->v().c_str(); 109 msg += " not found"; 110 throw InternalError(msg); 111 } 112 return it->second; 113 } 114 }; 115 116 /// Hash class for KeepAlive objects 117 struct KAHash { operator ()MiniZinc::KAHash118 size_t operator()(const KeepAlive& e) const { return Expression::hash(e()); } 119 }; 120 121 /// Equality test for KeepAlive objects 122 struct KAEq { operator ()MiniZinc::KAEq123 bool operator()(const KeepAlive& e0, const KeepAlive& e1) const { 124 return Expression::equal(e0(), e1()); 125 } 126 }; 127 128 /// Hash map from KeepAlive to \a T 129 template <class T> 130 class KeepAliveMap { 131 protected: 132 /// The underlying map implementation 133 std::unordered_map<KeepAlive, T, KAHash, KAEq> _m; 134 135 public: 136 /// Iterator type 137 typedef typename std::unordered_map<KeepAlive, T, KAHash, KAEq>::iterator iterator; 138 /// Insert mapping from \a e to \a t insert(KeepAlive & e,const T & t)139 void insert(KeepAlive& e, const T& t) { 140 assert(e() != nullptr); 141 _m.insert(std::pair<KeepAlive, T>(e, t)); 142 } 143 /// Find \a e in map find(KeepAlive & e)144 iterator find(KeepAlive& e) { return _m.find(e); } 145 /// Begin of iterator begin()146 iterator begin() { return _m.begin(); } 147 /// End of iterator end()148 iterator end() { return _m.end(); } 149 /// Remove binding of \a e from map remove(KeepAlive & e)150 void remove(KeepAlive& e) { _m.erase(e); } clear()151 void clear() { _m.clear(); } 152 template <class D> dump()153 void dump() { 154 for (auto i = _m.begin(); i != _m.end(); ++i) { 155 std::cerr << D::k(i->first()) << ": " << D::d(i->second) << std::endl; 156 } 157 } 158 }; 159 160 class ExpressionSetIter 161 : public std::unordered_set<Expression*, ExpressionHash, ExpressionEq>::iterator { 162 protected: 163 bool _empty; 164 typedef std::unordered_set<Expression*, ExpressionHash, ExpressionEq>::iterator Iter; 165 166 public: ExpressionSetIter()167 ExpressionSetIter() : _empty(false) {} ExpressionSetIter(bool)168 ExpressionSetIter(bool /*b*/) : _empty(true) {} ExpressionSetIter(const Iter & i)169 ExpressionSetIter(const Iter& i) : Iter(i), _empty(false) {} operator ==(const ExpressionSetIter & i) const170 bool operator==(const ExpressionSetIter& i) const { 171 return (_empty && i._empty) || static_cast<const Iter&>(*this) == static_cast<const Iter&>(i); 172 } operator !=(const ExpressionSetIter & i) const173 bool operator!=(const ExpressionSetIter& i) const { return !operator==(i); } 174 }; 175 176 /// Hash set for expressions 177 class ExpressionSet { 178 protected: 179 /// The underlying set implementation 180 std::unordered_set<Expression*, ExpressionHash, ExpressionEq> _s; 181 182 public: 183 /// Insert \a e insert(Expression * e)184 void insert(Expression* e) { 185 assert(e != nullptr); 186 _s.insert(e); 187 } 188 /// Find \a e in map find(Expression * e)189 ExpressionSetIter find(Expression* e) { return _s.find(e); } 190 /// Begin of iterator begin()191 ExpressionSetIter begin() { return _s.begin(); } 192 /// End of iterator end()193 ExpressionSetIter end() { return _s.end(); } 194 /// Remove binding of \a e from map remove(Expression * e)195 void remove(Expression* e) { _s.erase(e); } contains(Expression * e)196 bool contains(Expression* e) { return find(e) != end(); } 197 /// Remove all elements from the map clear()198 void clear() { _s.clear(); } isEmpty() const199 bool isEmpty() const { return _s.begin() == _s.end(); } 200 }; 201 202 } // namespace MiniZinc 203