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