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