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/copy.hh> 13#include <minizinc/hash.hh> 14 15namespace MiniZinc { 16 17void CopyMap::insert(Expression* e0, Expression* e1) { 18 if (!e0->isUnboxedVal() && !e1->isUnboxedVal()) node_m.insert(e0, e1); 19} 20Expression* CopyMap::find(Expression* e) { return static_cast<Expression*>(node_m.find(e)); } 21void CopyMap::insert(Item* e0, Item* e1) { node_m.insert(e0, e1); } 22Item* CopyMap::find(Item* e) { return static_cast<Item*>(node_m.find(e)); } 23void CopyMap::insert(Model* e0, Model* e1) { model_m.insert(std::make_pair(e0, e1)); } 24Model* CopyMap::find(Model* e) { 25 ModelMap::iterator it = model_m.find(e); 26 if (it == model_m.end()) return NULL; 27 return it->second; 28} 29void CopyMap::insert(const ASTString& e0, const ASTString& e1) { 30 node_m.insert(e0.aststr(), e1.aststr()); 31} 32ASTStringO* CopyMap::find(const ASTString& e) { 33 return static_cast<ASTStringO*>(node_m.find(e.aststr())); 34} 35void CopyMap::insert(IntSetVal* e0, IntSetVal* e1) { node_m.insert(e0, e1); } 36IntSetVal* CopyMap::find(IntSetVal* e) { return static_cast<IntSetVal*>(node_m.find(e)); } 37void CopyMap::insert(FloatSetVal* e0, FloatSetVal* e1) { node_m.insert(e0, e1); } 38FloatSetVal* CopyMap::find(FloatSetVal* e) { return static_cast<FloatSetVal*>(node_m.find(e)); } 39 40Location copy_location(CopyMap& m, const Location& _loc) { return _loc; } 41Location copy_location(CopyMap& m, Expression* e) { return copy_location(m, e->loc()); } 42Location copy_location(CopyMap& m, Item* i) { return copy_location(m, i->loc()); } 43 44void copy_ann(EnvI& env, CopyMap& m, Annotation& oldAnn, Annotation& newAnn, bool followIds, 45 bool copyFundecls, bool isFlatModel); 46 47Expression* copy(EnvI& env, CopyMap& m, Expression* e, bool followIds, bool copyFundecls, 48 bool isFlatModel) { 49 if (e == NULL) return NULL; 50 if (Expression* cached = m.find(e)) return cached; 51 Expression* ret = NULL; 52 switch (e->eid()) { 53 case Expression::E_INTLIT: { 54 IntLit* c = IntLit::a(e->cast<IntLit>()->v()); 55 m.insert(e, c); 56 ret = c; 57 } break; 58 case Expression::E_FLOATLIT: { 59 FloatLit* c = FloatLit::a(e->cast<FloatLit>()->v()); 60 m.insert(e, c); 61 ret = c; 62 } break; 63 case Expression::E_SETLIT: { 64 SetLit* s = e->cast<SetLit>(); 65 SetLit* c = new SetLit(copy_location(m, e), static_cast<IntSetVal*>(NULL)); 66 m.insert(e, c); 67 if (s->isv()) { 68 IntSetVal* isv; 69 if (IntSetVal* isvc = m.find(s->isv())) { 70 isv = isvc; 71 } else { 72 IntSetRanges r(s->isv()); 73 isv = IntSetVal::ai(r); 74 m.insert(s->isv(), isv); 75 } 76 c->isv(isv); 77 } else if (s->fsv()) { 78 FloatSetVal* fsv; 79 if (FloatSetVal* fsvc = m.find(s->fsv())) { 80 fsv = fsvc; 81 } else { 82 FloatSetRanges r(s->fsv()); 83 fsv = FloatSetVal::ai(r); 84 m.insert(s->fsv(), fsv); 85 } 86 c->fsv(fsv); 87 } else { 88 if (ASTExprVecO<Expression*>* ve = m.find(s->v())) { 89 c->v(ASTExprVec<Expression>(ve)); 90 } else { 91 std::vector<Expression*> elems(s->v().size()); 92 for (unsigned int i = s->v().size(); i--;) 93 elems[i] = copy(env, m, s->v()[i], followIds, copyFundecls, isFlatModel); 94 ASTExprVec<Expression> ce(elems); 95 m.insert(s->v(), ce); 96 c->v(ce); 97 } 98 } 99 ret = c; 100 } break; 101 case Expression::E_BOOLLIT: { 102 ret = e; 103 } break; 104 case Expression::E_STRINGLIT: { 105 StringLit* sl = e->cast<StringLit>(); 106 StringLit* c; 107 if (ASTStringO* cs = m.find(sl->v())) { 108 c = new StringLit(copy_location(m, e), ASTString(cs)); 109 } else { 110 ASTString s(sl->v().str()); 111 m.insert(sl->v(), s); 112 c = new StringLit(copy_location(m, e), s); 113 } 114 m.insert(e, c); 115 ret = c; 116 } break; 117 case Expression::E_ID: { 118 if (e == constants().absent) return e; 119 Id* id = e->cast<Id>(); 120 121 if (followIds) { 122 Id* prevId = id; 123 Expression* cur = e; 124 bool done = false; 125 do { 126 if (cur == NULL) { 127 cur = prevId; 128 done = true; 129 } else { 130 switch (cur->eid()) { 131 case Expression::E_ID: 132 prevId = cur->cast<Id>(); 133 cur = prevId->decl(); 134 break; 135 case Expression::E_VARDECL: 136 if (cur->cast<VarDecl>()->e()) { 137 cur = cur->cast<VarDecl>()->e(); 138 } else { 139 cur = prevId; 140 done = true; 141 } 142 break; 143 default: 144 done = true; 145 } 146 } 147 } while (!done); 148 if (cur->isa<Id>()) { 149 return cur; 150 } else { 151 return copy(env, m, cur, false); 152 } 153 } else { 154 Id* c; 155 if (id->decl()) { 156 VarDecl* vd = 157 static_cast<VarDecl*>(copy(env, m, id->decl(), followIds, copyFundecls, isFlatModel)); 158 c = vd->id(); 159 } else { 160 if (id->idn() != -1) { 161 c = new Id(copy_location(m, e), id->idn(), NULL); 162 } else { 163 ASTString id_v; 164 if (ASTStringO* cs = m.find(id->v())) { 165 id_v = ASTString(cs); 166 } else { 167 id_v = ASTString(id->v().str()); 168 m.insert(id->v(), id_v); 169 } 170 c = new Id(copy_location(m, e), id_v, NULL); 171 } 172 } 173 m.insert(e, c); 174 ret = c; 175 } 176 } break; 177 case Expression::E_ANON: { 178 AnonVar* c = new AnonVar(copy_location(m, e)); 179 m.insert(e, c); 180 ret = c; 181 } break; 182 case Expression::E_ARRAYLIT: { 183 ArrayLit* al = e->cast<ArrayLit>(); 184 std::vector<std::pair<int, int>> dims(al->dims()); 185 for (unsigned int i = 0; i < dims.size(); i++) { 186 dims[i].first = al->min(i); 187 dims[i].second = al->max(i); 188 } 189 if (ArrayLit* sliceView = al->getSliceLiteral()) { 190 ASTIntVec dimsInternal = al->dimsInternal(); 191 int sliceDims = sliceView->dims(); 192 int dimsOffset = al->dims() * 2; 193 std::vector<std::pair<int, int>> slice(sliceDims); 194 for (int i = 0; i < sliceDims; i++) { 195 slice[i].first = dimsInternal[dimsOffset + i * 2]; 196 slice[i].second = dimsInternal[dimsOffset + i * 2 + 1]; 197 } 198 ArrayLit* c = new ArrayLit( 199 copy_location(m, e), 200 copy(env, m, sliceView, followIds, copyFundecls, isFlatModel)->cast<ArrayLit>(), dims, 201 slice); 202 m.insert(e, c); 203 ret = c; 204 } else { 205 ArrayLit* c = new ArrayLit(copy_location(m, e), std::vector<Expression*>(), dims); 206 m.insert(e, c); 207 208 ASTExprVecO<Expression*>* v; 209 if (ASTExprVecO<Expression*>* cv = m.find(al->getVec())) { 210 v = cv; 211 } else { 212 std::vector<Expression*> elems(al->size()); 213 for (unsigned int i = al->size(); i--;) 214 elems[i] = copy(env, m, (*al)[i], followIds, copyFundecls, isFlatModel); 215 ASTExprVec<Expression> ce(elems); 216 m.insert(al->getVec(), ce); 217 v = ce.vec(); 218 } 219 c->setVec(ASTExprVec<Expression>(v)); 220 ret = c; 221 } 222 } break; 223 case Expression::E_ARRAYACCESS: { 224 ArrayAccess* aa = e->cast<ArrayAccess>(); 225 ArrayAccess* c = new ArrayAccess(copy_location(m, e), NULL, std::vector<Expression*>()); 226 m.insert(e, c); 227 228 ASTExprVecO<Expression*>* idx; 229 if (ASTExprVecO<Expression*>* cidx = m.find(aa->idx())) { 230 idx = cidx; 231 } else { 232 std::vector<Expression*> elems(aa->idx().size()); 233 for (unsigned int i = aa->idx().size(); i--;) 234 elems[i] = copy(env, m, aa->idx()[i], followIds, copyFundecls, isFlatModel); 235 ASTExprVec<Expression> ce(elems); 236 m.insert(aa->idx(), ce); 237 idx = ce.vec(); 238 } 239 c->v(copy(env, m, aa->v(), followIds, copyFundecls, isFlatModel)); 240 c->idx(ASTExprVec<Expression>(idx)); 241 ret = c; 242 } break; 243 case Expression::E_COMP: { 244 Comprehension* c = e->cast<Comprehension>(); 245 Generators g; 246 Comprehension* cc = new Comprehension(copy_location(m, e), NULL, g, c->set()); 247 m.insert(c, cc); 248 249 for (int i = 0; i < c->n_generators(); i++) { 250 std::vector<VarDecl*> vv; 251 for (int j = 0; j < c->n_decls(i); j++) 252 vv.push_back(static_cast<VarDecl*>( 253 copy(env, m, c->decl(i, j), followIds, copyFundecls, isFlatModel))); 254 g._g.push_back(Generator(vv, copy(env, m, c->in(i), followIds, copyFundecls, isFlatModel), 255 copy(env, m, c->where(i), followIds, copyFundecls, isFlatModel))); 256 } 257 cc->init(copy(env, m, c->e(), followIds, copyFundecls, isFlatModel), g); 258 ret = cc; 259 } break; 260 case Expression::E_ITE: { 261 ITE* ite = e->cast<ITE>(); 262 ITE* c = new ITE(copy_location(m, e), std::vector<Expression*>(), NULL); 263 m.insert(e, c); 264 std::vector<Expression*> ifthen(2 * ite->size()); 265 for (unsigned int i = ite->size(); i--;) { 266 ifthen[2 * i] = copy(env, m, ite->e_if(i), followIds, copyFundecls, isFlatModel); 267 ifthen[2 * i + 1] = copy(env, m, ite->e_then(i), followIds, copyFundecls, isFlatModel); 268 } 269 c->init(ifthen, copy(env, m, ite->e_else(), followIds, copyFundecls, isFlatModel)); 270 ret = c; 271 } break; 272 case Expression::E_BINOP: { 273 BinOp* b = e->cast<BinOp>(); 274 BinOp* c = new BinOp(copy_location(m, e), NULL, b->op(), NULL); 275 m.insert(e, c); 276 c->lhs(copy(env, m, b->lhs(), followIds, copyFundecls, isFlatModel)); 277 c->rhs(copy(env, m, b->rhs(), followIds, copyFundecls, isFlatModel)); 278 ret = c; 279 } break; 280 case Expression::E_UNOP: { 281 UnOp* b = e->cast<UnOp>(); 282 UnOp* c = new UnOp(copy_location(m, e), b->op(), NULL); 283 m.insert(e, c); 284 c->e(copy(env, m, b->e(), followIds, copyFundecls, isFlatModel)); 285 ret = c; 286 } break; 287 case Expression::E_CALL: { 288 Call* ca = e->cast<Call>(); 289 ASTString id_v; 290 if (ASTStringO* cs = m.find(ca->id())) { 291 id_v = ASTString(cs); 292 } else { 293 id_v = ASTString(ca->id().str()); 294 m.insert(ca->id(), id_v); 295 } 296 Call* c = new Call(copy_location(m, e), id_v, std::vector<Expression*>()); 297 298 if (ca->decl()) { 299 if (copyFundecls) { 300 c->decl(Item::cast<FunctionI>(copy(env, m, ca->decl()))); 301 } else { 302 c->decl(ca->decl()); 303 } 304 } 305 306 m.insert(e, c); 307 std::vector<Expression*> args(ca->n_args()); 308 for (unsigned int i = static_cast<unsigned int>(args.size()); i--;) 309 args[i] = copy(env, m, ca->arg(i), followIds, copyFundecls, isFlatModel); 310 c->args(args); 311 ret = c; 312 } break; 313 case Expression::E_VARDECL: { 314 VarDecl* vd = e->cast<VarDecl>(); 315 VarDecl* c; 316 if (vd->id()->idn() == -1) { 317 ASTString id_v; 318 if (ASTStringO* cs = m.find(vd->id()->v())) { 319 id_v = ASTString(cs); 320 } else { 321 id_v = ASTString(vd->id()->v().str()); 322 m.insert(vd->id()->v(), id_v); 323 } 324 c = new VarDecl(copy_location(m, e), NULL, id_v, NULL); 325 } else { 326 c = new VarDecl(copy_location(m, e), NULL, vd->id()->idn(), NULL); 327 } 328 c->toplevel(vd->toplevel()); 329 c->introduced(vd->introduced()); 330 if (isFlatModel && vd->flat() == vd) 331 c->flat(c); 332 else 333 c->flat(vd->flat()); 334 c->payload(vd->payload()); 335 m.insert(e, c); 336 m.insert(c, c); 337 c->ti(static_cast<TypeInst*>(copy(env, m, vd->ti(), followIds, copyFundecls, isFlatModel))); 338 c->e(copy(env, m, vd->e(), followIds, copyFundecls, isFlatModel)); 339 c->type(c->ti()->type()); 340 c->id()->type(c->type()); 341 ret = c; 342 } break; 343 case Expression::E_LET: { 344 Let* l = e->cast<Let>(); 345 std::vector<Expression*> let(l->let().size()); 346 for (unsigned int i = l->let().size(); i--;) 347 let[i] = copy(env, m, l->let()[i], followIds, copyFundecls, isFlatModel); 348 Let* c = new Let(copy_location(m, e), let, 349 copy(env, m, l->in(), followIds, copyFundecls, isFlatModel)); 350 for (unsigned int i = l->let().size(); i--;) { 351 c->_let_orig[i] = copy(env, m, l->_let_orig[i], followIds, copyFundecls, isFlatModel); 352 } 353 354 m.insert(e, c); 355 ret = c; 356 } break; 357 case Expression::E_TI: { 358 TypeInst* t = e->cast<TypeInst>(); 359 ASTExprVecO<TypeInst*>* r; 360 if (t->ranges().size() == 0) { 361 r = NULL; 362 } else if (ASTExprVecO<TypeInst*>* cr = m.find(t->ranges())) { 363 r = cr; 364 } else { 365 std::vector<TypeInst*> rr(t->ranges().size()); 366 for (unsigned int i = t->ranges().size(); i--;) 367 rr[i] = static_cast<TypeInst*>( 368 copy(env, m, t->ranges()[i], followIds, copyFundecls, isFlatModel)); 369 r = ASTExprVecO<TypeInst*>::a(rr); 370 } 371 TypeInst* c = new TypeInst(copy_location(m, e), t->type(), ASTExprVec<TypeInst>(r), 372 copy(env, m, t->domain(), followIds, copyFundecls, isFlatModel)); 373 c->setIsEnum(t->isEnum()); 374 m.insert(e, c); 375 ret = c; 376 } break; 377 case Expression::E_TIID: { 378 TIId* t = e->cast<TIId>(); 379 TIId* c = new TIId(copy_location(m, e), t->v().str()); 380 m.insert(e, c); 381 ret = c; 382 } break; 383 default: 384 assert(false); 385 } 386 if (!ret->isa<Id>() || ret->cast<Id>()->decl() == NULL) ret->type(e->type()); 387 copy_ann(env, m, e->ann(), ret->ann(), followIds, copyFundecls, isFlatModel); 388 return ret; 389} 390 391void copy_ann(EnvI& env, CopyMap& m, Annotation& oldAnn, Annotation& newAnn, bool followIds, 392 bool copyFundecls, bool isFlatModel) { 393 for (ExpressionSetIter it = oldAnn.begin(); it != oldAnn.end(); ++it) 394 newAnn.add(copy(env, m, *it, followIds, copyFundecls, isFlatModel)); 395} 396 397Expression* copy(EnvI& env, Expression* e, bool followIds, bool copyFundecls, bool isFlatModel) { 398 CopyMap m; 399 return copy(env, m, e, followIds, copyFundecls, isFlatModel); 400} 401 402Model* copy(EnvI& env, CopyMap& cm, Model* m, bool isFlatModel); 403 404Item* copy(EnvI& env, CopyMap& m, Item* i, bool followIds, bool copyFundecls, bool isFlatModel) { 405 if (i == NULL) return NULL; 406 if (Item* cached = m.find(i)) return cached; 407 switch (i->iid()) { 408 case Item::II_INC: { 409 IncludeI* ii = i->cast<IncludeI>(); 410 IncludeI* c = new IncludeI(copy_location(m, i), ASTString(ii->f().str())); 411 m.insert(i, c); 412 c->m(copy(env, m, ii->m()), ii->own()); 413 return c; 414 } 415 case Item::II_VD: { 416 VarDeclI* v = i->cast<VarDeclI>(); 417 VarDeclI* c = new VarDeclI(copy_location(m, i), NULL); 418 m.insert(i, c); 419 c->e(static_cast<VarDecl*>(copy(env, m, v->e(), followIds, copyFundecls, isFlatModel))); 420 return c; 421 } 422 case Item::II_ASN: { 423 AssignI* a = i->cast<AssignI>(); 424 AssignI* c = new AssignI(copy_location(m, i), a->id().str(), NULL); 425 m.insert(i, c); 426 c->e(copy(env, m, a->e(), followIds, copyFundecls, isFlatModel)); 427 c->decl(static_cast<VarDecl*>(copy(env, m, a->decl(), followIds, copyFundecls, isFlatModel))); 428 return c; 429 } 430 case Item::II_CON: { 431 ConstraintI* cc = i->cast<ConstraintI>(); 432 ConstraintI* c = new ConstraintI(copy_location(m, i), NULL); 433 m.insert(i, c); 434 c->e(copy(env, m, cc->e(), followIds, copyFundecls, isFlatModel)); 435 return c; 436 } 437 case Item::II_SOL: { 438 SolveI* s = i->cast<SolveI>(); 439 SolveI* c; 440 switch (s->st()) { 441 case SolveI::ST_SAT: 442 c = SolveI::sat(Location()); 443 break; 444 case SolveI::ST_MIN: 445 c = SolveI::min(Location(), copy(env, m, s->e(), followIds, copyFundecls, isFlatModel)); 446 break; 447 case SolveI::ST_MAX: 448 c = SolveI::max(Location(), copy(env, m, s->e(), followIds, copyFundecls, isFlatModel)); 449 break; 450 } 451 copy_ann(env, m, s->ann(), c->ann(), followIds, copyFundecls, isFlatModel); 452 m.insert(i, c); 453 return c; 454 } 455 case Item::II_OUT: { 456 OutputI* o = i->cast<OutputI>(); 457 OutputI* c = new OutputI(copy_location(m, i), 458 copy(env, m, o->e(), followIds, copyFundecls, isFlatModel)); 459 m.insert(i, c); 460 return c; 461 } 462 case Item::II_FUN: { 463 FunctionI* f = i->cast<FunctionI>(); 464 std::vector<VarDecl*> params(f->params().size()); 465 for (unsigned int j = f->params().size(); j--;) 466 params[j] = static_cast<VarDecl*>( 467 copy(env, m, f->params()[j], followIds, copyFundecls, isFlatModel)); 468 FunctionI* c = new FunctionI( 469 copy_location(m, i), f->id().str(), 470 static_cast<TypeInst*>(copy(env, m, f->ti(), followIds, copyFundecls, isFlatModel)), 471 params, copy(env, m, f->e(), followIds, copyFundecls, isFlatModel)); 472 c->_builtins.e = f->_builtins.e; 473 c->_builtins.i = f->_builtins.i; 474 c->_builtins.f = f->_builtins.f; 475 c->_builtins.b = f->_builtins.b; 476 c->_builtins.s = f->_builtins.s; 477 c->_builtins.str = f->_builtins.str; 478 479 copy_ann(env, m, f->ann(), c->ann(), followIds, copyFundecls, isFlatModel); 480 m.insert(i, c); 481 return c; 482 } 483 default: 484 assert(false); 485 return NULL; 486 } 487} 488 489Item* copy(EnvI& env, Item* i, bool followIds, bool copyFundecls, bool isFlatModel) { 490 CopyMap m; 491 return copy(env, m, i, followIds, copyFundecls, isFlatModel); 492} 493 494Model* copy(EnvI& env, CopyMap& cm, Model* m, bool isFlatModel) { 495 if (m == NULL) return NULL; 496 if (Model* cached = cm.find(m)) return cached; 497 Model* c = new Model; 498 for (unsigned int i = 0; i < m->size(); i++) c->addItem(copy(env, cm, (*m)[i], false, true)); 499 500 for (Model::FnMap::iterator it = m->fnmap.begin(); it != m->fnmap.end(); ++it) { 501 for (unsigned int i = 0; i < it->second.size(); i++) 502 c->registerFn(env, 503 copy(env, cm, it->second[i].fi, false, true, isFlatModel)->cast<FunctionI>()); 504 } 505 cm.insert(m, c); 506 return c; 507} 508Model* copy(EnvI& env, Model* m) { 509 CopyMap cm; 510 return copy(env, cm, m); 511} 512 513} // namespace MiniZinc