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