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 namespace MiniZinc {
13 
equal(const Expression * e0,const Expression * e1)14 inline bool Expression::equal(const Expression* e0, const Expression* e1) {
15   if (e0 == e1) {
16     return true;
17   }
18   if (e0 == nullptr || e1 == nullptr) {
19     return false;
20   }
21   if (e0->isUnboxedInt() || e1->isUnboxedInt()) {
22     return false;
23   }
24   if (e0->isUnboxedFloatVal() || e1->isUnboxedFloatVal()) {
25     if (e0->isUnboxedFloatVal() && e1->isUnboxedFloatVal()) {
26       return e0->unboxedFloatToFloatVal() == e1->unboxedFloatToFloatVal();
27     }
28     return false;
29   }
30   if (static_cast<ExpressionId>(e0->_id) != static_cast<ExpressionId>(e1->_id)) {
31     return false;
32   }
33   if (e0->type() != e1->type()) {
34     return false;
35   }
36   if (e0->hash() != e1->hash()) {
37     return false;
38   }
39   return equalInternal(e0, e1);
40 }
41 
type(const Type & t)42 inline void Expression::type(const Type& t) {
43   if (isUnboxedVal()) {
44     assert(!isUnboxedInt() || t == Type::parint());
45     assert(!isUnboxedFloatVal() || t == Type::parfloat());
46     return;
47   }
48   if (eid() == E_VARDECL) {
49     this->cast<VarDecl>()->id()->_type = t;
50   } else if (eid() == E_ID && (this->cast<Id>()->decl() != nullptr)) {
51     assert(_type.bt() == Type::BT_UNKNOWN || _type.dim() == t.dim() || t.dim() != -1);
52     this->cast<Id>()->decl()->_type = t;
53   }
54   _type = t;
55 }
56 
IntLit(const Location & loc,IntVal v)57 inline IntLit::IntLit(const Location& loc, IntVal v)
58     : Expression(loc, E_INTLIT, Type::parint()), _v(v) {
59   rehash();
60 }
61 
a(MiniZinc::IntVal v)62 inline IntLit* IntLit::a(MiniZinc::IntVal v) {
63   if (v.isFinite()) {
64     IntLit* ret = intToUnboxedInt(v.toInt());
65     if (ret != nullptr) {
66       return ret;
67     }
68   }
69 
70   auto it = constants().integerMap.find(v);
71   if (it == constants().integerMap.end() || it->second() == nullptr) {
72     auto* il = new IntLit(Location().introduce(), v);
73     if (it == constants().integerMap.end()) {
74       constants().integerMap.insert(std::make_pair(v, il));
75     } else {
76       it->second = il;
77     }
78     return il;
79   }
80   return it->second()->cast<IntLit>();
81 }
82 
aEnum(IntVal v,unsigned int enumId)83 inline IntLit* IntLit::aEnum(IntVal v, unsigned int enumId) {
84   if (enumId == 0) {
85     return a(v);
86   }
87   auto* il = new IntLit(Location().introduce(), v);
88   Type tt(il->type());
89   tt.enumId(enumId);
90   il->type(tt);
91   return il;
92 }
93 
filename() const94 inline ASTString Location::LocVec::filename() const {
95   return static_cast<ASTStringData*>(_data[0]);
96 }
firstLine() const97 inline unsigned int Location::LocVec::firstLine() const {
98   if (_size == 2) {
99     static const unsigned int pointerBits = sizeof(void*) * 8;
100     auto* il = static_cast<IntLit*>(_data[1]);
101     long long unsigned int mask = pointerBits <= 32 ? 0xFF : 0xFFFFF;
102     union {
103       long long int i;
104       unsigned long long int u;
105     } ui;
106     ui.i = il->v().toInt();
107     return static_cast<unsigned int>(ui.u & mask);
108   }
109   auto* il = static_cast<IntLit*>(_data[1]);
110   return il->v().toInt();
111 }
lastLine() const112 inline unsigned int Location::LocVec::lastLine() const {
113   if (_size == 2) {
114     static const unsigned int pointerBits = sizeof(void*) * 8;
115     auto* il = static_cast<IntLit*>(_data[1]);
116     long long unsigned int first_line_size = pointerBits <= 32 ? 8 : 20;
117     long long unsigned int mask = pointerBits <= 32 ? 0xFF : 0xFFFFF;
118     long long unsigned int offsetmask = pointerBits <= 32 ? 0x7F : 0xFFFFF;
119     union {
120       long long int i;
121       unsigned long long int u;
122     } ui;
123     ui.i = il->v().toInt();
124     // return first line (8 bit) + offset (7 bit)
125     return static_cast<unsigned int>((ui.u & mask) + ((ui.u >> first_line_size) & offsetmask));
126   }
127   auto* il = static_cast<IntLit*>(_data[2]);
128   return il->v().toInt();
129 }
firstColumn() const130 inline unsigned int Location::LocVec::firstColumn() const {
131   if (_size == 2) {
132     static const unsigned int pointerBits = sizeof(void*) * 8;
133     auto* il = static_cast<IntLit*>(_data[1]);
134     long long unsigned int first_col_offset = pointerBits <= 32 ? 8 + 7 : 20 + 20;
135     long long unsigned int mask = pointerBits <= 32 ? 0x3F : 0x3FF;
136     union {
137       long long int i;
138       unsigned long long int u;
139     } ui;
140     ui.i = il->v().toInt();
141     // return first line (8 bit) + offset (7 bit)
142     return static_cast<unsigned int>((ui.u >> first_col_offset) & mask);
143   }
144   auto* il = static_cast<IntLit*>(_data[3]);
145   return il->v().toInt();
146 }
lastColumn() const147 inline unsigned int Location::LocVec::lastColumn() const {
148   if (_size == 2) {
149     static const unsigned int pointerBits = sizeof(void*) * 8;
150     auto* il = static_cast<IntLit*>(_data[1]);
151     long long unsigned int last_col_offset = pointerBits <= 32 ? 8 + 7 + 6 : 20 + 20 + 10;
152     long long unsigned int mask = pointerBits <= 32 ? 0x7F : 0x3FF;
153     union {
154       long long int i;
155       unsigned long long int u;
156     } ui;
157     ui.i = il->v().toInt();
158     // return first line (8 bit) + offset (7 bit)
159     return static_cast<unsigned int>((ui.u >> last_col_offset) & mask);
160   }
161   auto* il = static_cast<IntLit*>(_data[4]);
162   return il->v().toInt();
163 }
164 
FloatLit(const Location & loc,FloatVal v)165 inline FloatLit::FloatLit(const Location& loc, FloatVal v)
166     : Expression(loc, E_FLOATLIT, Type::parfloat()), _v(v) {
167   rehash();
168 }
169 
a(MiniZinc::FloatVal v)170 inline FloatLit* FloatLit::a(MiniZinc::FloatVal v) {
171   if (sizeof(double) <= sizeof(void*) && v.isFinite()) {
172     FloatLit* ret = Expression::doubleToUnboxedFloatVal(v.toDouble());
173     if (ret != nullptr) {
174       return ret;
175     }
176   }
177 
178   auto it = constants().floatMap.find(v);
179   if (it == constants().floatMap.end() || it->second() == nullptr) {
180     auto* fl = new FloatLit(Location().introduce(), v);
181     if (it == constants().floatMap.end()) {
182       constants().floatMap.insert(std::make_pair(v, fl));
183     } else {
184       it->second = fl;
185     }
186     return fl;
187   }
188   return it->second()->cast<FloatLit>();
189 }
190 
SetLit(const Location & loc,const std::vector<Expression * > & v)191 inline SetLit::SetLit(const Location& loc, const std::vector<Expression*>& v)
192     : Expression(loc, E_SETLIT, Type()), _v(ASTExprVec<Expression>(v)) {
193   _u.isv = nullptr;
194   rehash();
195 }
196 
SetLit(const Location & loc,const ASTExprVec<Expression> & v)197 inline SetLit::SetLit(const Location& loc, const ASTExprVec<Expression>& v)
198     : Expression(loc, E_SETLIT, Type()), _v(v) {
199   _u.isv = nullptr;
200   rehash();
201 }
202 
SetLit(const Location & loc,IntSetVal * isv)203 inline SetLit::SetLit(const Location& loc, IntSetVal* isv) : Expression(loc, E_SETLIT, Type()) {
204   _type = Type::parsetint();
205   _u.isv = isv;
206   rehash();
207 }
208 
SetLit(const Location & loc,FloatSetVal * fsv)209 inline SetLit::SetLit(const Location& loc, FloatSetVal* fsv) : Expression(loc, E_SETLIT, Type()) {
210   _type = Type::parsetfloat();
211   _u.fsv = fsv;
212   rehash();
213 }
214 
BoolLit(const Location & loc,bool v)215 inline BoolLit::BoolLit(const Location& loc, bool v)
216     : Expression(loc, E_BOOLLIT, Type::parbool()), _v(v) {
217   rehash();
218 }
219 
StringLit(const Location & loc,const std::string & v)220 inline StringLit::StringLit(const Location& loc, const std::string& v)
221     : Expression(loc, E_STRINGLIT, Type::parstring()), _v(ASTString(v)) {
222   rehash();
223 }
224 
StringLit(const Location & loc,const ASTString & v)225 inline StringLit::StringLit(const Location& loc, const ASTString& v)
226     : Expression(loc, E_STRINGLIT, Type::parstring()), _v(v) {
227   rehash();
228 }
229 
Id(const Location & loc,const std::string & v0,VarDecl * decl)230 inline Id::Id(const Location& loc, const std::string& v0, VarDecl* decl)
231     : Expression(loc, E_ID, Type()), _decl(decl) {
232   v(v0);
233   rehash();
234 }
235 
Id(const Location & loc,const ASTString & v0,VarDecl * decl)236 inline Id::Id(const Location& loc, const ASTString& v0, VarDecl* decl)
237     : Expression(loc, E_ID, Type()), _decl(decl) {
238   v(v0);
239   rehash();
240 }
241 
Id(const Location & loc,long long int idn0,VarDecl * decl)242 inline Id::Id(const Location& loc, long long int idn0, VarDecl* decl)
243     : Expression(loc, E_ID, Type()), _decl(decl) {
244   idn(idn0);
245   rehash();
246 }
247 
decl(VarDecl * d)248 inline void Id::decl(VarDecl* d) { _decl = d; }
249 
v() const250 inline ASTString Id::v() const {
251   if ((_decl != nullptr) && _decl->isa<Id>()) {
252     Expression* d = _decl;
253     while ((d != nullptr) && d->isa<Id>()) {
254       d = d->cast<Id>()->_decl;
255     }
256     return d->cast<VarDecl>()->id()->v();
257   }
258   assert(hasStr());
259   return _vOrIdn.val;
260 }
261 
idn() const262 inline long long int Id::idn() const {
263   if ((_decl != nullptr) && _decl->isa<Id>()) {
264     Expression* d = _decl;
265     while ((d != nullptr) && d->isa<Id>()) {
266       d = d->cast<Id>()->_decl;
267     }
268     return d->cast<VarDecl>()->id()->idn();
269   }
270   if (hasStr()) {
271     return -1;
272   }
273   long long int i = reinterpret_cast<ptrdiff_t>(_vOrIdn.idn) & ~static_cast<ptrdiff_t>(1);
274   return i >> 1;
275 }
276 
TIId(const Location & loc,const std::string & v)277 inline TIId::TIId(const Location& loc, const std::string& v)
278     : Expression(loc, E_TIID, Type()), _v(ASTString(v)) {
279   rehash();
280 }
281 
TIId(const Location & loc,const ASTString & v)282 inline TIId::TIId(const Location& loc, const ASTString& v)
283     : Expression(loc, E_TIID, Type()), _v(v) {
284   rehash();
285 }
286 
AnonVar(const Location & loc)287 inline AnonVar::AnonVar(const Location& loc) : Expression(loc, E_ANON, Type()) { rehash(); }
288 
ArrayLit(const Location & loc,ArrayLit & v,const std::vector<std::pair<int,int>> & dims)289 inline ArrayLit::ArrayLit(const Location& loc, ArrayLit& v,
290                           const std::vector<std::pair<int, int> >& dims)
291     : Expression(loc, E_ARRAYLIT, Type()) {
292   _flag1 = false;
293   _flag2 = v._flag2;
294   if (_flag2) {
295     _u.al = v._u.al;
296     std::vector<int> d(dims.size() * 2 + v._dims.size() - v.dims() * 2);
297     for (auto i = static_cast<unsigned int>(dims.size()); (i--) != 0U;) {
298       d[i * 2] = dims[i].first;
299       d[i * 2 + 1] = dims[i].second;
300     }
301     int sliceOffset = static_cast<int>(dims.size()) * 2;
302     unsigned int origSliceOffset = v.dims() * 2;
303     for (int i = 0; i < _u.al->dims() * 2; i++) {
304       d[sliceOffset + i] = v._dims[origSliceOffset + i];
305     }
306     _dims = ASTIntVec(d);
307   } else {
308     std::vector<int> d(dims.size() * 2);
309     for (auto i = static_cast<unsigned int>(dims.size()); (i--) != 0U;) {
310       d[i * 2] = dims[i].first;
311       d[i * 2 + 1] = dims[i].second;
312     }
313     if (v._u.v->flag() || d.size() != 2 || d[0] != 1) {
314       // only allocate dims vector if it is not a 1d array indexed from 1
315       _dims = ASTIntVec(d);
316     }
317     _u.v = v._u.v;
318   }
319   rehash();
320 }
321 
ArrayLit(const Location & loc,ArrayLit & v)322 inline ArrayLit::ArrayLit(const Location& loc, ArrayLit& v) : Expression(loc, E_ARRAYLIT, Type()) {
323   _flag1 = false;
324   _flag2 = v._flag2;
325   if (_flag2) {
326     _u.al = v._u.al;
327     std::vector<int> d(2 + v._dims.size() - v.dims() * 2);
328     d[0] = 1;
329     d[1] = v.size();
330     int sliceOffset = 2;
331     unsigned int origSliceOffset = v.dims() * 2;
332     for (int i = 0; i < _u.al->dims() * 2; i++) {
333       d[sliceOffset + i] = v._dims[origSliceOffset + i];
334     }
335     _dims = ASTIntVec(d);
336   } else {
337     _u.v = v._u.v;
338     if (_u.v->flag()) {
339       std::vector<int> d(2);
340       d[0] = 1;
341       d[1] = v.length();
342       _dims = ASTIntVec(d);
343     } else {
344       // don't allocate dims vector since this is a 1d array indexed from 1
345     }
346   }
347   rehash();
348 }
349 
ArrayLit(const Location & loc,const std::vector<Expression * > & v)350 inline ArrayLit::ArrayLit(const Location& loc, const std::vector<Expression*>& v)
351     : Expression(loc, E_ARRAYLIT, Type()) {
352   _flag1 = false;
353   _flag2 = false;
354   std::vector<int> d(2);
355   d[0] = 1;
356   d[1] = static_cast<int>(v.size());
357   compress(v, d);
358   rehash();
359 }
360 
ArrayLit(const Location & loc,const std::vector<KeepAlive> & v)361 inline ArrayLit::ArrayLit(const Location& loc, const std::vector<KeepAlive>& v)
362     : Expression(loc, E_ARRAYLIT, Type()) {
363   _flag1 = false;
364   _flag2 = false;
365   std::vector<int> d(2);
366   d[0] = 1;
367   d[1] = static_cast<int>(v.size());
368   std::vector<Expression*> vv(v.size());
369   for (unsigned int i = 0; i < v.size(); i++) {
370     vv[i] = v[i]();
371   }
372   compress(vv, d);
373   rehash();
374 }
375 
ArrayLit(const Location & loc,const std::vector<std::vector<Expression * >> & v)376 inline ArrayLit::ArrayLit(const Location& loc, const std::vector<std::vector<Expression*> >& v)
377     : Expression(loc, E_ARRAYLIT, Type()) {
378   _flag1 = false;
379   _flag2 = false;
380   std::vector<int> dims(4);
381   dims[0] = 1;
382   dims[1] = static_cast<int>(v.size());
383   dims[2] = 1;
384   dims[3] = !v.empty() ? static_cast<int>(v[0].size()) : 0;
385   std::vector<Expression*> vv;
386   for (const auto& i : v) {
387     for (auto* j : i) {
388       vv.push_back(j);
389     }
390   }
391   compress(vv, dims);
392   rehash();
393 }
394 
ArrayAccess(const Location & loc,Expression * v,const std::vector<Expression * > & idx)395 inline ArrayAccess::ArrayAccess(const Location& loc, Expression* v,
396                                 const std::vector<Expression*>& idx)
397     : Expression(loc, E_ARRAYACCESS, Type()) {
398   _v = v;
399   _idx = ASTExprVec<Expression>(idx);
400   rehash();
401 }
402 
ArrayAccess(const Location & loc,Expression * v,const ASTExprVec<Expression> & idx)403 inline ArrayAccess::ArrayAccess(const Location& loc, Expression* v,
404                                 const ASTExprVec<Expression>& idx)
405     : Expression(loc, E_ARRAYACCESS, Type()) {
406   _v = v;
407   _idx = idx;
408   rehash();
409 }
410 
init(Expression * e,Generators & g)411 inline void Comprehension::init(Expression* e, Generators& g) {
412   _e = e;
413   std::vector<Expression*> es;
414   std::vector<int> idx;
415   for (auto& i : g.g) {
416     idx.push_back(static_cast<int>(es.size()));
417     es.push_back(i._in);
418     es.push_back(i._where);
419     for (auto& j : i._v) {
420       es.push_back(j);
421     }
422   }
423   idx.push_back(static_cast<int>(es.size()));
424   _g = ASTExprVec<Expression>(es);
425   _gIndex = ASTIntVec(idx);
426   rehash();
427 }
Comprehension(const Location & loc,Expression * e,Generators & g,bool set)428 inline Comprehension::Comprehension(const Location& loc, Expression* e, Generators& g, bool set)
429     : Expression(loc, E_COMP, Type()) {
430   _flag1 = set;
431   init(e, g);
432 }
init(const std::vector<Expression * > & e_if_then,Expression * e_else)433 inline void ITE::init(const std::vector<Expression*>& e_if_then, Expression* e_else) {
434   _eIfThen = ASTExprVec<Expression>(e_if_then);
435   _eElse = e_else;
436   rehash();
437 }
ITE(const Location & loc,const std::vector<Expression * > & e_if_then,Expression * e_else)438 inline ITE::ITE(const Location& loc, const std::vector<Expression*>& e_if_then, Expression* e_else)
439     : Expression(loc, E_ITE, Type()) {
440   init(e_if_then, e_else);
441 }
442 
BinOp(const Location & loc,Expression * e0,BinOpType op,Expression * e1)443 inline BinOp::BinOp(const Location& loc, Expression* e0, BinOpType op, Expression* e1)
444     : Expression(loc, E_BINOP, Type()), _e0(e0), _e1(e1), _decl(nullptr) {
445   _secondaryId = op;
446   rehash();
447 }
448 
UnOp(const Location & loc,UnOpType op,Expression * e)449 inline UnOp::UnOp(const Location& loc, UnOpType op, Expression* e)
450     : Expression(loc, E_UNOP, Type()), _e0(e), _decl(nullptr) {
451   _secondaryId = op;
452   rehash();
453 }
454 
hasId() const455 inline bool Call::hasId() const {
456   return (reinterpret_cast<ptrdiff_t>(_uId.decl) & static_cast<ptrdiff_t>(1)) == 0;
457 }
458 
id() const459 inline ASTString Call::id() const { return hasId() ? _uId.id : decl()->id(); }
460 
id(const ASTString & i)461 inline void Call::id(const ASTString& i) {
462   _uId.id = i;
463   assert(hasId());
464   assert(decl() == nullptr);
465 }
466 
decl() const467 inline FunctionI* Call::decl() const {
468   return hasId() ? nullptr
469                  : reinterpret_cast<FunctionI*>(reinterpret_cast<ptrdiff_t>(_uId.decl) &
470                                                 ~static_cast<ptrdiff_t>(1));
471 }
472 
decl(FunctionI * f)473 inline void Call::decl(FunctionI* f) {
474   assert(f != nullptr);
475   _uId.decl =
476       reinterpret_cast<FunctionI*>(reinterpret_cast<ptrdiff_t>(f) | static_cast<ptrdiff_t>(1));
477 }
478 
Call(const Location & loc,const std::string & id0,const std::vector<Expression * > & args)479 inline Call::Call(const Location& loc, const std::string& id0, const std::vector<Expression*>& args)
480     : Expression(loc, E_CALL, Type()) {
481   _flag1 = false;
482   id(ASTString(id0));
483   if (args.size() == 1) {
484     _u.oneArg = args[0]->isUnboxedVal() ? args[0] : args[0]->tag();
485   } else {
486     _u.args = ASTExprVec<Expression>(args).vec();
487   }
488   rehash();
489   assert(hasId());
490   assert(decl() == nullptr);
491 }
492 
Call(const Location & loc,const ASTString & id0,const std::vector<Expression * > & args)493 inline Call::Call(const Location& loc, const ASTString& id0, const std::vector<Expression*>& args)
494     : Expression(loc, E_CALL, Type()) {
495   _flag1 = false;
496   id(ASTString(id0));
497   if (args.size() == 1) {
498     _u.oneArg = args[0]->isUnboxedVal() ? args[0] : args[0]->tag();
499   } else {
500     _u.args = ASTExprVec<Expression>(args).vec();
501   }
502   rehash();
503   assert(hasId());
504   assert(decl() == nullptr);
505 }
506 
VarDecl(const Location & loc,TypeInst * ti,const ASTString & id,Expression * e)507 inline VarDecl::VarDecl(const Location& loc, TypeInst* ti, const ASTString& id, Expression* e)
508     : Expression(loc, E_VARDECL, ti != nullptr ? ti->type() : Type()),
509       _id(nullptr),
510       _flat(nullptr) {
511   _id = new Id(loc, id, this);
512   _flag1 = true;
513   _flag2 = false;
514   _ti = ti;
515   _e = e;
516   _id->type(type());
517   _payload = 0;
518   rehash();
519 }
520 
VarDecl(const Location & loc,TypeInst * ti,long long int idn,Expression * e)521 inline VarDecl::VarDecl(const Location& loc, TypeInst* ti, long long int idn, Expression* e)
522     : Expression(loc, E_VARDECL, ti != nullptr ? ti->type() : Type()),
523       _id(nullptr),
524       _flat(nullptr) {
525   _id = new Id(loc, idn, this);
526   _flag1 = true;
527   _flag2 = false;
528   _ti = ti;
529   _e = e;
530   _id->type(type());
531   _payload = 0;
532   rehash();
533 }
534 
VarDecl(const Location & loc,TypeInst * ti,const std::string & id,Expression * e)535 inline VarDecl::VarDecl(const Location& loc, TypeInst* ti, const std::string& id, Expression* e)
536     : Expression(loc, E_VARDECL, ti->type()), _id(nullptr), _flat(nullptr) {
537   _id = new Id(loc, ASTString(id), this);
538   _flag1 = true;
539   _flag2 = false;
540   _ti = ti;
541   _e = e;
542   _id->type(type());
543   _payload = 0;
544   rehash();
545 }
546 
VarDecl(const Location & loc,TypeInst * ti,Id * id,Expression * e)547 inline VarDecl::VarDecl(const Location& loc, TypeInst* ti, Id* id, Expression* e)
548     : Expression(loc, E_VARDECL, ti->type()), _id(nullptr), _flat(nullptr) {
549   if (id->idn() == -1) {
550     _id = new Id(id->loc(), id->v(), this);
551   } else {
552     _id = new Id(id->loc(), id->idn(), this);
553   }
554   _flag1 = true;
555   _flag2 = false;
556   _ti = ti;
557   _e = e;
558   _id->type(type());
559   _payload = 0;
560   rehash();
561 }
562 
e() const563 inline Expression* VarDecl::e() const {
564   return (_e == nullptr || _e->isUnboxedVal()) ? _e : _e->untag();
565 }
566 
e(Expression * rhs)567 inline void VarDecl::e(Expression* rhs) {
568   assert(rhs == nullptr || !rhs->isa<Id>() || rhs->cast<Id>() != _id);
569   _e = rhs;
570 }
571 
toplevel() const572 inline bool VarDecl::toplevel() const { return _flag1; }
toplevel(bool t)573 inline void VarDecl::toplevel(bool t) { _flag1 = t; }
introduced() const574 inline bool VarDecl::introduced() const { return _flag2; }
introduced(bool t)575 inline void VarDecl::introduced(bool t) { _flag2 = t; }
evaluated() const576 inline bool VarDecl::evaluated() const { return _e->isUnboxedVal() || _e->isTagged(); }
evaluated(bool t)577 inline void VarDecl::evaluated(bool t) {
578   if (!_e->isUnboxedVal()) {
579     if (t) {
580       _e = _e->tag();
581     } else {
582       _e = _e->untag();
583     }
584   }
585 }
flat(VarDecl * vd)586 inline void VarDecl::flat(VarDecl* vd) { _flat = WeakRef(vd); }
587 
TypeInst(const Location & loc,const Type & type,const ASTExprVec<TypeInst> & ranges,Expression * domain)588 inline TypeInst::TypeInst(const Location& loc, const Type& type, const ASTExprVec<TypeInst>& ranges,
589                           Expression* domain)
590     : Expression(loc, E_TI, type), _ranges(ranges), _domain(domain) {
591   _flag1 = false;
592   _flag2 = false;
593   rehash();
594 }
595 
TypeInst(const Location & loc,const Type & type,Expression * domain)596 inline TypeInst::TypeInst(const Location& loc, const Type& type, Expression* domain)
597     : Expression(loc, E_TI, type), _domain(domain) {
598   _flag1 = false;
599   _flag2 = false;
600   rehash();
601 }
602 
IncludeI(const Location & loc,const ASTString & f)603 inline IncludeI::IncludeI(const Location& loc, const ASTString& f)
604     : Item(loc, II_INC), _f(f), _m(nullptr) {}
605 
VarDeclI(const Location & loc,VarDecl * e)606 inline VarDeclI::VarDeclI(const Location& loc, VarDecl* e) : Item(loc, II_VD), _e(e) {}
607 
AssignI(const Location & loc,const std::string & id,Expression * e)608 inline AssignI::AssignI(const Location& loc, const std::string& id, Expression* e)
609     : Item(loc, II_ASN), _id(ASTString(id)), _e(e), _decl(nullptr) {}
610 
AssignI(const Location & loc,const ASTString & id,Expression * e)611 inline AssignI::AssignI(const Location& loc, const ASTString& id, Expression* e)
612     : Item(loc, II_ASN), _id(id), _e(e), _decl(nullptr) {}
613 
ConstraintI(const Location & loc,Expression * e)614 inline ConstraintI::ConstraintI(const Location& loc, Expression* e) : Item(loc, II_CON), _e(e) {}
615 
SolveI(const Location & loc,Expression * e)616 inline SolveI::SolveI(const Location& loc, Expression* e) : Item(loc, II_SOL), _e(e) {}
sat(const Location & loc)617 inline SolveI* SolveI::sat(const Location& loc) {
618   auto* si = new SolveI(loc, nullptr);
619   si->_secondaryId = ST_SAT;
620   return si;
621 }
min(const Location & loc,Expression * e)622 inline SolveI* SolveI::min(const Location& loc, Expression* e) {
623   auto* si = new SolveI(loc, e);
624   si->_secondaryId = ST_MIN;
625   return si;
626 }
max(const Location & loc,Expression * e)627 inline SolveI* SolveI::max(const Location& loc, Expression* e) {
628   auto* si = new SolveI(loc, e);
629   si->_secondaryId = ST_MAX;
630   return si;
631 }
st() const632 inline SolveI::SolveType SolveI::st() const { return static_cast<SolveType>(_secondaryId); }
st(SolveI::SolveType s)633 inline void SolveI::st(SolveI::SolveType s) { _secondaryId = s; }
634 
OutputI(const Location & loc,Expression * e)635 inline OutputI::OutputI(const Location& loc, Expression* e) : Item(loc, II_OUT), _e(e) {}
636 
FunctionI(const Location & loc,const std::string & id,TypeInst * ti,const std::vector<VarDecl * > & params,Expression * e,bool from_stdlib)637 inline FunctionI::FunctionI(const Location& loc, const std::string& id, TypeInst* ti,
638                             const std::vector<VarDecl*>& params, Expression* e, bool from_stdlib)
639     : Item(loc, II_FUN),
640       _id(ASTString(id)),
641       _ti(ti),
642       _params(ASTExprVec<VarDecl>(params)),
643       _e(e),
644       _fromStdLib(from_stdlib) {
645   builtins.e = nullptr;
646   builtins.b = nullptr;
647   builtins.f = nullptr;
648   builtins.i = nullptr;
649   builtins.s = nullptr;
650   builtins.str = nullptr;
651 }
652 
FunctionI(const Location & loc,const ASTString & id,TypeInst * ti,const ASTExprVec<VarDecl> & params,Expression * e,bool from_stdlib)653 inline FunctionI::FunctionI(const Location& loc, const ASTString& id, TypeInst* ti,
654                             const ASTExprVec<VarDecl>& params, Expression* e, bool from_stdlib)
655     : Item(loc, II_FUN), _id(id), _ti(ti), _params(params), _e(e), _fromStdLib(from_stdlib) {
656   builtins.e = nullptr;
657   builtins.b = nullptr;
658   builtins.f = nullptr;
659   builtins.i = nullptr;
660   builtins.s = nullptr;
661   builtins.str = nullptr;
662 }
663 
664 }  // namespace MiniZinc
665