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