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