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/aststring.hh>
15 #include <minizinc/astvec.hh>
16 #include <minizinc/gc.hh>
17 #include <minizinc/type.hh>
18 #include <minizinc/values.hh>
19 
20 #include <cstddef>
21 #include <cstdint>
22 #include <iostream>
23 #include <limits>
24 #include <utility>
25 #include <vector>
26 
27 namespace MiniZinc {
28 
29 class IntLit;
30 class FloatLit;
31 class SetLit;
32 class BoolLit;
33 class StringLit;
34 class Id;
35 class AnonVar;
36 class ArrayLit;
37 class ArrayAccess;
38 class Comprehension;
39 class ITE;
40 class BinOp;
41 class UnOp;
42 class Call;
43 class VarDecl;
44 class Let;
45 class TypeInst;
46 
47 class Item;
48 class FunctionI;
49 
50 class ExpressionSet;
51 class ExpressionSetIter;
52 
53 /// %Location of an expression used during parsing
54 class ParserLocation {
55 protected:
56   /// Source code file name
57   ASTString _filename;
58   /// Line where expression starts
59   unsigned int _firstLine;
60   /// Line where expression ends
61   unsigned int _lastLine;
62   /// Column where expression starts
63   unsigned int _firstColumn;
64   /// Column where expression ends
65   unsigned int _lastColumn;
66 
67 public:
68   /// Construct empty location
ParserLocation()69   ParserLocation() : _firstLine(1), _lastLine(1), _firstColumn(0), _lastColumn(0) {}
70 
71   /// Construct location
ParserLocation(const ASTString & filename,unsigned int first_line,unsigned int first_column,unsigned int last_line,unsigned int last_column)72   ParserLocation(const ASTString& filename, unsigned int first_line, unsigned int first_column,
73                  unsigned int last_line, unsigned int last_column)
74       : _filename(filename),
75         _firstLine(first_line),
76         _lastLine(last_line),
77         _firstColumn(first_column),
78         _lastColumn(last_column) {}
79 
filename() const80   ASTString filename() const { return _filename; }
filename(const ASTString & f)81   void filename(const ASTString& f) { _filename = f; }
82 
firstLine() const83   unsigned int firstLine() const { return _firstLine; }
firstLine(unsigned int l)84   void firstLine(unsigned int l) { _firstLine = l; }
85 
lastLine() const86   unsigned int lastLine() const { return _lastLine; }
lastLine(unsigned int l)87   void lastLine(unsigned int l) { _lastLine = l; }
88 
firstColumn() const89   unsigned int firstColumn() const { return _firstColumn; }
firstColumn(unsigned int c)90   void firstColumn(unsigned int c) { _firstColumn = c; }
91 
lastColumn() const92   unsigned int lastColumn() const { return _lastColumn; }
lastColumn(unsigned int c)93   void lastColumn(unsigned int c) { _lastColumn = c; }
94 
toString() const95   std::string toString() const {
96     std::ostringstream oss;
97     oss << _filename << ":" << _firstLine << "." << _firstColumn;
98     if (_firstLine != _lastLine) {
99       oss << "-" << _lastLine << "." << _lastColumn;
100     } else if (_firstColumn != _lastColumn) {
101       oss << "-" << _lastColumn;
102     }
103     return oss.str();
104   }
105 };
106 
107 /// %Location of an expression in the source code
108 class Location {
109 protected:
110   /// Internal representation of a Location
111   /// Layout depends on sizeof pointer and arguments
112   /// 32 bit pointers:
113   ///   Layout 1: filename (32 bit), first line (8 bit), last line-first line (7 bit), first column
114   ///   (6 bit), last column (7 bit) Layout 2: filename (32 bit), 4 IntLit for the lines/columns
115   /// 64 bit pointers:
116   ///   Layout 1: filename (64 bit), first line (20 bit), last line-first line (20 bit), first
117   ///   column (10 bit), last column (10 bit) Layout 2: filename (64 bit), 4 IntLit for the
118   ///   lines/columns
119   class LocVec : public ASTVec {
120   protected:
121     LocVec(const ASTString& filename, unsigned int first_line, unsigned int first_column,
122            unsigned int last_line, unsigned int last_column);
123     LocVec(const ASTString& filename, IntVal combined);
124 
125   public:
126     static LocVec* a(const ASTString& filename, unsigned int first_line, unsigned int first_column,
127                      unsigned int last_line, unsigned int last_column);
mark()128     void mark() {
129       _gcMark = 1;
130       if (_data[0] != nullptr) {
131         static_cast<ASTStringData*>(_data[0])->mark();
132       }
133     }
134 
135     ASTString filename() const;
136     unsigned int firstLine() const;
137     unsigned int lastLine() const;
138     unsigned int firstColumn() const;
139     unsigned int lastColumn() const;
140   };
141 
142   union LI {
143     LocVec* lv;
144     ptrdiff_t t;
145   } _locInfo;
146 
lv() const147   LocVec* lv() const {
148     LI li = _locInfo;
149     li.t &= ~static_cast<ptrdiff_t>(1);
150     return li.lv;
151   }
152 
153 public:
154   /// Construct empty location
Location()155   Location() { _locInfo.lv = nullptr; }
156 
157   /// Construct location
Location(const ASTString & filename,unsigned int first_line,unsigned int first_column,unsigned int last_line,unsigned int last_column)158   Location(const ASTString& filename, unsigned int first_line, unsigned int first_column,
159            unsigned int last_line, unsigned int last_column) {
160     if (last_line < first_line) {
161       throw InternalError("invalid location");
162     }
163     _locInfo.lv = LocVec::a(filename, first_line, first_column, last_line, last_column);
164   }
165 
Location(const ParserLocation & loc)166   Location(const ParserLocation& loc) {
167     _locInfo.lv = LocVec::a(loc.filename(), loc.firstLine(), loc.firstColumn(), loc.lastLine(),
168                             loc.lastColumn());
169   }
170 
171   /// Return string representation
172   std::string toString() const;
173 
174   /// Return filename
filename() const175   ASTString filename() const { return lv() != nullptr ? lv()->filename() : ASTString(); }
176 
177   /// Return first line number
firstLine() const178   unsigned int firstLine() const { return lv() != nullptr ? lv()->firstLine() : 0; }
179 
180   /// Return last line number
lastLine() const181   unsigned int lastLine() const { return lv() != nullptr ? lv()->lastLine() : 0; }
182 
183   /// Return first column number
firstColumn() const184   unsigned int firstColumn() const { return lv() != nullptr ? lv()->firstColumn() : 0; }
185 
186   /// Return last column number
lastColumn() const187   unsigned int lastColumn() const { return lv() != nullptr ? lv()->lastColumn() : 0; }
188 
189   /// Return whether location is introduced by the compiler
isIntroduced() const190   bool isIntroduced() const { return _locInfo.lv == nullptr || ((_locInfo.t & 1) != 0); }
191 
192   /// Mark as alive for garbage collection
193   void mark() const;
194 
195   /// Return location with introduced flag set
196   Location introduce() const;
197 
198   /// Location used for un-allocated expressions
199   static Location nonalloc;
200 
201   /// Return true if this is a location for an unallocated expression
isNonAlloc() const202   bool isNonAlloc() const { return this == &Location::nonalloc; }
203 
parserLocation() const204   ParserLocation parserLocation() const {
205     return ParserLocation(filename(), firstLine(), firstColumn(), lastLine(), lastColumn());
206   }
207 };
208 
209 /// Output operator for locations
210 template <class Char, class Traits>
operator <<(std::basic_ostream<Char,Traits> & os,const Location & loc)211 std::basic_ostream<Char, Traits>& operator<<(std::basic_ostream<Char, Traits>& os,
212                                              const Location& loc) {
213   std::basic_ostringstream<Char, Traits> s;
214   s.copyfmt(os);
215   s.width(0);
216   if (loc.filename() == "") {
217     s << "unknown file";
218   } else {
219     s << loc.filename();
220   }
221   s << ":" << loc.firstLine() << "." << loc.firstColumn();
222   if (loc.firstLine() != loc.lastLine()) {
223     s << "-" << loc.lastLine() << "." << loc.lastColumn();
224   } else if (loc.firstColumn() != loc.lastColumn()) {
225     s << "-" << loc.lastColumn();
226   }
227 
228   return os << s.str();
229 }
230 
231 /**
232  * \brief Annotations
233  */
234 class Annotation {
235 private:
236   ExpressionSet* _s;
237 
238   /// Delete
239   Annotation(const Annotation&);
240   /// Delete
241   Annotation& operator=(const Annotation&);
242 
243 public:
Annotation()244   Annotation() : _s(nullptr) {}
245   ~Annotation();
246   bool contains(Expression* e) const;
247   bool containsCall(const ASTString& id) const;
248   bool isEmpty() const;
249   ExpressionSetIter begin() const;
250   ExpressionSetIter end() const;
251   void add(Expression* e);
252   void add(std::vector<Expression*> e);
253   void remove(Expression* e);
254   void removeCall(const ASTString& id);
255   void clear();
256   void merge(const Annotation& ann);
257   Call* getCall(const ASTString& id) const;
258 
259   static Annotation empty;
260 };
261 
262 /// returns the Annotation specified by the string; returns NULL if not exists
263 Expression* get_annotation(const Annotation& ann, const std::string& str);
264 
265 /// returns the Annotation specified by the string; returns NULL if not exists
266 Expression* get_annotation(const Annotation& ann, const ASTString& str);
267 
268 /**
269  * \brief Base class for expressions
270  */
271 class Expression : public ASTNode {
272 protected:
273   /// The %MiniZinc type of the expression
274   Type _type;
275   /// The annotations
276   Annotation _ann;
277   /// The location of the expression
278   Location _loc;
279   /// The hash value of the expression
280   size_t _hash;
281 
282 public:
283   /// Identifier of the concrete expression type
284   enum ExpressionId {
285     E_INTLIT = ASTNode::NID_END + 1,
286     E_FLOATLIT,
287     E_SETLIT,
288     E_BOOLLIT,
289     E_STRINGLIT,
290     E_ID,
291     E_ANON,
292     E_ARRAYLIT,
293     E_ARRAYACCESS,
294     E_COMP,
295     E_ITE,
296     E_BINOP,
297     E_UNOP,
298     E_CALL,
299     E_VARDECL,
300     E_LET,
301     E_TI,
302     E_TIID,
303     EID_END = E_TIID
304   };
305 
isUnboxedVal() const306   bool isUnboxedVal() const {
307     if (sizeof(double) <= sizeof(void*)) {
308       // bit 1 or bit 0 is set
309       return (reinterpret_cast<ptrdiff_t>(this) & static_cast<ptrdiff_t>(3)) != 0;
310     }  // bit 0 is set
311     return (reinterpret_cast<ptrdiff_t>(this) & static_cast<ptrdiff_t>(1)) != 0;
312   }
isUnboxedInt() const313   bool isUnboxedInt() const {
314     if (sizeof(double) <= sizeof(void*)) {
315       // bit 1 is set, bit 0 is not set
316       return (reinterpret_cast<ptrdiff_t>(this) & static_cast<ptrdiff_t>(3)) == 2;
317     }  // bit 0 is set
318     return (reinterpret_cast<ptrdiff_t>(this) & static_cast<ptrdiff_t>(1)) == 1;
319   }
isUnboxedFloatVal() const320   bool isUnboxedFloatVal() const {
321     // bit 0 is set (and doubles fit inside pointers)
322     return (sizeof(double) <= sizeof(void*)) &&
323            (reinterpret_cast<ptrdiff_t>(this) & static_cast<ptrdiff_t>(1)) == 1;
324   }
325 
eid() const326   ExpressionId eid() const {
327     return isUnboxedInt() ? E_INTLIT
328                           : isUnboxedFloatVal() ? E_FLOATLIT : static_cast<ExpressionId>(_id);
329   }
330 
loc() const331   const Location& loc() const { return isUnboxedVal() ? Location::nonalloc : _loc; }
loc(const Location & l)332   void loc(const Location& l) {
333     if (!isUnboxedVal()) {
334       _loc = l;
335     }
336   }
type() const337   const Type& type() const {
338     return isUnboxedInt() ? Type::unboxedint : isUnboxedFloatVal() ? Type::unboxedfloat : _type;
339   }
340   void type(const Type& t);
hash() const341   size_t hash() const {
342     return isUnboxedInt() ? unboxedIntToIntVal().hash()
343                           : isUnboxedFloatVal() ? unboxedFloatToFloatVal().hash() : _hash;
344   }
345 
346 protected:
347   /// Combination function for hash values
combineHash(size_t h)348   void combineHash(size_t h) { _hash ^= h + 0x9e3779b9 + (_hash << 6) + (_hash >> 2); }
349   /// Combination function for hash values
combineHash(size_t seed,size_t h)350   static size_t combineHash(size_t seed, size_t h) {
351     seed ^= h + 0x9e3779b9 + (seed << 6) + (seed >> 2);
352     return seed;
353   }
354 
355   /// Compute base hash value
initHash()356   void initHash() { _hash = combineHash(0, _id); }
357 
358   /// Check if \a e0 and \a e1 are equal
359   static bool equalInternal(const Expression* e0, const Expression* e1);
360 
361   /// Constructor
Expression(const Location & loc,const ExpressionId & eid,const Type & t)362   Expression(const Location& loc, const ExpressionId& eid, const Type& t)
363       : ASTNode(eid), _type(t), _loc(loc) {}
364 
365 public:
unboxedIntToIntVal() const366   IntVal unboxedIntToIntVal() const {
367     assert(isUnboxedInt());
368     if (sizeof(double) <= sizeof(void*)) {
369       unsigned long long int i = reinterpret_cast<ptrdiff_t>(this) & ~static_cast<ptrdiff_t>(7);
370       bool pos = ((reinterpret_cast<ptrdiff_t>(this) & static_cast<ptrdiff_t>(4)) == 0);
371       if (pos) {
372         return static_cast<long long int>(i >> 3);
373       }
374       return -(static_cast<long long int>(i >> 3));
375     }
376     unsigned long long int i = reinterpret_cast<ptrdiff_t>(this) & ~static_cast<ptrdiff_t>(3);
377     bool pos = ((reinterpret_cast<ptrdiff_t>(this) & static_cast<ptrdiff_t>(2)) == 0);
378     if (pos) {
379       return static_cast<long long int>(i >> 2);
380     }
381     return -(static_cast<long long int>(i >> 2));
382   }
intToUnboxedInt(long long int i)383   static IntLit* intToUnboxedInt(long long int i) {
384     static const unsigned int pointerBits = sizeof(void*) * 8;
385     if (sizeof(double) <= sizeof(void*)) {
386       static const long long int maxUnboxedVal =
387           (static_cast<long long int>(1) << (pointerBits - 3)) - static_cast<long long int>(1);
388       if (i < -maxUnboxedVal || i > maxUnboxedVal) {
389         return nullptr;
390       }
391       long long int j = i < 0 ? -i : i;
392       ptrdiff_t ubi_p = (static_cast<ptrdiff_t>(j) << 3) | static_cast<ptrdiff_t>(2);
393       if (i < 0) {
394         ubi_p = ubi_p | static_cast<ptrdiff_t>(4);
395       }
396       return reinterpret_cast<IntLit*>(ubi_p);
397     }
398     static const long long int maxUnboxedVal =
399         (static_cast<long long int>(1) << (pointerBits - 2)) - static_cast<long long int>(1);
400     if (i < -maxUnboxedVal || i > maxUnboxedVal) {
401       return nullptr;
402     }
403     long long int j = i < 0 ? -i : i;
404     ptrdiff_t ubi_p = (static_cast<ptrdiff_t>(j) << 2) | static_cast<ptrdiff_t>(1);
405     if (i < 0) {
406       ubi_p = ubi_p | static_cast<ptrdiff_t>(2);
407     }
408     return reinterpret_cast<IntLit*>(ubi_p);
409   }
unboxedFloatToFloatVal() const410   FloatVal unboxedFloatToFloatVal() const {
411     assert(isUnboxedFloatVal());
412     union {
413       double d;
414       uint64_t bits;
415       const Expression* p;
416     } _u;
417     _u.p = this;
418     _u.bits = _u.bits >> 1;
419     uint64_t exponent = (_u.bits & (static_cast<uint64_t>(0x3FF) << 52)) >> 52;
420     if (exponent != 0) {
421       exponent += 512;  // reconstruct original bias of 1023
422     }
423     uint64_t sign = ((_u.bits & (static_cast<uint64_t>(1) << 62)) != 0U ? 1 : 0);
424     _u.bits = (sign << 63) | (exponent << 52) | (_u.bits & static_cast<uint64_t>(0xFFFFFFFFFFFFF));
425     return _u.d;
426   }
doubleToUnboxedFloatVal(double d)427   static FloatLit* doubleToUnboxedFloatVal(double d) {
428     if (sizeof(double) > sizeof(void*)) {
429       return nullptr;
430     }
431     union {
432       double d;
433       uint64_t bits;
434       FloatLit* p;
435     } _u;
436     _u.d = d;
437 
438     uint64_t exponent = (_u.bits & (static_cast<uint64_t>(0x7FF) << 52)) >> 52;
439     if (exponent != 0) {
440       if (exponent < 513 || exponent > 1534) {
441         return nullptr;  // exponent doesn't fit in 10 bits
442       }
443       exponent -= 512;  // make exponent fit in 10 bits, with bias 511
444     }
445     bool sign = (_u.bits & (static_cast<uint64_t>(1) << 63)) != 0;
446 
447     _u.bits = _u.bits &
448               ~(static_cast<uint64_t>(0x7FF) << 52);  // mask out top 11 bits (previously exponent)
449     _u.bits = (_u.bits << 1) | 1U;                    // shift by one bit and add tag for double
450     _u.bits =
451         _u.bits | (static_cast<uint64_t>(sign) << 63) | (static_cast<uint64_t>(exponent) << 53);
452     return _u.p;
453   }
454 
isTagged() const455   bool isTagged() const {
456     // only bit 2 is set
457     if (isUnboxedVal()) {
458       return false;
459     }
460     if (sizeof(double) <= sizeof(void*)) {
461       return (reinterpret_cast<ptrdiff_t>(this) & static_cast<ptrdiff_t>(7)) == 4;
462     }
463     return (reinterpret_cast<ptrdiff_t>(this) & static_cast<ptrdiff_t>(3)) == 2;
464   }
465 
tag() const466   Expression* tag() const {
467     assert(!isUnboxedVal());
468     if (sizeof(double) <= sizeof(void*)) {
469       return reinterpret_cast<Expression*>(reinterpret_cast<ptrdiff_t>(this) |
470                                            static_cast<ptrdiff_t>(4));
471     }
472     return reinterpret_cast<Expression*>(reinterpret_cast<ptrdiff_t>(this) |
473                                          static_cast<ptrdiff_t>(2));
474   }
untag()475   Expression* untag() {
476     if (isUnboxedVal()) {
477       return this;
478     }
479     if (sizeof(double) <= sizeof(void*)) {
480       return reinterpret_cast<Expression*>(reinterpret_cast<ptrdiff_t>(this) &
481                                            ~static_cast<ptrdiff_t>(4));
482     }
483     return reinterpret_cast<Expression*>(reinterpret_cast<ptrdiff_t>(this) &
484                                          ~static_cast<ptrdiff_t>(2));
485   }
486 
487   /// Test if expression is of type \a T
488   template <class T>
isa() const489   bool isa() const {
490 #ifdef __clang__
491 #pragma clang diagnostic push
492 #pragma clang diagnostic ignored "-Wtautological-undefined-compare"
493 #endif
494     if (nullptr == this) {
495       throw InternalError("isa: nullptr");
496     }
497 #ifdef __clang__
498 #pragma clang diagnostic pop
499 #endif
500     return isUnboxedInt() ? T::eid == E_INTLIT
501                           : isUnboxedFloatVal() ? T::eid == E_FLOATLIT : _id == T::eid;
502   }
503   /// Cast expression to type \a T*
504   template <class T>
cast()505   T* cast() {
506     assert(isa<T>());
507     return static_cast<T*>(this);
508   }
509   /// Cast expression to type \a const T*
510   template <class T>
cast() const511   const T* cast() const {
512     assert(isa<T>());
513     return static_cast<const T*>(this);
514   }
515   /// Cast expression to type \a T* or NULL if types do not match
516   template <class T>
dynamicCast()517   T* dynamicCast() {
518     return isa<T>() ? static_cast<T*>(this) : nullptr;
519   }
520   /// Cast expression to type \a const T* or NULL if types do not match
521   template <class T>
dynamicCast() const522   const T* dynamicCast() const {
523     return isa<T>() ? static_cast<const T*>(this) : nullptr;
524   }
525 
526   /// Cast expression to type \a T*
527   template <class T>
cast(Expression * e)528   static T* cast(Expression* e) {
529     return e == nullptr ? nullptr : e->cast<T>();
530   }
531   /// Cast expression to type \a const T*
532   template <class T>
cast(const Expression * e)533   static const T* cast(const Expression* e) {
534     return e == nullptr ? NULL : e->cast<T>();
535   }
536   /// Cast expression to type \a T* or NULL if types do not match
537   template <class T>
dynamicCast(Expression * e)538   static T* dynamicCast(Expression* e) {
539     return e == nullptr ? nullptr : e->dynamicCast<T>();
540   }
541   /// Cast expression to type \a const T* or NULL if types do not match
542   template <class T>
dynamicCast(const Expression * e)543   static const T* dynamicCast(const Expression* e) {
544     return e == nullptr ? NULL : e->dynamicCast<T>();
545   }
546 
547   /// Add annotation \a ann to the expression
548   void addAnnotation(Expression* ann);
549 
550   /// Add annotation \a ann to the expression
551   void addAnnotations(const std::vector<Expression*>& ann);
552 
ann() const553   const Annotation& ann() const { return isUnboxedVal() ? Annotation::empty : _ann; }
ann()554   Annotation& ann() { return isUnboxedVal() ? Annotation::empty : _ann; }
555 
556   /// Return hash value of \a e
hash(const Expression * e)557   static size_t hash(const Expression* e) { return e == nullptr ? 0 : e->hash(); }
558 
559   /// Check if \a e0 and \a e1 are equal
560   static bool equal(const Expression* e0, const Expression* e1);
561 
562   /// Mark \a e as alive for garbage collection
563   static void mark(Expression* e);
564 };
565 
566 /// \brief Integer literal expression
567 class IntLit : public Expression {
568 protected:
569   /// The value of this expression
570   IntVal _v;
571   /// Constructor
572   IntLit(const Location& loc, IntVal v);
573 
574 public:
575   /// The identifier of this expression type
576   static const ExpressionId eid = E_INTLIT;
577   /// Access value
v() const578   IntVal v() const { return isUnboxedInt() ? unboxedIntToIntVal() : _v; }
579   /// Recompute hash value
580   void rehash();
581   /// Allocate literal
582   static IntLit* a(IntVal v);
583   /// Allocate literal for enumerated type (only used internally for generators)
584   static IntLit* aEnum(IntVal v, unsigned int enumId);
585 };
586 /// \brief Float literal expression
587 class FloatLit : public Expression {
588 protected:
589   /// The value of this expression
590   FloatVal _v;
591   /// Constructor
592   FloatLit(const Location& loc, FloatVal v);
593 
594 public:
595   /// The identifier of this expression type
596   static const ExpressionId eid = E_FLOATLIT;
597   /// Access value
v() const598   FloatVal v() const { return isUnboxedFloatVal() ? unboxedFloatToFloatVal() : _v; }
599   /// Recompute hash value
600   void rehash();
601   /// Allocate literal
602   static FloatLit* a(FloatVal v);
603 };
604 /// \brief Set literal expression
605 class SetLit : public Expression {
606 protected:
607   /// The value of this expression
608   ASTExprVec<Expression> _v;
609   union {
610     /// A range-list based representation for an integer set, or NULL
611     IntSetVal* isv;
612     /// A range-list based representation for an float set, or NULL
613     FloatSetVal* fsv;
614   } _u;
615 
616 public:
617   /// The identifier of this expression type
618   static const ExpressionId eid = E_SETLIT;
619   /// Construct set \$f\{v1,\dots,vn\}\$f
620   SetLit(const Location& loc, const std::vector<Expression*>& v);
621   /// Construct set \$f\{v1,\dots,vn\}\$f
622   SetLit(const Location& loc, const ASTExprVec<Expression>& v);
623   /// Construct set
624   SetLit(const Location& loc, IntSetVal* isv);
625   /// Construct set
626   SetLit(const Location& loc, FloatSetVal* fsv);
627   /// Access value
v() const628   ASTExprVec<Expression> v() const { return _v; }
629   /// Set value
v(const ASTExprVec<Expression> & val)630   void v(const ASTExprVec<Expression>& val) { _v = val; }
631   /// Access integer set value if present
isv() const632   IntSetVal* isv() const {
633     return (type().bt() == Type::BT_INT || type().bt() == Type::BT_BOOL) ? _u.isv : nullptr;
634   }
635   /// Set integer set value
isv(IntSetVal * val)636   void isv(IntSetVal* val) { _u.isv = val; }
637   /// Access float set value if present
fsv() const638   FloatSetVal* fsv() const { return type().bt() == Type::BT_FLOAT ? _u.fsv : nullptr; }
639   /// Set integer set value
fsv(FloatSetVal * val)640   void fsv(FloatSetVal* val) { _u.fsv = val; }
641   /// Recompute hash value
642   void rehash();
643 };
644 /// \brief Boolean literal expression
645 class BoolLit : public Expression {
646 protected:
647   /// The value of this expression
648   bool _v;
649 
650 public:
651   /// The identifier of this expression type
652   static const ExpressionId eid = E_BOOLLIT;
653   /// Constructor
654   BoolLit(const Location& loc, bool v);
655   /// Access value
v() const656   bool v() const { return _v; }
657   /// Recompute hash value
658   void rehash();
659 };
660 /// \brief String literal expression
661 class StringLit : public Expression {
662 protected:
663   /// The value of this expression
664   ASTString _v;
665 
666 public:
667   /// The identifier of this expression type
668   static const ExpressionId eid = E_STRINGLIT;
669   /// Constructor
670   StringLit(const Location& loc, const std::string& v);
671   /// Constructor
672   StringLit(const Location& loc, const ASTString& v);
673   /// Access value
v() const674   ASTString v() const { return _v; }
675   /// Set value
v(const ASTString & val)676   void v(const ASTString& val) { _v = val; }
677   /// Recompute hash value
678   void rehash();
679 };
680 /// \brief Identifier expression
681 class Id : public Expression {
682 protected:
683   /// The string identifier
684   union {
685     /// Identifier of called predicate or function
686     ASTString val;
687     /// The predicate or function declaration (or NULL)
688     void* idn;
689   } _vOrIdn = {nullptr};
690   /// The declaration corresponding to this identifier (may be NULL)
691   Expression* _decl;
692 
693 public:
694   /// The identifier of this expression type
695   static const ExpressionId eid = E_ID;
696   /// Constructor (\a decl may be NULL)
697   Id(const Location& loc, const std::string& v, VarDecl* decl);
698   /// Constructor (\a decl may be NULL)
699   Id(const Location& loc, const ASTString& v, VarDecl* decl);
700   /// Constructor (\a decl may be NULL)
701   Id(const Location& loc, long long int idn, VarDecl* decl);
702   /// Access identifier
703   ASTString v() const;
hasStr() const704   inline bool hasStr() const {
705     return (reinterpret_cast<ptrdiff_t>(_vOrIdn.idn) & static_cast<ptrdiff_t>(1)) == 0;
706   }
707   /// Set identifier
v(const ASTString & val)708   void v(const ASTString& val) { _vOrIdn.val = val; }
709   /// Access identifier number
710   long long int idn() const;
711   /// Set identifier number
idn(long long int n)712   void idn(long long int n) {
713     _vOrIdn.idn =
714         reinterpret_cast<void*>((static_cast<ptrdiff_t>(n) << 1) | static_cast<ptrdiff_t>(1));
715     rehash();
716   }
717   /// Return identifier or X_INTRODUCED plus identifier number
718   ASTString str() const;
719   /// Access declaration
decl() const720   VarDecl* decl() const {
721     Expression* d = _decl;
722     while ((d != nullptr) && d->isa<Id>()) {
723       d = d->cast<Id>()->_decl;
724     }
725     return Expression::cast<VarDecl>(d);
726   }
727   /// Set declaration
728   void decl(VarDecl* d);
729   /// Redirect to another Id \a id
redirect(Id * id)730   void redirect(Id* id) {
731     assert(_decl == nullptr || _decl->isa<VarDecl>());
732     _decl = id;
733   }
734   /// Recompute hash value
735   void rehash();
736   /// Levenshtein distance to \a other identifier
737   int levenshteinDistance(Id* other) const;
738 };
739 /// \brief Type-inst identifier expression
740 class TIId : public Expression {
741 protected:
742   /// The string identifier
743   ASTString _v;
744 
745 public:
746   /// The identifier of this expression type
747   static const ExpressionId eid = E_TIID;
748   /// Constructor
749   TIId(const Location& loc, const std::string& v);
750   /// Constructor
751   TIId(const Location& loc, const ASTString& v);
752   /// Access identifier
v() const753   ASTString v() const { return _v; }
754   /// Set identifier
v(const ASTString & val)755   void v(const ASTString& val) { _v = val; }
756   /// Check whether it is an enum identifier (starting with two $ signs)
isEnum() const757   bool isEnum() const { return _v.c_str()[0] == '$'; }
758   /// Recompute hash value
759   void rehash();
760 };
761 /// \brief Anonymous variable expression
762 class AnonVar : public Expression {
763 public:
764   /// The identifier of this expression type
765   static const ExpressionId eid = E_ANON;
766   /// Constructor
767   AnonVar(const Location& loc);
768   /// Recompute hash value
769   void rehash();
770 };
771 /// \brief Array literal expression
772 class ArrayLit : public Expression {
773   friend class Expression;
774 
775 protected:
776   /// The array
777   union {
778     /// An expression vector (if _flag2==false)
779     ASTExprVecO<Expression*>* v;
780     /// Another array literal (if _flag2==true)
781     ArrayLit* al;
782   } _u;
783   /// The declared array dimensions
784   // If _flag2 is true, then this is an array view. In that case,
785   // the _dims array holds the sliced dimensions
786   ASTIntVec _dims;
787   /// Set compressed vector (initial repetitions are removed)
788   void compress(const std::vector<Expression*>& v, const std::vector<int>& dims);
789 
790 public:
791   /// Index conversion from slice to original
792   unsigned int origIdx(unsigned int i) const;
793   /// Get element \a i of a sliced array
794   Expression* getSlice(unsigned int i) const;
795   /// Set element \a i of a sliced array
796   void setSlice(unsigned int i, Expression* e);
797 
798   /// The identifier of this expression type
799   static const ExpressionId eid = E_ARRAYLIT;
800   /// Constructor
801   ArrayLit(const Location& loc, const std::vector<Expression*>& v,
802            const std::vector<std::pair<int, int> >& dims);
803   /// Constructor (existing content)
804   ArrayLit(const Location& loc, ArrayLit& v, const std::vector<std::pair<int, int> >& dims);
805   /// Constructor (one-dimensional, existing content)
806   ArrayLit(const Location& loc, ArrayLit& v);
807   /// Constructor (one-dimensional)
808   ArrayLit(const Location& loc, const std::vector<Expression*>& v);
809   /// Constructor (two-dimensional)
810   ArrayLit(const Location& loc, const std::vector<std::vector<Expression*> >& v);
811   /// Constructor for slices
812   ArrayLit(const Location& loc, ArrayLit* v, const std::vector<std::pair<int, int> >& dims,
813            const std::vector<std::pair<int, int> >& slice);
814   /// Constructor (one-dimensional)
815   ArrayLit(const Location& loc, const std::vector<KeepAlive>& v);
816   /// Recompute hash value
817   void rehash();
818 
819   // The following methods are only used for copying
820 
821   /// Access value
getVec() const822   ASTExprVec<Expression> getVec() const {
823     assert(!_flag2);
824     return _u.v;
825   }
826   /// Set value
setVec(const ASTExprVec<Expression> & val)827   void setVec(const ASTExprVec<Expression>& val) {
828     assert(!_flag2);
829     _u.v = val.vec();
830   }
831   /// Get underlying array (if this is an array slice) or NULL
getSliceLiteral() const832   ArrayLit* getSliceLiteral() const { return _flag2 ? _u.al : nullptr; }
833   /// Get underlying _dims vector
dimsInternal() const834   ASTIntVec dimsInternal() const { return _dims; }
835 
836   /// Return number of dimensions
837   unsigned int dims() const;
838   /// Return minimum index of dimension \a i
839   int min(unsigned int i) const;
840   /// Return maximum index of dimension \a i
841   int max(unsigned int i) const;
842   /// Return the length of the array
843   unsigned int length() const;
844   /// Turn into 1d array (only used at the end of flattening)
845   void make1d();
846   /// Check if this array was produced by flattening
flat() const847   bool flat() const { return _flag1; }
848   /// Set whether this array was produced by flattening
flat(bool b)849   void flat(bool b) { _flag1 = b; }
850   /// Return size of underlying array
size() const851   unsigned int size() const { return (_flag2 || _u.v->flag()) ? length() : _u.v->size(); }
852   /// Access element \a i
operator [](unsigned int i) const853   Expression* operator[](unsigned int i) const {
854     return (_flag2 || _u.v->flag()) ? getSlice(i) : (*_u.v)[i];
855   }
856   /// Set element \a i
set(unsigned int i,Expression * e)857   void set(unsigned int i, Expression* e) {
858     if (_flag2 || _u.v->flag()) {
859       setSlice(i, e);
860     } else {
861       (*_u.v)[i] = e;
862     }
863   }
864 };
865 /// \brief Array access expression
866 class ArrayAccess : public Expression {
867 protected:
868   /// The array to access
869   Expression* _v;
870   /// The indexes (for all array dimensions)
871   ASTExprVec<Expression> _idx;
872 
873 public:
874   /// The identifier of this expression type
875   static const ExpressionId eid = E_ARRAYACCESS;
876   /// Constructor
877   ArrayAccess(const Location& loc, Expression* v, const std::vector<Expression*>& idx);
878   /// Constructor
879   ArrayAccess(const Location& loc, Expression* v, const ASTExprVec<Expression>& idx);
880   /// Access value
v() const881   Expression* v() const { return _v; }
882   /// Set value
v(Expression * val)883   void v(Expression* val) { _v = val; }
884   /// Access index sets
idx() const885   ASTExprVec<Expression> idx() const { return _idx; }
886   /// Set index sets
idx(const ASTExprVec<Expression> & idx)887   void idx(const ASTExprVec<Expression>& idx) { _idx = idx; }
888   /// Recompute hash value
889   void rehash();
890 };
891 /**
892  * \brief Generators for comprehensions
893  *
894  * A generator consists of a list of variable declarations, one for
895  * each generated variable, and the expression to generate. E.g.,
896  * the Zinc expression [ x[i,j,k] | i,j in 1..10, k in 1..5] contains
897  * two generators. The first one has variable declarations for i and j
898  * and the expression 1..10, and the second one has a variable declaration
899  * for k and the expression 1..5.
900  *
901  */
902 class Generator {
903   friend class Comprehension;
904 
905 protected:
906   /// Variable declarations
907   std::vector<VarDecl*> _v;
908   /// in-expression
909   Expression* _in;
910   /// where-expression
911   Expression* _where;
912 
913 public:
914   /// Allocate
915   Generator(const std::vector<std::string>& v, Expression* in, Expression* where);
916   /// Allocate
917   Generator(const std::vector<ASTString>& v, Expression* in, Expression* where);
918   /// Allocate
919   Generator(const std::vector<Id*>& v, Expression* in, Expression* where);
920   /// Allocate
921   Generator(const std::vector<VarDecl*>& v, Expression* in, Expression* where);
922   /// Allocate single where clause (without generator) at position \a pos
923   Generator(int pos, Expression* where);
924 };
925 /// \brief A list of generators with one where-expression
926 struct Generators {
927   /// %Generators
928   std::vector<Generator> g;
929   /// Constructor
GeneratorsMiniZinc::Generators930   Generators() {}
931 };
932 /// \brief An expression representing an array- or set-comprehension
933 class Comprehension : public Expression {
934   friend class Expression;
935 
936 protected:
937   /// The expression to generate
938   Expression* _e;
939   /// A list of generator expressions
940   ASTExprVec<Expression> _g;
941   /// A list of indices where generators start
942   ASTIntVec _gIndex;
943 
944 public:
945   /// The identifier of this expression type
946   static const ExpressionId eid = E_COMP;
947   /// Constructor
948   Comprehension(const Location& loc, Expression* e, Generators& g, bool set);
949   /// Recompute hash value
950   void rehash();
951   /// Whether comprehension is a set
952   bool set() const;
953 
954   /// Return number of generators
955   unsigned int numberOfGenerators() const;
956   /// Return "in" expression for generator \a i
957   Expression* in(unsigned int i);
958   /// Return "in" expression for generator \a i
959   const Expression* in(unsigned int i) const;
960   /// Return number of declarations for generator \a i
961   unsigned int numberOfDecls(unsigned int i) const;
962   /// Return declaration \a i for generator \a gen
963   VarDecl* decl(unsigned int gen, unsigned int i);
964   /// Return declaration \a i for generator \a gen
965   const VarDecl* decl(unsigned int gen, unsigned int i) const;
966   /// Return where clause for generator \a i
967   Expression* where(unsigned int i);
968   /// Return where clause for generator \a i
969   const Expression* where(unsigned int i) const;
970   /// Return generator body
e() const971   Expression* e() const { return _e; }
972   /// Set generator body
e(Expression * e0)973   void e(Expression* e0) { _e = e0; }
974   /// Re-construct (used for copying)
975   void init(Expression* e, Generators& g);
976   /// Check if \a e contains one of the variables bound by this comprehension
977   bool containsBoundVariable(Expression* e);
978 };
979 /// \brief If-then-else expression
980 class ITE : public Expression {
981   friend class Expression;
982 
983 protected:
984   /// List of if-then-pairs
985   ASTExprVec<Expression> _eIfThen;
986   /// Else-expression
987   Expression* _eElse;
988 
989 public:
990   /// The identifier of this expression type
991   static const ExpressionId eid = E_ITE;
992   /// Constructor
993   ITE(const Location& loc, const std::vector<Expression*>& e_if_then, Expression* e_else);
size() const994   unsigned int size() const { return static_cast<int>(_eIfThen.size() / 2); }
ifExpr(unsigned int i)995   Expression* ifExpr(unsigned int i) { return _eIfThen[2 * i]; }
thenExpr(unsigned int i)996   Expression* thenExpr(unsigned int i) { return _eIfThen[2 * i + 1]; }
elseExpr()997   Expression* elseExpr() { return _eElse; }
ifExpr(unsigned int i) const998   const Expression* ifExpr(unsigned int i) const { return _eIfThen[2 * i]; }
thenExpr(unsigned int i) const999   const Expression* thenExpr(unsigned int i) const { return _eIfThen[2 * i + 1]; }
elseExpr() const1000   const Expression* elseExpr() const { return _eElse; }
thenExpr(unsigned int i,Expression * e)1001   void thenExpr(unsigned int i, Expression* e) { _eIfThen[2 * i + 1] = e; }
elseExpr(Expression * e)1002   void elseExpr(Expression* e) { _eElse = e; }
1003   /// Recompute hash value
1004   void rehash();
1005   /// Re-construct (used for copying)
1006   void init(const std::vector<Expression*>& e_if_then, Expression* e_else);
1007 };
1008 
1009 /// Type of binary operators
1010 enum BinOpType {
1011   BOT_PLUS,
1012   BOT_MINUS,
1013   BOT_MULT,
1014   BOT_DIV,
1015   BOT_IDIV,
1016   BOT_MOD,
1017   BOT_POW,
1018   BOT_LE,
1019   BOT_LQ,
1020   BOT_GR,
1021   BOT_GQ,
1022   BOT_EQ,
1023   BOT_NQ,
1024   BOT_IN,
1025   BOT_SUBSET,
1026   BOT_SUPERSET,
1027   BOT_UNION,
1028   BOT_DIFF,
1029   BOT_SYMDIFF,
1030   BOT_INTERSECT,
1031   BOT_PLUSPLUS,
1032   BOT_EQUIV,
1033   BOT_IMPL,
1034   BOT_RIMPL,
1035   BOT_OR,
1036   BOT_AND,
1037   BOT_XOR,
1038   BOT_DOTDOT
1039 };
1040 /// \brief Binary-operator expression
1041 class BinOp : public Expression {
1042 protected:
1043   /// Left hand side expression
1044   Expression* _e0;
1045   /// Right hand side expression
1046   Expression* _e1;
1047   /// The predicate or function declaration (or NULL)
1048   FunctionI* _decl;
1049 
1050 public:
1051   /// The identifier of this expression type
1052   static const ExpressionId eid = E_BINOP;
1053   /// Constructor
1054   BinOp(const Location& loc, Expression* e0, BinOpType op, Expression* e1);
1055   /// Access left hand side
lhs() const1056   Expression* lhs() const { return _e0; }
1057   /// Set left hand side
lhs(Expression * e)1058   void lhs(Expression* e) { _e0 = e; }
1059   /// Access right hand side
rhs() const1060   Expression* rhs() const { return _e1; }
1061   /// Set right hand side
rhs(Expression * e)1062   void rhs(Expression* e) { _e1 = e; }
1063   /// Access argument \a i
arg(int i)1064   Expression* arg(int i) {
1065     assert(i == 0 || i == 1);
1066     return i == 0 ? _e0 : _e1;
1067   }
1068   /// Return number of arguments
argCount()1069   static unsigned int argCount() { return 2; }
1070   /// Access declaration
decl() const1071   FunctionI* decl() const { return _decl; }
1072   /// Set declaration
decl(FunctionI * f)1073   void decl(FunctionI* f) { _decl = f; }
1074   /// Return string representation of the operator
1075   ASTString opToString() const;
1076   /// Recompute hash value
1077   void rehash();
1078   /// Return operator type
1079   BinOpType op() const;
1080   /// Morph into a call
1081   Call* morph(const ASTString& ident, const std::vector<Expression*>& args);
1082 };
1083 
1084 /// Type of unary operators
1085 enum UnOpType { UOT_NOT, UOT_PLUS, UOT_MINUS };
1086 /// \brief Unary-operator expressions
1087 class UnOp : public Expression {
1088 protected:
1089   /// %Expression
1090   Expression* _e0;
1091   /// The predicate or function declaration (or NULL)
1092   FunctionI* _decl;
1093 
1094 public:
1095   /// The identifier of this expression type
1096   static const ExpressionId eid = E_UNOP;
1097   /// Constructor
1098   UnOp(const Location& loc, UnOpType op, Expression* e);
1099   /// Access expression
e() const1100   Expression* e() const { return _e0; }
1101   /// Set expression
e(Expression * e0)1102   void e(Expression* e0) { _e0 = e0; }
1103   /// Access argument \a i
arg(int i)1104   Expression* arg(int i) {
1105     assert(i == 0);
1106     return _e0;
1107   }
1108   /// Return number of arguments
argCount()1109   static unsigned int argCount() { return 1; }
1110   /// Access declaration
decl() const1111   FunctionI* decl() const { return _decl; }
1112   /// Set declaration
decl(FunctionI * f)1113   void decl(FunctionI* f) { _decl = f; }
1114   ASTString opToString() const;
1115   /// Recompute hash value
1116   void rehash();
1117   /// Return operator type
1118   UnOpType op() const;
1119 };
1120 
1121 /// \brief A predicate or function call expression
1122 class Call : public Expression {
1123   friend class Expression;
1124 
1125 protected:
1126   union {
1127     /// Identifier of called predicate or function
1128     ASTString id;
1129     /// The predicate or function declaration (or NULL)
1130     FunctionI* decl;
1131   } _uId = {nullptr};
1132   union {
1133     /// Single-argument call (tagged pointer)
1134     Expression* oneArg;
1135     /// Arguments to the call
1136     ASTExprVecO<Expression*>* args;
1137   } _u;
1138   /// Check if _uId contains an id or a decl
1139   bool hasId() const;
1140 
1141 public:
1142   /// The identifier of this expression type
1143   static const ExpressionId eid = E_CALL;
1144   /// Constructor
1145   Call(const Location& loc, const std::string& id, const std::vector<Expression*>& args);
1146   /// Constructor
1147   Call(const Location& loc, const ASTString& id, const std::vector<Expression*>& args);
1148   /// Access identifier
1149   ASTString id() const;
1150   /// Set identifier (overwrites decl)
1151   void id(const ASTString& i);
1152   /// Number of arguments
argCount() const1153   unsigned int argCount() const {
1154     return _u.oneArg->isUnboxedVal() || _u.oneArg->isTagged() ? 1 : _u.args->size();
1155   }
1156   /// Access argument \a i
arg(unsigned int i) const1157   Expression* arg(unsigned int i) const {
1158     assert(i < argCount());
1159     if (_u.oneArg->isUnboxedVal() || _u.oneArg->isTagged()) {
1160       assert(i == 0U);
1161       return _u.oneArg->isUnboxedVal() ? _u.oneArg : _u.oneArg->untag();
1162     }
1163     return (*_u.args)[i];
1164   }
1165   /// Set argument \a i
arg(unsigned int i,Expression * e)1166   void arg(unsigned int i, Expression* e) {
1167     assert(i < argCount());
1168     if (_u.oneArg->isUnboxedVal() || _u.oneArg->isTagged()) {
1169       assert(i == 0U);
1170       _u.oneArg = e->isUnboxedVal() ? e : e->tag();
1171     } else {
1172       (*_u.args)[i] = e;
1173     }
1174   }
1175   /// Set arguments
args(const ASTExprVec<Expression> & a)1176   void args(const ASTExprVec<Expression>& a) {
1177     if (a.size() == 1) {
1178       _u.oneArg = a[0]->isUnboxedVal() ? a[0] : a[0]->tag();
1179     } else {
1180       _u.args = a.vec();
1181       assert(!_u.oneArg->isTagged());
1182     }
1183   }
1184   /// Access declaration
1185   FunctionI* decl() const;
1186   /// Set declaration (overwrites id)
1187   void decl(FunctionI* f);
1188   /// Recompute hash value
1189   void rehash();
1190 };
1191 /// \brief A variable declaration expression
1192 class VarDecl : public Expression {
1193 protected:
1194   /// Type-inst of the declared variable
1195   TypeInst* _ti;
1196   /// Identifier
1197   Id* _id;
1198   /// Initialisation expression (can be NULL)
1199   Expression* _e;
1200   /// Flattened version of the VarDecl
1201   WeakRef _flat;
1202   /// Integer payload
1203   int _payload;
1204 
1205 public:
1206   /// The identifier of this expression type
1207   static const ExpressionId eid = E_VARDECL;
1208   /// Constructor
1209   VarDecl(const Location& loc, TypeInst* ti, const std::string& id, Expression* e = nullptr);
1210   /// Constructor
1211   VarDecl(const Location& loc, TypeInst* ti, const ASTString& id, Expression* e = nullptr);
1212   /// Constructor
1213   VarDecl(const Location& loc, TypeInst* ti, long long int idn, Expression* e = nullptr);
1214   /// Constructor
1215   VarDecl(const Location& loc, TypeInst* ti, Id* id, Expression* e = nullptr);
1216 
1217   /// Access TypeInst
ti() const1218   TypeInst* ti() const { return _ti; }
1219   /// Set TypeInst
ti(TypeInst * t)1220   void ti(TypeInst* t) { _ti = t; }
1221   /// Access identifier
id() const1222   Id* id() const { return _id; }
1223   /// Access initialisation expression
1224   Expression* e() const;
1225   /// Set initialisation expression
1226   void e(Expression* rhs);
1227   /// Access flattened version
flat()1228   VarDecl* flat() { return _flat() != nullptr ? _flat()->cast<VarDecl>() : nullptr; }
1229   /// Set flattened version
1230   void flat(VarDecl* vd);
1231 
1232   /// Recompute hash value
1233   void rehash();
1234   /// Whether variable is toplevel
1235   bool toplevel() const;
1236   /// Whether variable is toplevel
1237   void toplevel(bool t);
1238   /// Whether variable is introduced
1239   bool introduced() const;
1240   /// Whether variable is introduced
1241   void introduced(bool t);
1242   /// Whether variable has been evaluated
1243   bool evaluated() const;
1244   /// Whether variable has been evaluated
1245   void evaluated(bool t);
1246   /// Access payload
payload() const1247   int payload() const { return _payload; }
1248   /// Set payload
payload(int i)1249   void payload(int i) { _payload = i; }
1250   /// Put current value on trail
1251   void trail();
1252 };
1253 
1254 class EnvI;
1255 class CopyMap;
1256 
1257 /// \brief %Let expression
1258 class Let : public Expression {
1259   friend Expression* copy(EnvI& env, CopyMap& m, Expression* e, bool followIds, bool copyFundecls,
1260                           bool isFlatModel);
1261   friend class Expression;
1262 
1263 protected:
1264   /// List of local declarations
1265   ASTExprVec<Expression> _let;
1266   /// Copy of original local declarations
1267   ASTExprVec<Expression> _letOrig;
1268   /// Body of the let
1269   Expression* _in;
1270 
1271 public:
1272   /// The identifier of this expression type
1273   static const ExpressionId eid = E_LET;
1274   /// Constructor
1275   Let(const Location& loc, const std::vector<Expression*>& let, Expression* in);
1276   /// Recompute hash value
1277   void rehash();
1278 
1279   /// Access local declarations
let() const1280   ASTExprVec<Expression> let() const { return _let; }
1281   /// Access local declarations
letOrig() const1282   ASTExprVec<Expression> letOrig() const { return _letOrig; }
1283   /// Access body
in() const1284   Expression* in() const { return _in; }
1285 
1286   /// Remember current let bindings
1287   void pushbindings();
1288   /// Restore previous let bindings
1289   void popbindings();
1290 };
1291 
1292 /// \brief Type-inst expression
1293 class TypeInst : public Expression {
1294 protected:
1295   /// Ranges of an array expression
1296   ASTExprVec<TypeInst> _ranges;
1297   /// Declared domain (or NULL)
1298   Expression* _domain;
1299 
1300 public:
1301   /// The identifier of this expression type
1302   static const ExpressionId eid = E_TI;
1303   /// Constructor
1304   TypeInst(const Location& loc, const Type& t, const ASTExprVec<TypeInst>& ranges,
1305            Expression* domain = nullptr);
1306   /// Constructor
1307   TypeInst(const Location& loc, const Type& t, Expression* domain = nullptr);
1308 
1309   /// Access ranges
ranges() const1310   ASTExprVec<TypeInst> ranges() const { return _ranges; }
1311   /// Access domain
domain() const1312   Expression* domain() const { return _domain; }
1313   //// Set domain
domain(Expression * d)1314   void domain(Expression* d) { _domain = d; }
1315 
1316   /// Set ranges to \a ranges
1317   void setRanges(const std::vector<TypeInst*>& ranges);
isarray() const1318   bool isarray() const { return _ranges.size() > 0; }
1319   bool hasTiVariable() const;
1320   /// Recompute hash value
1321   void rehash();
1322   /// Check if domain is computed from right hand side of variable
computedDomain() const1323   bool computedDomain() const { return _flag1; }
1324   /// Set if domain is computed from right hand side of variable
setComputedDomain(bool b)1325   void setComputedDomain(bool b) { _flag1 = b; }
1326   /// Check if this TypeInst represents an enum
isEnum() const1327   bool isEnum() const { return _flag2; }
1328   /// Set if this TypeInst represents an enum
setIsEnum(bool b)1329   void setIsEnum(bool b) { _flag2 = b; }
1330 };
1331 
1332 /**
1333  * \brief Base-class for items
1334  */
1335 class Item : public ASTNode {
1336 protected:
1337   /// Location of the item
1338   Location _loc;
1339 
1340 public:
1341   /// Identifier of the concrete item type
1342   enum ItemId {
1343     II_INC = Expression::EID_END + 1,
1344     II_VD,
1345     II_ASN,
1346     II_CON,
1347     II_SOL,
1348     II_OUT,
1349     II_FUN,
1350     II_END = II_FUN
1351   };
iid() const1352   ItemId iid() const { return static_cast<ItemId>(_id); }
1353 
loc() const1354   const Location& loc() const { return _loc; }
1355 
1356 protected:
1357   /// Constructor
Item(const Location & loc,const ItemId & iid)1358   Item(const Location& loc, const ItemId& iid) : ASTNode(iid), _loc(loc) { _flag1 = false; }
1359 
1360 public:
1361   /// Test if item is of type \a T
1362   template <class T>
isa() const1363   bool isa() const {
1364     return _id == T::iid;
1365   }
1366   /// Cast item to type \a T*
1367   template <class T>
cast()1368   T* cast() {
1369     assert(isa<T>());
1370     return static_cast<T*>(this);
1371   }
1372   /// Cast expression to type \a const T*
1373   template <class T>
cast() const1374   const T* cast() const {
1375     assert(isa<T>());
1376     return static_cast<const T*>(this);
1377   }
1378   /// Cast item to type \a T* or NULL if types do not match
1379   template <class T>
dynamicCast()1380   T* dynamicCast() {
1381     return isa<T>() ? static_cast<T*>(this) : nullptr;
1382   }
1383   /// Cast item to type \a const T* or NULL if types do not match
1384   template <class T>
dynamicCast() const1385   const T* dynamicCast() const {
1386     return isa<T>() ? static_cast<const T*>(this) : NULL;
1387   }
1388 
1389   /// Cast item to type \a T*
1390   template <class T>
cast(Item * i)1391   static T* cast(Item* i) {
1392     return i == nullptr ? nullptr : i->cast<T>();
1393   }
1394   /// Cast item to type \a const T*
1395   template <class T>
cast(const Item * i)1396   static const T* cast(const Item* i) {
1397     return i == nullptr ? NULL : i->cast<T>();
1398   }
1399   /// Cast item to type \a T* or NULL if types do not match
1400   template <class T>
dynamicCast(Item * i)1401   static T* dynamicCast(Item* i) {
1402     return i == nullptr ? nullptr : i->dynamicCast<T>();
1403   }
1404   /// Cast item to type \a const T* or NULL if types do not match
1405   template <class T>
dynamicCast(const Item * i)1406   static const T* dynamicCast(const Item* i) {
1407     return i == nullptr ? NULL : i->dynamicCast<T>();
1408   }
1409 
1410   /// Check if item should be removed
removed() const1411   bool removed() const { return _flag1; }
1412   /// Set flag to remove item
remove()1413   void remove() { _flag1 = true; }
1414   /// Unset remove item flag (only possible if not already removed by compact())
unremove()1415   void unremove() { _flag1 = false; }
1416 
1417   /// Mark alive for garbage collection
1418 #if defined(MINIZINC_GC_STATS)
1419   static void mark(Item* item, MINIZINC_GC_STAT_ARGS);
1420 #else
1421   static void mark(Item* item);
1422 #endif
hasMark()1423   bool hasMark() { return _gcMark != 0U; }
1424 };
1425 
1426 class Model;
1427 
1428 /// \brief Include item
1429 class IncludeI : public Item {
1430 protected:
1431   /// Filename to include
1432   ASTString _f;
1433   /// Model for that file
1434   Model* _m;
1435 
1436 public:
1437   /// The identifier of this item type
1438   static const ItemId iid = II_INC;
1439   /// Constructor
1440   IncludeI(const Location& loc, const ASTString& f);
1441   /// Access filename
f() const1442   ASTString f() const { return _f; }
1443   /// Set filename
f(const ASTString & nf)1444   void f(const ASTString& nf) { _f = nf; }
1445   /// Access model
m() const1446   Model* m() const { return _m; }
1447   /// Set the model
m(Model * m0,bool own=true)1448   void m(Model* m0, bool own = true) {
1449     assert(_m == nullptr || m0 == nullptr);
1450     _m = m0;
1451     _flag2 = own;
1452   }
own() const1453   bool own() const { return _flag2; }
1454 };
1455 
1456 /// \brief Variable declaration item
1457 class VarDeclI : public Item {
1458 protected:
1459   /// The declaration expression
1460   VarDecl* _e;
1461 
1462 public:
1463   /// The identifier of this item type
1464   static const ItemId iid = II_VD;
1465   /// Constructor
1466   VarDeclI(const Location& loc, VarDecl* e);
1467   /// Access expression
e() const1468   VarDecl* e() const { return _e; }
1469   /// Set expression
e(VarDecl * vd)1470   void e(VarDecl* vd) { _e = vd; }
1471   /// Flag used during compilation
flag() const1472   bool flag() const { return _flag2; }
1473   /// Set flag used during compilation
flag(bool b)1474   void flag(bool b) { _flag2 = b; }
1475 };
1476 
1477 /// \brief Assign item
1478 class AssignI : public Item {
1479 protected:
1480   /// Identifier of variable to assign to
1481   ASTString _id;
1482   /// Expression to assign to the variable
1483   Expression* _e;
1484   /// Declaration of the variable to assign to
1485   VarDecl* _decl;
1486 
1487 public:
1488   /// The identifier of this item type
1489   static const ItemId iid = II_ASN;
1490   /// Constructor
1491   AssignI(const Location& loc, const std::string& id, Expression* e);
1492   /// Constructor
1493   AssignI(const Location& loc, const ASTString& id, Expression* e);
1494   /// Access identifier
id() const1495   ASTString id() const { return _id; }
1496   /// Access expression
e() const1497   Expression* e() const { return _e; }
1498   /// Set expression
e(Expression * e0)1499   void e(Expression* e0) { _e = e0; }
1500   /// Access declaration
decl() const1501   VarDecl* decl() const { return _decl; }
1502   /// Set declaration
decl(VarDecl * d)1503   void decl(VarDecl* d) { _decl = d; }
1504 };
1505 
1506 /// \brief Constraint item
1507 class ConstraintI : public Item {
1508 protected:
1509   /// Constraint expression
1510   Expression* _e;
1511 
1512 public:
1513   /// The identifier of this item type
1514   static const ItemId iid = II_CON;
1515   /// Constructor
1516   ConstraintI(const Location& loc, Expression* e);
1517   /// Access expression
e() const1518   Expression* e() const { return _e; }
1519   /// Set expression
e(Expression * e0)1520   void e(Expression* e0) { _e = e0; }
1521   /// Flag used during compilation
flag() const1522   bool flag() const { return _flag2; }
1523   /// Set flag used during compilation
flag(bool b)1524   void flag(bool b) { _flag2 = b; }
1525 };
1526 
1527 /// \brief Solve item
1528 class SolveI : public Item {
1529 protected:
1530   /// Solve item annotation
1531   Annotation _ann;
1532   /// Expression for minimisation/maximisation (or NULL)
1533   Expression* _e;
1534   /// Constructor
1535   SolveI(const Location& loc, Expression* e);
1536 
1537 public:
1538   /// The identifier of this item type
1539   static const ItemId iid = II_SOL;
1540   /// Type of solving
1541   enum SolveType { ST_SAT, ST_MIN, ST_MAX };
1542   /// Allocate solve satisfy item
1543   static SolveI* sat(const Location& loc);
1544   /// Allocate solve minimize item
1545   static SolveI* min(const Location& loc, Expression* e);
1546   /// Allocate solve maximize item
1547   static SolveI* max(const Location& loc, Expression* e);
1548   /// Access solve annotation
ann() const1549   const Annotation& ann() const { return _ann; }
1550   /// Access solve annotation
ann()1551   Annotation& ann() { return _ann; }
1552   /// Access expression for optimisation
e() const1553   Expression* e() const { return _e; }
1554   /// Set expression for optimisation
e(Expression * e0)1555   void e(Expression* e0) { _e = e0; }
1556   /// Return type of solving
1557   SolveType st() const;
1558   /// Set type of solving
1559   void st(SolveType s);
1560 };
1561 
1562 /// \brief Output item
1563 class OutputI : public Item {
1564 protected:
1565   /// Expression to output
1566   Expression* _e;
1567 
1568 public:
1569   /// The identifier of this item type
1570   static const ItemId iid = II_OUT;
1571   /// Constructor
1572   OutputI(const Location& loc, Expression* e);
1573   /// Access expression
e() const1574   Expression* e() const { return _e; }
1575   /// Update expression
e(Expression * e)1576   void e(Expression* e) { _e = e; }
1577 };
1578 
1579 class EnvI;
1580 
1581 /// \brief Function declaration item
1582 class FunctionI : public Item {
1583 protected:
1584   /// Identifier of this function
1585   ASTString _id;
1586   /// Type-inst of the return value
1587   TypeInst* _ti;
1588   /// List of parameter declarations
1589   ASTExprVec<VarDecl> _params;
1590   /// Annotation
1591   Annotation _ann;
1592   /// Function body (or NULL)
1593   Expression* _e;
1594   /// Whether function is defined in the standard library
1595   bool _fromStdLib;
1596 
1597 public:
1598   /// The identifier of this item type
1599   static const ItemId iid = II_FUN;
1600 
1601   /// Type of builtin expression-valued functions
1602   typedef Expression* (*builtin_e)(EnvI&, Call*);
1603   /// Type of builtin int-valued functions
1604   typedef IntVal (*builtin_i)(EnvI&, Call*);
1605   /// Type of builtin bool-valued functions
1606   typedef bool (*builtin_b)(EnvI&, Call*);
1607   /// Type of builtin float-valued functions
1608   typedef FloatVal (*builtin_f)(EnvI&, Call*);
1609   /// Type of builtin set-valued functions
1610   typedef IntSetVal* (*builtin_s)(EnvI&, Call*);
1611   /// Type of builtin string-valued functions
1612   typedef std::string (*builtin_str)(EnvI&, Call*);
1613 
1614   /// Builtin functions (or NULL)
1615   struct {
1616     builtin_e e;
1617     builtin_i i;
1618     builtin_f f;
1619     builtin_b b;
1620     builtin_s s;
1621     builtin_str str;
1622   } builtins;
1623 
1624   /// Constructor
1625   FunctionI(const Location& loc, const std::string& id, TypeInst* ti,
1626             const std::vector<VarDecl*>& params, Expression* e = nullptr, bool from_stdlib = false);
1627   /// Constructor
1628   FunctionI(const Location& loc, const ASTString& id, TypeInst* ti,
1629             const ASTExprVec<VarDecl>& params, Expression* e = nullptr, bool from_stdlib = false);
1630 
1631   /// Access identifier
id() const1632   ASTString id() const { return _id; }
1633   /// Access TypeInst
ti() const1634   TypeInst* ti() const { return _ti; }
1635   /// Access parameters
params() const1636   ASTExprVec<VarDecl> params() const { return _params; }
1637   /// Access annotation
ann() const1638   const Annotation& ann() const { return _ann; }
1639   /// Access annotation
ann()1640   Annotation& ann() { return _ann; }
1641   /// Access body
e() const1642   Expression* e() const { return _e; }
1643   /// Set body
e(Expression * b)1644   void e(Expression* b) { _e = b; }
1645 
1646   /** \brief Compute return type given argument types \a ta
1647    */
1648   Type rtype(EnvI& env, const std::vector<Expression*>& ta, bool strictEnums);
1649   /** \brief Compute return type given argument types \a ta
1650    */
1651   Type rtype(EnvI& env, const std::vector<Type>& ta, bool strictEnums);
1652   /** \brief Compute expected type of argument \a n given argument types \a ta
1653    */
1654   Type argtype(EnvI& env, const std::vector<Expression*>& ta, unsigned int n) const;
1655 
1656   /// Return whether function is defined in the standard library
fromStdLib() const1657   bool fromStdLib() const { return _fromStdLib; };
1658 };
1659 
1660 /**
1661  * \brief Visitor for expressions
1662  *
1663  * This class implements no-ops for all expression types.
1664  * Override the methods to implement custom behaviour.
1665  */
1666 class EVisitor {
1667 public:
1668   /// Visit integer literal
vIntLit(const IntLit &)1669   void vIntLit(const IntLit& /*il*/) {}
1670   /// Visit floating point literal
vFloatLit(const FloatLit &)1671   void vFloatLit(const FloatLit& /*fl*/) {}
1672   /// Visit Boolean literal
vBoolLit(const BoolLit &)1673   void vBoolLit(const BoolLit& /*bl*/) {}
1674   /// Visit set literal
vSetLit(const SetLit &)1675   void vSetLit(const SetLit& /*sl*/) {}
1676   /// Visit string literal
vStringLit(const StringLit &)1677   void vStringLit(const StringLit& /*sl*/) {}
1678   /// Visit identifier
vId(const Id &)1679   void vId(const Id& /*ident*/) {}
1680   /// Visit anonymous variable
vAnonVar(const AnonVar &)1681   void vAnonVar(const AnonVar& /*x*/) {}
1682   /// Visit array literal
vArrayLit(const ArrayLit &)1683   void vArrayLit(const ArrayLit& /*al*/) {}
1684   /// Visit array access
vArrayAccess(const ArrayAccess &)1685   void vArrayAccess(const ArrayAccess& /*aa*/) {}
1686   /// Visit array comprehension
vComprehension(const Comprehension &)1687   void vComprehension(const Comprehension& /*c*/) {}
1688   /// Visit array comprehension (only generator \a gen_i)
vComprehensionGenerator(const Comprehension &,int)1689   void vComprehensionGenerator(const Comprehension& /*c*/, int /*gen_i*/) {}
1690   /// Visit if-then-else
vITE(const ITE &)1691   void vITE(const ITE& /*ite*/) {}
1692   /// Visit binary operator
vBinOp(const BinOp &)1693   void vBinOp(const BinOp& /*bo*/) {}
1694   /// Visit unary operator
vUnOp(const UnOp &)1695   void vUnOp(const UnOp& /*uo*/) {}
1696   /// Visit call
vCall(const Call &)1697   void vCall(const Call& /*c*/) {}
1698   /// Visit let
vLet(const Let &)1699   void vLet(const Let& /*let*/) {}
1700   /// Visit variable declaration
vVarDecl(const VarDecl &)1701   void vVarDecl(const VarDecl& /*vd*/) {}
1702   /// Visit type inst
vTypeInst(const TypeInst &)1703   void vTypeInst(const TypeInst& /*ti*/) {}
1704   /// Visit TIId
vTIId(const TIId &)1705   void vTIId(const TIId& /*tiid*/) {}
1706   /// Determine whether to enter node
enter(Expression *)1707   static bool enter(Expression* /*e*/) { return true; }
1708   /// Exit node after processing has finished
exit(Expression *)1709   void exit(Expression* /*e*/) {}
1710 };
1711 
1712 /// Statically allocated constants
1713 class Constants : public GCMarker {
1714 public:
1715   /// Literal true
1716   BoolLit* literalTrue;
1717   /// Variable bound to true
1718   VarDecl* varTrue;
1719   /// Literal false
1720   BoolLit* literalFalse;
1721   /// Variable bound to false
1722   VarDecl* varFalse;
1723   /// Special variable to signal compiler to ignore result
1724   VarDecl* varIgnore;
1725   /// Infinite set
1726   SetLit* infinity;
1727   /// Function item used to keep track of redefined variables
1728   FunctionI* varRedef;
1729   /// Literal absent value
1730   Expression* absent;
1731   /// Identifiers for builtins
1732   struct {
1733     ASTString forall;
1734     ASTString forallReif;
1735     ASTString exists;
1736     ASTString clause;
1737     ASTString bool2int;
1738     ASTString int2float;
1739     ASTString bool2float;
1740     ASTString assert;
1741     ASTString mzn_deprecate;                     // NOLINT(readability-identifier-naming)
1742     ASTString mzn_symmetry_breaking_constraint;  // NOLINT(readability-identifier-naming)
1743     ASTString mzn_redundant_constraint;          // NOLINT(readability-identifier-naming)
1744     ASTString trace;
1745 
1746     ASTString sum;
1747     ASTString lin_exp;  // NOLINT(readability-identifier-naming)
1748     ASTString element;
1749 
1750     ASTString show;
1751     ASTString fix;
1752     ASTString output;
1753 
1754     struct {
1755       ASTString lin_eq;  // NOLINT(readability-identifier-naming)
1756       ASTString lin_le;  // NOLINT(readability-identifier-naming)
1757       ASTString lin_ne;  // NOLINT(readability-identifier-naming)
1758       ASTString plus;
1759       ASTString minus;
1760       ASTString times;
1761       ASTString div;
1762       ASTString mod;
1763       ASTString lt;
1764       ASTString le;
1765       ASTString gt;
1766       ASTString ge;
1767       ASTString eq;
1768       ASTString ne;
1769     } int_;  // NOLINT(readability-identifier-naming)
1770 
1771     struct {
1772       ASTString lin_eq;  // NOLINT(readability-identifier-naming)
1773       ASTString lin_le;  // NOLINT(readability-identifier-naming)
1774       ASTString lin_ne;  // NOLINT(readability-identifier-naming)
1775       ASTString plus;
1776       ASTString minus;
1777       ASTString times;
1778       ASTString div;
1779       ASTString mod;
1780       ASTString lt;
1781       ASTString le;
1782       ASTString gt;
1783       ASTString ge;
1784       ASTString eq;
1785       ASTString ne;
1786     } int_reif;  // NOLINT(readability-identifier-naming)
1787 
1788     struct {
1789       ASTString lin_eq;  // NOLINT(readability-identifier-naming)
1790       ASTString lin_le;  // NOLINT(readability-identifier-naming)
1791       ASTString lin_lt;  // NOLINT(readability-identifier-naming)
1792       ASTString lin_ne;  // NOLINT(readability-identifier-naming)
1793       ASTString plus;
1794       ASTString minus;
1795       ASTString times;
1796       ASTString div;
1797       ASTString mod;
1798       ASTString lt;
1799       ASTString le;
1800       ASTString gt;
1801       ASTString ge;
1802       ASTString eq;
1803       ASTString ne;
1804       ASTString in;
1805       ASTString dom;
1806     } float_;  // NOLINT(readability-identifier-naming)
1807 
1808     struct {
1809       ASTString lin_eq;  // NOLINT(readability-identifier-naming)
1810       ASTString lin_le;  // NOLINT(readability-identifier-naming)
1811       ASTString lin_lt;  // NOLINT(readability-identifier-naming)
1812       ASTString lin_ne;  // NOLINT(readability-identifier-naming)
1813       ASTString plus;
1814       ASTString minus;
1815       ASTString times;
1816       ASTString div;
1817       ASTString mod;
1818       ASTString lt;
1819       ASTString le;
1820       ASTString gt;
1821       ASTString ge;
1822       ASTString eq;
1823       ASTString ne;
1824       ASTString in;
1825     } float_reif;  // NOLINT(readability-identifier-naming)
1826 
1827     ASTString bool_eq;           // NOLINT(readability-identifier-naming)
1828     ASTString bool_eq_reif;      // NOLINT(readability-identifier-naming)
1829     ASTString bool_not;          // NOLINT(readability-identifier-naming)
1830     ASTString array_bool_or;     // NOLINT(readability-identifier-naming)
1831     ASTString array_bool_and;    // NOLINT(readability-identifier-naming)
1832     ASTString bool_clause;       // NOLINT(readability-identifier-naming)
1833     ASTString bool_clause_reif;  // NOLINT(readability-identifier-naming)
1834     ASTString bool_xor;          // NOLINT(readability-identifier-naming)
1835     ASTString set_eq;            // NOLINT(readability-identifier-naming)
1836     ASTString set_in;            // NOLINT(readability-identifier-naming)
1837     ASTString set_subset;        // NOLINT(readability-identifier-naming)
1838     ASTString set_card;          // NOLINT(readability-identifier-naming)
1839     ASTString pow;
1840 
1841     ASTString mzn_set_in_internal;  // NOLINT(readability-identifier-naming)
1842 
1843     ASTString introduced_var;  // NOLINT(readability-identifier-naming)
1844     ASTString anonEnumFromStrings;
1845   } ids;
1846 
1847   /// Identifiers for Boolean contexts
1848   struct {
1849     Id* root;
1850     Id* pos;
1851     Id* neg;
1852     Id* mix;
1853   } ctx;
1854   /// Common annotations
1855   struct {
1856     Id* output_var;                // NOLINT(readability-identifier-naming)
1857     ASTString output_array;        // NOLINT(readability-identifier-naming)
1858     Id* add_to_output;             // NOLINT(readability-identifier-naming)
1859     Id* output_only;               // NOLINT(readability-identifier-naming)
1860     Id* mzn_check_var;             // NOLINT(readability-identifier-naming)
1861     ASTString mzn_check_enum_var;  // NOLINT(readability-identifier-naming)
1862     Id* is_defined_var;            // NOLINT(readability-identifier-naming)
1863     ASTString defines_var;         // NOLINT(readability-identifier-naming)
1864     Id* is_reverse_map;            // NOLINT(readability-identifier-naming)
1865     Id* promise_total;             // NOLINT(readability-identifier-naming)
1866     Id* maybe_partial;             // NOLINT(readability-identifier-naming)
1867     ASTString doc_comment;         // NOLINT(readability-identifier-naming)
1868     ASTString mzn_path;            // NOLINT(readability-identifier-naming)
1869     ASTString is_introduced;       // NOLINT(readability-identifier-naming)
1870     Id* user_cut;                  // NOLINT(readability-identifier-naming) // MIP
1871     Id* lazy_constraint;           // NOLINT(readability-identifier-naming) // MIP
1872     Id* mzn_break_here;            // NOLINT(readability-identifier-naming)
1873     Id* rhs_from_assignment;       // NOLINT(readability-identifier-naming)
1874     Id* domain_change_constraint;  // NOLINT(readability-identifier-naming)
1875     ASTString mzn_deprecated;      // NOLINT(readability-identifier-naming)
1876     Id* mzn_was_undefined;         // NOLINT(readability-identifier-naming)
1877     Id* array_check_form;          // NOLINT(readability-identifier-naming)
1878   } ann;
1879 
1880   /// Command line options
1881   struct {                                /// basic MiniZinc command line options
1882     ASTString cmdlineData_str;            // NOLINT(readability-identifier-naming)
1883     ASTString cmdlineData_short_str;      // NOLINT(readability-identifier-naming)
1884     ASTString datafile_str;               // NOLINT(readability-identifier-naming)
1885     ASTString datafile_short_str;         // NOLINT(readability-identifier-naming)
1886     ASTString globalsDir_str;             // NOLINT(readability-identifier-naming)
1887     ASTString globalsDir_alt_str;         // NOLINT(readability-identifier-naming)
1888     ASTString globalsDir_short_str;       // NOLINT(readability-identifier-naming)
1889     ASTString help_str;                   // NOLINT(readability-identifier-naming)
1890     ASTString help_short_str;             // NOLINT(readability-identifier-naming)
1891     ASTString ignoreStdlib_str;           // NOLINT(readability-identifier-naming)
1892     ASTString include_str;                // NOLINT(readability-identifier-naming)
1893     ASTString inputFromStdin_str;         // NOLINT(readability-identifier-naming)
1894     ASTString instanceCheckOnly_str;      // NOLINT(readability-identifier-naming)
1895     ASTString no_optimize_str;            // NOLINT(readability-identifier-naming)
1896     ASTString no_optimize_alt_str;        // NOLINT(readability-identifier-naming)
1897     ASTString no_outputOzn_str;           // NOLINT(readability-identifier-naming)
1898     ASTString no_outputOzn_short_str;     // NOLINT(readability-identifier-naming)
1899     ASTString no_typecheck_str;           // NOLINT(readability-identifier-naming)
1900     ASTString newfzn_str;                 // NOLINT(readability-identifier-naming)
1901     ASTString outputBase_str;             // NOLINT(readability-identifier-naming)
1902     ASTString outputFznToStdout_str;      // NOLINT(readability-identifier-naming)
1903     ASTString outputFznToStdout_alt_str;  // NOLINT(readability-identifier-naming)
1904     ASTString outputOznToFile_str;        // NOLINT(readability-identifier-naming)
1905     ASTString outputOznToStdout_str;      // NOLINT(readability-identifier-naming)
1906     ASTString outputFznToFile_str;        // NOLINT(readability-identifier-naming)
1907     ASTString outputFznToFile_alt_str;    // NOLINT(readability-identifier-naming)
1908     ASTString outputFznToFile_short_str;  // NOLINT(readability-identifier-naming)
1909     ASTString rangeDomainsOnly_str;       // NOLINT(readability-identifier-naming)
1910     ASTString statistics_str;             // NOLINT(readability-identifier-naming)
1911     ASTString statistics_short_str;       // NOLINT(readability-identifier-naming)
1912     ASTString stdlib_str;                 // NOLINT(readability-identifier-naming)
1913     ASTString verbose_str;                // NOLINT(readability-identifier-naming)
1914     ASTString verbose_short_str;          // NOLINT(readability-identifier-naming)
1915     ASTString version_str;                // NOLINT(readability-identifier-naming)
1916     ASTString werror_str;                 // NOLINT(readability-identifier-naming)
1917 
1918     struct {
1919       ASTString all_sols_str;    // NOLINT(readability-identifier-naming)
1920       ASTString fzn_solver_str;  // NOLINT(readability-identifier-naming)
1921     } solver;
1922 
1923   } cli;
1924 
1925   /// options strings to find setting in Options map
1926   struct {
1927     ASTString cmdlineData;
1928     ASTString datafile;
1929     ASTString datafiles;
1930     ASTString fznToStdout;
1931     ASTString fznToFile;
1932     ASTString globalsDir;
1933     ASTString ignoreStdlib;
1934     ASTString includeDir;
1935     ASTString includePaths;
1936     ASTString instanceCheckOnly;
1937     ASTString inputFromStdin;
1938     ASTString model;
1939     ASTString newfzn;
1940     ASTString noOznOutput;
1941     ASTString optimize;
1942     ASTString outputBase;
1943     ASTString oznToFile;
1944     ASTString oznToStdout;
1945     ASTString rangeDomainsOnly;
1946     ASTString statistics;
1947     ASTString stdlib;
1948     ASTString typecheck;
1949     ASTString verbose;
1950     ASTString werror;
1951 
1952     struct {
1953       ASTString allSols;
1954       ASTString numSols;
1955       ASTString threads;
1956       ASTString fzn_solver;         // NOLINT(readability-identifier-naming)
1957       ASTString fzn_flags;          // NOLINT(readability-identifier-naming)
1958       ASTString fzn_flag;           // NOLINT(readability-identifier-naming)
1959       ASTString fzn_time_limit_ms;  // NOLINT(readability-identifier-naming)
1960       ASTString fzn_sigint;         // NOLINT(readability-identifier-naming)
1961     } solver;
1962 
1963   } opts;
1964 
1965   /// categories of the command line interface options
1966   struct {
1967     ASTString general;
1968     ASTString io;
1969     ASTString solver;
1970     ASTString translation;
1971   } cli_cat;  // NOLINT(readability-identifier-naming)
1972 
1973   /// Keep track of allocated integer literals
1974   std::unordered_map<IntVal, WeakRef> integerMap;
1975   /// Keep track of allocated float literals
1976   std::unordered_map<FloatVal, WeakRef> floatMap;
1977   /// Constructor
1978   Constants();
1979   /// Return shared BoolLit
boollit(bool b)1980   BoolLit* boollit(bool b) { return b ? literalTrue : literalFalse; }
1981   static const int max_array_size = std::numeric_limits<int>::max() / 2;
1982 
1983   void mark(MINIZINC_GC_STAT_ARGS) override;
1984 };
1985 
1986 /// Return static instance
1987 Constants& constants();
1988 
1989 }  // namespace MiniZinc
1990 
1991 #include <minizinc/ast.hpp>
1992