this repo has no description
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#include <minizinc/ast.hh>
13#include <minizinc/astexception.hh>
14#include <minizinc/flatten_internal.hh>
15#include <minizinc/hash.hh>
16#include <minizinc/iter.hh>
17#include <minizinc/model.hh>
18#include <minizinc/prettyprinter.hh>
19
20namespace MiniZinc {
21
22Location::LocVec* Location::LocVec::a(const ASTString& filename, unsigned int first_line,
23 unsigned int first_column, unsigned int last_line,
24 unsigned int last_column) {
25 static const unsigned int pointerBits = sizeof(IntLit*) * 8;
26 if (pointerBits <= 32) {
27 if (first_line < (1 << 8) && last_line - first_line < (1 << 7) && first_column < (1 << 6) &&
28 last_column < (1 << 7)) {
29 long long int combined = first_line;
30 combined |= (last_line - first_line) << 8;
31 combined |= (first_column) << (8 + 7);
32 combined |= (last_column) << (8 + 7 + 6);
33 LocVec* v = static_cast<LocVec*>(alloc(2));
34 new (v) LocVec(filename, combined);
35 return v;
36 }
37 } else if (pointerBits >= 64) {
38 if (first_line < (1 << 20) && last_line - first_line < (1 << 20) && first_column < (1 << 10) &&
39 last_column < (1 << 10)) {
40 long long int combined = first_line;
41 combined |= (static_cast<unsigned long long int>(last_line - first_line)) << 20;
42 combined |= (static_cast<unsigned long long int>(first_column)) << (20 + 20);
43 combined |= (static_cast<unsigned long long int>(last_column)) << (20 + 20 + 10);
44 LocVec* v = static_cast<LocVec*>(alloc(2));
45 new (v) LocVec(filename, combined);
46 return v;
47 }
48 }
49
50 LocVec* v = static_cast<LocVec*>(alloc(5));
51 new (v) LocVec(filename, first_line, first_column, last_line, last_column);
52 return v;
53}
54
55Location::LocVec::LocVec(const ASTString& filename, IntVal combined) : ASTVec(2) {
56 *(_data + 0) = filename.aststr();
57 *(_data + 1) = IntLit::a(combined);
58}
59
60Location::LocVec::LocVec(const ASTString& filename, unsigned int fl, unsigned int first_column,
61 unsigned int last_line, unsigned int last_column)
62 : ASTVec(5) {
63 *(_data + 0) = filename.aststr();
64 *(_data + 1) = IntLit::a(fl);
65 *(_data + 2) = IntLit::a(last_line);
66 *(_data + 3) = IntLit::a(first_column);
67 *(_data + 4) = IntLit::a(last_column);
68}
69
70Location Location::nonalloc;
71
72Type Type::unboxedint = Type::parint();
73Type Type::unboxedfloat = Type::parfloat();
74
75Annotation Annotation::empty;
76
77std::string Location::toString(void) const {
78 std::ostringstream oss;
79 oss << filename() << ":" << first_line() << "." << first_column();
80 return oss.str();
81}
82
83void Location::mark(void) const {
84 if (lv()) lv()->mark();
85}
86
87Location Location::introduce() const {
88 Location l = *this;
89 if (l._loc_info.lv) {
90 l._loc_info.t |= 1;
91 }
92 return l;
93}
94
95void Expression::addAnnotation(Expression* ann) {
96 if (!isUnboxedVal()) _ann.add(ann);
97}
98void Expression::addAnnotations(std::vector<Expression*> ann) {
99 if (!isUnboxedVal())
100 for (unsigned int i = 0; i < ann.size(); i++)
101 if (ann[i]) _ann.add(ann[i]);
102}
103
104#define pushstack(e) \
105 do { \
106 if (e != NULL) { \
107 stack.push_back(e); \
108 } \
109 } while (0)
110#define pushall(v) \
111 do { \
112 v.mark(); \
113 for (unsigned int i = 0; i < v.size(); i++) \
114 if (v[i] != NULL) { \
115 stack.push_back(v[i]); \
116 } \
117 } while (0)
118#define pushann(a) \
119 do { \
120 for (ExpressionSetIter it = a.begin(); it != a.end(); ++it) { \
121 pushstack(*it); \
122 } \
123 } while (0)
124void Expression::mark(Expression* e) {
125 if (e == NULL || e->isUnboxedVal()) return;
126 std::vector<const Expression*> stack;
127 stack.reserve(1000);
128 stack.push_back(e);
129 while (!stack.empty()) {
130 const Expression* cur = stack.back();
131 stack.pop_back();
132 if (!cur->isUnboxedVal() && cur->_gc_mark == 0) {
133 cur->_gc_mark = 1;
134 cur->loc().mark();
135 pushann(cur->ann());
136 switch (cur->eid()) {
137 case Expression::E_INTLIT:
138 case Expression::E_FLOATLIT:
139 case Expression::E_BOOLLIT:
140 case Expression::E_ANON:
141 break;
142 case Expression::E_SETLIT:
143 if (cur->cast<SetLit>()->isv()) {
144 cur->cast<SetLit>()->isv()->mark();
145 } else if (cur->cast<SetLit>()->fsv()) {
146 cur->cast<SetLit>()->fsv()->mark();
147 } else {
148 pushall(cur->cast<SetLit>()->v());
149 }
150 break;
151 case Expression::E_STRINGLIT:
152 cur->cast<StringLit>()->v().mark();
153 break;
154 case Expression::E_ID:
155 if (cur->cast<Id>()->idn() == -1) cur->cast<Id>()->v().mark();
156 pushstack(cur->cast<Id>()->decl());
157 break;
158 case Expression::E_ARRAYLIT:
159 if (cur->_flag_2) {
160 pushstack(cur->cast<ArrayLit>()->_u._al);
161 } else {
162 pushall(ASTExprVec<Expression>(cur->cast<ArrayLit>()->_u._v));
163 }
164 cur->cast<ArrayLit>()->_dims.mark();
165 break;
166 case Expression::E_ARRAYACCESS:
167 pushstack(cur->cast<ArrayAccess>()->v());
168 pushall(cur->cast<ArrayAccess>()->idx());
169 break;
170 case Expression::E_COMP:
171 pushstack(cur->cast<Comprehension>()->_e);
172 pushall(cur->cast<Comprehension>()->_g);
173 cur->cast<Comprehension>()->_g_idx.mark();
174 break;
175 case Expression::E_ITE:
176 pushstack(cur->cast<ITE>()->e_else());
177 pushall(cur->cast<ITE>()->_e_if_then);
178 break;
179 case Expression::E_BINOP:
180 pushstack(cur->cast<BinOp>()->lhs());
181 pushstack(cur->cast<BinOp>()->rhs());
182 break;
183 case Expression::E_UNOP:
184 pushstack(cur->cast<UnOp>()->e());
185 break;
186 case Expression::E_CALL:
187 cur->cast<Call>()->id().mark();
188 for (unsigned int i = cur->cast<Call>()->n_args(); i--;)
189 pushstack(cur->cast<Call>()->arg(i));
190 if (!cur->cast<Call>()->_u._oneArg->isUnboxedVal() &&
191 !cur->cast<Call>()->_u._oneArg->isTagged())
192 cur->cast<Call>()->_u._args->mark();
193 if (FunctionI* fi = cur->cast<Call>()->decl()) {
194 fi->mark();
195 fi->id().mark();
196 pushstack(fi->ti());
197 pushann(fi->ann());
198 pushstack(fi->e());
199 pushall(fi->params());
200 }
201 break;
202 case Expression::E_VARDECL:
203 pushstack(cur->cast<VarDecl>()->ti());
204 pushstack(cur->cast<VarDecl>()->e());
205 pushstack(cur->cast<VarDecl>()->id());
206 break;
207 case Expression::E_LET:
208 pushall(cur->cast<Let>()->let());
209 pushall(cur->cast<Let>()->_let_orig);
210 pushstack(cur->cast<Let>()->in());
211 break;
212 case Expression::E_TI:
213 pushstack(cur->cast<TypeInst>()->domain());
214 pushall(cur->cast<TypeInst>()->ranges());
215 break;
216 case Expression::E_TIID:
217 cur->cast<TIId>()->v().mark();
218 break;
219 }
220 }
221 }
222}
223#undef pushstack
224#undef pushall
225
226void IntLit::rehash(void) {
227 init_hash();
228 std::hash<IntVal> h;
229 cmb_hash(h(_v));
230}
231
232void FloatLit::rehash(void) {
233 init_hash();
234 std::hash<FloatVal> h;
235 cmb_hash(h(_v));
236}
237
238void SetLit::rehash(void) {
239 init_hash();
240 if (isv()) {
241 std::hash<IntVal> h;
242 for (IntSetRanges r0(isv()); r0(); ++r0) {
243 cmb_hash(h(r0.min()));
244 cmb_hash(h(r0.max()));
245 }
246 } else if (fsv()) {
247 std::hash<FloatVal> h;
248 for (FloatSetRanges r0(fsv()); r0(); ++r0) {
249 cmb_hash(h(r0.min()));
250 cmb_hash(h(r0.max()));
251 }
252 } else {
253 for (unsigned int i = v().size(); i--;) cmb_hash(Expression::hash(_v[i]));
254 }
255}
256
257void BoolLit::rehash(void) {
258 init_hash();
259 std::hash<bool> h;
260 cmb_hash(h(_v));
261}
262
263void StringLit::rehash(void) {
264 init_hash();
265 cmb_hash(_v.hash());
266}
267
268void Id::rehash(void) {
269 init_hash();
270 std::hash<long long int> h;
271 if (idn() == -1)
272 cmb_hash(v().hash());
273 else
274 cmb_hash(h(idn()));
275}
276
277ASTString Id::str() const {
278 if (idn() == -1) return v();
279 std::ostringstream oss;
280 oss << "X_INTRODUCED_" << idn() << "_";
281 return oss.str();
282}
283
284void TIId::rehash(void) {
285 init_hash();
286 cmb_hash(_v.hash());
287}
288
289void AnonVar::rehash(void) { init_hash(); }
290
291int ArrayLit::dims(void) const {
292 return _flag_2 ? ((_dims.size() - 2 * _u._al->dims()) / 2)
293 : (_dims.size() == 0 ? 1 : _dims.size() / 2);
294}
295int ArrayLit::min(int i) const {
296 if (_dims.size() == 0) {
297 assert(i == 0);
298 return 1;
299 }
300 return _dims[2 * i];
301}
302int ArrayLit::max(int i) const {
303 if (_dims.size() == 0) {
304 assert(i == 0);
305 return _u._v->size();
306 }
307 return _dims[2 * i + 1];
308}
309int ArrayLit::length(void) const {
310 if (dims() == 0) return 0;
311 int l = max(0) - min(0) + 1;
312 for (int i = 1; i < dims(); i++) l *= (max(i) - min(i) + 1);
313 return l;
314}
315void ArrayLit::make1d(void) {
316 if (_dims.size() != 0) {
317 GCLock lock;
318 if (_flag_2) {
319 std::vector<int> d(2 + _u._al->dims() * 2);
320 int dimOffset = dims() * 2;
321 d[0] = 1;
322 d[1] = length();
323 for (unsigned int i = 2; i < d.size(); i++) {
324 d[i] = _dims[dimOffset + i];
325 }
326 _dims = ASTIntVec(d);
327 } else {
328 std::vector<int> d(2);
329 d[0] = 1;
330 d[1] = length();
331 _dims = ASTIntVec(d);
332 }
333 }
334}
335
336int ArrayLit::origIdx(int i) const {
337 assert(_flag_2);
338 int curIdx = i;
339 int multiplyer = 1;
340 int oIdx = 0;
341 int sliceOffset = dims() * 2;
342 for (int curDim = _u._al->dims() - 1; curDim >= 0; curDim--) {
343 oIdx +=
344 multiplyer *
345 ((curIdx % (_dims[sliceOffset + curDim * 2 + 1] - _dims[sliceOffset + curDim * 2] + 1)) +
346 (_dims[sliceOffset + curDim * 2] - _u._al->min(curDim)));
347 curIdx = curIdx / (_dims[sliceOffset + curDim * 2 + 1] - _dims[sliceOffset + curDim * 2] + 1);
348 multiplyer *= (_u._al->max(curDim) - _u._al->min(curDim) + 1);
349 }
350 return oIdx;
351}
352
353Expression* ArrayLit::slice_get(int i) const {
354 if (!_flag_2) {
355 assert(_u._v->flag());
356 int off = length() - _u._v->size();
357 return i <= off ? (*_u._v)[0] : (*_u._v)[i - off];
358 } else {
359 assert(_flag_2);
360 return (*_u._al)[origIdx(i)];
361 }
362}
363
364void ArrayLit::slice_set(int i, Expression* e) {
365 if (!_flag_2) {
366 assert(_u._v->flag());
367 int off = length() - _u._v->size();
368 if (i <= off) {
369 (*_u._v)[0] = e;
370 } else {
371 (*_u._v)[i - off] = e;
372 }
373 } else {
374 assert(_flag_2);
375 _u._al->set(origIdx(i), e);
376 }
377}
378
379ArrayLit::ArrayLit(const Location& loc, ArrayLit* v, const std::vector<std::pair<int, int> >& dims,
380 const std::vector<std::pair<int, int> >& slice)
381 : Expression(loc, E_ARRAYLIT, Type()) {
382 _flag_1 = false;
383 _flag_2 = true;
384 _u._al = v;
385 assert(slice.size() == v->dims());
386 std::vector<int> d(dims.size() * 2 + 2 * slice.size());
387 for (unsigned int i = static_cast<unsigned int>(dims.size()); i--;) {
388 d[i * 2] = dims[i].first;
389 d[i * 2 + 1] = dims[i].second;
390 }
391 int sliceOffset = static_cast<int>(2 * dims.size());
392 for (unsigned int i = static_cast<unsigned int>(slice.size()); i--;) {
393 d[sliceOffset + i * 2] = slice[i].first;
394 d[sliceOffset + i * 2 + 1] = slice[i].second;
395 }
396 _dims = ASTIntVec(d);
397}
398
399void ArrayLit::compress(const std::vector<Expression*>& v, const std::vector<int>& dims) {
400 if (v.size() >= 4 && Expression::equal(v[0], v[1]) && Expression::equal(v[1], v[2]) &&
401 Expression::equal(v[2], v[3])) {
402 std::vector<Expression*> compress(v.size());
403 compress[0] = v[0];
404 int k = 4;
405 while (k < v.size() && Expression::equal(v[k], v[0])) {
406 k++;
407 }
408 int i = 1;
409 for (; k < v.size(); k++) {
410 compress[i++] = v[k];
411 }
412 compress.resize(i);
413 _u._v = ASTExprVec<Expression>(compress).vec();
414 _u._v->flag(true);
415 _dims = ASTIntVec(dims);
416 } else {
417 _u._v = ASTExprVec<Expression>(v).vec();
418 if (dims.size() != 2 || dims[0] != 1) {
419 // only allocate dims vector if it is not a 1d array indexed from 1
420 _dims = ASTIntVec(dims);
421 }
422 }
423}
424
425ArrayLit::ArrayLit(const Location& loc, const std::vector<Expression*>& v,
426 const std::vector<std::pair<int, int> >& dims)
427 : Expression(loc, E_ARRAYLIT, Type()) {
428 _flag_1 = false;
429 _flag_2 = false;
430 std::vector<int> d(dims.size() * 2);
431 for (unsigned int i = static_cast<unsigned int>(dims.size()); i--;) {
432 d[i * 2] = dims[i].first;
433 d[i * 2 + 1] = dims[i].second;
434 }
435 compress(v, d);
436 rehash();
437}
438
439void ArrayLit::rehash(void) {
440 init_hash();
441 std::hash<int> h;
442 for (unsigned int i = 0; i < _dims.size(); i++) {
443 cmb_hash(h(_dims[i]));
444 }
445 if (_flag_2) {
446 cmb_hash(Expression::hash(_u._al));
447 } else {
448 for (unsigned int i = _u._v->size(); i--;) {
449 cmb_hash(h(i));
450 cmb_hash(Expression::hash((*_u._v)[i]));
451 }
452 }
453}
454
455void ArrayAccess::rehash(void) {
456 init_hash();
457 cmb_hash(Expression::hash(_v));
458 std::hash<unsigned int> h;
459 cmb_hash(h(_idx.size()));
460 for (unsigned int i = _idx.size(); i--;) cmb_hash(Expression::hash(_idx[i]));
461}
462
463Generator::Generator(const std::vector<ASTString>& v, Expression* in, Expression* where) {
464 std::vector<VarDecl*> vd;
465 Location loc = in == NULL ? where->loc() : in->loc();
466 for (unsigned int i = 0; i < v.size(); i++) {
467 VarDecl* nvd = new VarDecl(loc, new TypeInst(loc, Type::parint()), v[i]);
468 nvd->toplevel(false);
469 vd.push_back(nvd);
470 }
471 _v = vd;
472 _in = in;
473 _where = where;
474}
475Generator::Generator(const std::vector<Id*>& v, Expression* in, Expression* where) {
476 std::vector<VarDecl*> vd;
477 for (unsigned int i = 0; i < v.size(); i++) {
478 VarDecl* nvd = new VarDecl(v[i]->loc(), new TypeInst(v[i]->loc(), Type::parint()), v[i]->v());
479 nvd->toplevel(false);
480 vd.push_back(nvd);
481 }
482 _v = vd;
483 _in = in;
484 _where = where;
485}
486Generator::Generator(const std::vector<std::string>& v, Expression* in, Expression* where) {
487 std::vector<VarDecl*> vd;
488 Location loc = in == NULL ? where->loc() : in->loc();
489 for (unsigned int i = 0; i < v.size(); i++) {
490 VarDecl* nvd = new VarDecl(loc, new TypeInst(loc, Type::parint()), ASTString(v[i]));
491 nvd->toplevel(false);
492 vd.push_back(nvd);
493 }
494 _v = vd;
495 _in = in;
496 _where = where;
497}
498Generator::Generator(const std::vector<VarDecl*>& v, Expression* in, Expression* where) {
499 _v = v;
500 _in = in;
501 _where = where;
502}
503Generator::Generator(int pos, Expression* where) {
504 std::vector<VarDecl*> vd;
505 std::ostringstream oss;
506 oss << "__dummy" << pos;
507 VarDecl* nvd =
508 new VarDecl(Location().introduce(), new TypeInst(Location().introduce(), Type::parint()),
509 ASTString(oss.str()));
510 nvd->toplevel(false);
511 vd.push_back(nvd);
512 _v = vd;
513 _in = new ArrayLit(Location().introduce(), std::vector<Expression*>({IntLit::a(0)}));
514 _where = where;
515}
516
517bool Comprehension::set(void) const { return _flag_1; }
518void Comprehension::rehash(void) {
519 init_hash();
520 std::hash<unsigned int> h;
521 cmb_hash(h(set()));
522 cmb_hash(Expression::hash(_e));
523 cmb_hash(h(_g_idx.size()));
524 for (unsigned int i = _g_idx.size(); i--;) {
525 cmb_hash(h(_g_idx[i]));
526 }
527 cmb_hash(h(_g.size()));
528 for (unsigned int i = _g.size(); i--;) {
529 cmb_hash(Expression::hash(_g[i]));
530 }
531}
532
533int Comprehension::n_generators(void) const { return _g_idx.size() - 1; }
534Expression* Comprehension::in(int i) { return _g[_g_idx[i]]; }
535const Expression* Comprehension::in(int i) const { return _g[_g_idx[i]]; }
536const Expression* Comprehension::where(int i) const { return _g[_g_idx[i] + 1]; }
537Expression* Comprehension::where(int i) { return _g[_g_idx[i] + 1]; }
538
539int Comprehension::n_decls(int i) const { return _g_idx[i + 1] - _g_idx[i] - 2; }
540VarDecl* Comprehension::decl(int gen, int i) { return _g[_g_idx[gen] + 2 + i]->cast<VarDecl>(); }
541const VarDecl* Comprehension::decl(int gen, int i) const {
542 return _g[_g_idx[gen] + 2 + i]->cast<VarDecl>();
543}
544
545void ITE::rehash(void) {
546 init_hash();
547 std::hash<unsigned int> h;
548 cmb_hash(h(_e_if_then.size()));
549 for (unsigned int i = _e_if_then.size(); i--;) {
550 cmb_hash(Expression::hash(_e_if_then[i]));
551 }
552 cmb_hash(Expression::hash(e_else()));
553}
554
555BinOpType BinOp::op(void) const { return static_cast<BinOpType>(_sec_id); }
556void BinOp::rehash(void) {
557 init_hash();
558 std::hash<int> h;
559 cmb_hash(h(static_cast<int>(op())));
560 cmb_hash(Expression::hash(_e0));
561 cmb_hash(Expression::hash(_e1));
562}
563
564namespace {
565
566class OpToString {
567protected:
568 Model* rootSetModel;
569
570public:
571 Id* sBOT_PLUS;
572 Id* sBOT_MINUS;
573 Id* sBOT_MULT;
574 Id* sBOT_DIV;
575 Id* sBOT_IDIV;
576 Id* sBOT_MOD;
577 Id* sBOT_POW;
578 Id* sBOT_LE;
579 Id* sBOT_LQ;
580 Id* sBOT_GR;
581 Id* sBOT_GQ;
582 Id* sBOT_EQ;
583 Id* sBOT_NQ;
584 Id* sBOT_IN;
585 Id* sBOT_SUBSET;
586 Id* sBOT_SUPERSET;
587 Id* sBOT_UNION;
588 Id* sBOT_DIFF;
589 Id* sBOT_SYMDIFF;
590 Id* sBOT_INTERSECT;
591 Id* sBOT_PLUSPLUS;
592 Id* sBOT_EQUIV;
593 Id* sBOT_IMPL;
594 Id* sBOT_RIMPL;
595 Id* sBOT_OR;
596 Id* sBOT_AND;
597 Id* sBOT_XOR;
598 Id* sBOT_DOTDOT;
599 Id* sBOT_NOT;
600
601 OpToString(void) {
602 GCLock lock;
603 rootSetModel = new Model();
604 std::vector<Expression*> rootSet;
605 sBOT_PLUS = new Id(Location(), "'+'", NULL);
606 rootSet.push_back(sBOT_PLUS);
607 sBOT_MINUS = new Id(Location(), "'-'", NULL);
608 rootSet.push_back(sBOT_MINUS);
609 sBOT_MULT = new Id(Location(), "'*'", NULL);
610 rootSet.push_back(sBOT_MULT);
611 sBOT_DIV = new Id(Location(), "'/'", NULL);
612 rootSet.push_back(sBOT_DIV);
613 sBOT_IDIV = new Id(Location(), "'div'", NULL);
614 rootSet.push_back(sBOT_IDIV);
615 sBOT_MOD = new Id(Location(), "'mod'", NULL);
616 rootSet.push_back(sBOT_MOD);
617 sBOT_POW = new Id(Location(), "'^'", NULL);
618 rootSet.push_back(sBOT_POW);
619 sBOT_LE = new Id(Location(), "'<'", NULL);
620 rootSet.push_back(sBOT_LE);
621 sBOT_LQ = new Id(Location(), "'<='", NULL);
622 rootSet.push_back(sBOT_LQ);
623 sBOT_GR = new Id(Location(), "'>'", NULL);
624 rootSet.push_back(sBOT_GR);
625 sBOT_GQ = new Id(Location(), "'>='", NULL);
626 rootSet.push_back(sBOT_GQ);
627 sBOT_EQ = new Id(Location(), "'='", NULL);
628 rootSet.push_back(sBOT_EQ);
629 sBOT_NQ = new Id(Location(), "'!='", NULL);
630 rootSet.push_back(sBOT_NQ);
631 sBOT_IN = new Id(Location(), "'in'", NULL);
632 rootSet.push_back(sBOT_IN);
633 sBOT_SUBSET = new Id(Location(), "'subset'", NULL);
634 rootSet.push_back(sBOT_SUBSET);
635 sBOT_SUPERSET = new Id(Location(), "'superset'", NULL);
636 rootSet.push_back(sBOT_SUPERSET);
637 sBOT_UNION = new Id(Location(), "'union'", NULL);
638 rootSet.push_back(sBOT_UNION);
639 sBOT_DIFF = new Id(Location(), "'diff'", NULL);
640 rootSet.push_back(sBOT_DIFF);
641 sBOT_SYMDIFF = new Id(Location(), "'symdiff'", NULL);
642 rootSet.push_back(sBOT_SYMDIFF);
643 sBOT_INTERSECT = new Id(Location(), "'intersect'", NULL);
644 rootSet.push_back(sBOT_INTERSECT);
645 sBOT_PLUSPLUS = new Id(Location(), "'++'", NULL);
646 rootSet.push_back(sBOT_PLUSPLUS);
647 sBOT_EQUIV = new Id(Location(), "'<->'", NULL);
648 rootSet.push_back(sBOT_EQUIV);
649 sBOT_IMPL = new Id(Location(), "'->'", NULL);
650 rootSet.push_back(sBOT_IMPL);
651 sBOT_RIMPL = new Id(Location(), "'<-'", NULL);
652 rootSet.push_back(sBOT_RIMPL);
653 sBOT_OR = new Id(Location(), "'\\/'", NULL);
654 rootSet.push_back(sBOT_OR);
655 sBOT_AND = new Id(Location(), "'/\\'", NULL);
656 rootSet.push_back(sBOT_AND);
657 sBOT_XOR = new Id(Location(), "'xor'", NULL);
658 rootSet.push_back(sBOT_XOR);
659 sBOT_DOTDOT = new Id(Location(), "'..'", NULL);
660 rootSet.push_back(sBOT_DOTDOT);
661 sBOT_NOT = new Id(Location(), "'not'", NULL);
662 rootSet.push_back(sBOT_NOT);
663 rootSetModel->addItem(new ConstraintI(Location(), new ArrayLit(Location(), rootSet)));
664 }
665
666 static OpToString& o(void) {
667 static OpToString _o;
668 return _o;
669 }
670};
671} // namespace
672
673ASTString BinOp::opToString(void) const {
674 switch (op()) {
675 case BOT_PLUS:
676 return OpToString::o().sBOT_PLUS->v();
677 case BOT_MINUS:
678 return OpToString::o().sBOT_MINUS->v();
679 case BOT_MULT:
680 return OpToString::o().sBOT_MULT->v();
681 case BOT_DIV:
682 return OpToString::o().sBOT_DIV->v();
683 case BOT_IDIV:
684 return OpToString::o().sBOT_IDIV->v();
685 case BOT_MOD:
686 return OpToString::o().sBOT_MOD->v();
687 case BOT_POW:
688 return OpToString::o().sBOT_POW->v();
689 case BOT_LE:
690 return OpToString::o().sBOT_LE->v();
691 case BOT_LQ:
692 return OpToString::o().sBOT_LQ->v();
693 case BOT_GR:
694 return OpToString::o().sBOT_GR->v();
695 case BOT_GQ:
696 return OpToString::o().sBOT_GQ->v();
697 case BOT_EQ:
698 return OpToString::o().sBOT_EQ->v();
699 case BOT_NQ:
700 return OpToString::o().sBOT_NQ->v();
701 case BOT_IN:
702 return OpToString::o().sBOT_IN->v();
703 case BOT_SUBSET:
704 return OpToString::o().sBOT_SUBSET->v();
705 case BOT_SUPERSET:
706 return OpToString::o().sBOT_SUPERSET->v();
707 case BOT_UNION:
708 return OpToString::o().sBOT_UNION->v();
709 case BOT_DIFF:
710 return OpToString::o().sBOT_DIFF->v();
711 case BOT_SYMDIFF:
712 return OpToString::o().sBOT_SYMDIFF->v();
713 case BOT_INTERSECT:
714 return OpToString::o().sBOT_INTERSECT->v();
715 case BOT_PLUSPLUS:
716 return OpToString::o().sBOT_PLUSPLUS->v();
717 case BOT_EQUIV:
718 return OpToString::o().sBOT_EQUIV->v();
719 case BOT_IMPL:
720 return OpToString::o().sBOT_IMPL->v();
721 case BOT_RIMPL:
722 return OpToString::o().sBOT_RIMPL->v();
723 case BOT_OR:
724 return OpToString::o().sBOT_OR->v();
725 case BOT_AND:
726 return OpToString::o().sBOT_AND->v();
727 case BOT_XOR:
728 return OpToString::o().sBOT_XOR->v();
729 case BOT_DOTDOT:
730 return OpToString::o().sBOT_DOTDOT->v();
731 default:
732 assert(false);
733 return ASTString("");
734 }
735}
736
737UnOpType UnOp::op(void) const { return static_cast<UnOpType>(_sec_id); }
738void UnOp::rehash(void) {
739 init_hash();
740 std::hash<int> h;
741 cmb_hash(h(static_cast<int>(_sec_id)));
742 cmb_hash(Expression::hash(_e0));
743}
744
745ASTString UnOp::opToString(void) const {
746 switch (op()) {
747 case UOT_PLUS:
748 return OpToString::o().sBOT_PLUS->v();
749 case UOT_MINUS:
750 return OpToString::o().sBOT_MINUS->v();
751 case UOT_NOT:
752 return OpToString::o().sBOT_NOT->v();
753 default:
754 assert(false);
755 return ASTString("");
756 }
757}
758
759void Call::rehash(void) {
760 init_hash();
761 cmb_hash(id().hash());
762 std::hash<FunctionI*> hf;
763 cmb_hash(hf(decl()));
764 std::hash<unsigned int> hu;
765 cmb_hash(hu(n_args()));
766 for (unsigned int i = 0; i < n_args(); i++) cmb_hash(Expression::hash(arg(i)));
767}
768
769void VarDecl::trail(void) {
770 GC::trail(&_e, e());
771 if (_ti->ranges().size() > 0) {
772 GC::trail(reinterpret_cast<Expression**>(&_ti), _ti);
773 }
774}
775
776void VarDecl::rehash(void) {
777 init_hash();
778 cmb_hash(Expression::hash(_ti));
779 cmb_hash(_id->hash());
780 cmb_hash(Expression::hash(_e));
781}
782
783void Let::rehash(void) {
784 init_hash();
785 cmb_hash(Expression::hash(_in));
786 std::hash<unsigned int> h;
787 cmb_hash(h(_let.size()));
788 for (unsigned int i = _let.size(); i--;) cmb_hash(Expression::hash(_let[i]));
789}
790
791Let::Let(const Location& loc, const std::vector<Expression*>& let, Expression* in)
792 : Expression(loc, E_LET, Type()) {
793 _let = ASTExprVec<Expression>(let);
794 std::vector<Expression*> vde(let.size());
795 for (unsigned int i = 0; i < let.size(); i++) {
796 if (VarDecl* vd = Expression::dyn_cast<VarDecl>(let[i])) {
797 vde[i] = vd->e();
798 } else {
799 vde[i] = NULL;
800 }
801 }
802 _let_orig = ASTExprVec<Expression>(vde);
803 _in = in;
804 rehash();
805}
806
807void Let::pushbindings(void) {
808 GC::mark();
809 for (unsigned int i = _let.size(); i--;) {
810 if (VarDecl* vd = _let[i]->dyn_cast<VarDecl>()) {
811 vd->trail();
812 vd->e(_let_orig[i]);
813 }
814 }
815}
816void Let::popbindings(void) {
817 for (unsigned int i = _let.size(); i--;) {
818 if (VarDecl* vd = _let[i]->dyn_cast<VarDecl>()) {
819 GC::untrail();
820 break;
821 }
822 }
823}
824
825void TypeInst::rehash(void) {
826 init_hash();
827 std::hash<unsigned int> h;
828 unsigned int rsize = _ranges.size();
829 cmb_hash(h(rsize));
830 for (unsigned int i = rsize; i--;) cmb_hash(Expression::hash(_ranges[i]));
831 cmb_hash(Expression::hash(domain()));
832}
833
834void TypeInst::setRanges(const std::vector<TypeInst*>& ranges) {
835 _ranges = ASTExprVec<TypeInst>(ranges);
836 if (ranges.size() == 1 && ranges[0] && ranges[0]->isa<TypeInst>() &&
837 ranges[0]->cast<TypeInst>()->domain() && ranges[0]->cast<TypeInst>()->domain()->isa<TIId>() &&
838 !ranges[0]->cast<TypeInst>()->domain()->cast<TIId>()->v().beginsWith("$"))
839 _type.dim(-1);
840 else
841 _type.dim(static_cast<int>(ranges.size()));
842 rehash();
843}
844
845bool TypeInst::hasTiVariable(void) const {
846 if (domain() && domain()->isa<TIId>()) return true;
847 for (unsigned int i = _ranges.size(); i--;)
848 if (_ranges[i]->isa<TIId>()) return true;
849 return false;
850}
851
852namespace {
853Type getType(Expression* e) { return e->type(); }
854Type getType(const Type& t) { return t; }
855const Location& getLoc(Expression* e, FunctionI*) { return e->loc(); }
856const Location& getLoc(const Type&, FunctionI* fi) { return fi->loc(); }
857
858bool isaTIId(Expression* e) {
859 if (TIId* t = Expression::dyn_cast<TIId>(e)) {
860 return !t->v().beginsWith("$");
861 }
862 return false;
863}
864bool isaEnumTIId(Expression* e) {
865 if (TIId* t = Expression::dyn_cast<TIId>(e)) {
866 return t->v().beginsWith("$");
867 }
868 return false;
869}
870
871template <class T>
872Type return_type(EnvI& env, FunctionI* fi, const std::vector<T>& ta, bool strictEnum) {
873 if (fi->id() == constants().var_redef->id()) return Type::varbool();
874 Type ret = fi->ti()->type();
875 ASTString dh;
876 if (fi->ti()->domain() && fi->ti()->domain()->isa<TIId>())
877 dh = fi->ti()->domain()->cast<TIId>()->v();
878 ASTString rh;
879 if (fi->ti()->ranges().size() == 1 && isaTIId(fi->ti()->ranges()[0]->domain()))
880 rh = fi->ti()->ranges()[0]->domain()->cast<TIId>()->v();
881
882 ASTStringMap<Type>::t tmap;
883 for (unsigned int i = 0; i < ta.size(); i++) {
884 TypeInst* tii = fi->params()[i]->ti();
885 if (tii->domain() && tii->domain()->isa<TIId>()) {
886 ASTString tiid = tii->domain()->cast<TIId>()->v();
887 Type tiit = getType(ta[i]);
888 if (tiit.enumId() != 0 && tiit.dim() > 0) {
889 const std::vector<unsigned int>& enumIds = env.getArrayEnum(tiit.enumId());
890 tiit.enumId(enumIds[enumIds.size() - 1]);
891 }
892 tiit.dim(0);
893 if (tii->type().st() == Type::ST_SET) {
894 tiit.st(Type::ST_PLAIN);
895 }
896 if (isaEnumTIId(tii->domain())) {
897 tiit.st(Type::ST_SET);
898 }
899 ASTStringMap<Type>::t::iterator it = tmap.find(tiid);
900 if (it == tmap.end()) {
901 tmap.insert(std::pair<ASTString, Type>(tiid, tiit));
902 } else {
903 if (it->second.dim() > 0) {
904 throw TypeError(
905 env, getLoc(ta[i], fi),
906 "type-inst variable $" + tiid.str() + " used in both array and non-array position");
907 } else {
908 Type tiit_par = tiit;
909 tiit_par.ti(Type::TI_PAR);
910 tiit_par.ot(Type::OT_PRESENT);
911 Type its_par = it->second;
912 its_par.ti(Type::TI_PAR);
913 its_par.ot(Type::OT_PRESENT);
914 if (tiit_par.bt() == Type::BT_TOP || tiit_par.bt() == Type::BT_BOT) {
915 tiit_par.bt(its_par.bt());
916 }
917 if (its_par.bt() == Type::BT_TOP || its_par.bt() == Type::BT_BOT) {
918 its_par.bt(tiit_par.bt());
919 }
920 if (env.isSubtype(tiit_par, its_par, strictEnum)) {
921 if (it->second.bt() == Type::BT_TOP) it->second.bt(tiit.bt());
922 } else if (env.isSubtype(its_par, tiit_par, strictEnum)) {
923 it->second = tiit_par;
924 } else {
925 throw TypeError(env, getLoc(ta[i], fi),
926 "type-inst variable $" + tiid.str() +
927 " instantiated with different types (" + tiit.toString(env) +
928 " vs " + it->second.toString(env) + ")");
929 }
930 }
931 }
932 }
933 if (tii->ranges().size() == 1 && isaTIId(tii->ranges()[0]->domain())) {
934 ASTString tiid = tii->ranges()[0]->domain()->cast<TIId>()->v();
935 Type orig_tiit = getType(ta[i]);
936 if (orig_tiit.dim() == 0) {
937 throw TypeError(env, getLoc(ta[i], fi),
938 "type-inst variable $" + tiid.str() + " must be an array index");
939 }
940 Type tiit = Type::top(orig_tiit.dim());
941 if (orig_tiit.enumId() != 0) {
942 std::vector<unsigned int> enumIds(tiit.dim() + 1);
943 const std::vector<unsigned int>& orig_enumIds = env.getArrayEnum(orig_tiit.enumId());
944 for (unsigned int i = 0; i < enumIds.size() - 1; i++) {
945 enumIds[i] = orig_enumIds[i];
946 }
947 enumIds[enumIds.size() - 1] = 0;
948 tiit.enumId(env.registerArrayEnum(enumIds));
949 }
950 ASTStringMap<Type>::t::iterator it = tmap.find(tiid);
951 if (it == tmap.end()) {
952 tmap.insert(std::pair<ASTString, Type>(tiid, tiit));
953 } else {
954 if (it->second.dim() == 0) {
955 throw TypeError(
956 env, getLoc(ta[i], fi),
957 "type-inst variable $" + tiid.str() + " used in both array and non-array position");
958 } else if (it->second != tiit) {
959 throw TypeError(env, getLoc(ta[i], fi),
960 "type-inst variable $" + tiid.str() +
961 " instantiated with different types (" + tiit.toString(env) + " vs " +
962 it->second.toString(env) + ")");
963 }
964 }
965 } else if (tii->ranges().size() > 0) {
966 for (unsigned int j = 0; j < tii->ranges().size(); j++) {
967 if (isaEnumTIId(tii->ranges()[j]->domain())) {
968 ASTString enumTIId = tii->ranges()[j]->domain()->cast<TIId>()->v();
969 Type tiit = getType(ta[i]);
970 Type enumIdT;
971 if (tiit.enumId() != 0) {
972 unsigned int enumId = env.getArrayEnum(tiit.enumId())[j];
973 enumIdT = Type::parsetenum(enumId);
974 } else {
975 enumIdT = Type::parsetint();
976 }
977 ASTStringMap<Type>::t::iterator it = tmap.find(enumTIId);
978 // TODO: this may clash if the same enum TIId is used for different types
979 // but the same enum
980 if (it == tmap.end()) {
981 tmap.insert(std::pair<ASTString, Type>(enumTIId, enumIdT));
982 } else {
983 if (it->second.enumId() != enumIdT.enumId()) {
984 throw TypeError(
985 env, getLoc(ta[i], fi),
986 "type-inst variable $" + enumTIId.str() + " used for different enum types");
987 }
988 }
989 }
990 }
991 }
992 }
993 if (dh.size() != 0) {
994 ASTStringMap<Type>::t::iterator it = tmap.find(dh);
995 if (it == tmap.end())
996 throw TypeError(env, fi->loc(), "type-inst variable $" + dh.str() + " used but not defined");
997 if (dh.beginsWith("$")) {
998 // this is an enum
999 ret.bt(Type::BT_INT);
1000 } else {
1001 ret.bt(it->second.bt());
1002 if (ret.st() == Type::ST_PLAIN) ret.st(it->second.st());
1003 }
1004 if (fi->ti()->ranges().size() > 0 && it->second.enumId() != 0) {
1005 std::vector<unsigned int> enumIds(fi->ti()->ranges().size() + 1);
1006 for (unsigned int i = 0; i < fi->ti()->ranges().size(); i++) {
1007 enumIds[i] = 0;
1008 }
1009 enumIds[enumIds.size() - 1] = it->second.enumId();
1010 ret.enumId(env.registerArrayEnum(enumIds));
1011 } else {
1012 ret.enumId(it->second.enumId());
1013 }
1014 }
1015 if (rh.size() != 0) {
1016 ASTStringMap<Type>::t::iterator it = tmap.find(rh);
1017 if (it == tmap.end())
1018 throw TypeError(env, fi->loc(), "type-inst variable $" + rh.str() + " used but not defined");
1019 ret.dim(it->second.dim());
1020 if (it->second.enumId() != 0) {
1021 std::vector<unsigned int> enumIds(it->second.dim() + 1);
1022 const std::vector<unsigned int>& orig_enumIds = env.getArrayEnum(it->second.enumId());
1023 for (unsigned int i = 0; i < enumIds.size() - 1; i++) {
1024 enumIds[i] = orig_enumIds[i];
1025 }
1026 enumIds[enumIds.size() - 1] =
1027 ret.enumId() == 0 ? 0 : env.getArrayEnum(ret.enumId())[enumIds.size() - 1];
1028 ret.enumId(env.registerArrayEnum(enumIds));
1029 }
1030
1031 } else if (fi->ti()->ranges().size() > 0) {
1032 std::vector<unsigned int> enumIds(fi->ti()->ranges().size() + 1);
1033 bool hadRealEnum = false;
1034 if (ret.enumId() == 0) {
1035 enumIds[enumIds.size() - 1] = 0;
1036 } else {
1037 enumIds[enumIds.size() - 1] = env.getArrayEnum(ret.enumId())[enumIds.size() - 1];
1038 hadRealEnum = true;
1039 }
1040
1041 for (unsigned int i = 0; i < fi->ti()->ranges().size(); i++) {
1042 if (isaEnumTIId(fi->ti()->ranges()[i]->domain())) {
1043 ASTString enumTIId = fi->ti()->ranges()[i]->domain()->cast<TIId>()->v();
1044 ASTStringMap<Type>::t::iterator it = tmap.find(enumTIId);
1045 if (it == tmap.end())
1046 throw TypeError(env, fi->loc(),
1047 "type-inst variable $" + enumTIId.str() + " used but not defined");
1048 enumIds[i] = it->second.enumId();
1049 hadRealEnum |= (enumIds[i] != 0);
1050 } else {
1051 enumIds[i] = 0;
1052 }
1053 }
1054 if (hadRealEnum) ret.enumId(env.registerArrayEnum(enumIds));
1055 }
1056 return ret;
1057}
1058} // namespace
1059
1060Type FunctionI::rtype(EnvI& env, const std::vector<Expression*>& ta, bool strictEnums) {
1061 return return_type(env, this, ta, strictEnums);
1062}
1063
1064Type FunctionI::rtype(EnvI& env, const std::vector<Type>& ta, bool strictEnums) {
1065 return return_type(env, this, ta, strictEnums);
1066}
1067
1068Type FunctionI::argtype(EnvI& env, const std::vector<Expression*>& ta, int n) {
1069 TypeInst* tii = params()[n]->ti();
1070 if (tii->domain() && tii->domain()->isa<TIId>()) {
1071 Type ty = ta[n]->type();
1072 ty.st(tii->type().st());
1073 ty.dim(tii->type().dim());
1074 ASTString tv = tii->domain()->cast<TIId>()->v();
1075 for (unsigned int i = 0; i < params().size(); i++) {
1076 if (params()[i]->ti()->domain() && params()[i]->ti()->domain()->isa<TIId>() &&
1077 params()[i]->ti()->domain()->cast<TIId>()->v() == tv) {
1078 Type toCheck = ta[i]->type();
1079 toCheck.st(tii->type().st());
1080 toCheck.dim(tii->type().dim());
1081 if (toCheck != ty) {
1082 if (env.isSubtype(ty, toCheck, true)) {
1083 ty = toCheck;
1084 } else {
1085 Type ty_par = ty;
1086 ty_par.ti(Type::TI_PAR);
1087 Type toCheck_par = toCheck;
1088 toCheck_par.ti(Type::TI_PAR);
1089 if (env.isSubtype(ty_par, toCheck_par, true)) {
1090 ty.bt(toCheck.bt());
1091 }
1092 }
1093 }
1094 }
1095 }
1096 return ty;
1097 } else {
1098 return tii->type();
1099 }
1100}
1101
1102bool Expression::equal_internal(const Expression* e0, const Expression* e1) {
1103 switch (e0->eid()) {
1104 case Expression::E_INTLIT:
1105 return e0->cast<IntLit>()->v() == e1->cast<IntLit>()->v();
1106 case Expression::E_FLOATLIT:
1107 return e0->cast<FloatLit>()->v() == e1->cast<FloatLit>()->v();
1108 case Expression::E_SETLIT: {
1109 const SetLit* s0 = e0->cast<SetLit>();
1110 const SetLit* s1 = e1->cast<SetLit>();
1111 if (s0->isv()) {
1112 if (s1->isv()) {
1113 IntSetRanges r0(s0->isv());
1114 IntSetRanges r1(s1->isv());
1115 return Ranges::equal(r0, r1);
1116 } else {
1117 return false;
1118 }
1119 } else if (s0->fsv()) {
1120 if (s1->fsv()) {
1121 FloatSetRanges r0(s0->fsv());
1122 FloatSetRanges r1(s1->fsv());
1123 return Ranges::equal(r0, r1);
1124 } else {
1125 return false;
1126 }
1127 } else {
1128 if (s1->isv() || s1->fsv()) return false;
1129 if (s0->v().size() != s1->v().size()) return false;
1130 for (unsigned int i = 0; i < s0->v().size(); i++)
1131 if (!Expression::equal(s0->v()[i], s1->v()[i])) return false;
1132 return true;
1133 }
1134 }
1135 case Expression::E_BOOLLIT:
1136 return e0->cast<BoolLit>()->v() == e1->cast<BoolLit>()->v();
1137 case Expression::E_STRINGLIT:
1138 return e0->cast<StringLit>()->v() == e1->cast<StringLit>()->v();
1139 case Expression::E_ID: {
1140 const Id* id0 = e0->cast<Id>();
1141 const Id* id1 = e1->cast<Id>();
1142 if (id0->decl() == NULL || id1->decl() == NULL) {
1143 return id0->v() == id1->v() && id0->idn() == id1->idn();
1144 }
1145 return id0->decl() == id1->decl() ||
1146 (id0->decl()->flat() != NULL && id0->decl()->flat() == id1->decl()->flat());
1147 }
1148 case Expression::E_ANON:
1149 return false;
1150 case Expression::E_ARRAYLIT: {
1151 const ArrayLit* a0 = e0->cast<ArrayLit>();
1152 const ArrayLit* a1 = e1->cast<ArrayLit>();
1153 if (a0->size() != a1->size()) return false;
1154 if (a0->_dims.size() != a1->_dims.size()) return false;
1155 for (unsigned int i = 0; i < a0->_dims.size(); i++) {
1156 if (a0->_dims[i] != a1->_dims[i]) {
1157 return false;
1158 }
1159 }
1160 for (unsigned int i = 0; i < a0->size(); i++) {
1161 if (!Expression::equal((*a0)[i], (*a1)[i])) {
1162 return false;
1163 }
1164 }
1165 return true;
1166 }
1167 case Expression::E_ARRAYACCESS: {
1168 const ArrayAccess* a0 = e0->cast<ArrayAccess>();
1169 const ArrayAccess* a1 = e1->cast<ArrayAccess>();
1170 if (!Expression::equal(a0->v(), a1->v())) return false;
1171 if (a0->idx().size() != a1->idx().size()) return false;
1172 for (unsigned int i = 0; i < a0->idx().size(); i++)
1173 if (!Expression::equal(a0->idx()[i], a1->idx()[i])) return false;
1174 return true;
1175 }
1176 case Expression::E_COMP: {
1177 const Comprehension* c0 = e0->cast<Comprehension>();
1178 const Comprehension* c1 = e1->cast<Comprehension>();
1179 if (c0->set() != c1->set()) return false;
1180 if (!Expression::equal(c0->_e, c1->_e)) return false;
1181 if (c0->_g.size() != c1->_g.size()) return false;
1182 for (unsigned int i = 0; i < c0->_g.size(); i++) {
1183 if (!Expression::equal(c0->_g[i], c1->_g[i])) return false;
1184 }
1185 for (unsigned int i = 0; i < c0->_g_idx.size(); i++) {
1186 if (c0->_g_idx[i] != c1->_g_idx[i]) return false;
1187 }
1188 return true;
1189 }
1190 case Expression::E_ITE: {
1191 const ITE* i0 = e0->cast<ITE>();
1192 const ITE* i1 = e1->cast<ITE>();
1193 if (i0->_e_if_then.size() != i1->_e_if_then.size()) return false;
1194 for (unsigned int i = i0->_e_if_then.size(); i--;) {
1195 if (!Expression::equal(i0->_e_if_then[i], i1->_e_if_then[i])) return false;
1196 }
1197 if (!Expression::equal(i0->e_else(), i1->e_else())) return false;
1198 return true;
1199 }
1200 case Expression::E_BINOP: {
1201 const BinOp* b0 = e0->cast<BinOp>();
1202 const BinOp* b1 = e1->cast<BinOp>();
1203 if (b0->op() != b1->op()) return false;
1204 if (!Expression::equal(b0->lhs(), b1->lhs())) return false;
1205 if (!Expression::equal(b0->rhs(), b1->rhs())) return false;
1206 return true;
1207 }
1208 case Expression::E_UNOP: {
1209 const UnOp* b0 = e0->cast<UnOp>();
1210 const UnOp* b1 = e1->cast<UnOp>();
1211 if (b0->op() != b1->op()) return false;
1212 if (!Expression::equal(b0->e(), b1->e())) return false;
1213 return true;
1214 }
1215 case Expression::E_CALL: {
1216 const Call* c0 = e0->cast<Call>();
1217 const Call* c1 = e1->cast<Call>();
1218 if (c0->id() != c1->id()) return false;
1219 if (c0->decl() != c1->decl()) return false;
1220 if (c0->n_args() != c1->n_args()) return false;
1221 for (unsigned int i = 0; i < c0->n_args(); i++)
1222 if (!Expression::equal(c0->arg(i), c1->arg(i))) return false;
1223 return true;
1224 }
1225 case Expression::E_VARDECL: {
1226 const VarDecl* v0 = e0->cast<VarDecl>();
1227 const VarDecl* v1 = e1->cast<VarDecl>();
1228 if (!Expression::equal(v0->ti(), v1->ti())) return false;
1229 if (!Expression::equal(v0->id(), v1->id())) return false;
1230 if (!Expression::equal(v0->e(), v1->e())) return false;
1231 return true;
1232 }
1233 case Expression::E_LET: {
1234 const Let* l0 = e0->cast<Let>();
1235 const Let* l1 = e1->cast<Let>();
1236 if (!Expression::equal(l0->in(), l1->in())) return false;
1237 if (l0->let().size() != l1->let().size()) return false;
1238 for (unsigned int i = l0->let().size(); i--;)
1239 if (!Expression::equal(l0->let()[i], l1->let()[i])) return false;
1240 return true;
1241 }
1242 case Expression::E_TI: {
1243 const TypeInst* t0 = e0->cast<TypeInst>();
1244 const TypeInst* t1 = e1->cast<TypeInst>();
1245 if (t0->ranges().size() != t1->ranges().size()) return false;
1246 for (unsigned int i = t0->ranges().size(); i--;)
1247 if (!Expression::equal(t0->ranges()[i], t1->ranges()[i])) return false;
1248 if (!Expression::equal(t0->domain(), t1->domain())) return false;
1249 return true;
1250 }
1251 case Expression::E_TIID:
1252 return false;
1253 default:
1254 assert(false);
1255 return false;
1256 }
1257}
1258
1259Constants::Constants(void) {
1260 GCLock lock;
1261 TypeInst* ti = new TypeInst(Location(), Type::parbool());
1262 lit_true = new BoolLit(Location(), true);
1263 var_true = new VarDecl(Location(), ti, "_bool_true", lit_true);
1264 lit_false = new BoolLit(Location(), false);
1265 var_false = new VarDecl(Location(), ti, "_bool_false", lit_false);
1266 var_ignore = new VarDecl(Location(), ti, "_bool_ignore");
1267 absent = new Id(Location(), "_absent", NULL);
1268 Type absent_t;
1269 absent_t.bt(Type::BT_BOT);
1270 absent_t.dim(0);
1271 absent_t.st(Type::ST_PLAIN);
1272 absent_t.ot(Type::OT_OPTIONAL);
1273 absent->type(absent_t);
1274
1275 IntSetVal* isv_infty = IntSetVal::a(-IntVal::infinity(), IntVal::infinity());
1276 infinity = new SetLit(Location(), isv_infty);
1277
1278 ids.forall = ASTString("forall");
1279 ids.forall_reif = ASTString("forall_reif");
1280 ids.exists = ASTString("exists");
1281 ids.clause = ASTString("clause");
1282 ids.bool2int = ASTString("bool2int");
1283 ids.int2float = ASTString("int2float");
1284 ids.bool2float = ASTString("bool2float");
1285 ids.assert = ASTString("assert");
1286 ids.trace = ASTString("trace");
1287
1288 ids.sum = ASTString("sum");
1289 ids.lin_exp = ASTString("lin_exp");
1290 ids.element = ASTString("element");
1291
1292 ids.show = ASTString("show");
1293 ids.output = ASTString("output");
1294 ids.fix = ASTString("fix");
1295
1296 ids.int_.lin_eq = ASTString("int_lin_eq");
1297 ids.int_.lin_le = ASTString("int_lin_le");
1298 ids.int_.lin_ne = ASTString("int_lin_ne");
1299 ids.int_.plus = ASTString("int_plus");
1300 ids.int_.minus = ASTString("int_minus");
1301 ids.int_.times = ASTString("int_times");
1302 ids.int_.div = ASTString("int_div");
1303 ids.int_.mod = ASTString("int_mod");
1304 ids.int_.lt = ASTString("int_lt");
1305 ids.int_.le = ASTString("int_le");
1306 ids.int_.gt = ASTString("int_gt");
1307 ids.int_.ge = ASTString("int_ge");
1308 ids.int_.eq = ASTString("int_eq");
1309 ids.int_.ne = ASTString("int_ne");
1310
1311 ids.int_reif.lin_eq = ASTString("int_lin_eq_reif");
1312 ids.int_reif.lin_le = ASTString("int_lin_le_reif");
1313 ids.int_reif.lin_ne = ASTString("int_lin_ne_reif");
1314 ids.int_reif.plus = ASTString("int_plus_reif");
1315 ids.int_reif.minus = ASTString("int_minus_reif");
1316 ids.int_reif.times = ASTString("int_times_reif");
1317 ids.int_reif.div = ASTString("int_div_reif");
1318 ids.int_reif.mod = ASTString("int_mod_reif");
1319 ids.int_reif.lt = ASTString("int_lt_reif");
1320 ids.int_reif.le = ASTString("int_le_reif");
1321 ids.int_reif.gt = ASTString("int_gt_reif");
1322 ids.int_reif.ge = ASTString("int_ge_reif");
1323 ids.int_reif.eq = ASTString("int_eq_reif");
1324 ids.int_reif.ne = ASTString("int_ne_reif");
1325
1326 ids.float_.lin_eq = ASTString("float_lin_eq");
1327 ids.float_.lin_le = ASTString("float_lin_le");
1328 ids.float_.lin_lt = ASTString("float_lin_lt");
1329 ids.float_.lin_ne = ASTString("float_lin_ne");
1330 ids.float_.plus = ASTString("float_plus");
1331 ids.float_.minus = ASTString("float_minus");
1332 ids.float_.times = ASTString("float_times");
1333 ids.float_.div = ASTString("float_div");
1334 ids.float_.mod = ASTString("float_mod");
1335 ids.float_.lt = ASTString("float_lt");
1336 ids.float_.le = ASTString("float_le");
1337 ids.float_.gt = ASTString("float_gt");
1338 ids.float_.ge = ASTString("float_ge");
1339 ids.float_.eq = ASTString("float_eq");
1340 ids.float_.ne = ASTString("float_ne");
1341 ids.float_.in = ASTString("float_in");
1342 ids.float_.dom = ASTString("float_dom");
1343
1344 ids.float_reif.lin_eq = ASTString("float_lin_eq_reif");
1345 ids.float_reif.lin_le = ASTString("float_lin_le_reif");
1346 ids.float_reif.lin_lt = ASTString("float_lin_lt_reif");
1347 ids.float_reif.lin_ne = ASTString("float_lin_ne_reif");
1348 ids.float_reif.plus = ASTString("float_plus_reif");
1349 ids.float_reif.minus = ASTString("float_minus_reif");
1350 ids.float_reif.times = ASTString("float_times_reif");
1351 ids.float_reif.div = ASTString("float_div_reif");
1352 ids.float_reif.mod = ASTString("float_mod_reif");
1353 ids.float_reif.lt = ASTString("float_lt_reif");
1354 ids.float_reif.le = ASTString("float_le_reif");
1355 ids.float_reif.gt = ASTString("float_gt_reif");
1356 ids.float_reif.ge = ASTString("float_ge_reif");
1357 ids.float_reif.eq = ASTString("float_eq_reif");
1358 ids.float_reif.ne = ASTString("float_ne_reif");
1359 ids.float_reif.in = ASTString("float_in_reif");
1360
1361 ids.bool_eq = ASTString("bool_eq");
1362 ids.bool_eq_reif = ASTString("bool_eq_reif");
1363 ids.bool_clause = ASTString("bool_clause");
1364 ids.bool_clause_reif = ASTString("bool_clause_reif");
1365 ids.bool_xor = ASTString("bool_xor");
1366 ids.array_bool_or = ASTString("array_bool_or");
1367 ids.array_bool_and = ASTString("array_bool_and");
1368 ids.set_eq = ASTString("set_eq");
1369 ids.set_in = ASTString("set_in");
1370 ids.set_card = ASTString("set_card");
1371 ids.pow = ASTString("pow");
1372
1373 ids.introduced_var = ASTString("__INTRODUCED");
1374 ids.anonEnumFromStrings = ASTString("anon_enum");
1375
1376 ctx.root = new Id(Location(), ASTString("ctx_root"), NULL);
1377 ctx.root->type(Type::ann());
1378 ctx.pos = new Id(Location(), ASTString("ctx_pos"), NULL);
1379 ctx.pos->type(Type::ann());
1380 ctx.neg = new Id(Location(), ASTString("ctx_neg"), NULL);
1381 ctx.neg->type(Type::ann());
1382 ctx.mix = new Id(Location(), ASTString("ctx_mix"), NULL);
1383 ctx.mix->type(Type::ann());
1384
1385 ann.output_var = new Id(Location(), ASTString("output_var"), NULL);
1386 ann.output_var->type(Type::ann());
1387 ann.output_only = new Id(Location(), ASTString("output_only"), NULL);
1388 ann.output_only->type(Type::ann());
1389 ann.output_array = ASTString("output_array");
1390 ann.add_to_output = new Id(Location(), ASTString("add_to_output"), NULL);
1391 ann.add_to_output->type(Type::ann());
1392 ann.mzn_check_var = new Id(Location(), ASTString("mzn_check_var"), NULL);
1393 ann.mzn_check_var->type(Type::ann());
1394 ann.mzn_check_enum_var = ASTString("mzn_check_enum_var");
1395 ann.is_defined_var = new Id(Location(), ASTString("is_defined_var"), NULL);
1396 ann.is_defined_var->type(Type::ann());
1397 ann.defines_var = ASTString("defines_var");
1398 ann.is_reverse_map = new Id(Location(), ASTString("is_reverse_map"), NULL);
1399 ann.is_reverse_map->type(Type::ann());
1400 ann.promise_total = new Id(Location(), ASTString("promise_total"), NULL);
1401 ann.promise_total->type(Type::ann());
1402 ann._export = new Id(Location(), ASTString("export"), NULL);
1403 ann._export->type(Type::ann());
1404 ann.maybe_partial = new Id(Location(), ASTString("maybe_partial"), NULL);
1405 ann.maybe_partial->type(Type::ann());
1406 ann.doc_comment = ASTString("doc_comment");
1407 ann.mzn_path = ASTString("mzn_path");
1408 ann.is_introduced = ASTString("is_introduced");
1409 ann.user_cut = new Id(Location(), ASTString("user_cut"), NULL);
1410 ann.user_cut->type(Type::ann());
1411 ann.lazy_constraint = new Id(Location(), ASTString("lazy_constraint"), NULL);
1412 ann.lazy_constraint->type(Type::ann());
1413#ifndef NDEBUG
1414 ann.mzn_break_here = new Id(Location(), ASTString("mzn_break_here"), NULL);
1415 ann.mzn_break_here->type(Type::ann());
1416#endif
1417 ann.rhs_from_assignment = new Id(Location(), ASTString("mzn_rhs_from_assignment"), NULL);
1418 ann.rhs_from_assignment->type(Type::ann());
1419 ann.domain_change_constraint = new Id(Location(), ASTString("domain_change_constraint"), NULL);
1420 ann.domain_change_constraint->type(Type::ann());
1421 ann.global_register = ASTString("global_register");
1422
1423 var_redef = new FunctionI(Location(), "__internal_var_redef",
1424 new TypeInst(Location(), Type::varbool()), std::vector<VarDecl*>());
1425
1426 cli.cmdlineData_short_str = ASTString("-D");
1427 cli.cmdlineData_str = ASTString("--cmdline-data");
1428 cli.datafile_str = ASTString("--data");
1429 cli.datafile_short_str = ASTString("-d");
1430 cli.globalsDir_str = ASTString("--globals-dir");
1431 cli.globalsDir_alt_str = ASTString("--mzn-globals-dir");
1432 cli.globalsDir_short_str = ASTString("-G");
1433 cli.help_str = ASTString("--help");
1434 cli.help_short_str = ASTString("-h");
1435 cli.ignoreStdlib_str = ASTString("--ignore-stdlib");
1436 cli.include_str = ASTString("-I");
1437 cli.inputFromStdin_str = ASTString("--input-from-stdin");
1438 cli.instanceCheckOnly_str = ASTString("--instance-check-only");
1439 cli.newfzn_str = ASTString("--newfzn");
1440 cli.no_optimize_str = ASTString("--no-optimize");
1441 cli.no_optimize_alt_str = ASTString("--no-optimise");
1442 cli.no_outputOzn_str = ASTString("--no-output-ozn");
1443 cli.no_outputOzn_short_str = ASTString("-O-");
1444 cli.no_typecheck_str = ASTString("--no-typecheck");
1445 cli.outputBase_str = ASTString("--output-base");
1446 cli.outputFznToStdout_str = ASTString("--output-to-stdout");
1447 cli.outputFznToStdout_alt_str = ASTString("--output-fzn-to-stdout");
1448 cli.outputOznToFile_str = ASTString("--output-ozn-to-file");
1449 cli.outputOznToStdout_str = ASTString("--output-ozn-to-stdout");
1450 cli.outputFznToFile_alt_str = ASTString("--output-fzn-to-file");
1451 cli.outputFznToFile_short_str = ASTString("-o");
1452 cli.outputFznToFile_str = ASTString("--output-to-file");
1453 cli.rangeDomainsOnly_str = ASTString("--only-range-domains");
1454 cli.statistics_str = ASTString("--statistics");
1455 cli.statistics_short_str = ASTString("-s");
1456 cli.stdlib_str = ASTString("--stdlib-dir");
1457 cli.verbose_str = ASTString("--verbose");
1458 cli.verbose_short_str = ASTString("-v");
1459 cli.version_str = ASTString("--version");
1460 cli.werror_str = ASTString("-Werror");
1461
1462 cli.solver.all_sols_str = ASTString("-a");
1463 cli.solver.fzn_solver_str = ASTString("--solver");
1464
1465 opts.cmdlineData = ASTString("cmdlineData");
1466 opts.datafile = ASTString("datafile");
1467 opts.datafiles = ASTString("datafiles");
1468 opts.fznToFile = ASTString("fznToFile");
1469 opts.fznToStdout = ASTString("fznToStdout");
1470 opts.globalsDir = ASTString("globalsDir");
1471 opts.ignoreStdlib = ASTString("ignoreStdlib");
1472 opts.includeDir = ASTString("includeDir");
1473 opts.includePaths = ASTString("includePaths");
1474 opts.inputFromStdin = ASTString("inputStdin");
1475 opts.instanceCheckOnly = ASTString("instanceCheckOnly");
1476 opts.model = ASTString("model");
1477 opts.newfzn = ASTString("newfzn");
1478 opts.noOznOutput = ASTString("noOznOutput");
1479 opts.optimize = ASTString("optimize");
1480 opts.outputBase = ASTString("outputBase");
1481 opts.oznToFile = ASTString("oznToFile");
1482 opts.oznToStdout = ASTString("oznToStdout");
1483 opts.rangeDomainsOnly = ASTString("rangeDomainsOnly");
1484 opts.statistics = ASTString("statistics");
1485 opts.stdlib = ASTString("stdlib");
1486 opts.typecheck = ASTString("typecheck");
1487 opts.verbose = ASTString("verbose");
1488 opts.werror = ASTString("werror");
1489
1490 opts.solver.allSols = ASTString("allSols");
1491 opts.solver.numSols = ASTString("numSols");
1492 opts.solver.threads = ASTString("threads");
1493 opts.solver.fzn_solver = ASTString("fznsolver");
1494 opts.solver.fzn_flags = ASTString("fzn_flags");
1495 opts.solver.fzn_flag = ASTString("fzn_flag");
1496 opts.solver.fzn_time_limit_ms = ASTString("fzn_time_limit_ms");
1497 opts.solver.fzn_sigint = ASTString("fzn_sigint");
1498
1499 cli_cat.general = ASTString("General Options");
1500 cli_cat.io = ASTString("Input/Output Options");
1501 cli_cat.solver = ASTString("Solver Options");
1502 cli_cat.translation = ASTString("Translation Options");
1503
1504 std::vector<Expression*> v;
1505 v.push_back(ti);
1506 v.push_back(lit_true);
1507 v.push_back(var_true);
1508 v.push_back(lit_false);
1509 v.push_back(var_false);
1510 v.push_back(var_ignore);
1511 v.push_back(absent);
1512 v.push_back(infinity);
1513 v.push_back(new StringLit(Location(), ids.forall));
1514 v.push_back(new StringLit(Location(), ids.exists));
1515 v.push_back(new StringLit(Location(), ids.clause));
1516 v.push_back(new StringLit(Location(), ids.bool2int));
1517 v.push_back(new StringLit(Location(), ids.int2float));
1518 v.push_back(new StringLit(Location(), ids.bool2float));
1519 v.push_back(new StringLit(Location(), ids.sum));
1520 v.push_back(new StringLit(Location(), ids.lin_exp));
1521 v.push_back(new StringLit(Location(), ids.element));
1522 v.push_back(new StringLit(Location(), ids.show));
1523 v.push_back(new StringLit(Location(), ids.output));
1524 v.push_back(new StringLit(Location(), ids.fix));
1525
1526 v.push_back(new StringLit(Location(), ids.int_.lin_eq));
1527 v.push_back(new StringLit(Location(), ids.int_.lin_le));
1528 v.push_back(new StringLit(Location(), ids.int_.lin_ne));
1529 v.push_back(new StringLit(Location(), ids.int_.plus));
1530 v.push_back(new StringLit(Location(), ids.int_.minus));
1531 v.push_back(new StringLit(Location(), ids.int_.times));
1532 v.push_back(new StringLit(Location(), ids.int_.div));
1533 v.push_back(new StringLit(Location(), ids.int_.mod));
1534 v.push_back(new StringLit(Location(), ids.int_.lt));
1535 v.push_back(new StringLit(Location(), ids.int_.le));
1536 v.push_back(new StringLit(Location(), ids.int_.gt));
1537 v.push_back(new StringLit(Location(), ids.int_.ge));
1538 v.push_back(new StringLit(Location(), ids.int_.eq));
1539 v.push_back(new StringLit(Location(), ids.int_.ne));
1540
1541 v.push_back(new StringLit(Location(), ids.int_reif.lin_eq));
1542 v.push_back(new StringLit(Location(), ids.int_reif.lin_le));
1543 v.push_back(new StringLit(Location(), ids.int_reif.lin_ne));
1544 v.push_back(new StringLit(Location(), ids.int_reif.plus));
1545 v.push_back(new StringLit(Location(), ids.int_reif.minus));
1546 v.push_back(new StringLit(Location(), ids.int_reif.times));
1547 v.push_back(new StringLit(Location(), ids.int_reif.div));
1548 v.push_back(new StringLit(Location(), ids.int_reif.mod));
1549 v.push_back(new StringLit(Location(), ids.int_reif.lt));
1550 v.push_back(new StringLit(Location(), ids.int_reif.le));
1551 v.push_back(new StringLit(Location(), ids.int_reif.gt));
1552 v.push_back(new StringLit(Location(), ids.int_reif.ge));
1553 v.push_back(new StringLit(Location(), ids.int_reif.eq));
1554 v.push_back(new StringLit(Location(), ids.int_reif.ne));
1555
1556 v.push_back(new StringLit(Location(), ids.float_.lin_eq));
1557 v.push_back(new StringLit(Location(), ids.float_.lin_le));
1558 v.push_back(new StringLit(Location(), ids.float_.lin_lt));
1559 v.push_back(new StringLit(Location(), ids.float_.lin_ne));
1560 v.push_back(new StringLit(Location(), ids.float_.plus));
1561 v.push_back(new StringLit(Location(), ids.float_.minus));
1562 v.push_back(new StringLit(Location(), ids.float_.times));
1563 v.push_back(new StringLit(Location(), ids.float_.div));
1564 v.push_back(new StringLit(Location(), ids.float_.mod));
1565 v.push_back(new StringLit(Location(), ids.float_.lt));
1566 v.push_back(new StringLit(Location(), ids.float_.le));
1567 v.push_back(new StringLit(Location(), ids.float_.gt));
1568 v.push_back(new StringLit(Location(), ids.float_.ge));
1569 v.push_back(new StringLit(Location(), ids.float_.eq));
1570 v.push_back(new StringLit(Location(), ids.float_.ne));
1571 v.push_back(new StringLit(Location(), ids.float_.in));
1572 v.push_back(new StringLit(Location(), ids.float_.dom));
1573
1574 v.push_back(new StringLit(Location(), ids.float_reif.lin_eq));
1575 v.push_back(new StringLit(Location(), ids.float_reif.lin_le));
1576 v.push_back(new StringLit(Location(), ids.float_reif.lin_lt));
1577 v.push_back(new StringLit(Location(), ids.float_reif.lin_ne));
1578 v.push_back(new StringLit(Location(), ids.float_reif.plus));
1579 v.push_back(new StringLit(Location(), ids.float_reif.minus));
1580 v.push_back(new StringLit(Location(), ids.float_reif.times));
1581 v.push_back(new StringLit(Location(), ids.float_reif.div));
1582 v.push_back(new StringLit(Location(), ids.float_reif.mod));
1583 v.push_back(new StringLit(Location(), ids.float_reif.lt));
1584 v.push_back(new StringLit(Location(), ids.float_reif.le));
1585 v.push_back(new StringLit(Location(), ids.float_reif.gt));
1586 v.push_back(new StringLit(Location(), ids.float_reif.ge));
1587 v.push_back(new StringLit(Location(), ids.float_reif.eq));
1588 v.push_back(new StringLit(Location(), ids.float_reif.ne));
1589 v.push_back(new StringLit(Location(), ids.float_reif.in));
1590
1591 v.push_back(new StringLit(Location(), ids.bool_eq));
1592 v.push_back(new StringLit(Location(), ids.bool_eq_reif));
1593 v.push_back(new StringLit(Location(), ids.bool_clause));
1594 v.push_back(new StringLit(Location(), ids.bool_clause_reif));
1595 v.push_back(new StringLit(Location(), ids.bool_xor));
1596 v.push_back(new StringLit(Location(), ids.array_bool_or));
1597 v.push_back(new StringLit(Location(), ids.array_bool_and));
1598 v.push_back(new StringLit(Location(), ids.set_eq));
1599 v.push_back(new StringLit(Location(), ids.set_in));
1600 v.push_back(new StringLit(Location(), ids.set_card));
1601 v.push_back(new StringLit(Location(), ids.pow));
1602
1603 v.push_back(new StringLit(Location(), ids.assert));
1604 v.push_back(new StringLit(Location(), ids.trace));
1605 v.push_back(new StringLit(Location(), ids.introduced_var));
1606 v.push_back(new StringLit(Location(), ids.anonEnumFromStrings));
1607 v.push_back(ctx.root);
1608 v.push_back(ctx.pos);
1609 v.push_back(ctx.neg);
1610 v.push_back(ctx.mix);
1611 v.push_back(ann.output_var);
1612 v.push_back(ann.output_only);
1613 v.push_back(ann.add_to_output);
1614 v.push_back(ann.mzn_check_var);
1615 v.push_back(new StringLit(Location(), ann.mzn_check_enum_var));
1616 v.push_back(new StringLit(Location(), ann.output_array));
1617 v.push_back(ann.is_defined_var);
1618 v.push_back(new StringLit(Location(), ann.defines_var));
1619 v.push_back(ann.is_reverse_map);
1620 v.push_back(ann.promise_total);
1621 v.push_back(ann._export);
1622 v.push_back(ann.maybe_partial);
1623 v.push_back(new StringLit(Location(), ann.doc_comment));
1624 v.push_back(new StringLit(Location(), ann.mzn_path));
1625 v.push_back(new StringLit(Location(), ann.is_introduced));
1626 v.push_back(ann.user_cut);
1627 v.push_back(ann.lazy_constraint);
1628#ifndef NDEBUG
1629 v.push_back(ann.mzn_break_here);
1630#endif
1631 v.push_back(ann.rhs_from_assignment);
1632 v.push_back(ann.domain_change_constraint);
1633 v.push_back(new StringLit(Location(), ann.global_register));
1634
1635 v.push_back(new StringLit(Location(), cli.cmdlineData_short_str));
1636 v.push_back(new StringLit(Location(), cli.cmdlineData_str));
1637 v.push_back(new StringLit(Location(), cli.datafile_short_str));
1638 v.push_back(new StringLit(Location(), cli.datafile_str));
1639 v.push_back(new StringLit(Location(), cli.globalsDir_alt_str));
1640 v.push_back(new StringLit(Location(), cli.globalsDir_short_str));
1641 v.push_back(new StringLit(Location(), cli.globalsDir_str));
1642 v.push_back(new StringLit(Location(), cli.help_short_str));
1643 v.push_back(new StringLit(Location(), cli.help_str));
1644 v.push_back(new StringLit(Location(), cli.ignoreStdlib_str));
1645 v.push_back(new StringLit(Location(), cli.include_str));
1646 v.push_back(new StringLit(Location(), cli.inputFromStdin_str));
1647 v.push_back(new StringLit(Location(), cli.instanceCheckOnly_str));
1648 v.push_back(new StringLit(Location(), cli.newfzn_str));
1649 v.push_back(new StringLit(Location(), cli.no_optimize_alt_str));
1650 v.push_back(new StringLit(Location(), cli.no_optimize_str));
1651 v.push_back(new StringLit(Location(), cli.no_outputOzn_short_str));
1652 v.push_back(new StringLit(Location(), cli.no_outputOzn_str));
1653 v.push_back(new StringLit(Location(), cli.no_typecheck_str));
1654 v.push_back(new StringLit(Location(), cli.outputBase_str));
1655 v.push_back(new StringLit(Location(), cli.outputFznToStdout_alt_str));
1656 v.push_back(new StringLit(Location(), cli.outputFznToStdout_str));
1657 v.push_back(new StringLit(Location(), cli.outputOznToFile_str));
1658 v.push_back(new StringLit(Location(), cli.outputOznToStdout_str));
1659 v.push_back(new StringLit(Location(), cli.outputFznToFile_alt_str));
1660 v.push_back(new StringLit(Location(), cli.outputFznToFile_short_str));
1661 v.push_back(new StringLit(Location(), cli.outputFznToFile_str));
1662 v.push_back(new StringLit(Location(), cli.rangeDomainsOnly_str));
1663 v.push_back(new StringLit(Location(), cli.statistics_short_str));
1664 v.push_back(new StringLit(Location(), cli.statistics_str));
1665 v.push_back(new StringLit(Location(), cli.stdlib_str));
1666 v.push_back(new StringLit(Location(), cli.verbose_short_str));
1667 v.push_back(new StringLit(Location(), cli.verbose_str));
1668 v.push_back(new StringLit(Location(), cli.version_str));
1669 v.push_back(new StringLit(Location(), cli.werror_str));
1670
1671 v.push_back(new StringLit(Location(), cli.solver.all_sols_str));
1672 v.push_back(new StringLit(Location(), cli.solver.fzn_solver_str));
1673
1674 v.push_back(new StringLit(Location(), opts.cmdlineData));
1675 v.push_back(new StringLit(Location(), opts.datafile));
1676 v.push_back(new StringLit(Location(), opts.datafiles));
1677 v.push_back(new StringLit(Location(), opts.fznToFile));
1678 v.push_back(new StringLit(Location(), opts.fznToStdout));
1679 v.push_back(new StringLit(Location(), opts.globalsDir));
1680 v.push_back(new StringLit(Location(), opts.ignoreStdlib));
1681 v.push_back(new StringLit(Location(), opts.includePaths));
1682 v.push_back(new StringLit(Location(), opts.includeDir));
1683 v.push_back(new StringLit(Location(), opts.inputFromStdin));
1684 v.push_back(new StringLit(Location(), opts.instanceCheckOnly));
1685 v.push_back(new StringLit(Location(), opts.model));
1686 v.push_back(new StringLit(Location(), opts.newfzn));
1687 v.push_back(new StringLit(Location(), opts.noOznOutput));
1688 v.push_back(new StringLit(Location(), opts.optimize));
1689 v.push_back(new StringLit(Location(), opts.outputBase));
1690 v.push_back(new StringLit(Location(), opts.oznToFile));
1691 v.push_back(new StringLit(Location(), opts.oznToStdout));
1692 v.push_back(new StringLit(Location(), opts.rangeDomainsOnly));
1693 v.push_back(new StringLit(Location(), opts.statistics));
1694 v.push_back(new StringLit(Location(), opts.stdlib));
1695 v.push_back(new StringLit(Location(), opts.typecheck));
1696 v.push_back(new StringLit(Location(), opts.verbose));
1697 v.push_back(new StringLit(Location(), opts.werror));
1698
1699 v.push_back(new StringLit(Location(), opts.solver.allSols));
1700 v.push_back(new StringLit(Location(), opts.solver.numSols));
1701 v.push_back(new StringLit(Location(), opts.solver.threads));
1702 v.push_back(new StringLit(Location(), opts.solver.fzn_solver));
1703 v.push_back(new StringLit(Location(), opts.solver.fzn_flags));
1704 v.push_back(new StringLit(Location(), opts.solver.fzn_flag));
1705 v.push_back(new StringLit(Location(), opts.solver.fzn_time_limit_ms));
1706 v.push_back(new StringLit(Location(), opts.solver.fzn_sigint));
1707
1708 v.push_back(new StringLit(Location(), cli_cat.general));
1709 v.push_back(new StringLit(Location(), cli_cat.io));
1710 v.push_back(new StringLit(Location(), cli_cat.solver));
1711 v.push_back(new StringLit(Location(), cli_cat.translation));
1712
1713 m = new Model();
1714 m->addItem(new ConstraintI(Location(), new ArrayLit(Location(), v)));
1715 m->addItem(var_redef);
1716}
1717
1718const int Constants::max_array_size;
1719
1720Constants& constants(void) {
1721 static Constants _c;
1722 return _c;
1723}
1724
1725Annotation::~Annotation(void) { delete _s; }
1726
1727bool Annotation::contains(Expression* e) const { return _s && _s->contains(e); }
1728
1729bool Annotation::isEmpty(void) const { return _s == NULL || _s->isEmpty(); }
1730
1731ExpressionSetIter Annotation::begin(void) const {
1732 return _s == NULL ? ExpressionSetIter(true) : _s->begin();
1733}
1734
1735ExpressionSetIter Annotation::end(void) const {
1736 return _s == NULL ? ExpressionSetIter(true) : _s->end();
1737}
1738
1739void Annotation::add(Expression* e) {
1740 if (_s == NULL) _s = new ExpressionSet;
1741 if (e) _s->insert(e);
1742}
1743
1744void Annotation::add(std::vector<Expression*> e) {
1745 if (_s == NULL) _s = new ExpressionSet;
1746 for (unsigned int i = static_cast<unsigned int>(e.size()); i--;)
1747 if (e[i]) _s->insert(e[i]);
1748}
1749
1750void Annotation::remove(Expression* e) {
1751 if (_s && e) {
1752 _s->remove(e);
1753 }
1754}
1755
1756void Annotation::removeCall(const ASTString& id) {
1757 if (_s == NULL) return;
1758 std::vector<Expression*> toRemove;
1759 for (ExpressionSetIter it = _s->begin(); it != _s->end(); ++it) {
1760 if (Call* c = (*it)->dyn_cast<Call>()) {
1761 if (c->id() == id) toRemove.push_back(*it);
1762 }
1763 }
1764 for (unsigned int i = static_cast<unsigned int>(toRemove.size()); i--;) _s->remove(toRemove[i]);
1765}
1766
1767Call* Annotation::getCall(const ASTString& id) const {
1768 if (_s == NULL) return NULL;
1769 for (ExpressionSetIter it = _s->begin(); it != _s->end(); ++it) {
1770 if (Call* c = (*it)->dyn_cast<Call>()) {
1771 if (c->id() == id) return c;
1772 }
1773 }
1774 return NULL;
1775}
1776
1777bool Annotation::containsCall(const MiniZinc::ASTString& id) const {
1778 if (_s == NULL) return false;
1779 for (ExpressionSetIter it = _s->begin(); it != _s->end(); ++it) {
1780 if (Call* c = (*it)->dyn_cast<Call>()) {
1781 if (c->id() == id) return true;
1782 }
1783 }
1784 return false;
1785}
1786
1787void Annotation::clear(void) {
1788 if (_s) {
1789 _s->clear();
1790 }
1791}
1792
1793void Annotation::merge(const Annotation& ann) {
1794 if (ann._s == NULL) return;
1795 if (_s == NULL) {
1796 _s = new ExpressionSet;
1797 }
1798 for (ExpressionSetIter it = ann.begin(); it != ann.end(); ++it) {
1799 _s->insert(*it);
1800 }
1801}
1802
1803Expression* getAnnotation(const Annotation& ann, std::string str) {
1804 for (ExpressionSetIter i = ann.begin(); i != ann.end(); ++i) {
1805 Expression* e = *i;
1806 if ((e->isa<Id>() && e->cast<Id>()->str().str() == str) ||
1807 (e->isa<Call>() && e->cast<Call>()->id().str() == str))
1808 return e;
1809 }
1810 return NULL;
1811}
1812Expression* getAnnotation(const Annotation& ann, const ASTString& str) {
1813 for (ExpressionSetIter i = ann.begin(); i != ann.end(); ++i) {
1814 Expression* e = *i;
1815 if ((e->isa<Id>() && e->cast<Id>()->str() == str) ||
1816 (e->isa<Call>() && e->cast<Call>()->id() == str))
1817 return e;
1818 }
1819 return NULL;
1820}
1821} // namespace MiniZinc