The models, scripts, and results of the benchmarks performed for a Half Reification Journal paper
at develop 3224 lines 108 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/astexception.hh> 13#include <minizinc/astiterator.hh> 14#include <minizinc/copy.hh> 15#include <minizinc/eval_par.hh> 16#include <minizinc/flat_exp.hh> 17#include <minizinc/flatten.hh> 18#include <minizinc/hash.hh> 19#include <minizinc/iter.hh> 20 21#include <cmath> 22 23namespace MiniZinc { 24 25bool check_par_domain(EnvI& env, Expression* e, Expression* domain) { 26 if (e->type() == Type::parint()) { 27 IntSetVal* isv = eval_intset(env, domain); 28 if (!isv->contains(eval_int(env, e))) { 29 return false; 30 } 31 } else if (e->type() == Type::parfloat()) { 32 FloatSetVal* fsv = eval_floatset(env, domain); 33 if (!fsv->contains(eval_float(env, e))) { 34 return false; 35 } 36 } else if (e->type() == Type::parsetint()) { 37 IntSetVal* isv = eval_intset(env, domain); 38 IntSetRanges ir(isv); 39 IntSetVal* rsv = eval_intset(env, e); 40 IntSetRanges rr(rsv); 41 if (!Ranges::subset(rr, ir)) { 42 return false; 43 } 44 } else if (e->type() == Type::parsetfloat()) { 45 FloatSetVal* fsv = eval_floatset(env, domain); 46 FloatSetRanges fr(fsv); 47 FloatSetVal* rsv = eval_floatset(env, e); 48 FloatSetRanges rr(rsv); 49 if (!Ranges::subset(rr, fr)) { 50 return false; 51 } 52 } 53 return true; 54} 55 56void check_par_declaration(EnvI& env, VarDecl* vd) { 57 if (vd->type().dim() > 0) { 58 check_index_sets(env, vd, vd->e()); 59 if (vd->ti()->domain() != nullptr) { 60 ArrayLit* al = eval_array_lit(env, vd->e()); 61 for (unsigned int i = 0; i < al->size(); i++) { 62 if (!check_par_domain(env, (*al)[i], vd->ti()->domain())) { 63 throw ResultUndefinedError(env, vd->e()->loc(), "parameter value out of range"); 64 } 65 } 66 } 67 } else { 68 if (vd->ti()->domain() != nullptr) { 69 if (!check_par_domain(env, vd->e(), vd->ti()->domain())) { 70 throw ResultUndefinedError(env, vd->e()->loc(), "parameter value out of range"); 71 } 72 } 73 } 74} 75 76template <class E> 77typename E::Val eval_id(EnvI& env, Expression* e) { 78 Id* id = e->cast<Id>(); 79 if (!id->decl()) { 80 throw EvalError(env, e->loc(), "undeclared identifier", id->str()); 81 } 82 VarDecl* vd = id->decl(); 83 while (vd->flat() && vd->flat() != vd) { 84 vd = vd->flat(); 85 } 86 if (!vd->e()) { 87 throw EvalError(env, vd->loc(), "cannot evaluate expression", id->str()); 88 } 89 typename E::Val r = E::e(env, vd->e()); 90 if (!vd->evaluated() && (vd->toplevel() || vd->type().dim() > 0)) { 91 Expression* ne = E::exp(r); 92 vd->e(ne); 93 vd->evaluated(true); 94 } 95 return r; 96} 97 98bool EvalBase::evalBoolCV(EnvI& env, Expression* e) { 99 GCLock lock; 100 if (e->type().cv()) { 101 return eval_bool(env, flat_cv_exp(env, Ctx(), e)()); 102 } 103 return eval_bool(env, e); 104}; 105 106KeepAlive EvalBase::flattenCV(EnvI& env, Expression* e) { 107 GCLock lock; 108 Ctx ctx; 109 ctx.i = C_MIX; 110 ctx.b = (e->type().bt() == Type::BT_BOOL) ? C_MIX : C_ROOT; 111 EE ee = flat_exp(env, ctx, e, nullptr, constants().varTrue); 112 return ee.r; 113} 114 115class EvalIntLit : public EvalBase { 116public: 117 typedef IntLit* Val; 118 typedef Expression* ArrayVal; 119 static IntLit* e(EnvI& env, Expression* e) { return IntLit::a(eval_int(env, e)); } 120 static Expression* exp(IntLit* e) { return e; } 121}; 122class EvalIntVal : public EvalBase { 123public: 124 typedef IntVal Val; 125 typedef IntVal ArrayVal; 126 static IntVal e(EnvI& env, Expression* e) { return eval_int(env, e); } 127 static Expression* exp(IntVal e) { return IntLit::a(e); } 128 static void checkRetVal(EnvI& env, Val v, FunctionI* fi) { 129 if ((fi->ti()->domain() != nullptr) && !fi->ti()->domain()->isa<TIId>()) { 130 IntSetVal* isv = eval_intset(env, fi->ti()->domain()); 131 if (!isv->contains(v)) { 132 throw ResultUndefinedError(env, Location().introduce(), 133 "function result violates function type-inst"); 134 } 135 } 136 } 137}; 138class EvalFloatVal : public EvalBase { 139public: 140 typedef FloatVal Val; 141 typedef FloatVal ArrayVal; 142 static FloatVal e(EnvI& env, Expression* e) { return eval_float(env, e); } 143 static Expression* exp(FloatVal e) { return FloatLit::a(e); } 144 static void checkRetVal(EnvI& env, Val v, FunctionI* fi) { 145 if ((fi->ti()->domain() != nullptr) && !fi->ti()->domain()->isa<TIId>()) { 146 FloatSetVal* fsv = eval_floatset(env, fi->ti()->domain()); 147 if (!fsv->contains(v)) { 148 throw ResultUndefinedError(env, Location().introduce(), 149 "function result violates function type-inst"); 150 } 151 } 152 } 153}; 154class EvalFloatLit : public EvalBase { 155public: 156 typedef FloatLit* Val; 157 typedef Expression* ArrayVal; 158 static FloatLit* e(EnvI& env, Expression* e) { return FloatLit::a(eval_float(env, e)); } 159 static Expression* exp(Expression* e) { return e; } 160}; 161class EvalString : public EvalBase { 162public: 163 typedef std::string Val; 164 typedef std::string ArrayVal; 165 static std::string e(EnvI& env, Expression* e) { return eval_string(env, e); } 166 static Expression* exp(const std::string& e) { return new StringLit(Location(), e); } 167 static void checkRetVal(EnvI& env, const Val& v, FunctionI* fi) {} 168}; 169class EvalStringLit : public EvalBase { 170public: 171 typedef StringLit* Val; 172 typedef Expression* ArrayVal; 173 static StringLit* e(EnvI& env, Expression* e) { 174 return new StringLit(Location(), eval_string(env, e)); 175 } 176 static Expression* exp(Expression* e) { return e; } 177}; 178class EvalBoolLit : public EvalBase { 179public: 180 typedef BoolLit* Val; 181 typedef Expression* ArrayVal; 182 static BoolLit* e(EnvI& env, Expression* e) { return constants().boollit(eval_bool(env, e)); } 183 static Expression* exp(Expression* e) { return e; } 184}; 185class EvalBoolVal : public EvalBase { 186public: 187 typedef bool Val; 188 static bool e(EnvI& env, Expression* e) { return eval_bool(env, e); } 189 static Expression* exp(bool e) { return constants().boollit(e); } 190 static void checkRetVal(EnvI& env, Val v, FunctionI* fi) {} 191}; 192class EvalArrayLit : public EvalBase { 193public: 194 typedef ArrayLit* Val; 195 typedef Expression* ArrayVal; 196 static ArrayLit* e(EnvI& env, Expression* e) { return eval_array_lit(env, e); } 197 static Expression* exp(Expression* e) { return e; } 198}; 199class EvalArrayLitCopy : public EvalBase { 200public: 201 typedef ArrayLit* Val; 202 typedef Expression* ArrayVal; 203 static ArrayLit* e(EnvI& env, Expression* e) { 204 return copy(env, eval_array_lit(env, e), true)->cast<ArrayLit>(); 205 } 206 static Expression* exp(Expression* e) { return e; } 207 static void checkRetVal(EnvI& env, Val v, FunctionI* fi) { 208 for (unsigned int i = 0; i < fi->ti()->ranges().size(); i++) { 209 if ((fi->ti()->ranges()[i]->domain() != nullptr) && 210 !fi->ti()->ranges()[i]->domain()->isa<TIId>()) { 211 IntSetVal* isv = eval_intset(env, fi->ti()->ranges()[i]->domain()); 212 bool bothEmpty = isv->min() > isv->max() && v->min(i) > v->max(i); 213 if (!bothEmpty && (v->min(i) != isv->min() || v->max(i) != isv->max())) { 214 std::ostringstream oss; 215 oss << "array index set " << (i + 1) << " of function result violates function type-inst"; 216 throw ResultUndefinedError(env, fi->e()->loc(), oss.str()); 217 } 218 } 219 } 220 if ((fi->ti()->domain() != nullptr) && !fi->ti()->domain()->isa<TIId>() && 221 fi->ti()->type().ti() == Type::TI_PAR) { 222 Type base_t = fi->ti()->type(); 223 if (base_t.bt() == Type::BT_INT) { 224 IntSetVal* isv = eval_intset(env, fi->ti()->domain()); 225 if (base_t.st() == Type::ST_PLAIN) { 226 for (unsigned int i = 0; i < v->size(); i++) { 227 IntVal iv = eval_int(env, (*v)[i]); 228 if (!isv->contains(iv)) { 229 std::ostringstream oss; 230 oss << "array contains value " << iv << " which is not contained in " << *isv; 231 throw ResultUndefinedError( 232 env, fi->e()->loc(), "function result violates function type-inst, " + oss.str()); 233 } 234 } 235 } else { 236 for (unsigned int i = 0; i < v->size(); i++) { 237 IntSetVal* iv = eval_intset(env, (*v)[i]); 238 IntSetRanges isv_r(isv); 239 IntSetRanges v_r(iv); 240 if (!Ranges::subset(v_r, isv_r)) { 241 std::ostringstream oss; 242 oss << "array contains value " << *iv << " which is not a subset of " << *isv; 243 throw ResultUndefinedError( 244 env, fi->e()->loc(), "function result violates function type-inst, " + oss.str()); 245 } 246 } 247 } 248 } else if (base_t.bt() == Type::BT_FLOAT) { 249 FloatSetVal* fsv = eval_floatset(env, fi->ti()->domain()); 250 if (base_t.st() == Type::ST_PLAIN) { 251 for (unsigned int i = 0; i < v->size(); i++) { 252 FloatVal fv = eval_float(env, (*v)[i]); 253 if (!fsv->contains(fv)) { 254 std::ostringstream oss; 255 oss << "array contains value " << fv << " which is not contained in " << *fsv; 256 throw ResultUndefinedError( 257 env, fi->e()->loc(), "function result violates function type-inst, " + oss.str()); 258 } 259 } 260 } else { 261 for (unsigned int i = 0; i < v->size(); i++) { 262 FloatSetVal* fv = eval_floatset(env, (*v)[i]); 263 FloatSetRanges fsv_r(fsv); 264 FloatSetRanges v_r(fv); 265 if (!Ranges::subset(v_r, fsv_r)) { 266 std::ostringstream oss; 267 oss << "array contains value " << *fv << " which is not a subset of " << *fsv; 268 throw ResultUndefinedError( 269 env, fi->e()->loc(), "function result violates function type-inst, " + oss.str()); 270 } 271 } 272 } 273 } 274 } 275 } 276}; 277class EvalIntSet : public EvalBase { 278public: 279 typedef IntSetVal* Val; 280 static IntSetVal* e(EnvI& env, Expression* e) { return eval_intset(env, e); } 281 static Expression* exp(IntSetVal* e) { return new SetLit(Location(), e); } 282 static void checkRetVal(EnvI& env, Val v, FunctionI* fi) { 283 if ((fi->ti()->domain() != nullptr) && !fi->ti()->domain()->isa<TIId>()) { 284 IntSetVal* isv = eval_intset(env, fi->ti()->domain()); 285 IntSetRanges isv_r(isv); 286 IntSetRanges v_r(v); 287 if (!Ranges::subset(v_r, isv_r)) { 288 throw ResultUndefinedError(env, Location().introduce(), 289 "function result violates function type-inst"); 290 } 291 } 292 } 293}; 294class EvalFloatSet : public EvalBase { 295public: 296 typedef FloatSetVal* Val; 297 static FloatSetVal* e(EnvI& env, Expression* e) { return eval_floatset(env, e); } 298 static Expression* exp(FloatSetVal* e) { return new SetLit(Location(), e); } 299 static void checkRetVal(EnvI& env, Val v, FunctionI* fi) { 300 if ((fi->ti()->domain() != nullptr) && !fi->ti()->domain()->isa<TIId>()) { 301 FloatSetVal* fsv = eval_floatset(env, fi->ti()->domain()); 302 FloatSetRanges fsv_r(fsv); 303 FloatSetRanges v_r(v); 304 if (!Ranges::subset(v_r, fsv_r)) { 305 throw ResultUndefinedError(env, Location().introduce(), 306 "function result violates function type-inst"); 307 } 308 } 309 } 310}; 311class EvalBoolSet : public EvalBase { 312public: 313 typedef IntSetVal* Val; 314 static IntSetVal* e(EnvI& env, Expression* e) { return eval_boolset(env, e); } 315 static Expression* exp(IntSetVal* e) { 316 auto* sl = new SetLit(Location(), e); 317 sl->type(Type::parsetbool()); 318 return sl; 319 } 320 static void checkRetVal(EnvI& env, Val v, FunctionI* fi) {} 321}; 322class EvalSetLit : public EvalBase { 323public: 324 typedef SetLit* Val; 325 typedef Expression* ArrayVal; 326 static SetLit* e(EnvI& env, Expression* e) { return eval_set_lit(env, e); } 327 static Expression* exp(Expression* e) { return e; } 328}; 329class EvalFloatSetLit : public EvalBase { 330public: 331 typedef SetLit* Val; 332 typedef Expression* ArrayVal; 333 static SetLit* e(EnvI& env, Expression* e) { return new SetLit(e->loc(), eval_floatset(env, e)); } 334 static Expression* exp(Expression* e) { return e; } 335}; 336class EvalBoolSetLit : public EvalBase { 337public: 338 typedef SetLit* Val; 339 typedef Expression* ArrayVal; 340 static SetLit* e(EnvI& env, Expression* e) { 341 auto* sl = new SetLit(e->loc(), eval_boolset(env, e)); 342 sl->type(Type::parsetbool()); 343 return sl; 344 } 345 static Expression* exp(Expression* e) { return e; } 346}; 347class EvalCopy : public EvalBase { 348public: 349 typedef Expression* Val; 350 typedef Expression* ArrayVal; 351 static Expression* e(EnvI& env, Expression* e) { return copy(env, e, true); } 352 static Expression* exp(Expression* e) { return e; } 353}; 354class EvalPar : public EvalBase { 355public: 356 typedef Expression* Val; 357 typedef Expression* ArrayVal; 358 static Expression* e(EnvI& env, Expression* e) { return eval_par(env, e); } 359 static Expression* exp(Expression* e) { return e; } 360 static void checkRetVal(EnvI& env, Val v, FunctionI* fi) {} 361}; 362 363void check_dom(EnvI& env, Id* arg, IntSetVal* dom, Expression* e) { 364 bool oob = false; 365 if (!e->type().isOpt()) { 366 if (e->type().isIntSet()) { 367 IntSetVal* ev = eval_intset(env, e); 368 IntSetRanges ev_r(ev); 369 IntSetRanges dom_r(dom); 370 oob = !Ranges::subset(ev_r, dom_r); 371 } else { 372 oob = !dom->contains(eval_int(env, e)); 373 } 374 } 375 if (oob) { 376 std::ostringstream oss; 377 oss << "value for argument `" << *arg << "' out of bounds"; 378 throw EvalError(env, e->loc(), oss.str()); 379 } 380} 381 382void check_dom(EnvI& env, Id* arg, FloatVal dom_min, FloatVal dom_max, Expression* e) { 383 if (!e->type().isOpt()) { 384 FloatVal ev = eval_float(env, e); 385 if (ev < dom_min || ev > dom_max) { 386 std::ostringstream oss; 387 oss << "value for argument `" << *arg << "' out of bounds"; 388 throw EvalError(env, e->loc(), oss.str()); 389 } 390 } 391} 392 393template <class Eval, class CallClass = Call> 394typename Eval::Val eval_call(EnvI& env, CallClass* ce) { 395 std::vector<Expression*> previousParameters(ce->decl()->paramCount()); 396 std::vector<Expression*> params(ce->decl()->paramCount()); 397 for (unsigned int i = 0; i < ce->decl()->paramCount(); i++) { 398 params[i] = eval_par(env, ce->arg(i)); 399 } 400 for (unsigned int i = ce->decl()->paramCount(); i--;) { 401 VarDecl* vd = ce->decl()->param(i); 402 if (vd->type().dim() > 0) { 403 // Check array index sets 404 auto* al = params[i]->cast<ArrayLit>(); 405 for (unsigned int j = 0; j < vd->ti()->ranges().size(); j++) { 406 TypeInst* range_ti = vd->ti()->ranges()[j]; 407 if (range_ti->domain() && !range_ti->domain()->isa<TIId>()) { 408 IntSetVal* isv = eval_intset(env, range_ti->domain()); 409 if (isv->min() != al->min(j) || isv->max() != al->max(j)) { 410 std::ostringstream oss; 411 oss << "array index set " << (j + 1) << " of argument " << (i + 1) 412 << " does not match declared index set"; 413 throw EvalError(env, ce->loc(), oss.str()); 414 } 415 } 416 } 417 } 418 previousParameters[i] = vd->e(); 419 vd->flat(vd); 420 vd->e(params[i]); 421 if (vd->e()->type().isPar()) { 422 if (Expression* dom = vd->ti()->domain()) { 423 if (!dom->isa<TIId>()) { 424 if (vd->e()->type().bt() == Type::BT_INT) { 425 IntSetVal* isv = eval_intset(env, dom); 426 if (vd->e()->type().dim() > 0) { 427 ArrayLit* al = eval_array_lit(env, vd->e()); 428 for (unsigned int i = 0; i < al->size(); i++) { 429 check_dom(env, vd->id(), isv, (*al)[i]); 430 } 431 } else { 432 check_dom(env, vd->id(), isv, vd->e()); 433 } 434 } else if (vd->e()->type().bt() == Type::BT_FLOAT) { 435 GCLock lock; 436 FloatSetVal* fsv = eval_floatset(env, dom); 437 FloatVal dom_min = fsv->min(); 438 FloatVal dom_max = fsv->max(); 439 check_dom(env, vd->id(), dom_min, dom_max, vd->e()); 440 } 441 } 442 } 443 } 444 } 445 KeepAlive previousCapture; 446 if (ce->decl()->capturedAnnotationsVar() != nullptr) { 447 previousCapture = ce->decl()->capturedAnnotationsVar()->e(); 448 GCLock lock; 449 ce->decl()->capturedAnnotationsVar()->flat(ce->decl()->capturedAnnotationsVar()); 450 ce->decl()->capturedAnnotationsVar()->e(env.createAnnotationArray(C_MIX)); 451 } 452 typename Eval::Val ret = Eval::e(env, ce->decl()->e()); 453 Eval::checkRetVal(env, ret, ce->decl()); 454 for (unsigned int i = ce->decl()->paramCount(); i--;) { 455 VarDecl* vd = ce->decl()->param(i); 456 vd->e(previousParameters[i]); 457 vd->flat(vd->e() ? vd : nullptr); 458 } 459 if (ce->decl()->capturedAnnotationsVar() != nullptr) { 460 ce->decl()->capturedAnnotationsVar()->e(previousCapture()); 461 ce->decl()->capturedAnnotationsVar()->flat(ce->decl()->capturedAnnotationsVar()->e() != nullptr 462 ? ce->decl()->capturedAnnotationsVar() 463 : nullptr); 464 } 465 return ret; 466} 467 468ArrayLit* eval_array_comp(EnvI& env, Comprehension* e) { 469 ArrayLit* ret; 470 if (e->type() == Type::parint(1)) { 471 std::vector<Expression*> a = eval_comp<EvalIntLit>(env, e); 472 ret = new ArrayLit(e->loc(), a); 473 } else if (e->type() == Type::parbool(1)) { 474 std::vector<Expression*> a = eval_comp<EvalBoolLit>(env, e); 475 ret = new ArrayLit(e->loc(), a); 476 } else if (e->type() == Type::parfloat(1)) { 477 std::vector<Expression*> a = eval_comp<EvalFloatLit>(env, e); 478 ret = new ArrayLit(e->loc(), a); 479 } else if (e->type().st() == Type::ST_SET) { 480 std::vector<Expression*> a = eval_comp<EvalSetLit>(env, e); 481 ret = new ArrayLit(e->loc(), a); 482 } else if (e->type() == Type::parstring(1)) { 483 std::vector<Expression*> a = eval_comp<EvalStringLit>(env, e); 484 ret = new ArrayLit(e->loc(), a); 485 } else { 486 std::vector<Expression*> a = eval_comp<EvalCopy>(env, e); 487 ret = new ArrayLit(e->loc(), a); 488 } 489 ret->type(e->type()); 490 return ret; 491} 492 493ArrayLit* eval_array_lit(EnvI& env, Expression* e) { 494 CallStackItem csi(env, e); 495 switch (e->eid()) { 496 case Expression::E_INTLIT: 497 case Expression::E_FLOATLIT: 498 case Expression::E_BOOLLIT: 499 case Expression::E_STRINGLIT: 500 case Expression::E_SETLIT: 501 case Expression::E_ANON: 502 case Expression::E_TI: 503 case Expression::E_TIID: 504 case Expression::E_VARDECL: 505 throw EvalError(env, e->loc(), "not an array expression"); 506 case Expression::E_ID: 507 return eval_id<EvalArrayLit>(env, e); 508 case Expression::E_ARRAYLIT: 509 return e->cast<ArrayLit>(); 510 case Expression::E_ARRAYACCESS: 511 throw EvalError(env, e->loc(), "arrays of arrays not supported"); 512 case Expression::E_COMP: 513 return eval_array_comp(env, e->cast<Comprehension>()); 514 case Expression::E_ITE: { 515 ITE* ite = e->cast<ITE>(); 516 for (int i = 0; i < ite->size(); i++) { 517 if (eval_bool(env, ite->ifExpr(i))) { 518 return eval_array_lit(env, ite->thenExpr(i)); 519 } 520 } 521 return eval_array_lit(env, ite->elseExpr()); 522 } 523 case Expression::E_BINOP: { 524 auto* bo = e->cast<BinOp>(); 525 if (bo->op() == BOT_PLUSPLUS) { 526 ArrayLit* al0 = eval_array_lit(env, bo->lhs()); 527 ArrayLit* al1 = eval_array_lit(env, bo->rhs()); 528 std::vector<Expression*> v(al0->size() + al1->size()); 529 for (unsigned int i = al0->size(); (i--) != 0U;) { 530 v[i] = (*al0)[i]; 531 } 532 for (unsigned int i = al1->size(); (i--) != 0U;) { 533 v[al0->size() + i] = (*al1)[i]; 534 } 535 auto* ret = new ArrayLit(e->loc(), v); 536 ret->flat(al0->flat() && al1->flat()); 537 ret->type(e->type()); 538 return ret; 539 } 540 if ((bo->decl() != nullptr) && (bo->decl()->e() != nullptr)) { 541 return eval_call<EvalArrayLitCopy, BinOp>(env, bo); 542 } 543 throw EvalError(env, e->loc(), "not an array expression", bo->opToString()); 544 545 } break; 546 case Expression::E_UNOP: { 547 UnOp* uo = e->cast<UnOp>(); 548 if ((uo->decl() != nullptr) && (uo->decl()->e() != nullptr)) { 549 return eval_call<EvalArrayLitCopy, UnOp>(env, uo); 550 } 551 throw EvalError(env, e->loc(), "not an array expression"); 552 } 553 case Expression::E_CALL: { 554 Call* ce = e->cast<Call>(); 555 if (ce->decl() == nullptr) { 556 throw EvalError(env, e->loc(), "undeclared function", ce->id()); 557 } 558 559 if (ce->decl()->builtins.e != nullptr) { 560 return eval_array_lit(env, ce->decl()->builtins.e(env, ce)); 561 } 562 563 if (ce->decl()->e() == nullptr) { 564 std::ostringstream ss; 565 ss << "internal error: missing builtin '" << ce->id() << "'"; 566 throw EvalError(env, ce->loc(), ss.str()); 567 } 568 569 return eval_call<EvalArrayLitCopy>(env, ce); 570 } 571 case Expression::E_LET: { 572 Let* l = e->cast<Let>(); 573 l->pushbindings(); 574 for (unsigned int i = 0; i < l->let().size(); i++) { 575 // Evaluate all variable declarations 576 if (auto* vdi = l->let()[i]->dynamicCast<VarDecl>()) { 577 vdi->e(eval_par(env, vdi->e())); 578 check_par_declaration(env, vdi); 579 } else { 580 // This is a constraint item. Since the let is par, 581 // it can only be a par bool expression. If it evaluates 582 // to false, it means that the value of this let is undefined. 583 if (!eval_bool(env, l->let()[i])) { 584 throw ResultUndefinedError(env, l->let()[i]->loc(), "constraint in let failed"); 585 } 586 } 587 } 588 ArrayLit* l_in = eval_array_lit(env, l->in()); 589 auto* ret = copy(env, l_in, true)->cast<ArrayLit>(); 590 ret->flat(l_in->flat()); 591 l->popbindings(); 592 return ret; 593 } 594 } 595 assert(false); 596 return nullptr; 597} 598 599Expression* eval_arrayaccess(EnvI& env, ArrayLit* al, const std::vector<IntVal>& idx, 600 bool& success) { 601 success = true; 602 assert(al->dims() == idx.size()); 603 IntVal realidx = 0; 604 int realdim = 1; 605 for (int i = 0; i < al->dims(); i++) { 606 realdim *= al->max(i) - al->min(i) + 1; 607 } 608 for (int i = 0; i < al->dims(); i++) { 609 IntVal ix = idx[i]; 610 if (ix < al->min(i) || ix > al->max(i)) { 611 success = false; 612 Type t = al->type(); 613 t.dim(0); 614 if (t.isint()) { 615 return IntLit::a(0); 616 } 617 if (t.isbool()) { 618 return constants().literalFalse; 619 } 620 if (t.isfloat()) { 621 return FloatLit::a(0.0); 622 } 623 if (t.st() == Type::ST_SET || t.isbot()) { 624 auto* ret = new SetLit(Location(), std::vector<Expression*>()); 625 ret->type(t); 626 return ret; 627 } 628 if (t.isstring()) { 629 return new StringLit(Location(), ""); 630 } 631 throw EvalError(env, al->loc(), "Internal error: unexpected type in array access expression"); 632 } 633 realdim /= al->max(i) - al->min(i) + 1; 634 realidx += (ix - al->min(i)) * realdim; 635 } 636 assert(realidx >= 0 && realidx <= al->size()); 637 return (*al)[static_cast<unsigned int>(realidx.toInt())]; 638} 639Expression* eval_arrayaccess(EnvI& env, ArrayAccess* e, bool& success) { 640 ArrayLit* al = eval_array_lit(env, e->v()); 641 std::vector<IntVal> dims(e->idx().size()); 642 for (unsigned int i = e->idx().size(); (i--) != 0U;) { 643 dims[i] = eval_int(env, e->idx()[i]); 644 } 645 return eval_arrayaccess(env, al, dims, success); 646} 647Expression* eval_arrayaccess(EnvI& env, ArrayAccess* e) { 648 bool success; 649 Expression* ret = eval_arrayaccess(env, e, success); 650 if (success) { 651 return ret; 652 } 653 throw ResultUndefinedError(env, e->loc(), "array access out of bounds"); 654} 655 656SetLit* eval_set_lit(EnvI& env, Expression* e) { 657 switch (e->type().bt()) { 658 case Type::BT_INT: 659 case Type::BT_BOT: 660 return new SetLit(e->loc(), eval_intset(env, e)); 661 case Type::BT_BOOL: { 662 auto* sl = new SetLit(e->loc(), eval_boolset(env, e)); 663 sl->type(Type::parsetbool()); 664 return sl; 665 } 666 case Type::BT_FLOAT: 667 return new SetLit(e->loc(), eval_floatset(env, e)); 668 default: 669 throw InternalError("invalid set literal type"); 670 } 671} 672 673IntSetVal* eval_intset(EnvI& env, Expression* e) { 674 if (auto* sl = e->dynamicCast<SetLit>()) { 675 if (sl->isv() != nullptr) { 676 return sl->isv(); 677 } 678 } 679 CallStackItem csi(env, e); 680 switch (e->eid()) { 681 case Expression::E_SETLIT: { 682 auto* sl = e->cast<SetLit>(); 683 std::vector<IntVal> vals; 684 for (unsigned int i = 0; i < sl->v().size(); i++) { 685 Expression* vi = eval_par(env, sl->v()[i]); 686 if (vi != constants().absent) { 687 vals.push_back(eval_int(env, vi)); 688 } 689 } 690 return IntSetVal::a(vals); 691 } 692 case Expression::E_BOOLLIT: 693 case Expression::E_INTLIT: 694 case Expression::E_FLOATLIT: 695 case Expression::E_STRINGLIT: 696 case Expression::E_ANON: 697 case Expression::E_TIID: 698 case Expression::E_VARDECL: 699 case Expression::E_TI: 700 throw EvalError(env, e->loc(), "not a set of int expression"); 701 break; 702 case Expression::E_ARRAYLIT: { 703 auto* al = e->cast<ArrayLit>(); 704 std::vector<IntVal> vals(al->size()); 705 for (unsigned int i = 0; i < al->size(); i++) { 706 vals[i] = eval_int(env, (*al)[i]); 707 } 708 return IntSetVal::a(vals); 709 } break; 710 case Expression::E_COMP: { 711 auto* c = e->cast<Comprehension>(); 712 std::vector<IntVal> a = eval_comp<EvalIntVal>(env, c); 713 return IntSetVal::a(a); 714 } 715 case Expression::E_ID: { 716 GCLock lock; 717 return eval_id<EvalSetLit>(env, e)->isv(); 718 } break; 719 case Expression::E_ARRAYACCESS: { 720 GCLock lock; 721 return eval_intset(env, eval_arrayaccess(env, e->cast<ArrayAccess>())); 722 } break; 723 case Expression::E_ITE: { 724 ITE* ite = e->cast<ITE>(); 725 for (int i = 0; i < ite->size(); i++) { 726 if (eval_bool(env, ite->ifExpr(i))) { 727 return eval_intset(env, ite->thenExpr(i)); 728 } 729 } 730 return eval_intset(env, ite->elseExpr()); 731 } break; 732 case Expression::E_BINOP: { 733 auto* bo = e->cast<BinOp>(); 734 if ((bo->decl() != nullptr) && (bo->decl()->e() != nullptr)) { 735 return eval_call<EvalIntSet, BinOp>(env, bo); 736 } 737 Expression* lhs = eval_par(env, bo->lhs()); 738 Expression* rhs = eval_par(env, bo->rhs()); 739 if (lhs->type().isIntSet() && rhs->type().isIntSet()) { 740 IntSetVal* v0 = eval_intset(env, lhs); 741 IntSetVal* v1 = eval_intset(env, rhs); 742 IntSetRanges ir0(v0); 743 IntSetRanges ir1(v1); 744 switch (bo->op()) { 745 case BOT_UNION: { 746 Ranges::Union<IntVal, IntSetRanges, IntSetRanges> u(ir0, ir1); 747 return IntSetVal::ai(u); 748 } 749 case BOT_DIFF: { 750 Ranges::Diff<IntVal, IntSetRanges, IntSetRanges> u(ir0, ir1); 751 return IntSetVal::ai(u); 752 } 753 case BOT_SYMDIFF: { 754 Ranges::Union<IntVal, IntSetRanges, IntSetRanges> u(ir0, ir1); 755 Ranges::Inter<IntVal, IntSetRanges, IntSetRanges> i(ir0, ir1); 756 Ranges::Diff<IntVal, Ranges::Union<IntVal, IntSetRanges, IntSetRanges>, 757 Ranges::Inter<IntVal, IntSetRanges, IntSetRanges>> 758 sd(u, i); 759 return IntSetVal::ai(sd); 760 } 761 case BOT_INTERSECT: { 762 Ranges::Inter<IntVal, IntSetRanges, IntSetRanges> u(ir0, ir1); 763 return IntSetVal::ai(u); 764 } 765 default: 766 throw EvalError(env, e->loc(), "not a set of int expression", bo->opToString()); 767 } 768 } else if (lhs->type().isint() && rhs->type().isint()) { 769 if (bo->op() != BOT_DOTDOT) { 770 throw EvalError(env, e->loc(), "not a set of int expression", bo->opToString()); 771 } 772 return IntSetVal::a(eval_int(env, lhs), eval_int(env, rhs)); 773 } else { 774 throw EvalError(env, e->loc(), "not a set of int expression", bo->opToString()); 775 } 776 } break; 777 case Expression::E_UNOP: { 778 UnOp* uo = e->cast<UnOp>(); 779 if ((uo->decl() != nullptr) && (uo->decl()->e() != nullptr)) { 780 return eval_call<EvalIntSet, UnOp>(env, uo); 781 } 782 throw EvalError(env, e->loc(), "not a set of int expression"); 783 } 784 case Expression::E_CALL: { 785 Call* ce = e->cast<Call>(); 786 if (ce->decl() == nullptr) { 787 throw EvalError(env, e->loc(), "undeclared function", ce->id()); 788 } 789 790 if (ce->decl()->builtins.s != nullptr) { 791 return ce->decl()->builtins.s(env, ce); 792 } 793 794 if (ce->decl()->builtins.e != nullptr) { 795 return eval_intset(env, ce->decl()->builtins.e(env, ce)); 796 } 797 798 if (ce->decl()->e() == nullptr) { 799 std::ostringstream ss; 800 ss << "internal error: missing builtin '" << ce->id() << "'"; 801 throw EvalError(env, ce->loc(), ss.str()); 802 } 803 804 return eval_call<EvalIntSet>(env, ce); 805 } break; 806 case Expression::E_LET: { 807 Let* l = e->cast<Let>(); 808 l->pushbindings(); 809 for (unsigned int i = 0; i < l->let().size(); i++) { 810 // Evaluate all variable declarations 811 if (auto* vdi = l->let()[i]->dynamicCast<VarDecl>()) { 812 vdi->e(eval_par(env, vdi->e())); 813 check_par_declaration(env, vdi); 814 } else { 815 // This is a constraint item. Since the let is par, 816 // it can only be a par bool expression. If it evaluates 817 // to false, it means that the value of this let is undefined. 818 if (!eval_bool(env, l->let()[i])) { 819 throw ResultUndefinedError(env, l->let()[i]->loc(), "constraint in let failed"); 820 } 821 } 822 } 823 IntSetVal* ret = eval_intset(env, l->in()); 824 l->popbindings(); 825 return ret; 826 } break; 827 default: 828 assert(false); 829 return nullptr; 830 } 831} 832 833FloatSetVal* eval_floatset(EnvI& env, Expression* e) { 834 if (auto* sl = e->dynamicCast<SetLit>()) { 835 if (sl->fsv() != nullptr) { 836 return sl->fsv(); 837 } 838 if (sl->isv() != nullptr) { 839 IntSetRanges isr(sl->isv()); 840 return FloatSetVal::ai(isr); 841 } 842 } 843 CallStackItem csi(env, e); 844 switch (e->eid()) { 845 case Expression::E_SETLIT: { 846 auto* sl = e->cast<SetLit>(); 847 std::vector<FloatVal> vals; 848 for (unsigned int i = 0; i < sl->v().size(); i++) { 849 Expression* vi = eval_par(env, sl->v()[i]); 850 if (vi != constants().absent) { 851 vals.push_back(eval_float(env, vi)); 852 } 853 } 854 return FloatSetVal::a(vals); 855 } 856 case Expression::E_BOOLLIT: 857 case Expression::E_INTLIT: 858 case Expression::E_FLOATLIT: 859 case Expression::E_STRINGLIT: 860 case Expression::E_ANON: 861 case Expression::E_TIID: 862 case Expression::E_VARDECL: 863 case Expression::E_TI: 864 throw EvalError(env, e->loc(), "not a set of float expression"); 865 break; 866 case Expression::E_ARRAYLIT: { 867 auto* al = e->cast<ArrayLit>(); 868 std::vector<FloatVal> vals(al->size()); 869 for (unsigned int i = 0; i < al->size(); i++) { 870 vals[i] = eval_float(env, (*al)[i]); 871 } 872 return FloatSetVal::a(vals); 873 } break; 874 case Expression::E_COMP: { 875 auto* c = e->cast<Comprehension>(); 876 std::vector<FloatVal> a = eval_comp<EvalFloatVal>(env, c); 877 return FloatSetVal::a(a); 878 } 879 case Expression::E_ID: { 880 GCLock lock; 881 return eval_floatset(env, eval_id<EvalFloatSetLit>(env, e)); 882 } break; 883 case Expression::E_ARRAYACCESS: { 884 GCLock lock; 885 return eval_floatset(env, eval_arrayaccess(env, e->cast<ArrayAccess>())); 886 } break; 887 case Expression::E_ITE: { 888 ITE* ite = e->cast<ITE>(); 889 for (int i = 0; i < ite->size(); i++) { 890 if (eval_bool(env, ite->ifExpr(i))) { 891 return eval_floatset(env, ite->thenExpr(i)); 892 } 893 } 894 return eval_floatset(env, ite->elseExpr()); 895 } break; 896 case Expression::E_BINOP: { 897 auto* bo = e->cast<BinOp>(); 898 if ((bo->decl() != nullptr) && (bo->decl()->e() != nullptr)) { 899 return eval_call<EvalFloatSet, BinOp>(env, bo); 900 } 901 Expression* lhs = eval_par(env, bo->lhs()); 902 Expression* rhs = eval_par(env, bo->rhs()); 903 if (lhs->type().isFloatSet() && rhs->type().isFloatSet()) { 904 FloatSetVal* v0 = eval_floatset(env, lhs); 905 FloatSetVal* v1 = eval_floatset(env, rhs); 906 FloatSetRanges fr0(v0); 907 FloatSetRanges fr1(v1); 908 switch (bo->op()) { 909 case BOT_UNION: { 910 Ranges::Union<FloatVal, FloatSetRanges, FloatSetRanges> u(fr0, fr1); 911 return FloatSetVal::ai(u); 912 } 913 case BOT_DIFF: { 914 Ranges::Diff<FloatVal, FloatSetRanges, FloatSetRanges> u(fr0, fr1); 915 return FloatSetVal::ai(u); 916 } 917 case BOT_SYMDIFF: { 918 Ranges::Union<FloatVal, FloatSetRanges, FloatSetRanges> u(fr0, fr1); 919 Ranges::Inter<FloatVal, FloatSetRanges, FloatSetRanges> i(fr0, fr1); 920 Ranges::Diff<FloatVal, Ranges::Union<FloatVal, FloatSetRanges, FloatSetRanges>, 921 Ranges::Inter<FloatVal, FloatSetRanges, FloatSetRanges>> 922 sd(u, i); 923 return FloatSetVal::ai(sd); 924 } 925 case BOT_INTERSECT: { 926 Ranges::Inter<FloatVal, FloatSetRanges, FloatSetRanges> u(fr0, fr1); 927 return FloatSetVal::ai(u); 928 } 929 default: 930 throw EvalError(env, e->loc(), "not a set of int expression", bo->opToString()); 931 } 932 } else if (lhs->type().isfloat() && rhs->type().isfloat()) { 933 if (bo->op() != BOT_DOTDOT) { 934 throw EvalError(env, e->loc(), "not a set of float expression", bo->opToString()); 935 } 936 return FloatSetVal::a(eval_float(env, lhs), eval_float(env, rhs)); 937 } else { 938 throw EvalError(env, e->loc(), "not a set of float expression", bo->opToString()); 939 } 940 } break; 941 case Expression::E_UNOP: { 942 UnOp* uo = e->cast<UnOp>(); 943 if ((uo->decl() != nullptr) && (uo->decl()->e() != nullptr)) { 944 return eval_call<EvalFloatSet, UnOp>(env, uo); 945 } 946 throw EvalError(env, e->loc(), "not a set of float expression"); 947 } 948 case Expression::E_CALL: { 949 Call* ce = e->cast<Call>(); 950 if (ce->decl() == nullptr) { 951 throw EvalError(env, e->loc(), "undeclared function", ce->id()); 952 } 953 954 if (ce->decl()->builtins.e != nullptr) { 955 return eval_floatset(env, ce->decl()->builtins.e(env, ce)); 956 } 957 958 if (ce->decl()->e() == nullptr) { 959 std::ostringstream ss; 960 ss << "internal error: missing builtin '" << ce->id() << "'"; 961 throw EvalError(env, ce->loc(), ss.str()); 962 } 963 964 return eval_call<EvalFloatSet>(env, ce); 965 } break; 966 case Expression::E_LET: { 967 Let* l = e->cast<Let>(); 968 l->pushbindings(); 969 for (unsigned int i = 0; i < l->let().size(); i++) { 970 // Evaluate all variable declarations 971 if (auto* vdi = l->let()[i]->dynamicCast<VarDecl>()) { 972 vdi->e(eval_par(env, vdi->e())); 973 check_par_declaration(env, vdi); 974 } else { 975 // This is a constraint item. Since the let is par, 976 // it can only be a par bool expression. If it evaluates 977 // to false, it means that the value of this let is undefined. 978 if (!eval_bool(env, l->let()[i])) { 979 throw ResultUndefinedError(env, l->let()[i]->loc(), "constraint in let failed"); 980 } 981 } 982 } 983 FloatSetVal* ret = eval_floatset(env, l->in()); 984 l->popbindings(); 985 return ret; 986 } break; 987 default: 988 assert(false); 989 return nullptr; 990 } 991} 992 993bool eval_bool(EnvI& env, Expression* e) { 994 CallStackItem csi(env, e); 995 try { 996 if (auto* bl = e->dynamicCast<BoolLit>()) { 997 return bl->v(); 998 } 999 switch (e->eid()) { 1000 case Expression::E_INTLIT: 1001 case Expression::E_FLOATLIT: 1002 case Expression::E_STRINGLIT: 1003 case Expression::E_ANON: 1004 case Expression::E_TIID: 1005 case Expression::E_SETLIT: 1006 case Expression::E_ARRAYLIT: 1007 case Expression::E_COMP: 1008 case Expression::E_VARDECL: 1009 case Expression::E_TI: 1010 assert(false); 1011 throw EvalError(env, e->loc(), "not a bool expression"); 1012 break; 1013 case Expression::E_ID: { 1014 GCLock lock; 1015 return eval_id<EvalBoolLit>(env, e)->v(); 1016 } break; 1017 case Expression::E_ARRAYACCESS: { 1018 GCLock lock; 1019 return eval_bool(env, eval_arrayaccess(env, e->cast<ArrayAccess>())); 1020 } break; 1021 case Expression::E_ITE: { 1022 ITE* ite = e->cast<ITE>(); 1023 for (int i = 0; i < ite->size(); i++) { 1024 if (eval_bool(env, ite->ifExpr(i))) { 1025 return eval_bool(env, ite->thenExpr(i)); 1026 } 1027 } 1028 return eval_bool(env, ite->elseExpr()); 1029 } break; 1030 case Expression::E_BINOP: { 1031 auto* bo = e->cast<BinOp>(); 1032 Expression* lhs = bo->lhs(); 1033 if (lhs->type().bt() == Type::BT_TOP) { 1034 lhs = eval_par(env, lhs); 1035 } 1036 Expression* rhs = bo->rhs(); 1037 if (rhs->type().bt() == Type::BT_TOP) { 1038 rhs = eval_par(env, rhs); 1039 } 1040 if ((bo->decl() != nullptr) && (bo->decl()->e() != nullptr)) { 1041 return eval_call<EvalBoolVal, BinOp>(env, bo); 1042 } 1043 1044 if (lhs->type().isbool() && rhs->type().isbool()) { 1045 try { 1046 switch (bo->op()) { 1047 case BOT_LE: 1048 return static_cast<int>(eval_bool(env, lhs)) < 1049 static_cast<int>(eval_bool(env, rhs)); 1050 case BOT_LQ: 1051 return static_cast<int>(eval_bool(env, lhs)) <= 1052 static_cast<int>(eval_bool(env, rhs)); 1053 case BOT_GR: 1054 return static_cast<int>(eval_bool(env, lhs)) > 1055 static_cast<int>(eval_bool(env, rhs)); 1056 case BOT_GQ: 1057 return static_cast<int>(eval_bool(env, lhs)) >= 1058 static_cast<int>(eval_bool(env, rhs)); 1059 case BOT_EQ: 1060 return eval_bool(env, lhs) == eval_bool(env, rhs); 1061 case BOT_NQ: 1062 return eval_bool(env, lhs) != eval_bool(env, rhs); 1063 case BOT_EQUIV: 1064 return eval_bool(env, lhs) == eval_bool(env, rhs); 1065 case BOT_IMPL: 1066 return (!eval_bool(env, lhs)) || eval_bool(env, rhs); 1067 case BOT_RIMPL: 1068 return (!eval_bool(env, rhs)) || eval_bool(env, lhs); 1069 case BOT_OR: 1070 return eval_bool(env, lhs) || eval_bool(env, rhs); 1071 case BOT_AND: 1072 return eval_bool(env, lhs) && eval_bool(env, rhs); 1073 case BOT_XOR: 1074 return eval_bool(env, lhs) ^ eval_bool(env, rhs); 1075 default: 1076 assert(false); 1077 throw EvalError(env, e->loc(), "not a bool expression", bo->opToString()); 1078 } 1079 } catch (ResultUndefinedError&) { 1080 return false; 1081 } 1082 } else if (lhs->type().isint() && rhs->type().isint()) { 1083 try { 1084 IntVal v0 = eval_int(env, lhs); 1085 IntVal v1 = eval_int(env, rhs); 1086 switch (bo->op()) { 1087 case BOT_LE: 1088 return v0 < v1; 1089 case BOT_LQ: 1090 return v0 <= v1; 1091 case BOT_GR: 1092 return v0 > v1; 1093 case BOT_GQ: 1094 return v0 >= v1; 1095 case BOT_EQ: 1096 return v0 == v1; 1097 case BOT_NQ: 1098 return v0 != v1; 1099 default: 1100 assert(false); 1101 throw EvalError(env, e->loc(), "not a bool expression", bo->opToString()); 1102 } 1103 } catch (ResultUndefinedError&) { 1104 return false; 1105 } 1106 } else if (lhs->type().isfloat() && rhs->type().isfloat()) { 1107 try { 1108 FloatVal v0 = eval_float(env, lhs); 1109 FloatVal v1 = eval_float(env, rhs); 1110 switch (bo->op()) { 1111 case BOT_LE: 1112 return v0 < v1; 1113 case BOT_LQ: 1114 return v0 <= v1; 1115 case BOT_GR: 1116 return v0 > v1; 1117 case BOT_GQ: 1118 return v0 >= v1; 1119 case BOT_EQ: 1120 return v0 == v1; 1121 case BOT_NQ: 1122 return v0 != v1; 1123 default: 1124 assert(false); 1125 throw EvalError(env, e->loc(), "not a bool expression", bo->opToString()); 1126 } 1127 } catch (ResultUndefinedError&) { 1128 return false; 1129 } 1130 } else if (lhs->type().isint() && rhs->type().isIntSet()) { 1131 try { 1132 IntVal v0 = eval_int(env, lhs); 1133 GCLock lock; 1134 IntSetVal* v1 = eval_intset(env, rhs); 1135 switch (bo->op()) { 1136 case BOT_IN: 1137 return v1->contains(v0); 1138 default: 1139 assert(false); 1140 throw EvalError(env, e->loc(), "not a bool expression", bo->opToString()); 1141 } 1142 } catch (ResultUndefinedError&) { 1143 return false; 1144 } 1145 } else if (lhs->type().isfloat() && rhs->type().isFloatSet()) { 1146 try { 1147 FloatVal v0 = eval_float(env, lhs); 1148 GCLock lock; 1149 FloatSetVal* v1 = eval_floatset(env, rhs); 1150 switch (bo->op()) { 1151 case BOT_IN: 1152 return v1->contains(v0); 1153 default: 1154 assert(false); 1155 throw EvalError(env, e->loc(), "not a bool expression", bo->opToString()); 1156 } 1157 } catch (ResultUndefinedError&) { 1158 return false; 1159 } 1160 } else if (lhs->type().isSet() && rhs->type().isSet()) { 1161 try { 1162 GCLock lock; 1163 IntSetVal* v0 = eval_intset(env, lhs); 1164 IntSetVal* v1 = eval_intset(env, rhs); 1165 IntSetRanges ir0(v0); 1166 IntSetRanges ir1(v1); 1167 switch (bo->op()) { 1168 case BOT_LE: 1169 return Ranges::less(ir0, ir1); 1170 case BOT_LQ: 1171 return Ranges::less_eq(ir0, ir1); 1172 case BOT_GR: 1173 return Ranges::less(ir1, ir0); 1174 case BOT_GQ: 1175 return Ranges::less_eq(ir1, ir0); 1176 case BOT_EQ: 1177 return Ranges::equal(ir0, ir1); 1178 case BOT_NQ: 1179 return !Ranges::equal(ir0, ir1); 1180 case BOT_SUBSET: 1181 return Ranges::subset(ir0, ir1); 1182 case BOT_SUPERSET: 1183 return Ranges::subset(ir1, ir0); 1184 default: 1185 throw EvalError(env, e->loc(), "not a bool expression", bo->opToString()); 1186 } 1187 } catch (ResultUndefinedError&) { 1188 return false; 1189 } 1190 } else if (lhs->type().isstring() && rhs->type().isstring()) { 1191 try { 1192 GCLock lock; 1193 std::string s0 = eval_string(env, lhs); 1194 std::string s1 = eval_string(env, rhs); 1195 switch (bo->op()) { 1196 case BOT_EQ: 1197 return s0 == s1; 1198 case BOT_NQ: 1199 return s0 != s1; 1200 case BOT_LE: 1201 return s0 < s1; 1202 case BOT_LQ: 1203 return s0 <= s1; 1204 case BOT_GR: 1205 return s0 > s1; 1206 case BOT_GQ: 1207 return s0 >= s1; 1208 default: 1209 throw EvalError(env, e->loc(), "not a bool expression", bo->opToString()); 1210 } 1211 } catch (ResultUndefinedError&) { 1212 return false; 1213 } 1214 } else if (bo->op() == BOT_EQ && lhs->type().isAnn()) { 1215 // follow ann id to value, since there might be indirection (e.g. func argument, see 1216 // test_equality_of_indirect_annotations.mzn) 1217 return Expression::equal(follow_id_to_value(lhs), follow_id_to_value(rhs)); 1218 } else if (bo->op() == BOT_EQ && lhs->type().dim() > 0 && rhs->type().dim() > 0) { 1219 try { 1220 ArrayLit* al0 = eval_array_lit(env, lhs); 1221 ArrayLit* al1 = eval_array_lit(env, rhs); 1222 if (al0->size() != al1->size()) { 1223 return false; 1224 } 1225 for (unsigned int i = 0; i < al0->size(); i++) { 1226 if (!Expression::equal(eval_par(env, (*al0)[i]), eval_par(env, (*al1)[i]))) { 1227 return false; 1228 } 1229 } 1230 return true; 1231 } catch (ResultUndefinedError&) { 1232 return false; 1233 } 1234 } else { 1235 throw EvalError(env, e->loc(), "not a bool expression", bo->opToString()); 1236 } 1237 } break; 1238 case Expression::E_UNOP: { 1239 UnOp* uo = e->cast<UnOp>(); 1240 if ((uo->decl() != nullptr) && (uo->decl()->e() != nullptr)) { 1241 return eval_call<EvalBoolVal, UnOp>(env, uo); 1242 } 1243 bool v0 = eval_bool(env, uo->e()); 1244 switch (uo->op()) { 1245 case UOT_NOT: 1246 return !v0; 1247 default: 1248 assert(false); 1249 throw EvalError(env, e->loc(), "not a bool expression", uo->opToString()); 1250 } 1251 } break; 1252 case Expression::E_CALL: { 1253 try { 1254 Call* ce = e->cast<Call>(); 1255 if (ce->decl() == nullptr) { 1256 throw EvalError(env, e->loc(), "undeclared function", ce->id()); 1257 } 1258 1259 if (ce->decl()->builtins.b != nullptr) { 1260 return ce->decl()->builtins.b(env, ce); 1261 } 1262 1263 if (ce->decl()->builtins.e != nullptr) { 1264 return eval_bool(env, ce->decl()->builtins.e(env, ce)); 1265 } 1266 1267 if (ce->decl()->e() == nullptr) { 1268 std::ostringstream ss; 1269 ss << "internal error: missing builtin '" << ce->id() << "'"; 1270 throw EvalError(env, ce->loc(), ss.str()); 1271 } 1272 1273 return eval_call<EvalBoolVal>(env, ce); 1274 } catch (ResultUndefinedError&) { 1275 return false; 1276 } 1277 } break; 1278 case Expression::E_LET: { 1279 Let* l = e->cast<Let>(); 1280 l->pushbindings(); 1281 bool ret = true; 1282 for (unsigned int i = 0; i < l->let().size(); i++) { 1283 // Evaluate all variable declarations 1284 if (auto* vdi = l->let()[i]->dynamicCast<VarDecl>()) { 1285 vdi->e(eval_par(env, vdi->e())); 1286 bool maybe_partial = vdi->ann().contains(constants().ann.maybe_partial); 1287 if (maybe_partial) { 1288 env.inMaybePartial++; 1289 } 1290 try { 1291 check_par_declaration(env, vdi); 1292 } catch (ResultUndefinedError&) { 1293 ret = false; 1294 } 1295 if (maybe_partial) { 1296 env.inMaybePartial--; 1297 } 1298 } else { 1299 // This is a constraint item. Since the let is par, 1300 // it can only be a par bool expression. If it evaluates 1301 // to false, it means that the value of this let is false. 1302 if (!eval_bool(env, l->let()[i])) { 1303 if (l->let()[i]->ann().contains(constants().ann.maybe_partial)) { 1304 ret = false; 1305 } else { 1306 throw ResultUndefinedError(env, l->let()[i]->loc(), 1307 "domain constraint in let failed"); 1308 } 1309 } 1310 } 1311 } 1312 ret = ret && eval_bool(env, l->in()); 1313 l->popbindings(); 1314 return ret; 1315 } break; 1316 default: 1317 assert(false); 1318 return false; 1319 } 1320 } catch (ResultUndefinedError&) { 1321 // undefined means false 1322 return false; 1323 } 1324} 1325 1326IntSetVal* eval_boolset(EnvI& env, Expression* e) { 1327 CallStackItem csi(env, e); 1328 switch (e->eid()) { 1329 case Expression::E_SETLIT: { 1330 auto* sl = e->cast<SetLit>(); 1331 if (sl->isv() != nullptr) { 1332 return sl->isv(); 1333 } 1334 std::vector<IntVal> vals; 1335 for (unsigned int i = 0; i < sl->v().size(); i++) { 1336 Expression* vi = eval_par(env, sl->v()[i]); 1337 if (vi != constants().absent) { 1338 vals.push_back(eval_int(env, vi)); 1339 } 1340 } 1341 return IntSetVal::a(vals); 1342 } 1343 case Expression::E_BOOLLIT: 1344 case Expression::E_INTLIT: 1345 case Expression::E_FLOATLIT: 1346 case Expression::E_STRINGLIT: 1347 case Expression::E_ANON: 1348 case Expression::E_TIID: 1349 case Expression::E_VARDECL: 1350 case Expression::E_TI: 1351 throw EvalError(env, e->loc(), "not a set of bool expression"); 1352 break; 1353 case Expression::E_ARRAYLIT: { 1354 auto* al = e->cast<ArrayLit>(); 1355 std::vector<IntVal> vals(al->size()); 1356 for (unsigned int i = 0; i < al->size(); i++) { 1357 vals[i] = static_cast<long long>(eval_bool(env, (*al)[i])); 1358 } 1359 return IntSetVal::a(vals); 1360 } break; 1361 case Expression::E_COMP: { 1362 auto* c = e->cast<Comprehension>(); 1363 std::vector<IntVal> a = eval_comp<EvalIntVal>(env, c); 1364 return IntSetVal::a(a); 1365 } 1366 case Expression::E_ID: { 1367 GCLock lock; 1368 return eval_id<EvalBoolSetLit>(env, e)->isv(); 1369 } break; 1370 case Expression::E_ARRAYACCESS: { 1371 GCLock lock; 1372 return eval_boolset(env, eval_arrayaccess(env, e->cast<ArrayAccess>())); 1373 } break; 1374 case Expression::E_ITE: { 1375 ITE* ite = e->cast<ITE>(); 1376 for (int i = 0; i < ite->size(); i++) { 1377 if (eval_bool(env, ite->ifExpr(i))) { 1378 return eval_boolset(env, ite->thenExpr(i)); 1379 } 1380 } 1381 return eval_boolset(env, ite->elseExpr()); 1382 } break; 1383 case Expression::E_BINOP: { 1384 auto* bo = e->cast<BinOp>(); 1385 if ((bo->decl() != nullptr) && (bo->decl()->e() != nullptr)) { 1386 return eval_call<EvalBoolSet, BinOp>(env, bo); 1387 } 1388 Expression* lhs = eval_par(env, bo->lhs()); 1389 Expression* rhs = eval_par(env, bo->rhs()); 1390 if (lhs->type().isIntSet() && rhs->type().isIntSet()) { 1391 IntSetVal* v0 = eval_boolset(env, lhs); 1392 IntSetVal* v1 = eval_boolset(env, rhs); 1393 IntSetRanges ir0(v0); 1394 IntSetRanges ir1(v1); 1395 switch (bo->op()) { 1396 case BOT_UNION: { 1397 Ranges::Union<IntVal, IntSetRanges, IntSetRanges> u(ir0, ir1); 1398 return IntSetVal::ai(u); 1399 } 1400 case BOT_DIFF: { 1401 Ranges::Diff<IntVal, IntSetRanges, IntSetRanges> u(ir0, ir1); 1402 return IntSetVal::ai(u); 1403 } 1404 case BOT_SYMDIFF: { 1405 Ranges::Union<IntVal, IntSetRanges, IntSetRanges> u(ir0, ir1); 1406 Ranges::Inter<IntVal, IntSetRanges, IntSetRanges> i(ir0, ir1); 1407 Ranges::Diff<IntVal, Ranges::Union<IntVal, IntSetRanges, IntSetRanges>, 1408 Ranges::Inter<IntVal, IntSetRanges, IntSetRanges>> 1409 sd(u, i); 1410 return IntSetVal::ai(sd); 1411 } 1412 case BOT_INTERSECT: { 1413 Ranges::Inter<IntVal, IntSetRanges, IntSetRanges> u(ir0, ir1); 1414 return IntSetVal::ai(u); 1415 } 1416 default: 1417 throw EvalError(env, e->loc(), "not a set of bool expression", bo->opToString()); 1418 } 1419 } else if (lhs->type().isbool() && rhs->type().isbool()) { 1420 if (bo->op() != BOT_DOTDOT) { 1421 throw EvalError(env, e->loc(), "not a set of bool expression", bo->opToString()); 1422 } 1423 return IntSetVal::a(static_cast<long long>(eval_bool(env, lhs)), 1424 static_cast<long long>(eval_bool(env, rhs))); 1425 } else { 1426 throw EvalError(env, e->loc(), "not a set of bool expression", bo->opToString()); 1427 } 1428 } break; 1429 case Expression::E_UNOP: { 1430 UnOp* uo = e->cast<UnOp>(); 1431 if ((uo->decl() != nullptr) && (uo->decl()->e() != nullptr)) { 1432 return eval_call<EvalBoolSet, UnOp>(env, uo); 1433 } 1434 throw EvalError(env, e->loc(), "not a set of bool expression"); 1435 } 1436 case Expression::E_CALL: { 1437 Call* ce = e->cast<Call>(); 1438 if (ce->decl() == nullptr) { 1439 throw EvalError(env, e->loc(), "undeclared function", ce->id()); 1440 } 1441 1442 if (ce->decl()->builtins.s != nullptr) { 1443 return ce->decl()->builtins.s(env, ce); 1444 } 1445 1446 if (ce->decl()->builtins.e != nullptr) { 1447 return eval_boolset(env, ce->decl()->builtins.e(env, ce)); 1448 } 1449 1450 if (ce->decl()->e() == nullptr) { 1451 std::ostringstream ss; 1452 ss << "internal error: missing builtin '" << ce->id() << "'"; 1453 throw EvalError(env, ce->loc(), ss.str()); 1454 } 1455 1456 return eval_call<EvalBoolSet>(env, ce); 1457 } break; 1458 case Expression::E_LET: { 1459 Let* l = e->cast<Let>(); 1460 l->pushbindings(); 1461 for (unsigned int i = 0; i < l->let().size(); i++) { 1462 // Evaluate all variable declarations 1463 if (auto* vdi = l->let()[i]->dynamicCast<VarDecl>()) { 1464 vdi->e(eval_par(env, vdi->e())); 1465 check_par_declaration(env, vdi); 1466 } else { 1467 // This is a constraint item. Since the let is par, 1468 // it can only be a par bool expression. If it evaluates 1469 // to false, it means that the value of this let is undefined. 1470 if (!eval_bool(env, l->let()[i])) { 1471 throw ResultUndefinedError(env, l->let()[i]->loc(), "constraint in let failed"); 1472 } 1473 } 1474 } 1475 IntSetVal* ret = eval_boolset(env, l->in()); 1476 l->popbindings(); 1477 return ret; 1478 } break; 1479 default: 1480 assert(false); 1481 return nullptr; 1482 } 1483} 1484 1485IntVal eval_int(EnvI& env, Expression* e) { 1486 if (e->type().isbool()) { 1487 return static_cast<long long>(eval_bool(env, e)); 1488 } 1489 if (auto* il = e->dynamicCast<IntLit>()) { 1490 return il->v(); 1491 } 1492 CallStackItem csi(env, e); 1493 try { 1494 switch (e->eid()) { 1495 case Expression::E_FLOATLIT: 1496 case Expression::E_BOOLLIT: 1497 case Expression::E_STRINGLIT: 1498 case Expression::E_ANON: 1499 case Expression::E_TIID: 1500 case Expression::E_SETLIT: 1501 case Expression::E_ARRAYLIT: 1502 case Expression::E_COMP: 1503 case Expression::E_VARDECL: 1504 case Expression::E_TI: 1505 throw EvalError(env, e->loc(), "not an integer expression"); 1506 break; 1507 case Expression::E_ID: { 1508 GCLock lock; 1509 return eval_id<EvalIntLit>(env, e)->v(); 1510 } break; 1511 case Expression::E_ARRAYACCESS: { 1512 GCLock lock; 1513 return eval_int(env, eval_arrayaccess(env, e->cast<ArrayAccess>())); 1514 } break; 1515 case Expression::E_ITE: { 1516 ITE* ite = e->cast<ITE>(); 1517 for (int i = 0; i < ite->size(); i++) { 1518 if (eval_bool(env, ite->ifExpr(i))) { 1519 return eval_int(env, ite->thenExpr(i)); 1520 } 1521 } 1522 return eval_int(env, ite->elseExpr()); 1523 } break; 1524 case Expression::E_BINOP: { 1525 auto* bo = e->cast<BinOp>(); 1526 if ((bo->decl() != nullptr) && (bo->decl()->e() != nullptr)) { 1527 return eval_call<EvalIntVal, BinOp>(env, bo); 1528 } 1529 IntVal v0 = eval_int(env, bo->lhs()); 1530 IntVal v1 = eval_int(env, bo->rhs()); 1531 switch (bo->op()) { 1532 case BOT_PLUS: 1533 return v0 + v1; 1534 case BOT_MINUS: 1535 return v0 - v1; 1536 case BOT_MULT: 1537 return v0 * v1; 1538 case BOT_POW: 1539 return v0.pow(v1); 1540 case BOT_IDIV: 1541 if (v1 == 0) { 1542 throw ResultUndefinedError(env, e->loc(), "division by zero"); 1543 } 1544 return v0 / v1; 1545 case BOT_MOD: 1546 if (v1 == 0) { 1547 throw ResultUndefinedError(env, e->loc(), "division by zero"); 1548 } 1549 return v0 % v1; 1550 default: 1551 throw EvalError(env, e->loc(), "not an integer expression", bo->opToString()); 1552 } 1553 } break; 1554 case Expression::E_UNOP: { 1555 UnOp* uo = e->cast<UnOp>(); 1556 if ((uo->decl() != nullptr) && (uo->decl()->e() != nullptr)) { 1557 return eval_call<EvalIntVal, UnOp>(env, uo); 1558 } 1559 IntVal v0 = eval_int(env, uo->e()); 1560 switch (uo->op()) { 1561 case UOT_PLUS: 1562 return v0; 1563 case UOT_MINUS: 1564 return -v0; 1565 default: 1566 throw EvalError(env, e->loc(), "not an integer expression", uo->opToString()); 1567 } 1568 } break; 1569 case Expression::E_CALL: { 1570 Call* ce = e->cast<Call>(); 1571 if (ce->decl() == nullptr) { 1572 throw EvalError(env, e->loc(), "undeclared function", ce->id()); 1573 } 1574 if (ce->decl()->builtins.i != nullptr) { 1575 return ce->decl()->builtins.i(env, ce); 1576 } 1577 1578 if (ce->decl()->builtins.e != nullptr) { 1579 return eval_int(env, ce->decl()->builtins.e(env, ce)); 1580 } 1581 1582 if (ce->decl()->e() == nullptr) { 1583 std::ostringstream ss; 1584 ss << "internal error: missing builtin '" << ce->id() << "'"; 1585 throw EvalError(env, ce->loc(), ss.str()); 1586 } 1587 1588 return eval_call<EvalIntVal>(env, ce); 1589 } break; 1590 case Expression::E_LET: { 1591 Let* l = e->cast<Let>(); 1592 l->pushbindings(); 1593 for (unsigned int i = 0; i < l->let().size(); i++) { 1594 // Evaluate all variable declarations 1595 if (auto* vdi = l->let()[i]->dynamicCast<VarDecl>()) { 1596 vdi->e(eval_par(env, vdi->e())); 1597 check_par_declaration(env, vdi); 1598 } else { 1599 // This is a constraint item. Since the let is par, 1600 // it can only be a par bool expression. If it evaluates 1601 // to false, it means that the value of this let is undefined. 1602 if (!eval_bool(env, l->let()[i])) { 1603 throw ResultUndefinedError(env, l->let()[i]->loc(), "constraint in let failed"); 1604 } 1605 } 1606 } 1607 IntVal ret = eval_int(env, l->in()); 1608 l->popbindings(); 1609 return ret; 1610 } break; 1611 default: 1612 assert(false); 1613 return 0; 1614 } 1615 } catch (ArithmeticError& err) { 1616 throw EvalError(env, e->loc(), err.msg()); 1617 } 1618} 1619 1620FloatVal eval_float(EnvI& env, Expression* e) { 1621 if (e->type().isint()) { 1622 return static_cast<double>(eval_int(env, e).toInt()); 1623 } 1624 if (e->type().isbool()) { 1625 return static_cast<double>(eval_bool(env, e)); 1626 } 1627 CallStackItem csi(env, e); 1628 try { 1629 if (auto* fl = e->dynamicCast<FloatLit>()) { 1630 return fl->v(); 1631 } 1632 switch (e->eid()) { 1633 case Expression::E_INTLIT: 1634 case Expression::E_BOOLLIT: 1635 case Expression::E_STRINGLIT: 1636 case Expression::E_ANON: 1637 case Expression::E_TIID: 1638 case Expression::E_SETLIT: 1639 case Expression::E_ARRAYLIT: 1640 case Expression::E_COMP: 1641 case Expression::E_VARDECL: 1642 case Expression::E_TI: 1643 throw EvalError(env, e->loc(), "not a float expression"); 1644 break; 1645 case Expression::E_ID: { 1646 GCLock lock; 1647 return eval_id<EvalFloatLit>(env, e)->v(); 1648 } break; 1649 case Expression::E_ARRAYACCESS: { 1650 GCLock lock; 1651 return eval_float(env, eval_arrayaccess(env, e->cast<ArrayAccess>())); 1652 } break; 1653 case Expression::E_ITE: { 1654 ITE* ite = e->cast<ITE>(); 1655 for (int i = 0; i < ite->size(); i++) { 1656 if (eval_bool(env, ite->ifExpr(i))) { 1657 return eval_float(env, ite->thenExpr(i)); 1658 } 1659 } 1660 return eval_float(env, ite->elseExpr()); 1661 } break; 1662 case Expression::E_BINOP: { 1663 auto* bo = e->cast<BinOp>(); 1664 if ((bo->decl() != nullptr) && (bo->decl()->e() != nullptr)) { 1665 return eval_call<EvalFloatVal, BinOp>(env, bo); 1666 } 1667 FloatVal v0 = eval_float(env, bo->lhs()); 1668 FloatVal v1 = eval_float(env, bo->rhs()); 1669 switch (bo->op()) { 1670 case BOT_PLUS: 1671 return v0 + v1; 1672 case BOT_MINUS: 1673 return v0 - v1; 1674 case BOT_MULT: 1675 return v0 * v1; 1676 case BOT_POW: 1677 return std::pow(v0.toDouble(), v1.toDouble()); 1678 case BOT_DIV: 1679 if (v1 == 0.0) { 1680 throw ResultUndefinedError(env, e->loc(), "division by zero"); 1681 } 1682 return v0 / v1; 1683 default: 1684 throw EvalError(env, e->loc(), "not a float expression", bo->opToString()); 1685 } 1686 } break; 1687 case Expression::E_UNOP: { 1688 UnOp* uo = e->cast<UnOp>(); 1689 if ((uo->decl() != nullptr) && (uo->decl()->e() != nullptr)) { 1690 return eval_call<EvalFloatVal, UnOp>(env, uo); 1691 } 1692 FloatVal v0 = eval_float(env, uo->e()); 1693 switch (uo->op()) { 1694 case UOT_PLUS: 1695 return v0; 1696 case UOT_MINUS: 1697 return -v0; 1698 default: 1699 throw EvalError(env, e->loc(), "not a float expression", uo->opToString()); 1700 } 1701 } break; 1702 case Expression::E_CALL: { 1703 Call* ce = e->cast<Call>(); 1704 if (ce->decl() == nullptr) { 1705 throw EvalError(env, e->loc(), "undeclared function", ce->id()); 1706 } 1707 if (ce->decl()->builtins.f != nullptr) { 1708 return ce->decl()->builtins.f(env, ce); 1709 } 1710 1711 if (ce->decl()->builtins.e != nullptr) { 1712 return eval_float(env, ce->decl()->builtins.e(env, ce)); 1713 } 1714 1715 if (ce->decl()->e() == nullptr) { 1716 std::ostringstream ss; 1717 ss << "internal error: missing builtin '" << ce->id() << "'"; 1718 throw EvalError(env, ce->loc(), ss.str()); 1719 } 1720 1721 return eval_call<EvalFloatVal>(env, ce); 1722 } break; 1723 case Expression::E_LET: { 1724 Let* l = e->cast<Let>(); 1725 l->pushbindings(); 1726 for (unsigned int i = 0; i < l->let().size(); i++) { 1727 // Evaluate all variable declarations 1728 if (auto* vdi = l->let()[i]->dynamicCast<VarDecl>()) { 1729 vdi->e(eval_par(env, vdi->e())); 1730 check_par_declaration(env, vdi); 1731 } else { 1732 // This is a constraint item. Since the let is par, 1733 // it can only be a par bool expression. If it evaluates 1734 // to false, it means that the value of this let is undefined. 1735 if (!eval_bool(env, l->let()[i])) { 1736 throw ResultUndefinedError(env, l->let()[i]->loc(), "constraint in let failed"); 1737 } 1738 } 1739 } 1740 FloatVal ret = eval_float(env, l->in()); 1741 l->popbindings(); 1742 return ret; 1743 } break; 1744 default: 1745 assert(false); 1746 return 0.0; 1747 } 1748 } catch (ArithmeticError& err) { 1749 throw EvalError(env, e->loc(), err.msg()); 1750 } 1751} 1752 1753std::string eval_string(EnvI& env, Expression* e) { 1754 CallStackItem csi(env, e); 1755 switch (e->eid()) { 1756 case Expression::E_STRINGLIT: { 1757 ASTString str = e->cast<StringLit>()->v(); 1758 return std::string(str.c_str(), str.size()); 1759 } 1760 case Expression::E_FLOATLIT: 1761 case Expression::E_INTLIT: 1762 case Expression::E_BOOLLIT: 1763 case Expression::E_ANON: 1764 case Expression::E_TIID: 1765 case Expression::E_SETLIT: 1766 case Expression::E_ARRAYLIT: 1767 case Expression::E_COMP: 1768 case Expression::E_VARDECL: 1769 case Expression::E_TI: 1770 throw EvalError(env, e->loc(), "not a string expression"); 1771 break; 1772 case Expression::E_ID: { 1773 GCLock lock; 1774 ASTString str = eval_id<EvalStringLit>(env, e)->v(); 1775 return std::string(str.c_str(), str.size()); 1776 } break; 1777 case Expression::E_ARRAYACCESS: { 1778 GCLock lock; 1779 return eval_string(env, eval_arrayaccess(env, e->cast<ArrayAccess>())); 1780 } break; 1781 case Expression::E_ITE: { 1782 ITE* ite = e->cast<ITE>(); 1783 for (int i = 0; i < ite->size(); i++) { 1784 if (eval_bool(env, ite->ifExpr(i))) { 1785 return eval_string(env, ite->thenExpr(i)); 1786 } 1787 } 1788 return eval_string(env, ite->elseExpr()); 1789 } break; 1790 case Expression::E_BINOP: { 1791 auto* bo = e->cast<BinOp>(); 1792 if ((bo->decl() != nullptr) && (bo->decl()->e() != nullptr)) { 1793 return eval_call<EvalString, BinOp>(env, bo); 1794 } 1795 std::string v0 = eval_string(env, bo->lhs()); 1796 std::string v1 = eval_string(env, bo->rhs()); 1797 switch (bo->op()) { 1798 case BOT_PLUSPLUS: 1799 return v0 + v1; 1800 default: 1801 throw EvalError(env, e->loc(), "not a string expression", bo->opToString()); 1802 } 1803 } break; 1804 case Expression::E_UNOP: { 1805 UnOp* uo = e->cast<UnOp>(); 1806 if ((uo->decl() != nullptr) && (uo->decl()->e() != nullptr)) { 1807 return eval_call<EvalString, UnOp>(env, uo); 1808 } 1809 throw EvalError(env, e->loc(), "not a string expression"); 1810 } break; 1811 case Expression::E_CALL: { 1812 Call* ce = e->cast<Call>(); 1813 if (ce->decl() == nullptr) { 1814 throw EvalError(env, e->loc(), "undeclared function", ce->id()); 1815 } 1816 1817 if (ce->decl()->builtins.str != nullptr) { 1818 return ce->decl()->builtins.str(env, ce); 1819 } 1820 if (ce->decl()->builtins.e != nullptr) { 1821 return eval_string(env, ce->decl()->builtins.e(env, ce)); 1822 } 1823 1824 if (ce->decl()->e() == nullptr) { 1825 std::ostringstream ss; 1826 ss << "internal error: missing builtin '" << ce->id() << "'"; 1827 throw EvalError(env, ce->loc(), ss.str()); 1828 } 1829 1830 return eval_call<EvalString>(env, ce); 1831 } break; 1832 case Expression::E_LET: { 1833 Let* l = e->cast<Let>(); 1834 l->pushbindings(); 1835 for (unsigned int i = 0; i < l->let().size(); i++) { 1836 // Evaluate all variable declarations 1837 if (auto* vdi = l->let()[i]->dynamicCast<VarDecl>()) { 1838 vdi->e(eval_par(env, vdi->e())); 1839 check_par_declaration(env, vdi); 1840 } else { 1841 // This is a constraint item. Since the let is par, 1842 // it can only be a par bool expression. If it evaluates 1843 // to false, it means that the value of this let is undefined. 1844 if (!eval_bool(env, l->let()[i])) { 1845 throw ResultUndefinedError(env, l->let()[i]->loc(), "constraint in let failed"); 1846 } 1847 } 1848 } 1849 std::string ret = eval_string(env, l->in()); 1850 l->popbindings(); 1851 return ret; 1852 } break; 1853 default: 1854 assert(false); 1855 return ""; 1856 } 1857} 1858 1859Expression* eval_par(EnvI& env, Expression* e) { 1860 if (e == nullptr) { 1861 return nullptr; 1862 } 1863 switch (e->eid()) { 1864 case Expression::E_ANON: 1865 case Expression::E_TIID: { 1866 return e; 1867 } 1868 case Expression::E_COMP: 1869 if (e->cast<Comprehension>()->set()) { 1870 return EvalSetLit::e(env, e); 1871 } 1872 // fall through 1873 case Expression::E_ARRAYLIT: { 1874 ArrayLit* al = eval_array_lit(env, e); 1875 std::vector<Expression*> args(al->size()); 1876 bool allFlat = true; 1877 for (unsigned int i = 0; i < al->size(); i++) { 1878 Expression* ali = (*al)[i]; 1879 if (!ali->isa<IntLit>() && !ali->isa<FloatLit>() && !ali->isa<BoolLit>() && 1880 !(ali->isa<SetLit>() && ali->cast<SetLit>()->evaluated())) { 1881 allFlat = false; 1882 args[i] = eval_par(env, ali); 1883 } else { 1884 args[i] = ali; 1885 } 1886 } 1887 if (allFlat) { 1888 return al; 1889 } 1890 std::vector<std::pair<int, int>> dims(al->dims()); 1891 for (unsigned int i = al->dims(); (i--) != 0U;) { 1892 dims[i].first = al->min(i); 1893 dims[i].second = al->max(i); 1894 } 1895 auto* ret = new ArrayLit(al->loc(), args, dims); 1896 Type t = al->type(); 1897 if (t.isbot() && ret->size() > 0) { 1898 t.bt((*ret)[0]->type().bt()); 1899 } 1900 ret->type(t); 1901 return ret; 1902 } 1903 case Expression::E_VARDECL: { 1904 auto* vd = e->cast<VarDecl>(); 1905 throw EvalError(env, vd->loc(), "cannot evaluate variable declaration", vd->id()->v()); 1906 } 1907 case Expression::E_TI: { 1908 auto* t = e->cast<TypeInst>(); 1909 ASTExprVec<TypeInst> r; 1910 if (t->ranges().size() > 0) { 1911 std::vector<TypeInst*> rv(t->ranges().size()); 1912 for (unsigned int i = t->ranges().size(); (i--) != 0U;) { 1913 rv[i] = static_cast<TypeInst*>(eval_par(env, t->ranges()[i])); 1914 } 1915 r = ASTExprVec<TypeInst>(rv); 1916 } 1917 return new TypeInst(Location(), t->type(), r, eval_par(env, t->domain())); 1918 } 1919 case Expression::E_ID: { 1920 if (e == constants().absent) { 1921 return e; 1922 } 1923 Id* id = e->cast<Id>(); 1924 if (id->decl() == nullptr) { 1925 throw EvalError(env, e->loc(), "undefined identifier", id->v()); 1926 } 1927 if (id->decl()->ti()->domain() != nullptr) { 1928 if (auto* bl = id->decl()->ti()->domain()->dynamicCast<BoolLit>()) { 1929 return bl; 1930 } 1931 if (id->decl()->ti()->type().isint()) { 1932 if (auto* sl = id->decl()->ti()->domain()->dynamicCast<SetLit>()) { 1933 if ((sl->isv() != nullptr) && sl->isv()->min() == sl->isv()->max()) { 1934 return IntLit::a(sl->isv()->min()); 1935 } 1936 } 1937 } else if (id->decl()->ti()->type().isfloat()) { 1938 if (id->decl()->ti()->domain() != nullptr) { 1939 FloatSetVal* fsv = eval_floatset(env, id->decl()->ti()->domain()); 1940 if (fsv->min() == fsv->max()) { 1941 return FloatLit::a(fsv->min()); 1942 } 1943 } 1944 } 1945 } 1946 if (id->decl()->e() == nullptr) { 1947 return id; 1948 } 1949 return eval_par(env, id->decl()->e()); 1950 } 1951 case Expression::E_STRINGLIT: 1952 return e; 1953 default: { 1954 if (e->type().dim() != 0) { 1955 ArrayLit* al = eval_array_lit(env, e); 1956 std::vector<Expression*> args(al->size()); 1957 for (unsigned int i = al->size(); (i--) != 0U;) { 1958 args[i] = eval_par(env, (*al)[i]); 1959 } 1960 std::vector<std::pair<int, int>> dims(al->dims()); 1961 for (unsigned int i = al->dims(); (i--) != 0U;) { 1962 dims[i].first = al->min(i); 1963 dims[i].second = al->max(i); 1964 } 1965 auto* ret = new ArrayLit(al->loc(), args, dims); 1966 Type t = al->type(); 1967 if ((t.bt() == Type::BT_BOT || t.bt() == Type::BT_TOP) && ret->size() > 0) { 1968 t.bt((*ret)[0]->type().bt()); 1969 } 1970 ret->type(t); 1971 return ret; 1972 } 1973 if (e->type().isPar()) { 1974 if (e->type().isSet()) { 1975 return EvalSetLit::e(env, e); 1976 } 1977 if (e->type() == Type::parint()) { 1978 return EvalIntLit::e(env, e); 1979 } 1980 if (e->type() == Type::parbool()) { 1981 return EvalBoolLit::e(env, e); 1982 } 1983 if (e->type() == Type::parfloat()) { 1984 return EvalFloatLit::e(env, e); 1985 } 1986 if (e->type() == Type::parstring()) { 1987 return EvalStringLit::e(env, e); 1988 } 1989 } 1990 switch (e->eid()) { 1991 case Expression::E_ITE: { 1992 ITE* ite = e->cast<ITE>(); 1993 for (int i = 0; i < ite->size(); i++) { 1994 if (ite->ifExpr(i)->type() == Type::parbool()) { 1995 if (eval_bool(env, ite->ifExpr(i))) { 1996 return eval_par(env, ite->thenExpr(i)); 1997 } 1998 } else { 1999 std::vector<Expression*> e_ifthen(ite->size() * 2); 2000 for (int i = 0; i < ite->size(); i++) { 2001 e_ifthen[2 * i] = eval_par(env, ite->ifExpr(i)); 2002 e_ifthen[2 * i + 1] = eval_par(env, ite->thenExpr(i)); 2003 } 2004 ITE* n_ite = new ITE(ite->loc(), e_ifthen, eval_par(env, ite->elseExpr())); 2005 n_ite->type(ite->type()); 2006 return n_ite; 2007 } 2008 } 2009 return eval_par(env, ite->elseExpr()); 2010 } 2011 case Expression::E_CALL: { 2012 Call* c = e->cast<Call>(); 2013 if (c->decl() != nullptr) { 2014 if (c->decl()->builtins.e != nullptr) { 2015 return eval_par(env, c->decl()->builtins.e(env, c)); 2016 } 2017 if (c->decl()->e() == nullptr) { 2018 if (c->id() == "deopt" && Expression::equal(c->arg(0), constants().absent)) { 2019 throw ResultUndefinedError(env, e->loc(), "deopt(<>) is undefined"); 2020 } 2021 return c; 2022 } 2023 return eval_call<EvalPar>(env, c); 2024 } 2025 std::vector<Expression*> args(c->argCount()); 2026 for (unsigned int i = 0; i < args.size(); i++) { 2027 args[i] = eval_par(env, c->arg(i)); 2028 } 2029 Call* nc = new Call(c->loc(), c->id(), args); 2030 nc->type(c->type()); 2031 return nc; 2032 } 2033 case Expression::E_BINOP: { 2034 auto* bo = e->cast<BinOp>(); 2035 if ((bo->decl() != nullptr) && (bo->decl()->e() != nullptr)) { 2036 return eval_call<EvalPar, BinOp>(env, bo); 2037 } 2038 auto* nbo = 2039 new BinOp(e->loc(), eval_par(env, bo->lhs()), bo->op(), eval_par(env, bo->rhs())); 2040 nbo->type(bo->type()); 2041 return nbo; 2042 } 2043 case Expression::E_UNOP: { 2044 UnOp* uo = e->cast<UnOp>(); 2045 if ((uo->decl() != nullptr) && (uo->decl()->e() != nullptr)) { 2046 return eval_call<EvalPar, UnOp>(env, uo); 2047 } 2048 UnOp* nuo = new UnOp(e->loc(), uo->op(), eval_par(env, uo->e())); 2049 nuo->type(uo->type()); 2050 return nuo; 2051 } 2052 case Expression::E_ARRAYACCESS: { 2053 auto* aa = e->cast<ArrayAccess>(); 2054 for (unsigned int i = 0; i < aa->idx().size(); i++) { 2055 if (!aa->idx()[i]->type().isPar()) { 2056 std::vector<Expression*> idx(aa->idx().size()); 2057 for (unsigned int j = 0; j < aa->idx().size(); j++) { 2058 idx[j] = eval_par(env, aa->idx()[j]); 2059 } 2060 auto* aa_new = new ArrayAccess(e->loc(), eval_par(env, aa->v()), idx); 2061 aa_new->type(aa->type()); 2062 return aa_new; 2063 } 2064 } 2065 return eval_par(env, eval_arrayaccess(env, aa)); 2066 } 2067 case Expression::E_LET: { 2068 Let* l = e->cast<Let>(); 2069 assert(l->type().isPar()); 2070 l->pushbindings(); 2071 for (unsigned int i = 0; i < l->let().size(); i++) { 2072 // Evaluate all variable declarations 2073 if (auto* vdi = l->let()[i]->dynamicCast<VarDecl>()) { 2074 vdi->e(eval_par(env, vdi->e())); 2075 check_par_declaration(env, vdi); 2076 } else { 2077 // This is a constraint item. Since the let is par, 2078 // it can only be a par bool expression. If it evaluates 2079 // to false, it means that the value of this let is undefined. 2080 if (!eval_bool(env, l->let()[i])) { 2081 throw ResultUndefinedError(env, l->let()[i]->loc(), "constraint in let failed"); 2082 } 2083 } 2084 } 2085 Expression* ret = eval_par(env, l->in()); 2086 l->popbindings(); 2087 return ret; 2088 } 2089 default: 2090 return e; 2091 } 2092 } 2093 } 2094} 2095 2096class ComputeIntBounds : public EVisitor { 2097public: 2098 typedef std::pair<IntVal, IntVal> Bounds; 2099 std::vector<Bounds> bounds; 2100 bool valid; 2101 EnvI& env; 2102 ComputeIntBounds(EnvI& env0) : valid(true), env(env0) {} 2103 bool enter(Expression* e) { 2104 if (e->type().isAnn()) { 2105 return false; 2106 } 2107 if (e->isa<VarDecl>()) { 2108 return false; 2109 } 2110 if (e->type().dim() > 0) { 2111 return false; 2112 } 2113 if (e->type().isPar()) { 2114 if (e->type().isint()) { 2115 Expression* exp = eval_par(env, e); 2116 if (exp == constants().absent) { 2117 valid = false; 2118 } else { 2119 IntVal v = exp->cast<IntLit>()->v(); 2120 bounds.emplace_back(v, v); 2121 } 2122 } else { 2123 valid = false; 2124 } 2125 return false; 2126 } 2127 if (e->type().isint()) { 2128 if (ITE* ite = e->dynamicCast<ITE>()) { 2129 Bounds itebounds(IntVal::infinity(), -IntVal::infinity()); 2130 for (int i = 0; i < ite->size(); i++) { 2131 if (ite->ifExpr(i)->type().isPar() && 2132 static_cast<int>(ite->ifExpr(i)->type().cv()) == Type::CV_NO) { 2133 if (eval_bool(env, ite->ifExpr(i))) { 2134 BottomUpIterator<ComputeIntBounds> cbi(*this); 2135 cbi.run(ite->thenExpr(i)); 2136 Bounds& back = bounds.back(); 2137 back.first = std::min(itebounds.first, back.first); 2138 back.second = std::max(itebounds.second, back.second); 2139 return false; 2140 } 2141 } else { 2142 BottomUpIterator<ComputeIntBounds> cbi(*this); 2143 cbi.run(ite->thenExpr(i)); 2144 Bounds back = bounds.back(); 2145 bounds.pop_back(); 2146 itebounds.first = std::min(itebounds.first, back.first); 2147 itebounds.second = std::max(itebounds.second, back.second); 2148 } 2149 } 2150 BottomUpIterator<ComputeIntBounds> cbi(*this); 2151 cbi.run(ite->elseExpr()); 2152 Bounds& back = bounds.back(); 2153 back.first = std::min(itebounds.first, back.first); 2154 back.second = std::max(itebounds.second, back.second); 2155 return false; 2156 } 2157 return true; 2158 } 2159 return false; 2160 } 2161 /// Visit integer literal 2162 void vIntLit(const IntLit& i) { bounds.emplace_back(i.v(), i.v()); } 2163 /// Visit floating point literal 2164 void vFloatLit(const FloatLit& /*f*/) { 2165 valid = false; 2166 bounds.emplace_back(0, 0); 2167 } 2168 /// Visit Boolean literal 2169 void vBoolLit(const BoolLit& /*b*/) { 2170 valid = false; 2171 bounds.emplace_back(0, 0); 2172 } 2173 /// Visit set literal 2174 void vSetLit(const SetLit& /*sl*/) { 2175 valid = false; 2176 bounds.emplace_back(0, 0); 2177 } 2178 /// Visit string literal 2179 void vStringLit(const StringLit& /*sl*/) { 2180 valid = false; 2181 bounds.emplace_back(0, 0); 2182 } 2183 /// Visit identifier 2184 void vId(const Id& id) { 2185 VarDecl* vd = id.decl(); 2186 while ((vd->flat() != nullptr) && vd->flat() != vd) { 2187 vd = vd->flat(); 2188 } 2189 if (vd->ti()->domain() != nullptr) { 2190 GCLock lock; 2191 IntSetVal* isv = eval_intset(env, vd->ti()->domain()); 2192 if (isv->size() == 0) { 2193 valid = false; 2194 bounds.emplace_back(0, 0); 2195 } else { 2196 bounds.emplace_back(isv->min(0), isv->max(isv->size() - 1)); 2197 } 2198 } else { 2199 if (vd->e() != nullptr) { 2200 BottomUpIterator<ComputeIntBounds> cbi(*this); 2201 cbi.run(vd->e()); 2202 } else { 2203 bounds.emplace_back(-IntVal::infinity(), IntVal::infinity()); 2204 } 2205 } 2206 } 2207 /// Visit anonymous variable 2208 void vAnonVar(const AnonVar& /*v*/) { 2209 valid = false; 2210 bounds.emplace_back(0, 0); 2211 } 2212 /// Visit array literal 2213 void vArrayLit(const ArrayLit& /*al*/) {} 2214 /// Visit array access 2215 void vArrayAccess(ArrayAccess& aa) { 2216 bool parAccess = true; 2217 for (unsigned int i = aa.idx().size(); (i--) != 0U;) { 2218 bounds.pop_back(); 2219 if (!aa.idx()[i]->type().isPar()) { 2220 parAccess = false; 2221 } 2222 } 2223 if (Id* id = aa.v()->dynamicCast<Id>()) { 2224 while ((id->decl()->e() != nullptr) && id->decl()->e()->isa<Id>()) { 2225 id = id->decl()->e()->cast<Id>(); 2226 } 2227 if (parAccess && (id->decl()->e() != nullptr)) { 2228 bool success; 2229 Expression* e = eval_arrayaccess(env, &aa, success); 2230 if (success) { 2231 BottomUpIterator<ComputeIntBounds> cbi(*this); 2232 cbi.run(e); 2233 return; 2234 } 2235 } 2236 if (id->decl()->ti()->domain() != nullptr) { 2237 GCLock lock; 2238 IntSetVal* isv = eval_intset(env, id->decl()->ti()->domain()); 2239 if (isv->size() > 0) { 2240 bounds.emplace_back(isv->min(0), isv->max(isv->size() - 1)); 2241 return; 2242 } 2243 } 2244 } 2245 valid = false; 2246 bounds.emplace_back(0, 0); 2247 } 2248 /// Visit array comprehension 2249 void vComprehension(const Comprehension& c) { 2250 valid = false; 2251 bounds.emplace_back(0, 0); 2252 } 2253 /// Visit if-then-else 2254 void vITE(const ITE& /*ite*/) { 2255 valid = false; 2256 bounds.emplace_back(0, 0); 2257 } 2258 /// Visit binary operator 2259 void vBinOp(const BinOp& bo) { 2260 Bounds b1 = bounds.back(); 2261 bounds.pop_back(); 2262 Bounds b0 = bounds.back(); 2263 bounds.pop_back(); 2264 if (!b1.first.isFinite() || !b1.second.isFinite() || !b0.first.isFinite() || 2265 !b0.second.isFinite()) { 2266 valid = false; 2267 bounds.emplace_back(0, 0); 2268 } else { 2269 switch (bo.op()) { 2270 case BOT_PLUS: 2271 bounds.emplace_back(b0.first + b1.first, b0.second + b1.second); 2272 break; 2273 case BOT_MINUS: 2274 bounds.emplace_back(b0.first - b1.second, b0.second - b1.first); 2275 break; 2276 case BOT_MULT: { 2277 IntVal x0 = b0.first * b1.first; 2278 IntVal x1 = b0.first * b1.second; 2279 IntVal x2 = b0.second * b1.first; 2280 IntVal x3 = b0.second * b1.second; 2281 IntVal m = std::min(x0, std::min(x1, std::min(x2, x3))); 2282 IntVal n = std::max(x0, std::max(x1, std::max(x2, x3))); 2283 bounds.emplace_back(m, n); 2284 } break; 2285 case BOT_IDIV: { 2286 IntVal b0f = b0.first == 0 ? 1 : b0.first; 2287 IntVal b0s = b0.second == 0 ? -1 : b0.second; 2288 IntVal b1f = b1.first == 0 ? 1 : b1.first; 2289 IntVal b1s = b1.second == 0 ? -1 : b1.second; 2290 IntVal x0 = b0f / b1f; 2291 IntVal x1 = b0f / b1s; 2292 IntVal x2 = b0s / b1f; 2293 IntVal x3 = b0s / b1s; 2294 IntVal m = std::min(x0, std::min(x1, std::min(x2, x3))); 2295 IntVal n = std::max(x0, std::max(x1, std::max(x2, x3))); 2296 bounds.emplace_back(m, n); 2297 } break; 2298 case BOT_MOD: { 2299 IntVal b0f = b0.first == 0 ? 1 : b0.first; 2300 IntVal b0s = b0.second == 0 ? -1 : b0.second; 2301 IntVal b1f = b1.first == 0 ? 1 : b1.first; 2302 IntVal b1s = b1.second == 0 ? -1 : b1.second; 2303 IntVal x0 = b0f % b1f; 2304 IntVal x1 = b0f % b1s; 2305 IntVal x2 = b0s % b1f; 2306 IntVal x3 = b0s % b1s; 2307 IntVal m = std::min(x0, std::min(x1, std::min(x2, x3))); 2308 IntVal n = std::max(x0, std::max(x1, std::max(x2, x3))); 2309 bounds.emplace_back(m, n); 2310 } break; 2311 case BOT_POW: { 2312 IntVal exp_min = std::min(0, b1.first); 2313 IntVal exp_max = std::min(0, b1.second); 2314 2315 IntVal x0 = b0.first.pow(exp_min); 2316 IntVal x1 = b0.first.pow(exp_max); 2317 IntVal x2 = b0.second.pow(exp_min); 2318 IntVal x3 = b0.second.pow(exp_max); 2319 IntVal m = std::min(x0, std::min(x1, std::min(x2, x3))); 2320 IntVal n = std::max(x0, std::max(x1, std::max(x2, x3))); 2321 bounds.emplace_back(m, n); 2322 } break; 2323 case BOT_DIV: 2324 case BOT_LE: 2325 case BOT_LQ: 2326 case BOT_GR: 2327 case BOT_GQ: 2328 case BOT_EQ: 2329 case BOT_NQ: 2330 case BOT_IN: 2331 case BOT_SUBSET: 2332 case BOT_SUPERSET: 2333 case BOT_UNION: 2334 case BOT_DIFF: 2335 case BOT_SYMDIFF: 2336 case BOT_INTERSECT: 2337 case BOT_PLUSPLUS: 2338 case BOT_EQUIV: 2339 case BOT_IMPL: 2340 case BOT_RIMPL: 2341 case BOT_OR: 2342 case BOT_AND: 2343 case BOT_XOR: 2344 case BOT_DOTDOT: 2345 valid = false; 2346 bounds.emplace_back(0, 0); 2347 } 2348 } 2349 } 2350 /// Visit unary operator 2351 void vUnOp(const UnOp& uo) { 2352 switch (uo.op()) { 2353 case UOT_PLUS: 2354 break; 2355 case UOT_MINUS: 2356 bounds.back().first = -bounds.back().first; 2357 bounds.back().second = -bounds.back().second; 2358 std::swap(bounds.back().first, bounds.back().second); 2359 break; 2360 case UOT_NOT: 2361 valid = false; 2362 } 2363 } 2364 /// Visit call 2365 void vCall(Call& c) { 2366 if (c.id() == constants().ids.lin_exp || c.id() == constants().ids.sum) { 2367 bool le = c.id() == constants().ids.lin_exp; 2368 ArrayLit* coeff = le ? eval_array_lit(env, c.arg(0)) : nullptr; 2369 if (c.arg(le ? 1 : 0)->type().isOpt()) { 2370 valid = false; 2371 bounds.emplace_back(0, 0); 2372 return; 2373 } 2374 ArrayLit* al = eval_array_lit(env, c.arg(le ? 1 : 0)); 2375 if (le) { 2376 bounds.pop_back(); // remove constant (third arg) from stack 2377 } 2378 2379 IntVal d = le ? c.arg(2)->cast<IntLit>()->v() : 0; 2380 int stacktop = static_cast<int>(bounds.size()); 2381 for (unsigned int i = al->size(); (i--) != 0U;) { 2382 BottomUpIterator<ComputeIntBounds> cbi(*this); 2383 cbi.run((*al)[i]); 2384 if (!valid) { 2385 for (unsigned int j = al->size() - 1; j > i; j--) { 2386 bounds.pop_back(); 2387 } 2388 return; 2389 } 2390 } 2391 assert(stacktop + al->size() == bounds.size()); 2392 IntVal lb = d; 2393 IntVal ub = d; 2394 for (unsigned int i = 0; i < al->size(); i++) { 2395 Bounds b = bounds.back(); 2396 bounds.pop_back(); 2397 IntVal cv = le ? eval_int(env, (*coeff)[i]) : 1; 2398 if (cv > 0) { 2399 if (b.first.isFinite()) { 2400 if (lb.isFinite()) { 2401 lb += cv * b.first; 2402 } 2403 } else { 2404 lb = b.first; 2405 } 2406 if (b.second.isFinite()) { 2407 if (ub.isFinite()) { 2408 ub += cv * b.second; 2409 } 2410 } else { 2411 ub = b.second; 2412 } 2413 } else { 2414 if (b.second.isFinite()) { 2415 if (lb.isFinite()) { 2416 lb += cv * b.second; 2417 } 2418 } else { 2419 lb = -b.second; 2420 } 2421 if (b.first.isFinite()) { 2422 if (ub.isFinite()) { 2423 ub += cv * b.first; 2424 } 2425 } else { 2426 ub = -b.first; 2427 } 2428 } 2429 } 2430 bounds.emplace_back(lb, ub); 2431 } else if (c.id() == "card") { 2432 if (IntSetVal* isv = compute_intset_bounds(env, c.arg(0))) { 2433 IntSetRanges isr(isv); 2434 bounds.emplace_back(0, Ranges::cardinality(isr)); 2435 } else { 2436 valid = false; 2437 bounds.emplace_back(0, 0); 2438 } 2439 } else if (c.id() == "int_times") { 2440 Bounds b1 = bounds.back(); 2441 bounds.pop_back(); 2442 Bounds b0 = bounds.back(); 2443 bounds.pop_back(); 2444 if (!b1.first.isFinite() || !b1.second.isFinite() || !b0.first.isFinite() || 2445 !b0.second.isFinite()) { 2446 valid = false; 2447 bounds.emplace_back(0, 0); 2448 } else { 2449 IntVal x0 = b0.first * b1.first; 2450 IntVal x1 = b0.first * b1.second; 2451 IntVal x2 = b0.second * b1.first; 2452 IntVal x3 = b0.second * b1.second; 2453 IntVal m = std::min(x0, std::min(x1, std::min(x2, x3))); 2454 IntVal n = std::max(x0, std::max(x1, std::max(x2, x3))); 2455 bounds.emplace_back(m, n); 2456 } 2457 } else if (c.id() == constants().ids.bool2int) { 2458 bounds.emplace_back(0, 1); 2459 } else if (c.id() == "abs") { 2460 Bounds b0 = bounds.back(); 2461 if (b0.first < 0) { 2462 bounds.pop_back(); 2463 if (b0.second < 0) { 2464 bounds.emplace_back(-b0.second, -b0.first); 2465 } else { 2466 bounds.emplace_back(0, std::max(-b0.first, b0.second)); 2467 } 2468 } 2469 } else if ((c.decl() != nullptr) && (c.decl()->ti()->domain() != nullptr) && 2470 !c.decl()->ti()->domain()->isa<TIId>()) { 2471 for (int i = 0; i < c.argCount(); i++) { 2472 if (c.arg(i)->type().isint()) { 2473 assert(!bounds.empty()); 2474 bounds.pop_back(); 2475 } 2476 } 2477 IntSetVal* isv = eval_intset(env, c.decl()->ti()->domain()); 2478 bounds.emplace_back(isv->min(), isv->max()); 2479 } else { 2480 valid = false; 2481 bounds.emplace_back(0, 0); 2482 } 2483 } 2484 /// Visit let 2485 void vLet(const Let& l) { 2486 valid = false; 2487 bounds.emplace_back(0, 0); 2488 } 2489 /// Visit variable declaration 2490 void vVarDecl(const VarDecl& vd) { 2491 valid = false; 2492 bounds.emplace_back(0, 0); 2493 } 2494 /// Visit annotation 2495 void vAnnotation(const Annotation& e) { 2496 valid = false; 2497 bounds.emplace_back(0, 0); 2498 } 2499 /// Visit type inst 2500 void vTypeInst(const TypeInst& e) { 2501 valid = false; 2502 bounds.emplace_back(0, 0); 2503 } 2504 /// Visit TIId 2505 void vTIId(const TIId& e) { 2506 valid = false; 2507 bounds.emplace_back(0, 0); 2508 } 2509}; 2510 2511IntBounds compute_int_bounds(EnvI& env, Expression* e) { 2512 try { 2513 ComputeIntBounds cb(env); 2514 BottomUpIterator<ComputeIntBounds> cbi(cb); 2515 cbi.run(e); 2516 if (cb.valid) { 2517 assert(cb.bounds.size() == 1); 2518 return IntBounds(cb.bounds.back().first, cb.bounds.back().second, true); 2519 } 2520 return IntBounds(0, 0, false); 2521 2522 } catch (ResultUndefinedError&) { 2523 return IntBounds(0, 0, false); 2524 } 2525} 2526 2527class ComputeFloatBounds : public EVisitor { 2528protected: 2529 typedef std::pair<FloatVal, FloatVal> FBounds; 2530 2531public: 2532 std::vector<FBounds> bounds; 2533 bool valid; 2534 EnvI& env; 2535 ComputeFloatBounds(EnvI& env0) : valid(true), env(env0) {} 2536 bool enter(Expression* e) { 2537 if (e->type().isAnn()) { 2538 return false; 2539 } 2540 if (e->isa<VarDecl>()) { 2541 return false; 2542 } 2543 if (e->type().dim() > 0) { 2544 return false; 2545 } 2546 if (e->type().isPar()) { 2547 if (e->type().isfloat()) { 2548 Expression* exp = eval_par(env, e); 2549 if (exp == constants().absent) { 2550 valid = false; 2551 } else { 2552 FloatVal v = exp->cast<FloatLit>()->v(); 2553 bounds.emplace_back(v, v); 2554 } 2555 } 2556 return false; 2557 } 2558 if (e->type().isfloat()) { 2559 if (ITE* ite = e->dynamicCast<ITE>()) { 2560 FBounds itebounds(FloatVal::infinity(), -FloatVal::infinity()); 2561 for (int i = 0; i < ite->size(); i++) { 2562 if (ite->ifExpr(i)->type().isPar() && 2563 static_cast<int>(ite->ifExpr(i)->type().cv()) == Type::CV_NO) { 2564 if (eval_bool(env, ite->ifExpr(i))) { 2565 BottomUpIterator<ComputeFloatBounds> cbi(*this); 2566 cbi.run(ite->thenExpr(i)); 2567 FBounds& back = bounds.back(); 2568 back.first = std::min(itebounds.first, back.first); 2569 back.second = std::max(itebounds.second, back.second); 2570 return false; 2571 } 2572 } else { 2573 BottomUpIterator<ComputeFloatBounds> cbi(*this); 2574 cbi.run(ite->thenExpr(i)); 2575 FBounds back = bounds.back(); 2576 bounds.pop_back(); 2577 itebounds.first = std::min(itebounds.first, back.first); 2578 itebounds.second = std::max(itebounds.second, back.second); 2579 } 2580 } 2581 BottomUpIterator<ComputeFloatBounds> cbi(*this); 2582 cbi.run(ite->elseExpr()); 2583 FBounds& back = bounds.back(); 2584 back.first = std::min(itebounds.first, back.first); 2585 back.second = std::max(itebounds.second, back.second); 2586 return false; 2587 } 2588 return true; 2589 } 2590 return false; 2591 } 2592 /// Visit integer literal 2593 void vIntLit(const IntLit& i) { 2594 valid = false; 2595 bounds.emplace_back(0.0, 0.0); 2596 } 2597 /// Visit floating point literal 2598 void vFloatLit(const FloatLit& f) { bounds.emplace_back(f.v(), f.v()); } 2599 /// Visit Boolean literal 2600 void vBoolLit(const BoolLit& /*b*/) { 2601 valid = false; 2602 bounds.emplace_back(0.0, 0.0); 2603 } 2604 /// Visit set literal 2605 void vSetLit(const SetLit& /*sl*/) { 2606 valid = false; 2607 bounds.emplace_back(0.0, 0.0); 2608 } 2609 /// Visit string literal 2610 void vStringLit(const StringLit& /*sl*/) { 2611 valid = false; 2612 bounds.emplace_back(0.0, 0.0); 2613 } 2614 /// Visit identifier 2615 void vId(const Id& id) { 2616 VarDecl* vd = id.decl(); 2617 while ((vd->flat() != nullptr) && vd->flat() != vd) { 2618 vd = vd->flat(); 2619 } 2620 if (vd->ti()->domain() != nullptr) { 2621 GCLock lock; 2622 FloatSetVal* fsv = eval_floatset(env, vd->ti()->domain()); 2623 if (fsv->size() == 0) { 2624 valid = false; 2625 bounds.emplace_back(0, 0); 2626 } else { 2627 bounds.emplace_back(fsv->min(0), fsv->max(fsv->size() - 1)); 2628 } 2629 } else { 2630 if (vd->e() != nullptr) { 2631 BottomUpIterator<ComputeFloatBounds> cbi(*this); 2632 cbi.run(vd->e()); 2633 } else { 2634 bounds.emplace_back(-FloatVal::infinity(), FloatVal::infinity()); 2635 } 2636 } 2637 } 2638 /// Visit anonymous variable 2639 void vAnonVar(const AnonVar& v) { 2640 valid = false; 2641 bounds.emplace_back(0.0, 0.0); 2642 } 2643 /// Visit array literal 2644 void vArrayLit(const ArrayLit& al) {} 2645 /// Visit array access 2646 void vArrayAccess(ArrayAccess& aa) { 2647 bool parAccess = true; 2648 for (unsigned int i = aa.idx().size(); (i--) != 0U;) { 2649 if (!aa.idx()[i]->type().isPar()) { 2650 parAccess = false; 2651 } 2652 } 2653 if (Id* id = aa.v()->dynamicCast<Id>()) { 2654 while ((id->decl()->e() != nullptr) && id->decl()->e()->isa<Id>()) { 2655 id = id->decl()->e()->cast<Id>(); 2656 } 2657 if (parAccess && (id->decl()->e() != nullptr)) { 2658 bool success; 2659 Expression* e = eval_arrayaccess(env, &aa, success); 2660 if (success) { 2661 BottomUpIterator<ComputeFloatBounds> cbi(*this); 2662 cbi.run(e); 2663 return; 2664 } 2665 } 2666 if (id->decl()->ti()->domain() != nullptr) { 2667 FloatSetVal* fsv = eval_floatset(env, id->decl()->ti()->domain()); 2668 FBounds b(fsv->min(), fsv->max()); 2669 bounds.push_back(b); 2670 return; 2671 } 2672 } 2673 valid = false; 2674 bounds.emplace_back(0.0, 0.0); 2675 } 2676 /// Visit array comprehension 2677 void vComprehension(const Comprehension& c) { 2678 valid = false; 2679 bounds.emplace_back(0.0, 0.0); 2680 } 2681 /// Visit if-then-else 2682 void vITE(const ITE& ite) { 2683 valid = false; 2684 bounds.emplace_back(0.0, 0.0); 2685 } 2686 /// Visit binary operator 2687 void vBinOp(const BinOp& bo) { 2688 FBounds b1 = bounds.back(); 2689 bounds.pop_back(); 2690 FBounds b0 = bounds.back(); 2691 bounds.pop_back(); 2692 if (!b1.first.isFinite() || !b1.second.isFinite() || !b0.first.isFinite() || 2693 !b0.second.isFinite()) { 2694 valid = false; 2695 bounds.emplace_back(0.0, 0.0); 2696 } else { 2697 switch (bo.op()) { 2698 case BOT_PLUS: 2699 bounds.emplace_back(b0.first + b1.first, b0.second + b1.second); 2700 break; 2701 case BOT_MINUS: 2702 bounds.emplace_back(b0.first - b1.second, b0.second - b1.first); 2703 break; 2704 case BOT_MULT: { 2705 FloatVal x0 = b0.first * b1.first; 2706 FloatVal x1 = b0.first * b1.second; 2707 FloatVal x2 = b0.second * b1.first; 2708 FloatVal x3 = b0.second * b1.second; 2709 FloatVal m = std::min(x0, std::min(x1, std::min(x2, x3))); 2710 FloatVal n = std::max(x0, std::max(x1, std::max(x2, x3))); 2711 bounds.emplace_back(m, n); 2712 } break; 2713 case BOT_POW: { 2714 FloatVal x0 = std::pow(b0.first.toDouble(), b1.first.toDouble()); 2715 FloatVal x1 = std::pow(b0.first.toDouble(), b1.second.toDouble()); 2716 FloatVal x2 = std::pow(b0.second.toDouble(), b1.first.toDouble()); 2717 FloatVal x3 = std::pow(b0.second.toDouble(), b1.second.toDouble()); 2718 FloatVal m = std::min(x0, std::min(x1, std::min(x2, x3))); 2719 FloatVal n = std::max(x0, std::max(x1, std::max(x2, x3))); 2720 bounds.emplace_back(m, n); 2721 } break; 2722 case BOT_DIV: 2723 case BOT_IDIV: 2724 case BOT_MOD: 2725 case BOT_LE: 2726 case BOT_LQ: 2727 case BOT_GR: 2728 case BOT_GQ: 2729 case BOT_EQ: 2730 case BOT_NQ: 2731 case BOT_IN: 2732 case BOT_SUBSET: 2733 case BOT_SUPERSET: 2734 case BOT_UNION: 2735 case BOT_DIFF: 2736 case BOT_SYMDIFF: 2737 case BOT_INTERSECT: 2738 case BOT_PLUSPLUS: 2739 case BOT_EQUIV: 2740 case BOT_IMPL: 2741 case BOT_RIMPL: 2742 case BOT_OR: 2743 case BOT_AND: 2744 case BOT_XOR: 2745 case BOT_DOTDOT: 2746 valid = false; 2747 bounds.emplace_back(0.0, 0.0); 2748 } 2749 } 2750 } 2751 /// Visit unary operator 2752 void vUnOp(const UnOp& uo) { 2753 switch (uo.op()) { 2754 case UOT_PLUS: 2755 break; 2756 case UOT_MINUS: 2757 bounds.back().first = -bounds.back().first; 2758 bounds.back().second = -bounds.back().second; 2759 break; 2760 case UOT_NOT: 2761 valid = false; 2762 bounds.emplace_back(0.0, 0.0); 2763 } 2764 } 2765 /// Visit call 2766 void vCall(Call& c) { 2767 if (c.id() == constants().ids.lin_exp || c.id() == constants().ids.sum) { 2768 bool le = c.id() == constants().ids.lin_exp; 2769 ArrayLit* coeff = le ? eval_array_lit(env, c.arg(0)) : nullptr; 2770 if (le) { 2771 bounds.pop_back(); // remove constant (third arg) from stack 2772 } 2773 if (c.arg(le ? 1 : 0)->type().isOpt()) { 2774 valid = false; 2775 bounds.emplace_back(0.0, 0.0); 2776 return; 2777 } 2778 ArrayLit* al = eval_array_lit(env, c.arg(le ? 1 : 0)); 2779 FloatVal d = le ? c.arg(2)->cast<FloatLit>()->v() : 0.0; 2780 int stacktop = static_cast<int>(bounds.size()); 2781 for (unsigned int i = al->size(); (i--) != 0U;) { 2782 BottomUpIterator<ComputeFloatBounds> cbi(*this); 2783 cbi.run((*al)[i]); 2784 if (!valid) { 2785 return; 2786 } 2787 } 2788 assert(stacktop + al->size() == bounds.size()); 2789 FloatVal lb = d; 2790 FloatVal ub = d; 2791 for (unsigned int i = 0; i < (*al).size(); i++) { 2792 FBounds b = bounds.back(); 2793 bounds.pop_back(); 2794 FloatVal cv = le ? eval_float(env, (*coeff)[i]) : 1.0; 2795 2796 if (cv > 0) { 2797 if (b.first.isFinite()) { 2798 if (lb.isFinite()) { 2799 lb += cv * b.first; 2800 } 2801 } else { 2802 lb = b.first; 2803 } 2804 if (b.second.isFinite()) { 2805 if (ub.isFinite()) { 2806 ub += cv * b.second; 2807 } 2808 } else { 2809 ub = b.second; 2810 } 2811 } else { 2812 if (b.second.isFinite()) { 2813 if (lb.isFinite()) { 2814 lb += cv * b.second; 2815 } 2816 } else { 2817 lb = -b.second; 2818 } 2819 if (b.first.isFinite()) { 2820 if (ub.isFinite()) { 2821 ub += cv * b.first; 2822 } 2823 } else { 2824 ub = -b.first; 2825 } 2826 } 2827 } 2828 bounds.emplace_back(lb, ub); 2829 } else if (c.id() == "float_times") { 2830 BottomUpIterator<ComputeFloatBounds> cbi(*this); 2831 cbi.run(c.arg(0)); 2832 cbi.run(c.arg(1)); 2833 FBounds b1 = bounds.back(); 2834 bounds.pop_back(); 2835 FBounds b0 = bounds.back(); 2836 bounds.pop_back(); 2837 if (!b1.first.isFinite() || !b1.second.isFinite() || !b0.first.isFinite() || 2838 !b0.second.isFinite()) { 2839 valid = false; 2840 bounds.emplace_back(0, 0); 2841 } else { 2842 FloatVal x0 = b0.first * b1.first; 2843 FloatVal x1 = b0.first * b1.second; 2844 FloatVal x2 = b0.second * b1.first; 2845 FloatVal x3 = b0.second * b1.second; 2846 FloatVal m = std::min(x0, std::min(x1, std::min(x2, x3))); 2847 FloatVal n = std::max(x0, std::max(x1, std::max(x2, x3))); 2848 bounds.emplace_back(m, n); 2849 } 2850 } else if (c.id() == "int2float") { 2851 ComputeIntBounds ib(env); 2852 BottomUpIterator<ComputeIntBounds> cbi(ib); 2853 cbi.run(c.arg(0)); 2854 if (!ib.valid) { 2855 valid = false; 2856 } 2857 ComputeIntBounds::Bounds result = ib.bounds.back(); 2858 if (!result.first.isFinite() || !result.second.isFinite()) { 2859 valid = false; 2860 bounds.emplace_back(0.0, 0.0); 2861 } else { 2862 bounds.emplace_back(static_cast<double>(result.first.toInt()), 2863 static_cast<double>(result.second.toInt())); 2864 } 2865 } else if (c.id() == "abs") { 2866 BottomUpIterator<ComputeFloatBounds> cbi(*this); 2867 cbi.run(c.arg(0)); 2868 FBounds b0 = bounds.back(); 2869 if (b0.first < 0) { 2870 bounds.pop_back(); 2871 if (b0.second < 0) { 2872 bounds.emplace_back(-b0.second, -b0.first); 2873 } else { 2874 bounds.emplace_back(0.0, std::max(-b0.first, b0.second)); 2875 } 2876 } 2877 } else if ((c.decl() != nullptr) && (c.decl()->ti()->domain() != nullptr) && 2878 !c.decl()->ti()->domain()->isa<TIId>()) { 2879 for (int i = 0; i < c.argCount(); i++) { 2880 if (c.arg(i)->type().isfloat()) { 2881 assert(!bounds.empty()); 2882 bounds.pop_back(); 2883 } 2884 } 2885 FloatSetVal* fsv = eval_floatset(env, c.decl()->ti()->domain()); 2886 bounds.emplace_back(fsv->min(), fsv->max()); 2887 } else { 2888 valid = false; 2889 bounds.emplace_back(0.0, 0.0); 2890 } 2891 } 2892 /// Visit let 2893 void vLet(const Let& l) { 2894 valid = false; 2895 bounds.emplace_back(0.0, 0.0); 2896 } 2897 /// Visit variable declaration 2898 void vVarDecl(const VarDecl& vd) { 2899 valid = false; 2900 bounds.emplace_back(0.0, 0.0); 2901 } 2902 /// Visit annotation 2903 void vAnnotation(const Annotation& e) { 2904 valid = false; 2905 bounds.emplace_back(0.0, 0.0); 2906 } 2907 /// Visit type inst 2908 void vTypeInst(const TypeInst& e) { 2909 valid = false; 2910 bounds.emplace_back(0.0, 0.0); 2911 } 2912 /// Visit TIId 2913 void vTIId(const TIId& e) { 2914 valid = false; 2915 bounds.emplace_back(0.0, 0.0); 2916 } 2917}; 2918 2919FloatBounds compute_float_bounds(EnvI& env, Expression* e) { 2920 try { 2921 ComputeFloatBounds cb(env); 2922 BottomUpIterator<ComputeFloatBounds> cbi(cb); 2923 cbi.run(e); 2924 if (cb.valid) { 2925 assert(!cb.bounds.empty()); 2926 return FloatBounds(cb.bounds.back().first, cb.bounds.back().second, true); 2927 } 2928 return FloatBounds(0.0, 0.0, false); 2929 2930 } catch (ResultUndefinedError&) { 2931 return FloatBounds(0.0, 0.0, false); 2932 } 2933} 2934 2935class ComputeIntSetBounds : public EVisitor { 2936public: 2937 std::vector<IntSetVal*> bounds; 2938 bool valid; 2939 EnvI& env; 2940 ComputeIntSetBounds(EnvI& env0) : valid(true), env(env0) {} 2941 bool enter(Expression* e) { 2942 if (e->type().isAnn()) { 2943 return false; 2944 } 2945 if (e->isa<VarDecl>()) { 2946 return false; 2947 } 2948 if (e->type().dim() > 0) { 2949 return false; 2950 } 2951 if (!e->type().isIntSet()) { 2952 return false; 2953 } 2954 if (e->type().isPar()) { 2955 bounds.push_back(eval_intset(env, e)); 2956 return false; 2957 } 2958 return true; 2959 } 2960 /// Visit set literal 2961 void vSetLit(const SetLit& sl) { 2962 assert(sl.type().isvar()); 2963 assert(sl.isv() == nullptr); 2964 2965 IntSetVal* isv = IntSetVal::a(); 2966 for (unsigned int i = 0; i < sl.v().size(); i++) { 2967 IntSetRanges i0(isv); 2968 IntBounds ib = compute_int_bounds(env, sl.v()[i]); 2969 if (!ib.valid || !ib.l.isFinite() || !ib.u.isFinite()) { 2970 valid = false; 2971 bounds.push_back(nullptr); 2972 return; 2973 } 2974 Ranges::Const<IntVal> cr(ib.l, ib.u); 2975 Ranges::Union<IntVal, IntSetRanges, Ranges::Const<IntVal>> u(i0, cr); 2976 isv = IntSetVal::ai(u); 2977 } 2978 bounds.push_back(isv); 2979 } 2980 /// Visit identifier 2981 void vId(const Id& id) { 2982 if ((id.decl()->ti()->domain() != nullptr) && !id.decl()->ti()->domain()->isa<TIId>()) { 2983 bounds.push_back(eval_intset(env, id.decl()->ti()->domain())); 2984 } else { 2985 if (id.decl()->e() != nullptr) { 2986 BottomUpIterator<ComputeIntSetBounds> cbi(*this); 2987 cbi.run(id.decl()->e()); 2988 } else { 2989 valid = false; 2990 bounds.push_back(nullptr); 2991 } 2992 } 2993 } 2994 /// Visit anonymous variable 2995 void vAnonVar(const AnonVar& v) { 2996 valid = false; 2997 bounds.push_back(nullptr); 2998 } 2999 /// Visit array access 3000 void vArrayAccess(ArrayAccess& aa) { 3001 bool parAccess = true; 3002 for (unsigned int i = aa.idx().size(); (i--) != 0U;) { 3003 if (!aa.idx()[i]->type().isPar()) { 3004 parAccess = false; 3005 break; 3006 } 3007 } 3008 if (Id* id = aa.v()->dynamicCast<Id>()) { 3009 while ((id->decl()->e() != nullptr) && id->decl()->e()->isa<Id>()) { 3010 id = id->decl()->e()->cast<Id>(); 3011 } 3012 if (parAccess && (id->decl()->e() != nullptr)) { 3013 bool success; 3014 Expression* e = eval_arrayaccess(env, &aa, success); 3015 if (success) { 3016 BottomUpIterator<ComputeIntSetBounds> cbi(*this); 3017 cbi.run(e); 3018 return; 3019 } 3020 } 3021 if (id->decl()->ti()->domain() != nullptr) { 3022 bounds.push_back(eval_intset(env, id->decl()->ti()->domain())); 3023 return; 3024 } 3025 } 3026 valid = false; 3027 bounds.push_back(nullptr); 3028 } 3029 /// Visit array comprehension 3030 void vComprehension(const Comprehension& c) { 3031 valid = false; 3032 bounds.push_back(nullptr); 3033 } 3034 /// Visit if-then-else 3035 void vITE(const ITE& ite) { 3036 valid = false; 3037 bounds.push_back(nullptr); 3038 } 3039 /// Visit binary operator 3040 void vBinOp(const BinOp& bo) { 3041 if (bo.op() == BOT_DOTDOT) { 3042 IntBounds lb = compute_int_bounds(env, bo.lhs()); 3043 IntBounds ub = compute_int_bounds(env, bo.rhs()); 3044 valid = valid && lb.valid && ub.valid; 3045 bounds.push_back(IntSetVal::a(lb.l, ub.u)); 3046 } else { 3047 IntSetVal* b1 = bounds.back(); 3048 bounds.pop_back(); 3049 IntSetVal* b0 = bounds.back(); 3050 bounds.pop_back(); 3051 switch (bo.op()) { 3052 case BOT_INTERSECT: 3053 case BOT_UNION: { 3054 IntSetRanges b0r(b0); 3055 IntSetRanges b1r(b1); 3056 Ranges::Union<IntVal, IntSetRanges, IntSetRanges> u(b0r, b1r); 3057 bounds.push_back(IntSetVal::ai(u)); 3058 } break; 3059 case BOT_DIFF: { 3060 bounds.push_back(b0); 3061 } break; 3062 case BOT_SYMDIFF: 3063 valid = false; 3064 bounds.push_back(nullptr); 3065 break; 3066 case BOT_PLUS: 3067 case BOT_MINUS: 3068 case BOT_MULT: 3069 case BOT_POW: 3070 case BOT_DIV: 3071 case BOT_IDIV: 3072 case BOT_MOD: 3073 case BOT_LE: 3074 case BOT_LQ: 3075 case BOT_GR: 3076 case BOT_GQ: 3077 case BOT_EQ: 3078 case BOT_NQ: 3079 case BOT_IN: 3080 case BOT_SUBSET: 3081 case BOT_SUPERSET: 3082 case BOT_PLUSPLUS: 3083 case BOT_EQUIV: 3084 case BOT_IMPL: 3085 case BOT_RIMPL: 3086 case BOT_OR: 3087 case BOT_AND: 3088 case BOT_XOR: 3089 case BOT_DOTDOT: 3090 valid = false; 3091 bounds.push_back(nullptr); 3092 } 3093 } 3094 } 3095 /// Visit unary operator 3096 void vUnOp(const UnOp& uo) { 3097 valid = false; 3098 bounds.push_back(nullptr); 3099 } 3100 /// Visit call 3101 void vCall(Call& c) { 3102 if (valid && (c.id() == "set_intersect" || c.id() == "set_union")) { 3103 IntSetVal* b0 = bounds.back(); 3104 bounds.pop_back(); 3105 IntSetVal* b1 = bounds.back(); 3106 bounds.pop_back(); 3107 IntSetRanges b0r(b0); 3108 IntSetRanges b1r(b1); 3109 Ranges::Union<IntVal, IntSetRanges, IntSetRanges> u(b0r, b1r); 3110 bounds.push_back(IntSetVal::ai(u)); 3111 } else if (valid && c.id() == "set_diff") { 3112 IntSetVal* b0 = bounds.back(); 3113 bounds.pop_back(); 3114 bounds.pop_back(); // don't need bounds of right hand side 3115 bounds.push_back(b0); 3116 } else if ((c.decl() != nullptr) && (c.decl()->ti()->domain() != nullptr) && 3117 !c.decl()->ti()->domain()->isa<TIId>()) { 3118 for (int i = 0; i < c.argCount(); i++) { 3119 if (c.arg(i)->type().isIntSet()) { 3120 assert(!bounds.empty()); 3121 bounds.pop_back(); 3122 } 3123 } 3124 IntSetVal* fsv = eval_intset(env, c.decl()->ti()->domain()); 3125 bounds.push_back(fsv); 3126 } else { 3127 valid = false; 3128 bounds.push_back(nullptr); 3129 } 3130 } 3131 /// Visit let 3132 void vLet(const Let& l) { 3133 valid = false; 3134 bounds.push_back(nullptr); 3135 } 3136 /// Visit variable declaration 3137 void vVarDecl(const VarDecl& vd) { 3138 valid = false; 3139 bounds.push_back(nullptr); 3140 } 3141 /// Visit annotation 3142 void vAnnotation(const Annotation& e) { 3143 valid = false; 3144 bounds.push_back(nullptr); 3145 } 3146 /// Visit type inst 3147 void vTypeInst(const TypeInst& e) { 3148 valid = false; 3149 bounds.push_back(nullptr); 3150 } 3151 /// Visit TIId 3152 void vTIId(const TIId& e) { 3153 valid = false; 3154 bounds.push_back(nullptr); 3155 } 3156}; 3157 3158IntSetVal* compute_intset_bounds(EnvI& env, Expression* e) { 3159 try { 3160 ComputeIntSetBounds cb(env); 3161 BottomUpIterator<ComputeIntSetBounds> cbi(cb); 3162 cbi.run(e); 3163 if (cb.valid) { 3164 return cb.bounds.back(); 3165 } 3166 return nullptr; 3167 3168 } catch (ResultUndefinedError&) { 3169 return nullptr; 3170 } 3171} 3172 3173Expression* follow_id(Expression* e) { 3174 for (;;) { 3175 if (e == nullptr) { 3176 return nullptr; 3177 } 3178 if (e->eid() == Expression::E_ID && e != constants().absent) { 3179 e = e->cast<Id>()->decl()->e(); 3180 } else { 3181 return e; 3182 } 3183 } 3184} 3185 3186Expression* follow_id_to_decl(Expression* e) { 3187 for (;;) { 3188 if (e == nullptr) { 3189 return nullptr; 3190 } 3191 if (e == constants().absent) { 3192 return e; 3193 } 3194 switch (e->eid()) { 3195 case Expression::E_ID: 3196 e = e->cast<Id>()->decl(); 3197 break; 3198 case Expression::E_VARDECL: { 3199 Expression* vd_e = e->cast<VarDecl>()->e(); 3200 if ((vd_e != nullptr) && vd_e->isa<Id>() && vd_e != constants().absent) { 3201 e = vd_e; 3202 } else { 3203 return e; 3204 } 3205 break; 3206 } 3207 default: 3208 return e; 3209 } 3210 } 3211} 3212 3213Expression* follow_id_to_value(Expression* e) { 3214 Expression* decl = follow_id_to_decl(e); 3215 if (auto* vd = decl->dynamicCast<VarDecl>()) { 3216 if ((vd->e() != nullptr) && vd->e()->type().isPar()) { 3217 return vd->e(); 3218 } 3219 return vd->id(); 3220 } 3221 return decl; 3222} 3223 3224} // namespace MiniZinc