1 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2 
3 /*
4  *  Main authors:
5  *     Guido Tack <guido.tack@monash.edu>
6  */
7 
8 /* This Source Code Form is subject to the terms of the Mozilla Public
9  * License, v. 2.0. If a copy of the MPL was not distributed with this
10  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
11 
12 #include <minizinc/ast.hh>
13 #include <minizinc/astexception.hh>
14 #include <minizinc/astiterator.hh>
15 #include <minizinc/builtins.hh>
16 #include <minizinc/config.hh>
17 #include <minizinc/eval_par.hh>
18 #include <minizinc/file_utils.hh>
19 #include <minizinc/flat_exp.hh>
20 #include <minizinc/flatten_internal.hh>
21 #include <minizinc/output.hh>
22 #include <minizinc/prettyprinter.hh>
23 #include <minizinc/support/regex.hh>
24 #include <minizinc/typecheck.hh>
25 
26 #include <climits>
27 #include <cmath>
28 #include <iomanip>
29 #include <random>
30 #include <regex>
31 
32 namespace MiniZinc {
33 
rb(EnvI & env,Model * m,const ASTString & id,const std::vector<Type> & t,FunctionI::builtin_e b,bool fromGlobals=false)34 void rb(EnvI& env, Model* m, const ASTString& id, const std::vector<Type>& t,
35         FunctionI::builtin_e b, bool fromGlobals = false) {
36   FunctionI* fi = m->matchFn(env, id, t, false);
37   if (fi != nullptr) {
38     fi->builtins.e = b;
39   } else if (!fromGlobals) {
40     std::ostringstream ss;
41     ss << "no definition found for builtin " << id;
42     throw InternalError(ss.str());
43   }
44 }
rb(EnvI & env,Model * m,const ASTString & id,const std::vector<Type> & t,FunctionI::builtin_f b,bool fromGlobals=false)45 void rb(EnvI& env, Model* m, const ASTString& id, const std::vector<Type>& t,
46         FunctionI::builtin_f b, bool fromGlobals = false) {
47   FunctionI* fi = m->matchFn(env, id, t, false);
48   if (fi != nullptr) {
49     fi->builtins.f = b;
50   } else if (!fromGlobals) {
51     std::ostringstream ss;
52     ss << "no definition found for builtin " << id;
53     throw InternalError(ss.str());
54   }
55 }
rb(EnvI & env,Model * m,const ASTString & id,const std::vector<Type> & t,FunctionI::builtin_i b,bool fromGlobals=false)56 void rb(EnvI& env, Model* m, const ASTString& id, const std::vector<Type>& t,
57         FunctionI::builtin_i b, bool fromGlobals = false) {
58   FunctionI* fi = m->matchFn(env, id, t, false);
59   if (fi != nullptr) {
60     fi->builtins.i = b;
61   } else if (!fromGlobals) {
62     std::ostringstream ss;
63     ss << "no definition found for builtin " << id;
64     throw InternalError(ss.str());
65   }
66 }
rb(EnvI & env,Model * m,const ASTString & id,const std::vector<Type> & t,FunctionI::builtin_b b,bool fromGlobals=false)67 void rb(EnvI& env, Model* m, const ASTString& id, const std::vector<Type>& t,
68         FunctionI::builtin_b b, bool fromGlobals = false) {
69   FunctionI* fi = m->matchFn(env, id, t, false);
70   if (fi != nullptr) {
71     fi->builtins.b = b;
72   } else if (!fromGlobals) {
73     std::ostringstream ss;
74     ss << "no definition found for builtin " << id;
75     throw InternalError(ss.str());
76   }
77 }
rb(EnvI & env,Model * m,const ASTString & id,const std::vector<Type> & t,FunctionI::builtin_s b,bool fromGlobals=false)78 void rb(EnvI& env, Model* m, const ASTString& id, const std::vector<Type>& t,
79         FunctionI::builtin_s b, bool fromGlobals = false) {
80   FunctionI* fi = m->matchFn(env, id, t, false);
81   if (fi != nullptr) {
82     fi->builtins.s = b;
83   } else if (!fromGlobals) {
84     std::ostringstream ss;
85     ss << "no definition found for builtin " << id;
86     throw InternalError(ss.str());
87   }
88 }
rb(EnvI & env,Model * m,const ASTString & id,const std::vector<Type> & t,FunctionI::builtin_str b,bool fromGlobals=false)89 void rb(EnvI& env, Model* m, const ASTString& id, const std::vector<Type>& t,
90         FunctionI::builtin_str b, bool fromGlobals = false) {
91   FunctionI* fi = m->matchFn(env, id, t, false);
92   if (fi != nullptr) {
93     fi->builtins.str = b;
94   } else if (!fromGlobals) {
95     std::ostringstream ss;
96     ss << "no definition found for builtin " << id;
97     throw InternalError(ss.str());
98   }
99 }
100 
b_int_min(EnvI & env,Call * call)101 IntVal b_int_min(EnvI& env, Call* call) {
102   switch (call->argCount()) {
103     case 1:
104       if (call->arg(0)->type().isSet()) {
105         throw EvalError(env, call->arg(0)->loc(), "sets not supported");
106       } else {
107         GCLock lock;
108         ArrayLit* al = eval_array_lit(env, call->arg(0));
109         if (al->size() == 0) {
110           throw ResultUndefinedError(env, al->loc(), "minimum of empty array is undefined");
111         }
112         IntVal m = eval_int(env, (*al)[0]);
113         for (unsigned int i = 1; i < al->size(); i++) {
114           m = std::min(m, eval_int(env, (*al)[i]));
115         }
116         return m;
117       }
118     case 2: {
119       return std::min(eval_int(env, call->arg(0)), eval_int(env, call->arg(1)));
120     }
121     default:
122       throw EvalError(env, Location(), "dynamic type error");
123   }
124 }
125 
b_int_max(EnvI & env,Call * call)126 IntVal b_int_max(EnvI& env, Call* call) {
127   switch (call->argCount()) {
128     case 1:
129       if (call->arg(0)->type().isSet()) {
130         throw EvalError(env, call->arg(0)->loc(), "sets not supported");
131       } else {
132         GCLock lock;
133         ArrayLit* al = eval_array_lit(env, call->arg(0));
134         if (al->size() == 0) {
135           throw ResultUndefinedError(env, al->loc(), "maximum of empty array is undefined");
136         }
137         IntVal m = eval_int(env, (*al)[0]);
138         for (unsigned int i = 1; i < al->size(); i++) {
139           m = std::max(m, eval_int(env, (*al)[i]));
140         }
141         return m;
142       }
143     case 2: {
144       return std::max(eval_int(env, call->arg(0)), eval_int(env, call->arg(1)));
145     }
146     default:
147       throw EvalError(env, Location(), "dynamic type error");
148   }
149 }
150 
b_arg_min_bool(EnvI & env,Call * call)151 IntVal b_arg_min_bool(EnvI& env, Call* call) {
152   GCLock lock;
153   ArrayLit* al = eval_array_lit(env, call->arg(0));
154   if (al->size() == 0) {
155     throw ResultUndefinedError(env, al->loc(), "arg_min of empty array is undefined");
156   }
157   assert(al->dims() == 1);
158   for (unsigned int i = 0; i < al->size(); i++) {
159     bool val = eval_bool(env, (*al)[i]);
160     if (!val) {
161       return IntVal(i) + al->min(0);
162     }
163   }
164   return al->min(0);
165 }
b_arg_max_bool(EnvI & env,Call * call)166 IntVal b_arg_max_bool(EnvI& env, Call* call) {
167   GCLock lock;
168   ArrayLit* al = eval_array_lit(env, call->arg(0));
169   if (al->size() == 0) {
170     throw ResultUndefinedError(env, al->loc(), "arg_max of empty array is undefined");
171   }
172   assert(al->dims() == 1);
173   for (unsigned int i = 0; i < al->size(); i++) {
174     bool val = eval_bool(env, (*al)[i]);
175     if (val) {
176       return IntVal(i) + al->min(0);
177     }
178   }
179   return al->min(0);
180 }
b_arg_min_int(EnvI & env,Call * call)181 IntVal b_arg_min_int(EnvI& env, Call* call) {
182   GCLock lock;
183   ArrayLit* al = eval_array_lit(env, call->arg(0));
184   if (al->size() == 0) {
185     throw ResultUndefinedError(env, al->loc(), "argmin of empty array is undefined");
186   }
187   assert(al->dims() == 1);
188   IntVal m = eval_int(env, (*al)[0]);
189   unsigned int m_idx = 0;
190   for (unsigned int i = 1; i < al->size(); i++) {
191     IntVal mi = eval_int(env, (*al)[i]);
192     if (mi < m) {
193       m = mi;
194       m_idx = i;
195     }
196   }
197   return IntVal(m_idx) + al->min(0);
198 }
b_arg_max_int(EnvI & env,Call * call)199 IntVal b_arg_max_int(EnvI& env, Call* call) {
200   GCLock lock;
201   ArrayLit* al = eval_array_lit(env, call->arg(0));
202   if (al->size() == 0) {
203     throw ResultUndefinedError(env, al->loc(), "argmax of empty array is undefined");
204   }
205   assert(al->dims() == 1);
206   IntVal m = eval_int(env, (*al)[0]);
207   unsigned int m_idx = 0;
208   for (unsigned int i = 1; i < al->size(); i++) {
209     IntVal mi = eval_int(env, (*al)[i]);
210     if (mi > m) {
211       m = mi;
212       m_idx = i;
213     }
214   }
215   return IntVal(m_idx) + al->min(0);
216 }
b_arg_min_float(EnvI & env,Call * call)217 IntVal b_arg_min_float(EnvI& env, Call* call) {
218   GCLock lock;
219   ArrayLit* al = eval_array_lit(env, call->arg(0));
220   if (al->size() == 0) {
221     throw ResultUndefinedError(env, al->loc(), "argmin of empty array is undefined");
222   }
223   assert(al->dims() == 1);
224   FloatVal m = eval_float(env, (*al)[0]);
225   unsigned int m_idx = 0;
226   for (unsigned int i = 1; i < al->size(); i++) {
227     FloatVal mi = eval_float(env, (*al)[i]);
228     if (mi < m) {
229       m = mi;
230       m_idx = i;
231     }
232   }
233   return IntVal(m_idx) + al->min(0);
234 }
b_arg_max_float(EnvI & env,Call * call)235 IntVal b_arg_max_float(EnvI& env, Call* call) {
236   GCLock lock;
237   ArrayLit* al = eval_array_lit(env, call->arg(0));
238   if (al->size() == 0) {
239     throw ResultUndefinedError(env, al->loc(), "argmax of empty array is undefined");
240   }
241   assert(al->dims() == 1);
242   FloatVal m = eval_float(env, (*al)[0]);
243   unsigned int m_idx = 0;
244   for (unsigned int i = 1; i < al->size(); i++) {
245     FloatVal mi = eval_float(env, (*al)[i]);
246     if (mi > m) {
247       m = mi;
248       m_idx = i;
249     }
250   }
251   return IntVal(m_idx) + al->min(0);
252 }
253 
b_abs_int(EnvI & env,Call * call)254 IntVal b_abs_int(EnvI& env, Call* call) {
255   assert(call->argCount() == 1);
256   return std::abs(eval_int(env, call->arg(0)));
257 }
258 
b_abs_float(EnvI & env,Call * call)259 FloatVal b_abs_float(EnvI& env, Call* call) {
260   assert(call->argCount() == 1);
261   return std::abs(eval_float(env, call->arg(0)));
262 }
263 
b_has_bounds_int(EnvI & env,Call * call)264 bool b_has_bounds_int(EnvI& env, Call* call) {
265   if (call->argCount() != 1) {
266     throw EvalError(env, Location(), "dynamic type error");
267   }
268   IntBounds ib = compute_int_bounds(env, call->arg(0));
269   return ib.valid && ib.l.isFinite() && ib.u.isFinite();
270 }
b_has_bounds_float(EnvI & env,Call * call)271 bool b_has_bounds_float(EnvI& env, Call* call) {
272   if (call->argCount() != 1) {
273     throw EvalError(env, Location(), "dynamic type error");
274   }
275   FloatBounds fb = compute_float_bounds(env, call->arg(0));
276   return fb.valid;
277 }
278 
lb_varoptint(EnvI & env,Expression * e)279 IntVal lb_varoptint(EnvI& env, Expression* e) {
280   IntBounds b = compute_int_bounds(env, e);
281   if (b.valid) {
282     return b.l;
283   }
284   return -IntVal::infinity();
285 }
b_lb_varoptint(EnvI & env,Call * call)286 IntVal b_lb_varoptint(EnvI& env, Call* call) {
287   if (call->argCount() != 1) {
288     throw EvalError(env, Location(), "dynamic type error");
289   }
290   return lb_varoptint(env, call->arg(0));
291 }
292 
b_occurs(EnvI & env,Call * call)293 bool b_occurs(EnvI& env, Call* call) {
294   GCLock lock;
295   return eval_par(env, call->arg(0)) != constants().absent;
296 }
297 
b_deopt_int(EnvI & env,Call * call)298 IntVal b_deopt_int(EnvI& env, Call* call) {
299   GCLock lock;
300   Expression* e = eval_par(env, call->arg(0));
301   if (e == constants().absent) {
302     throw EvalError(env, e->loc(), "cannot evaluate deopt on absent value");
303   }
304   return eval_int(env, e);
305 }
306 
b_deopt_bool(EnvI & env,Call * call)307 bool b_deopt_bool(EnvI& env, Call* call) {
308   GCLock lock;
309   Expression* e = eval_par(env, call->arg(0));
310   if (e == constants().absent) {
311     throw EvalError(env, e->loc(), "cannot evaluate deopt on absent value");
312   }
313   return eval_bool(env, e);
314 }
315 
b_deopt_float(EnvI & env,Call * call)316 FloatVal b_deopt_float(EnvI& env, Call* call) {
317   GCLock lock;
318   Expression* e = eval_par(env, call->arg(0));
319   if (e == constants().absent) {
320     throw EvalError(env, e->loc(), "cannot evaluate deopt on absent value");
321   }
322   return eval_float(env, e);
323 }
324 
b_deopt_intset(EnvI & env,Call * call)325 IntSetVal* b_deopt_intset(EnvI& env, Call* call) {
326   GCLock lock;
327   Expression* e = eval_par(env, call->arg(0));
328   if (e == constants().absent) {
329     throw EvalError(env, e->loc(), "cannot evaluate deopt on absent value");
330   }
331   return eval_intset(env, e);
332 }
333 
b_deopt_string(EnvI & env,Call * call)334 std::string b_deopt_string(EnvI& env, Call* call) {
335   GCLock lock;
336   Expression* e = eval_par(env, call->arg(0));
337   if (e == constants().absent) {
338     throw EvalError(env, e->loc(), "cannot evaluate deopt on absent value");
339   }
340   return eval_string(env, e);
341 }
342 
b_deopt_expr(EnvI & env,Call * call)343 Expression* b_deopt_expr(EnvI& env, Call* call) {
344   GCLock lock;
345   Expression* e = eval_par(env, call->arg(0));
346   if (e == constants().absent) {
347     throw EvalError(env, e->loc(), "cannot evaluate deopt on absent value");
348   }
349   return e;
350 };
351 
b_array_lb_int(EnvI & env,Call * call)352 IntVal b_array_lb_int(EnvI& env, Call* call) {
353   assert(call->argCount() == 1);
354   Expression* e = follow_id_to_decl(call->arg(0));
355 
356   bool foundMin = false;
357   IntVal array_lb = -IntVal::infinity();
358 
359   if (auto* vd = e->dynamicCast<VarDecl>()) {
360     if (vd->ti()->domain() != nullptr) {
361       GCLock lock;
362       IntSetVal* isv = eval_intset(env, vd->ti()->domain());
363       if (isv->size() != 0) {
364         array_lb = isv->min();
365         foundMin = true;
366       }
367     }
368     e = vd->e();
369   }
370 
371   if (e != nullptr) {
372     GCLock lock;
373     ArrayLit* al = eval_array_lit(env, e);
374     if (al->size() == 0) {
375       throw EvalError(env, Location(), "lower bound of empty array undefined");
376     }
377     IntVal min = IntVal::infinity();
378     for (unsigned int i = 0; i < al->size(); i++) {
379       IntBounds ib = compute_int_bounds(env, (*al)[i]);
380       if (!ib.valid) {
381         goto b_array_lb_int_done;
382       }
383       min = std::min(min, ib.l);
384     }
385     if (foundMin) {
386       array_lb = std::max(array_lb, min);
387     } else {
388       array_lb = min;
389     }
390     foundMin = true;
391   }
392 b_array_lb_int_done:
393   if (foundMin) {
394     return array_lb;
395   } else {
396     return -IntVal::infinity();
397   }
398 }
399 
ub_varoptint(EnvI & env,Expression * e)400 IntVal ub_varoptint(EnvI& env, Expression* e) {
401   IntBounds b = compute_int_bounds(env, e);
402   if (b.valid) {
403     return b.u;
404   }
405   return IntVal::infinity();
406 }
b_ub_varoptint(EnvI & env,Call * call)407 IntVal b_ub_varoptint(EnvI& env, Call* call) {
408   if (call->argCount() != 1) {
409     throw EvalError(env, Location(), "dynamic type error");
410   }
411   return ub_varoptint(env, call->arg(0));
412 }
413 
b_array_ub_int(EnvI & env,Call * call)414 IntVal b_array_ub_int(EnvI& env, Call* call) {
415   assert(call->argCount() == 1);
416   Expression* e = follow_id_to_decl(call->arg(0));
417 
418   bool foundMax = false;
419   IntVal array_ub = IntVal::infinity();
420 
421   if (auto* vd = e->dynamicCast<VarDecl>()) {
422     if (vd->ti()->domain() != nullptr) {
423       GCLock lock;
424       IntSetVal* isv = eval_intset(env, vd->ti()->domain());
425       if (isv->size() != 0) {
426         array_ub = isv->max();
427         foundMax = true;
428       }
429     }
430     e = vd->e();
431   }
432 
433   if (e != nullptr) {
434     GCLock lock;
435     ArrayLit* al = eval_array_lit(env, e);
436     if (al->size() == 0) {
437       throw EvalError(env, Location(), "upper bound of empty array undefined");
438     }
439     IntVal max = -IntVal::infinity();
440     for (unsigned int i = 0; i < al->size(); i++) {
441       IntBounds ib = compute_int_bounds(env, (*al)[i]);
442       if (!ib.valid) {
443         goto b_array_ub_int_done;
444       }
445       max = std::max(max, ib.u);
446     }
447     if (foundMax) {
448       array_ub = std::min(array_ub, max);
449     } else {
450       array_ub = max;
451     }
452     foundMax = true;
453   }
454 b_array_ub_int_done:
455   if (foundMax) {
456     return array_ub;
457   } else {
458     return IntVal::infinity();
459   }
460 }
461 
b_idiv(EnvI & env,Call * call)462 IntVal b_idiv(EnvI& env, Call* call) {
463   assert(call->argCount() == 2);
464   IntVal a = eval_int(env, call->arg(0));
465   IntVal b = eval_int(env, call->arg(1));
466   if (b == 0) {
467     throw ResultUndefinedError(env, call->loc(), "division by zero");
468   }
469   return a / b;
470 }
b_mod(EnvI & env,Call * call)471 IntVal b_mod(EnvI& env, Call* call) {
472   assert(call->argCount() == 2);
473   IntVal a = eval_int(env, call->arg(0));
474   IntVal b = eval_int(env, call->arg(1));
475   if (b == 0) {
476     throw ResultUndefinedError(env, call->loc(), "division by zero");
477   }
478   return a % b;
479 }
b_fdiv(EnvI & env,Call * call)480 FloatVal b_fdiv(EnvI& env, Call* call) {
481   assert(call->argCount() == 2);
482   FloatVal a = eval_float(env, call->arg(0));
483   FloatVal b = eval_float(env, call->arg(1));
484   if (b == 0.0) {
485     throw ResultUndefinedError(env, call->loc(), "division by zero");
486   }
487   return a / b;
488 }
b_dotdot(EnvI & env,Call * call)489 IntSetVal* b_dotdot(EnvI& env, Call* call) {
490   assert(call->argCount() == 2);
491   IntVal a = eval_int(env, call->arg(0));
492   IntVal b = eval_int(env, call->arg(1));
493   return IntSetVal::a(a, b);
494 }
495 
b_sum_int(EnvI & env,Call * call)496 IntVal b_sum_int(EnvI& env, Call* call) {
497   assert(call->argCount() == 1);
498   GCLock lock;
499   ArrayLit* al = eval_array_lit(env, call->arg(0));
500   if (al->size() == 0) {
501     return 0;
502   }
503   IntVal m = 0;
504   for (unsigned int i = 0; i < al->size(); i++) {
505     m += eval_int(env, (*al)[i]);
506   }
507   return m;
508 }
509 
b_product_int(EnvI & env,Call * call)510 IntVal b_product_int(EnvI& env, Call* call) {
511   assert(call->argCount() == 1);
512   GCLock lock;
513   ArrayLit* al = eval_array_lit(env, call->arg(0));
514   if (al->size() == 0) {
515     return 1;
516   }
517   IntVal m = 1;
518   for (unsigned int i = 0; i < al->size(); i++) {
519     m *= eval_int(env, (*al)[i]);
520   }
521   return m;
522 }
523 
b_product_float(EnvI & env,Call * call)524 FloatVal b_product_float(EnvI& env, Call* call) {
525   assert(call->argCount() == 1);
526   GCLock lock;
527   ArrayLit* al = eval_array_lit(env, call->arg(0));
528   if (al->size() == 0) {
529     return 1;
530   }
531   FloatVal m = 1.0;
532   for (unsigned int i = 0; i < al->size(); i++) {
533     m *= eval_float(env, (*al)[i]);
534   }
535   return m;
536 }
537 
lb_varoptfloat(EnvI & env,Expression * e)538 FloatVal lb_varoptfloat(EnvI& env, Expression* e) {
539   FloatBounds b = compute_float_bounds(env, e);
540   if (b.valid) {
541     return b.l;
542   }
543   throw EvalError(env, e->loc(), "cannot determine bounds");
544 }
ub_varoptfloat(EnvI & env,Expression * e)545 FloatVal ub_varoptfloat(EnvI& env, Expression* e) {
546   FloatBounds b = compute_float_bounds(env, e);
547   if (b.valid) {
548     return b.u;
549   }
550   throw EvalError(env, e->loc(), "cannot determine bounds");
551 }
552 
b_lb_varoptfloat(EnvI & env,Call * call)553 FloatVal b_lb_varoptfloat(EnvI& env, Call* call) {
554   if (call->argCount() != 1) {
555     throw EvalError(env, Location(), "dynamic type error");
556   }
557   return lb_varoptfloat(env, call->arg(0));
558 }
b_ub_varoptfloat(EnvI & env,Call * call)559 FloatVal b_ub_varoptfloat(EnvI& env, Call* call) {
560   if (call->argCount() != 1) {
561     throw EvalError(env, Location(), "dynamic type error");
562   }
563   return ub_varoptfloat(env, call->arg(0));
564 }
565 
b_array_lb_float(EnvI & env,Call * call)566 FloatVal b_array_lb_float(EnvI& env, Call* call) {
567   assert(call->argCount() == 1);
568   Expression* e = follow_id_to_decl(call->arg(0));
569 
570   bool foundMin = false;
571   FloatVal array_lb = 0.0;
572 
573   if (auto* vd = e->dynamicCast<VarDecl>()) {
574     if (vd->ti()->domain() != nullptr) {
575       FloatSetVal* fsv = eval_floatset(env, vd->ti()->domain());
576       array_lb = fsv->min();
577       foundMin = true;
578     }
579     e = vd->e();
580   }
581 
582   if (e != nullptr) {
583     GCLock lock;
584     ArrayLit* al = eval_array_lit(env, e);
585     if (al->size() == 0) {
586       throw EvalError(env, Location(), "lower bound of empty array undefined");
587     }
588     bool min_valid = false;
589     FloatVal min = 0.0;
590     for (unsigned int i = 0; i < al->size(); i++) {
591       FloatBounds fb = compute_float_bounds(env, (*al)[i]);
592       if (!fb.valid) {
593         goto b_array_lb_float_done;
594       }
595       if (min_valid) {
596         min = std::min(min, fb.l);
597       } else {
598         min_valid = true;
599         min = fb.l;
600       }
601     }
602     assert(min_valid);
603     if (foundMin) {
604       array_lb = std::max(array_lb, min);
605     } else {
606       array_lb = min;
607     }
608     foundMin = true;
609   }
610 b_array_lb_float_done:
611   if (foundMin) {
612     return array_lb;
613   } else {
614     throw EvalError(env, e->loc(), "cannot determine lower bound");
615   }
616 }
617 
b_array_ub_float(EnvI & env,Call * call)618 FloatVal b_array_ub_float(EnvI& env, Call* call) {
619   assert(call->argCount() == 1);
620   Expression* e = follow_id_to_decl(call->arg(0));
621 
622   bool foundMax = false;
623   FloatVal array_ub = 0.0;
624 
625   if (auto* vd = e->dynamicCast<VarDecl>()) {
626     if (vd->ti()->domain() != nullptr) {
627       FloatSetVal* fsv = eval_floatset(env, vd->ti()->domain());
628       array_ub = fsv->max();
629       foundMax = true;
630     }
631     e = vd->e();
632   }
633 
634   if (e != nullptr) {
635     GCLock lock;
636     ArrayLit* al = eval_array_lit(env, e);
637     if (al->size() == 0) {
638       throw EvalError(env, Location(), "upper bound of empty array undefined");
639     }
640     bool max_valid = false;
641     FloatVal max = 0.0;
642     for (unsigned int i = 0; i < al->size(); i++) {
643       FloatBounds fb = compute_float_bounds(env, (*al)[i]);
644       if (!fb.valid) {
645         goto b_array_ub_float_done;
646       }
647       if (max_valid) {
648         max = std::max(max, fb.u);
649       } else {
650         max_valid = true;
651         max = fb.u;
652       }
653     }
654     assert(max_valid);
655     if (foundMax) {
656       array_ub = std::min(array_ub, max);
657     } else {
658       array_ub = max;
659     }
660     foundMax = true;
661   }
662 b_array_ub_float_done:
663   if (foundMax) {
664     return array_ub;
665   } else {
666     throw EvalError(env, e->loc(), "cannot determine upper bound");
667   }
668 }
669 
b_sum_float(EnvI & env,Call * call)670 FloatVal b_sum_float(EnvI& env, Call* call) {
671   assert(call->argCount() == 1);
672   GCLock lock;
673   ArrayLit* al = eval_array_lit(env, call->arg(0));
674   if (al->size() == 0) {
675     return 0;
676   }
677   FloatVal m = 0;
678   for (unsigned int i = 0; i < al->size(); i++) {
679     m += eval_float(env, (*al)[i]);
680   }
681   return m;
682 }
683 
b_float_min(EnvI & env,Call * call)684 FloatVal b_float_min(EnvI& env, Call* call) {
685   switch (call->argCount()) {
686     case 1:
687       if (call->arg(0)->type().isSet()) {
688         throw EvalError(env, call->arg(0)->loc(), "sets not supported");
689       } else {
690         GCLock lock;
691         ArrayLit* al = eval_array_lit(env, call->arg(0));
692         if (al->size() == 0) {
693           throw EvalError(env, al->loc(), "min on empty array undefined");
694         }
695         FloatVal m = eval_float(env, (*al)[0]);
696         for (unsigned int i = 1; i < al->size(); i++) {
697           m = std::min(m, eval_float(env, (*al)[i]));
698         }
699         return m;
700       }
701     case 2: {
702       return std::min(eval_float(env, call->arg(0)), eval_float(env, call->arg(1)));
703     }
704     default:
705       throw EvalError(env, Location(), "dynamic type error");
706   }
707 }
708 
b_float_max(EnvI & env,Call * call)709 FloatVal b_float_max(EnvI& env, Call* call) {
710   switch (call->argCount()) {
711     case 1:
712       if (call->arg(0)->type().isSet()) {
713         throw EvalError(env, call->arg(0)->loc(), "sets not supported");
714       } else {
715         GCLock lock;
716         ArrayLit* al = eval_array_lit(env, call->arg(0));
717         if (al->size() == 0) {
718           throw EvalError(env, al->loc(), "max on empty array undefined");
719         }
720         FloatVal m = eval_float(env, (*al)[0]);
721         for (unsigned int i = 1; i < al->size(); i++) {
722           m = std::max(m, eval_float(env, (*al)[i]));
723         }
724         return m;
725       }
726     case 2: {
727       return std::max(eval_float(env, call->arg(0)), eval_float(env, call->arg(1)));
728     }
729     default:
730       throw EvalError(env, Location(), "dynamic type error");
731   }
732 }
733 
b_index_set(EnvI & env,Expression * e,int i)734 IntSetVal* b_index_set(EnvI& env, Expression* e, int i) {
735   if (e->eid() != Expression::E_ID) {
736     GCLock lock;
737     ArrayLit* al = eval_array_lit(env, e);
738     if (al->dims() < i) {
739       throw EvalError(env, e->loc(), "index_set: wrong dimension");
740     }
741     return IntSetVal::a(al->min(i - 1), al->max(i - 1));
742   }
743   Id* id = e->cast<Id>();
744   if (id->decl() == nullptr) {
745     throw EvalError(env, id->loc(), "undefined identifier");
746   }
747   if ((id->decl()->ti()->ranges().size() == 1 &&
748        id->decl()->ti()->ranges()[0]->domain() != nullptr &&
749        id->decl()->ti()->ranges()[0]->domain()->isa<TIId>()) ||
750       (static_cast<int>(id->decl()->ti()->ranges().size()) >= i &&
751        (id->decl()->ti()->ranges()[i - 1]->domain() == nullptr ||
752         id->decl()->ti()->ranges()[i - 1]->domain()->isa<TIId>()))) {
753     GCLock lock;
754     ArrayLit* al = eval_array_lit(env, id);
755     if (al->dims() < i) {
756       throw EvalError(env, id->loc(), "index_set: wrong dimension");
757     }
758     return IntSetVal::a(al->min(i - 1), al->max(i - 1));
759   }
760   if (static_cast<int>(id->decl()->ti()->ranges().size()) < i) {
761     throw EvalError(env, id->loc(), "index_set: wrong dimension");
762   }
763   return eval_intset(env, id->decl()->ti()->ranges()[i - 1]->domain());
764 }
b_index_sets_agree(EnvI & env,Call * call)765 bool b_index_sets_agree(EnvI& env, Call* call) {
766   if (call->argCount() != 2) {
767     throw EvalError(env, Location(), "index_sets_agree needs exactly two arguments");
768   }
769   GCLock lock;
770   ArrayLit* al0 = eval_array_lit(env, call->arg(0));
771   ArrayLit* al1 = eval_array_lit(env, call->arg(1));
772   if (al0->type().dim() != al1->type().dim()) {
773     return false;
774   }
775   for (int i = 1; i <= al0->type().dim(); i++) {
776     IntSetVal* index0 = b_index_set(env, al0, i);
777     IntSetVal* index1 = b_index_set(env, al1, i);
778     if (!index0->equal(index1)) {
779       return false;
780     }
781   }
782   return true;
783 }
b_index_set1(EnvI & env,Call * call)784 IntSetVal* b_index_set1(EnvI& env, Call* call) {
785   if (call->argCount() != 1) {
786     throw EvalError(env, Location(), "index_set needs exactly one argument");
787   }
788   return b_index_set(env, call->arg(0), 1);
789 }
b_index_set2(EnvI & env,Call * call)790 IntSetVal* b_index_set2(EnvI& env, Call* call) {
791   if (call->argCount() != 1) {
792     throw EvalError(env, Location(), "index_set needs exactly one argument");
793   }
794   return b_index_set(env, call->arg(0), 2);
795 }
b_index_set3(EnvI & env,Call * call)796 IntSetVal* b_index_set3(EnvI& env, Call* call) {
797   if (call->argCount() != 1) {
798     throw EvalError(env, Location(), "index_set needs exactly one argument");
799   }
800   return b_index_set(env, call->arg(0), 3);
801 }
b_index_set4(EnvI & env,Call * call)802 IntSetVal* b_index_set4(EnvI& env, Call* call) {
803   if (call->argCount() != 1) {
804     throw EvalError(env, Location(), "index_set needs exactly one argument");
805   }
806   return b_index_set(env, call->arg(0), 4);
807 }
b_index_set5(EnvI & env,Call * call)808 IntSetVal* b_index_set5(EnvI& env, Call* call) {
809   if (call->argCount() != 1) {
810     throw EvalError(env, Location(), "index_set needs exactly one argument");
811   }
812   return b_index_set(env, call->arg(0), 5);
813 }
b_index_set6(EnvI & env,Call * call)814 IntSetVal* b_index_set6(EnvI& env, Call* call) {
815   if (call->argCount() != 1) {
816     throw EvalError(env, Location(), "index_set needs exactly one argument");
817   }
818   return b_index_set(env, call->arg(0), 6);
819 }
820 
b_min_parsetint(EnvI & env,Call * call)821 IntVal b_min_parsetint(EnvI& env, Call* call) {
822   assert(call->argCount() == 1);
823   IntSetVal* isv = eval_intset(env, call->arg(0));
824   return isv->min();
825 }
b_max_parsetint(EnvI & env,Call * call)826 IntVal b_max_parsetint(EnvI& env, Call* call) {
827   assert(call->argCount() == 1);
828   IntSetVal* isv = eval_intset(env, call->arg(0));
829   return isv->max();
830 }
b_lb_set(EnvI & env,Call * e)831 IntSetVal* b_lb_set(EnvI& env, Call* e) {
832   Expression* ee = follow_id_to_value(e->arg(0));
833   if (ee->type().isPar()) {
834     return eval_intset(env, ee);
835   }
836   return IntSetVal::a();
837 }
b_ub_set(EnvI & env,Expression * e)838 IntSetVal* b_ub_set(EnvI& env, Expression* e) {
839   IntSetVal* isv = compute_intset_bounds(env, e);
840   if (isv != nullptr) {
841     return isv;
842   }
843   throw EvalError(env, e->loc(), "cannot determine bounds of set expression");
844 }
b_ub_set(EnvI & env,Call * call)845 IntSetVal* b_ub_set(EnvI& env, Call* call) {
846   assert(call->argCount() == 1);
847   return b_ub_set(env, call->arg(0));
848 }
b_has_ub_set(EnvI & env,Call * call)849 bool b_has_ub_set(EnvI& env, Call* call) {
850   Expression* e = call->arg(0);
851   for (;;) {
852     switch (e->eid()) {
853       case Expression::E_SETLIT:
854         return true;
855       case Expression::E_ID: {
856         Id* id = e->cast<Id>();
857         if (id->decl() == nullptr) {
858           throw EvalError(env, id->loc(), "undefined identifier");
859         }
860         if (id->decl()->e() == nullptr) {
861           return id->decl()->ti()->domain() != nullptr;
862         }
863         e = id->decl()->e();
864 
865       } break;
866       default:
867         throw EvalError(env, e->loc(), "invalid argument to has_ub_set");
868     }
869   }
870 }
871 
b_array_ub_set(EnvI & env,Call * call)872 IntSetVal* b_array_ub_set(EnvI& env, Call* call) {
873   assert(call->argCount() == 1);
874   GCLock lock;
875   ArrayLit* al = eval_array_lit(env, call->arg(0));
876   if (al->size() == 0) {
877     throw EvalError(env, Location(), "upper bound of empty array undefined");
878   }
879   IntSetVal* ub = b_ub_set(env, (*al)[0]);
880   for (unsigned int i = 1; i < al->size(); i++) {
881     IntSetRanges isr(ub);
882     IntSetRanges r(b_ub_set(env, (*al)[i]));
883     Ranges::Union<IntVal, IntSetRanges, IntSetRanges> u(isr, r);
884     ub = IntSetVal::ai(u);
885   }
886   return ub;
887 }
888 
b_dom_varint(EnvI & env,Expression * e)889 IntSetVal* b_dom_varint(EnvI& env, Expression* e) {
890   Id* lastid = nullptr;
891   Expression* cur = e;
892   for (;;) {
893     if (cur == nullptr) {
894       if (lastid == nullptr || lastid->decl()->ti()->domain() == nullptr) {
895         IntBounds b = compute_int_bounds(env, e);
896         if (b.valid) {
897           return IntSetVal::a(b.l, b.u);
898         }
899         return IntSetVal::a(-IntVal::infinity(), IntVal::infinity());
900       }
901       return eval_intset(env, lastid->decl()->ti()->domain());
902     }
903     switch (cur->eid()) {
904       case Expression::E_INTLIT: {
905         IntVal v = cur->cast<IntLit>()->v();
906         return IntSetVal::a(v, v);
907       }
908       case Expression::E_ID: {
909         lastid = cur->cast<Id>();
910         if (lastid == constants().absent) {
911           return IntSetVal::a(-IntVal::infinity(), IntVal::infinity());
912         }
913         if (lastid->decl() == nullptr) {
914           throw EvalError(env, lastid->loc(), "undefined identifier");
915         }
916         cur = lastid->decl()->e();
917       } break;
918       case Expression::E_ARRAYACCESS: {
919         bool success;
920         cur = eval_arrayaccess(env, cur->cast<ArrayAccess>(), success);
921         if (!success) {
922           cur = nullptr;
923         }
924       } break;
925       default:
926         cur = nullptr;
927         break;
928     }
929   }
930 }
b_dom_varint(EnvI & env,Call * call)931 IntSetVal* b_dom_varint(EnvI& env, Call* call) {
932   assert(call->argCount() == 1);
933   return b_dom_varint(env, call->arg(0));
934 }
935 
b_dom_bounds_array(EnvI & env,Call * call)936 IntSetVal* b_dom_bounds_array(EnvI& env, Call* call) {
937   assert(call->argCount() == 1);
938   Expression* arg_e = call->arg(0);
939   Expression* e = follow_id_to_decl(arg_e);
940 
941   bool foundBounds = false;
942   IntVal array_lb = -IntVal::infinity();
943   IntVal array_ub = IntVal::infinity();
944 
945   if (auto* vd = e->dynamicCast<VarDecl>()) {
946     if (vd->ti()->domain() != nullptr) {
947       GCLock lock;
948       IntSetVal* isv = eval_intset(env, vd->ti()->domain());
949       if (isv->size() != 0) {
950         array_lb = isv->min();
951         array_ub = isv->max();
952         foundBounds = true;
953       }
954     }
955     e = vd->e();
956     if (e == nullptr) {
957       e = vd->flat()->e();
958     }
959   }
960 
961   if (foundBounds) {
962     return IntSetVal::a(array_lb, array_ub);
963   }
964 
965   if (e != nullptr) {
966     GCLock lock;
967     ArrayLit* al = eval_array_lit(env, e);
968     if (al->size() == 0) {
969       throw EvalError(env, Location(), "lower bound of empty array undefined");
970     }
971     IntVal min = IntVal::infinity();
972     IntVal max = -IntVal::infinity();
973     for (unsigned int i = 0; i < al->size(); i++) {
974       IntBounds ib = compute_int_bounds(env, (*al)[i]);
975       if (!ib.valid) {
976         goto b_array_lb_int_done;
977       }
978       min = std::min(min, ib.l);
979       max = std::max(max, ib.u);
980     }
981     array_lb = std::max(array_lb, min);
982     array_ub = std::min(array_ub, max);
983     foundBounds = true;
984   }
985 b_array_lb_int_done:
986   if (foundBounds) {
987     return IntSetVal::a(array_lb, array_ub);
988   } else {
989     throw EvalError(env, e->loc(), "cannot determine lower bound");
990   }
991 }
992 
b_dom_array(EnvI & env,Call * call)993 IntSetVal* b_dom_array(EnvI& env, Call* call) {
994   assert(call->argCount() == 1);
995   Expression* ae = call->arg(0);
996   ArrayLit* al = nullptr;
997   while (al == nullptr) {
998     switch (ae->eid()) {
999       case Expression::E_ARRAYLIT:
1000         al = ae->cast<ArrayLit>();
1001         break;
1002       case Expression::E_ID: {
1003         Id* id = ae->cast<Id>();
1004         if (id->decl() == nullptr) {
1005           throw EvalError(env, id->loc(), "undefined identifier");
1006         }
1007         if (id->decl()->e() == nullptr) {
1008           if (id->decl()->flat() == nullptr) {
1009             throw EvalError(env, id->loc(), "array without initialiser");
1010           }
1011           if (id->decl()->flat()->e() == nullptr) {
1012             throw EvalError(env, id->loc(), "array without initialiser");
1013           }
1014           ae = id->decl()->flat()->e();
1015 
1016         } else {
1017           ae = id->decl()->e();
1018         }
1019       } break;
1020       default:
1021         throw EvalError(env, ae->loc(), "invalid argument to dom");
1022     }
1023   }
1024   if (al->size() == 0) {
1025     return IntSetVal::a();
1026   }
1027   IntSetVal* isv = b_dom_varint(env, (*al)[0]);
1028   for (unsigned int i = 1; i < al->size(); i++) {
1029     IntSetRanges isr(isv);
1030     IntSetRanges r(b_dom_varint(env, (*al)[i]));
1031     Ranges::Union<IntVal, IntSetRanges, IntSetRanges> u(isr, r);
1032     isv = IntSetVal::ai(u);
1033   }
1034   return isv;
1035 }
b_compute_div_bounds(EnvI & env,Call * call)1036 IntSetVal* b_compute_div_bounds(EnvI& env, Call* call) {
1037   assert(call->argCount() == 2);
1038   IntBounds bx = compute_int_bounds(env, call->arg(0));
1039   if (!bx.valid) {
1040     throw EvalError(env, call->arg(0)->loc(), "cannot determine bounds");
1041   }
1042   /// TODO: better bounds if only some input bounds are infinite
1043   if (!bx.l.isFinite() || !bx.u.isFinite()) {
1044     return constants().infinity->isv();
1045   }
1046   IntBounds by = compute_int_bounds(env, call->arg(1));
1047   if (!by.valid) {
1048     throw EvalError(env, call->arg(1)->loc(), "cannot determine bounds");
1049   }
1050   if (!by.l.isFinite() || !by.u.isFinite()) {
1051     return constants().infinity->isv();
1052   }
1053   Ranges::Const<IntVal> byr(by.l, by.u);
1054   Ranges::Const<IntVal> by0(0, 0);
1055   Ranges::Diff<IntVal, Ranges::Const<IntVal>, Ranges::Const<IntVal>> byr0(byr, by0);
1056 
1057   IntVal min = IntVal::maxint();
1058   IntVal max = IntVal::minint();
1059   if (byr0()) {
1060     min = std::min(min, bx.l / byr0.min());
1061     min = std::min(min, bx.l / byr0.max());
1062     min = std::min(min, bx.u / byr0.min());
1063     min = std::min(min, bx.u / byr0.max());
1064     max = std::max(max, bx.l / byr0.min());
1065     max = std::max(max, bx.l / byr0.max());
1066     max = std::max(max, bx.u / byr0.min());
1067     max = std::max(max, bx.u / byr0.max());
1068     ++byr0;
1069     if (byr0()) {
1070       min = std::min(min, bx.l / byr0.min());
1071       min = std::min(min, bx.l / byr0.max());
1072       min = std::min(min, bx.u / byr0.min());
1073       min = std::min(min, bx.u / byr0.max());
1074       max = std::max(max, bx.l / byr0.min());
1075       max = std::max(max, bx.l / byr0.max());
1076       max = std::max(max, bx.u / byr0.min());
1077       max = std::max(max, bx.u / byr0.max());
1078     }
1079   }
1080   return IntSetVal::a(min, max);
1081 }
1082 
1083 // NOLINTNEXTLINE(readability-identifier-naming)
b_arrayXd(EnvI & env,Call * call,int d)1084 ArrayLit* b_arrayXd(EnvI& env, Call* call, int d) {
1085   GCLock lock;
1086   bool check_form = call->ann().contains(constants().ann.array_check_form);
1087   ArrayLit* al = eval_array_lit(env, call->arg(d));
1088   std::vector<std::pair<int, int>> dims(d);
1089   unsigned int dim1d = 1;
1090 
1091   if (check_form && d != al->dims()) {
1092     std::ostringstream ss;
1093     ss << "number of dimensions of original array (" << al->dims()
1094        << ") does not match the given number of index sets (" << d << ")";
1095     throw EvalError(env, call->loc(), ss.str());
1096   }
1097 
1098   for (int i = 0; i < d; i++) {
1099     IntSetVal* di = eval_intset(env, call->arg(i));
1100     if (di->size() == 0) {
1101       dims[i] = std::pair<int, int>(1, 0);
1102       dim1d = 0;
1103     } else if (di->size() != 1) {
1104       throw EvalError(env, call->arg(i)->loc(), "arrayXd only defined for ranges");
1105     } else {
1106       dims[i] = std::pair<int, int>(static_cast<int>(di->min(0).toInt()),
1107                                     static_cast<int>(di->max(0).toInt()));
1108       dim1d *= dims[i].second - dims[i].first + 1;
1109       if (check_form && dims[i].second - dims[i].first != al->max(i) - al->min(i)) {
1110         std::ostringstream ss;
1111         ss << "index set " << i + 1 << " (" << dims[i].first << ".." << dims[i].second
1112            << ") does not match index set " << i + 1 << " of original array (" << al->min(i) << ".."
1113            << al->max(i) << ")";
1114         throw EvalError(env, call->arg(i)->loc(), ss.str());
1115       }
1116     }
1117   }
1118   if (dim1d != al->size()) {
1119     throw EvalError(env, al->loc(), "mismatch in array dimensions");
1120   }
1121   auto* ret = new ArrayLit(al->loc(), *al, dims);
1122   Type t = al->type();
1123   t.dim(d);
1124   ret->type(t);
1125   ret->flat(al->flat());
1126   return ret;
1127 }
b_array1d_list(EnvI & env,Call * call)1128 Expression* b_array1d_list(EnvI& env, Call* call) {
1129   GCLock lock;
1130   ArrayLit* al = eval_array_lit(env, call->arg(0));
1131   if (al->dims() == 1 && al->min(0) == 1) {
1132     return call->arg(0)->isa<Id>() ? call->arg(0) : al;
1133   }
1134   auto* ret = new ArrayLit(al->loc(), *al);
1135   Type t = al->type();
1136   t.dim(1);
1137   ret->type(t);
1138   ret->flat(al->flat());
1139   return ret;
1140 }
b_array1d(EnvI & env,Call * call)1141 Expression* b_array1d(EnvI& env, Call* call) { return b_arrayXd(env, call, 1); }
b_array2d(EnvI & env,Call * call)1142 Expression* b_array2d(EnvI& env, Call* call) { return b_arrayXd(env, call, 2); }
b_array3d(EnvI & env,Call * call)1143 Expression* b_array3d(EnvI& env, Call* call) { return b_arrayXd(env, call, 3); }
b_array4d(EnvI & env,Call * call)1144 Expression* b_array4d(EnvI& env, Call* call) { return b_arrayXd(env, call, 4); }
b_array5d(EnvI & env,Call * call)1145 Expression* b_array5d(EnvI& env, Call* call) { return b_arrayXd(env, call, 5); }
b_array6d(EnvI & env,Call * call)1146 Expression* b_array6d(EnvI& env, Call* call) { return b_arrayXd(env, call, 6); }
1147 
1148 // NOLINTNEXTLINE(readability-identifier-naming)
b_arrayXd(EnvI & env,Call * call)1149 Expression* b_arrayXd(EnvI& env, Call* call) {
1150   GCLock lock;
1151   ArrayLit* al0 = eval_array_lit(env, call->arg(0));
1152   ArrayLit* al1 = eval_array_lit(env, call->arg(1));
1153   if (al0->dims() == al1->dims()) {
1154     bool sameDims = true;
1155     for (unsigned int i = al0->dims(); (i--) != 0U;) {
1156       if (al0->min(i) != al1->min(i) || al0->max(i) != al1->max(i)) {
1157         sameDims = false;
1158         break;
1159       }
1160     }
1161     if (sameDims) {
1162       return call->arg(1)->isa<Id>() ? call->arg(1) : al1;
1163     }
1164   }
1165   std::vector<std::pair<int, int>> dims(al0->dims());
1166   for (unsigned int i = al0->dims(); (i--) != 0U;) {
1167     dims[i] = std::make_pair(al0->min(i), al0->max(i));
1168   }
1169   auto* ret = new ArrayLit(al1->loc(), *al1, dims);
1170   Type t = al1->type();
1171   t.dim(static_cast<int>(dims.size()));
1172   ret->type(t);
1173   ret->flat(al1->flat());
1174   return ret;
1175 }
1176 
b_length(EnvI & env,Call * call)1177 IntVal b_length(EnvI& env, Call* call) {
1178   GCLock lock;
1179   ArrayLit* al = eval_array_lit(env, call->arg(0));
1180   return al->size();
1181 }
1182 
b_bool2int(EnvI & env,Call * call)1183 IntVal b_bool2int(EnvI& env, Call* call) { return eval_bool(env, call->arg(0)) ? 1 : 0; }
1184 
b_forall_par(EnvI & env,Call * call)1185 bool b_forall_par(EnvI& env, Call* call) {
1186   if (call->argCount() != 1) {
1187     throw EvalError(env, Location(), "forall needs exactly one argument");
1188   }
1189   GCLock lock;
1190   ArrayLit* al = eval_array_lit(env, call->arg(0));
1191   for (unsigned int i = al->size(); (i--) != 0U;) {
1192     if (!eval_bool(env, (*al)[i])) {
1193       return false;
1194     }
1195   }
1196   return true;
1197 }
b_exists_par(EnvI & env,Call * call)1198 bool b_exists_par(EnvI& env, Call* call) {
1199   if (call->argCount() != 1) {
1200     throw EvalError(env, Location(), "exists needs exactly one argument");
1201   }
1202   GCLock lock;
1203   ArrayLit* al = eval_array_lit(env, call->arg(0));
1204   for (unsigned int i = al->size(); (i--) != 0U;) {
1205     if (eval_bool(env, (*al)[i])) {
1206       return true;
1207     }
1208   }
1209   return false;
1210 }
b_clause_par(EnvI & env,Call * call)1211 bool b_clause_par(EnvI& env, Call* call) {
1212   if (call->argCount() != 2) {
1213     throw EvalError(env, Location(), "clause needs exactly two arguments");
1214   }
1215   GCLock lock;
1216   ArrayLit* al = eval_array_lit(env, call->arg(0));
1217   for (unsigned int i = al->size(); (i--) != 0U;) {
1218     if (eval_bool(env, (*al)[i])) {
1219       return true;
1220     }
1221   }
1222   al = eval_array_lit(env, call->arg(1));
1223   for (unsigned int i = al->size(); (i--) != 0U;) {
1224     if (!eval_bool(env, (*al)[i])) {
1225       return true;
1226     }
1227   }
1228   return false;
1229 }
b_xorall_par(EnvI & env,Call * call)1230 bool b_xorall_par(EnvI& env, Call* call) {
1231   if (call->argCount() != 1) {
1232     throw EvalError(env, Location(), "xorall needs exactly one argument");
1233   }
1234   GCLock lock;
1235   int count = 0;
1236   ArrayLit* al = eval_array_lit(env, call->arg(0));
1237   for (unsigned int i = al->size(); (i--) != 0U;) {
1238     count += static_cast<int>(eval_bool(env, (*al)[i]));
1239   }
1240   return count % 2 == 1;
1241 }
b_iffall_par(EnvI & env,Call * call)1242 bool b_iffall_par(EnvI& env, Call* call) {
1243   if (call->argCount() != 1) {
1244     throw EvalError(env, Location(), "xorall needs exactly one argument");
1245   }
1246   GCLock lock;
1247   int count = 0;
1248   ArrayLit* al = eval_array_lit(env, call->arg(0));
1249   for (unsigned int i = al->size(); (i--) != 0U;) {
1250     count += static_cast<int>(eval_bool(env, (*al)[i]));
1251   }
1252   return count % 2 == 0;
1253 }
b_not_par(EnvI & env,Call * call)1254 bool b_not_par(EnvI& env, Call* call) {
1255   assert(call->argCount() == 1);
1256   return !eval_bool(env, call->arg(0));
1257 }
1258 
b_card(EnvI & env,Call * call)1259 IntVal b_card(EnvI& env, Call* call) {
1260   if (call->argCount() != 1) {
1261     throw EvalError(env, Location(), "card needs exactly one argument");
1262   }
1263   IntSetVal* isv = eval_intset(env, call->arg(0));
1264   IntSetRanges isr(isv);
1265   return Ranges::cardinality(isr);
1266 }
1267 
exp_is_fixed(EnvI & env,Expression * e)1268 Expression* exp_is_fixed(EnvI& env, Expression* e) {
1269   GCLock lock;
1270   Expression* cur = e;
1271   for (;;) {
1272     if (cur == nullptr) {
1273       return nullptr;
1274     }
1275     if (cur->type().isPar()) {
1276       return eval_par(env, cur);
1277     }
1278     switch (cur->eid()) {
1279       case Expression::E_ID:
1280         cur = cur->cast<Id>()->decl();
1281         break;
1282       case Expression::E_VARDECL:
1283         if (cur->type().st() != Type::ST_SET) {
1284           Expression* dom = cur->cast<VarDecl>()->ti()->domain();
1285           if ((dom != nullptr) &&
1286               (dom->isa<IntLit>() || dom->isa<BoolLit>() || dom->isa<FloatLit>())) {
1287             return dom;
1288           }
1289           if ((dom != nullptr) && dom->isa<SetLit>()) {
1290             auto* sl = dom->cast<SetLit>();
1291             auto* isv = sl->isv();
1292             if ((isv != nullptr) && isv->min() == isv->max()) {
1293               return IntLit::a(isv->min());
1294             }
1295             auto* fsv = sl->fsv();
1296             if ((fsv != nullptr) && fsv->min() == fsv->max()) {
1297               return FloatLit::a(fsv->min());
1298             }
1299           }
1300         }
1301         cur = cur->cast<VarDecl>()->e();
1302         break;
1303       default:
1304         return nullptr;
1305     }
1306   }
1307 }
1308 
b_is_fixed(EnvI & env,Call * call)1309 bool b_is_fixed(EnvI& env, Call* call) {
1310   assert(call->argCount() == 1);
1311   return exp_is_fixed(env, call->arg(0)) != nullptr;
1312 }
1313 
b_is_fixed_array(EnvI & env,Call * call)1314 bool b_is_fixed_array(EnvI& env, Call* call) {
1315   assert(call->argCount() == 1);
1316   GCLock lock;
1317   ArrayLit* al = eval_array_lit(env, call->arg(0));
1318   if (al->size() == 0) {
1319     return true;
1320   }
1321   for (unsigned int i = 0; i < al->size(); i++) {
1322     if (exp_is_fixed(env, (*al)[i]) == nullptr) {
1323       return false;
1324     }
1325   }
1326   return true;
1327 }
1328 
b_is_same(EnvI & env,Call * call)1329 bool b_is_same(EnvI& env, Call* call) {
1330   assert(call->argCount() == 2);
1331   return follow_id_to_decl(call->arg(0)) == follow_id_to_decl(call->arg(1));
1332 }
1333 
b_fix(EnvI & env,Call * call)1334 Expression* b_fix(EnvI& env, Call* call) {
1335   assert(call->argCount() == 1);
1336   Expression* ret = exp_is_fixed(env, call->arg(0));
1337   if (ret == nullptr) {
1338     throw EvalError(env, call->arg(0)->loc(), "expression is not fixed");
1339   }
1340   return ret;
1341 }
1342 
b_fix_int(EnvI & env,Call * call)1343 IntVal b_fix_int(EnvI& env, Call* call) { return eval_int(env, b_fix(env, call)); }
b_fix_bool(EnvI & env,Call * call)1344 bool b_fix_bool(EnvI& env, Call* call) { return eval_bool(env, b_fix(env, call)); }
b_fix_float(EnvI & env,Call * call)1345 FloatVal b_fix_float(EnvI& env, Call* call) { return eval_float(env, b_fix(env, call)); }
b_fix_set(EnvI & env,Call * call)1346 IntSetVal* b_fix_set(EnvI& env, Call* call) { return eval_intset(env, b_fix(env, call)); }
1347 
b_fix_array(EnvI & env,Call * call)1348 Expression* b_fix_array(EnvI& env, Call* call) {
1349   assert(call->argCount() == 1);
1350   GCLock lock;
1351   ArrayLit* al = eval_array_lit(env, call->arg(0));
1352   std::vector<Expression*> fixed(al->size());
1353   for (unsigned int i = 0; i < fixed.size(); i++) {
1354     fixed[i] = exp_is_fixed(env, (*al)[i]);
1355     if (fixed[i] == nullptr) {
1356       throw EvalError(env, (*al)[i]->loc(), "expression is not fixed");
1357     }
1358   }
1359   auto* ret = new ArrayLit(Location(), fixed);
1360   Type tt = al->type();
1361   tt.ti(Type::TI_PAR);
1362   ret->type(tt);
1363   return ret;
1364 }
1365 
b_has_ann(EnvI & env,Call * call)1366 bool b_has_ann(EnvI& env, Call* call) {
1367   assert(call->argCount() == 2);
1368   Expression* expr = call->arg(0);
1369   if (!expr->isa<Id>()) {
1370     // Argument is a literal, unable to verify annotations
1371     return false;
1372   }
1373   expr = follow_id_to_decl(expr);
1374   Expression* ann = call->arg(1);
1375   if (ann->isa<Id>()) {
1376     return expr->ann().contains(ann);
1377   }
1378   auto* key = ann->cast<Call>();
1379   if (Call* c = expr->ann().getCall(key->id())) {
1380     if (c->argCount() != key->argCount()) {
1381       return false;
1382     }
1383     for (int i = 0; i < c->argCount(); ++i) {
1384       if (c->arg(i)->type() != key->arg(i)->type()) {
1385         return false;
1386       }
1387       if (c->arg(i)->type().isPar()) {
1388         GCLock lock;
1389         Expression* check_eq = new BinOp(Location().introduce(), c->arg(i), BOT_EQ, key->arg(i));
1390         check_eq->type(Type::parbool());
1391         if (!eval_bool(env, check_eq)) {
1392           return false;
1393         }
1394       } else {
1395         if (c->arg(i)->isa<Id>() && key->arg(i)->isa<Id>()) {
1396           if (follow_id_to_decl(c->arg(i)) != follow_id_to_decl(key->arg(i))) {
1397             return false;
1398           }
1399         } else {
1400           throw EvalError(env, call->loc(), "Unable to determine equality of variable expressions");
1401         }
1402       }
1403     }
1404     return true;
1405   }
1406   return false;
1407 }
1408 
b_annotate(EnvI & env,Call * call)1409 bool b_annotate(EnvI& env, Call* call) {
1410   assert(call->argCount() == 2);
1411   Expression* expr = call->arg(0);
1412   if (!expr->isa<Id>()) {
1413     // Argument is a literal, unable to annotate
1414     std::ostringstream ss;
1415     ss << "Unable to annotate literal expression `" << *expr << "'.";
1416     env.addWarning(ss.str());
1417     return true;
1418   }
1419   auto* var_decl = follow_id_to_decl(expr)->cast<VarDecl>();
1420   // Add annotation
1421   Expression* ann = call->arg(1);
1422   var_decl->ann().add(ann);
1423   // Increase usage count of the annotation
1424   if (auto* ann_decl = follow_id_to_decl(ann)->dynamicCast<VarDecl>()) {
1425     auto var_it = env.varOccurrences.idx.find(var_decl->id());
1426     assert(var_it != env.varOccurrences.idx.end());
1427     env.varOccurrences.add(ann_decl, (*env.flat())[var_it->second]);
1428   }
1429   return true;
1430 }
1431 
b_int2float(EnvI & env,Call * call)1432 FloatVal b_int2float(EnvI& env, Call* call) { return eval_int(env, call->arg(0)); }
b_ceil(EnvI & env,Call * call)1433 IntVal b_ceil(EnvI& env, Call* call) {
1434   return static_cast<IntVal>(std::ceil(eval_float(env, call->arg(0))));
1435 }
b_floor(EnvI & env,Call * call)1436 IntVal b_floor(EnvI& env, Call* call) {
1437   return static_cast<IntVal>(std::floor(eval_float(env, call->arg(0))));
1438 }
b_round(EnvI & env,Call * call)1439 IntVal b_round(EnvI& env, Call* call) {
1440   /// Cast to int truncates, so cannot just add 0.5 and cast
1441   return {static_cast<long long>(std::round(eval_float(env, call->arg(0)).toDouble()))};
1442 }
b_log10(EnvI & env,Call * call)1443 FloatVal b_log10(EnvI& env, Call* call) {
1444   return std::log10(eval_float(env, call->arg(0)).toDouble());
1445 }
b_log2(EnvI & env,Call * call)1446 FloatVal b_log2(EnvI& env, Call* call) {
1447   return std::log(eval_float(env, call->arg(0)).toDouble()) / std::log(2.0);
1448 }
b_ln(EnvI & env,Call * call)1449 FloatVal b_ln(EnvI& env, Call* call) { return std::log(eval_float(env, call->arg(0)).toDouble()); }
b_log(EnvI & env,Call * call)1450 FloatVal b_log(EnvI& env, Call* call) {
1451   return std::log(eval_float(env, call->arg(1)).toDouble()) /
1452          std::log(eval_float(env, call->arg(0)).toDouble());
1453 }
b_exp(EnvI & env,Call * call)1454 FloatVal b_exp(EnvI& env, Call* call) { return std::exp(eval_float(env, call->arg(0)).toDouble()); }
b_pow(EnvI & env,Call * call)1455 FloatVal b_pow(EnvI& env, Call* call) {
1456   return std::pow(eval_float(env, call->arg(0)).toDouble(),
1457                   eval_float(env, call->arg(1)).toDouble());
1458 }
b_pow_int(EnvI & env,Call * call)1459 IntVal b_pow_int(EnvI& env, Call* call) {
1460   IntVal p = eval_int(env, call->arg(0));
1461   IntVal r = 1;
1462   long long int e = eval_int(env, call->arg(1)).toInt();
1463   if (e < 0) {
1464     throw EvalError(env, call->arg(1)->loc(), "Cannot raise integer to a negative power");
1465   }
1466   for (long long int i = e; (i--) != 0;) {
1467     r = r * p;
1468   }
1469   return r;
1470 }
b_sqrt(EnvI & env,Call * call)1471 FloatVal b_sqrt(EnvI& env, Call* call) {
1472   return std::sqrt(eval_float(env, call->arg(0)).toDouble());
1473 }
1474 
b_assert_bool(EnvI & env,Call * call)1475 bool b_assert_bool(EnvI& env, Call* call) {
1476   assert(call->argCount() == 2);
1477   GCLock lock;
1478   Expression* cond_e;
1479   if (call->arg(0)->type().cv()) {
1480     Ctx ctx;
1481     ctx.b = C_MIX;
1482     cond_e = flat_cv_exp(env, ctx, call->arg(0))();
1483   } else {
1484     cond_e = call->arg(0);
1485   }
1486   if (eval_bool(env, cond_e)) {
1487     return true;
1488   }
1489   Expression* msg_e;
1490   if (call->arg(1)->type().cv()) {
1491     msg_e = flat_cv_exp(env, Ctx(), call->arg(1))();
1492   } else {
1493     msg_e = call->arg(1);
1494   }
1495   std::ostringstream ss;
1496   ss << "Assertion failed: " << eval_string(env, msg_e);
1497   throw EvalError(env, call->arg(0)->loc(), ss.str());
1498 }
1499 
b_assert(EnvI & env,Call * call)1500 Expression* b_assert(EnvI& env, Call* call) {
1501   assert(call->argCount() == 3);
1502   GCLock lock;
1503   Expression* cond_e;
1504   if (call->arg(0)->type().cv()) {
1505     Ctx ctx;
1506     ctx.b = C_MIX;
1507     cond_e = flat_cv_exp(env, ctx, call->arg(0))();
1508   } else {
1509     cond_e = call->arg(0);
1510   }
1511   if (eval_bool(env, cond_e)) {
1512     return call->arg(2);
1513   }
1514   Expression* msg_e;
1515   if (call->arg(1)->type().cv()) {
1516     msg_e = flat_cv_exp(env, Ctx(), call->arg(1))();
1517   } else {
1518     msg_e = call->arg(1);
1519   }
1520   std::ostringstream ss;
1521   ss << "Assertion failed: " << eval_string(env, msg_e);
1522   throw EvalError(env, call->arg(0)->loc(), ss.str());
1523 }
1524 
b_mzn_deprecate(EnvI & env,Call * call)1525 Expression* b_mzn_deprecate(EnvI& env, Call* call) {
1526   assert(call->argCount() == 4);
1527   GCLock lock;
1528   std::string fnName = eval_string(env, call->arg(0));
1529   if (env.deprecationWarnings.find(fnName) == env.deprecationWarnings.end()) {
1530     env.deprecationWarnings.insert(fnName);
1531     env.dumpStack(env.errstream, false);
1532     env.errstream << "  The function/predicate `" << fnName;
1533     env.errstream << "' was deprecated in MiniZinc version " << eval_string(env, call->arg(1));
1534     env.errstream << ".\n  More information can be found at " << eval_string(env, call->arg(2))
1535                   << ".\n";
1536   }
1537   return call->arg(3);
1538 }
1539 
b_abort(EnvI & env,Call * call)1540 bool b_abort(EnvI& env, Call* call) {
1541   GCLock lock;
1542   Expression* msg_e;
1543   if (call->arg(0)->type().cv()) {
1544     msg_e = flat_cv_exp(env, Ctx(), call->arg(0))();
1545   } else {
1546     msg_e = call->arg(0);
1547   }
1548   std::ostringstream ss;
1549   ss << "Abort: " << eval_string(env, msg_e);
1550   throw EvalError(env, call->arg(0)->loc(), ss.str());
1551 }
1552 
b_mzn_symmetry_breaking_constraint(EnvI & env,Call * call)1553 Expression* b_mzn_symmetry_breaking_constraint(EnvI& env, Call* call) {
1554   GCLock lock;
1555   Call* check = new Call(Location().introduce(),
1556                          ASTString("mzn_check_ignore_symmetry_breaking_constraints"), {});
1557   check->type(Type::parbool());
1558   check->decl(env.model->matchFn(env, check, false, true));
1559   if (eval_bool(env, check)) {
1560     return constants().literalTrue;
1561   }
1562   Call* nc = new Call(call->loc(), ASTString("symmetry_breaking_constraint"), {call->arg(0)});
1563   nc->type(Type::varbool());
1564   nc->decl(env.model->matchFn(env, nc, false, true));
1565   return nc;
1566 }
1567 
b_mzn_redundant_constraint(EnvI & env,Call * call)1568 Expression* b_mzn_redundant_constraint(EnvI& env, Call* call) {
1569   GCLock lock;
1570   Call* check =
1571       new Call(Location().introduce(), ASTString("mzn_check_ignore_redundant_constraints"), {});
1572   check->type(Type::parbool());
1573   check->decl(env.model->matchFn(env, check, false, true));
1574   if (eval_bool(env, check)) {
1575     return constants().literalTrue;
1576   }
1577   Call* nc = new Call(call->loc(), ASTString("redundant_constraint"), {call->arg(0)});
1578   nc->type(Type::varbool());
1579   nc->decl(env.model->matchFn(env, nc, false, true));
1580   return nc;
1581 }
1582 
b_trace(EnvI & env,Call * call)1583 Expression* b_trace(EnvI& env, Call* call) {
1584   GCLock lock;
1585   Expression* msg_e;
1586   if (call->arg(0)->type().cv()) {
1587     msg_e = flat_cv_exp(env, Ctx(), call->arg(0))();
1588   } else {
1589     msg_e = call->arg(0);
1590   }
1591   env.errstream << eval_string(env, msg_e);
1592   return call->argCount() == 1 ? constants().literalTrue : call->arg(1);
1593 }
1594 
b_trace_stdout(EnvI & env,Call * call)1595 Expression* b_trace_stdout(EnvI& env, Call* call) {
1596   GCLock lock;
1597   Expression* msg_e;
1598   if (call->arg(0)->type().cv()) {
1599     msg_e = flat_cv_exp(env, Ctx(), call->arg(0))();
1600   } else {
1601     msg_e = call->arg(0);
1602   }
1603   env.errstream << eval_string(env, msg_e);
1604   return call->argCount() == 1 ? constants().literalTrue : call->arg(1);
1605 }
1606 
b_trace_logstream(EnvI & env,Call * call)1607 Expression* b_trace_logstream(EnvI& env, Call* call) {
1608   GCLock lock;
1609   StringLit* msg;
1610   if (call->arg(0)->type().cv()) {
1611     msg = flat_cv_exp(env, Ctx(), call->arg(0))()->cast<StringLit>();
1612   } else {
1613     msg = eval_par(env, call->arg(0))->cast<StringLit>();
1614   }
1615   env.logstream << msg->v();
1616   return call->argCount() == 1 ? constants().literalTrue : call->arg(1);
1617 }
b_logstream(EnvI & env,Call * call)1618 std::string b_logstream(EnvI& env, Call* call) { return env.logstream.str(); }
1619 
b_in_redundant_constraint(EnvI & env,Call *)1620 bool b_in_redundant_constraint(EnvI& env, Call* /*call*/) { return env.inRedundantConstraint > 0; }
1621 
b_in_symmetry_breaking_constraint(EnvI & env,Call *)1622 bool b_in_symmetry_breaking_constraint(EnvI& env, Call* /*call*/) {
1623   return env.inSymmetryBreakingConstraint > 0;
1624 }
1625 
b_set2array(EnvI & env,Call * call)1626 Expression* b_set2array(EnvI& env, Call* call) {
1627   assert(call->argCount() == 1);
1628   GCLock lock;
1629   IntSetVal* isv = eval_intset(env, call->arg(0));
1630   std::vector<Expression*> elems;
1631   IntSetRanges isr(isv);
1632   for (Ranges::ToValues<IntSetRanges> isr_v(isr); isr_v(); ++isr_v) {
1633     elems.push_back(IntLit::a(isr_v.val()));
1634   }
1635   auto* al = new ArrayLit(call->arg(0)->loc(), elems);
1636   al->type(Type::parint(1));
1637   return al;
1638 }
1639 
b_string_length(EnvI & env,Call * call)1640 IntVal b_string_length(EnvI& env, Call* call) {
1641   GCLock lock;
1642   std::string s = eval_string(env, call->arg(0));
1643   return s.size();
1644 }
1645 
show(EnvI & env,Expression * exp)1646 std::string show(EnvI& env, Expression* exp) {
1647   std::ostringstream oss;
1648   GCLock lock;
1649   Printer p(oss, 0, false);
1650   Expression* e = follow_id_to_decl(exp);
1651   if (auto* vd = e->dynamicCast<VarDecl>()) {
1652     if ((vd->e() != nullptr) && !vd->e()->isa<Call>()) {
1653       e = vd->e();
1654     } else {
1655       e = vd->id();
1656     }
1657   }
1658   if (e->type().isPar()) {
1659     e = eval_par(env, e);
1660   }
1661   if (e->type().dim() > 0) {
1662     e = eval_array_lit(env, e);
1663   }
1664   if (auto* al = e->dynamicCast<ArrayLit>()) {
1665     oss << "[";
1666     for (unsigned int i = 0; i < al->size(); i++) {
1667       p.print((*al)[i]);
1668       if (i < al->size() - 1) {
1669         oss << ", ";
1670       }
1671     }
1672     oss << "]";
1673   } else {
1674     p.print(e);
1675   }
1676   return oss.str();
1677 }
b_show(EnvI & env,Call * call)1678 std::string b_show(EnvI& env, Call* call) { return show(env, call->arg(0)); }
b_show_dzn_id(EnvI & env,Call * call)1679 std::string b_show_dzn_id(EnvI& env, Call* call) {
1680   GCLock lock;
1681   std::string s = eval_string(env, call->arg(0));
1682   size_t nonIdChar =
1683       s.find_first_not_of("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_");
1684   size_t nonIdBegin = s.find_first_of("0123456789_");
1685   if (nonIdChar != std::string::npos || nonIdBegin == 0) {
1686     s = "'" + s + "'";
1687   }
1688   return s;
1689 }
1690 
b_show_json_basic(EnvI & env,Expression * e)1691 std::string b_show_json_basic(EnvI& env, Expression* e) {
1692   std::ostringstream oss;
1693   Printer p(oss, 0, false);
1694   if (auto* sl = e->dynamicCast<SetLit>()) {
1695     oss << "{ \"set\" : [";
1696     if (IntSetVal* isv = sl->isv()) {
1697       bool first = true;
1698       for (IntSetRanges isr(isv); isr(); ++isr) {
1699         if (first) {
1700           first = false;
1701         } else {
1702           oss << ",";
1703         }
1704         if (isr.min() == isr.max()) {
1705           oss << isr.min();
1706         } else {
1707           oss << "[" << isr.min() << "," << isr.max() << "]";
1708         }
1709       }
1710     } else if (FloatSetVal* fsv = sl->fsv()) {
1711       bool first = true;
1712       for (FloatSetRanges fsr(fsv); fsr(); ++fsr) {
1713         if (first) {
1714           first = false;
1715         } else {
1716           oss << ",";
1717         }
1718         if (fsr.min() == fsr.max()) {
1719           pp_floatval(oss, fsr.min());
1720         } else {
1721           oss << "[";
1722           pp_floatval(oss, fsr.min());
1723           oss << ",";
1724           pp_floatval(oss, fsr.max());
1725           oss << "]";
1726         }
1727       }
1728     } else {
1729       for (unsigned int i = 0; i < sl->v().size(); i++) {
1730         p.print(sl->v()[i]);
1731         if (i < sl->v().size() - 1) {
1732           oss << ",";
1733         }
1734       }
1735     }
1736     oss << "]}";
1737   } else if (e == constants().absent) {
1738     oss << "null";
1739   } else {
1740     p.print(e);
1741   }
1742   return oss.str();
1743 }
1744 
b_show_json(EnvI & env,Call * call)1745 std::string b_show_json(EnvI& env, Call* call) {
1746   Expression* exp = call->arg(0);
1747   GCLock lock;
1748   Expression* e = eval_par(env, exp);
1749   if (e->type().isvar()) {
1750     std::ostringstream oss;
1751     Printer p(oss, 0, false);
1752     p.print(e);
1753     return oss.str();
1754   }
1755   if (auto* al = e->dynamicCast<ArrayLit>()) {
1756     std::vector<unsigned int> dims(al->dims() - 1);
1757     if (!dims.empty()) {
1758       dims[0] = al->max(al->dims() - 1) - al->min(al->dims() - 1) + 1;
1759     }
1760 
1761     for (int i = 1; i < al->dims() - 1; i++) {
1762       dims[i] = dims[i - 1] * (al->max(al->dims() - 1 - i) - al->min(al->dims() - 1 - i) + 1);
1763     }
1764 
1765     std::ostringstream oss;
1766     oss << "[";
1767     for (unsigned int i = 0; i < al->size(); i++) {
1768       for (unsigned int dim : dims) {
1769         if (i % dim == 0) {
1770           oss << "[";
1771         }
1772       }
1773       oss << b_show_json_basic(env, (*al)[i]);
1774       for (unsigned int dim : dims) {
1775         if (i % dim == dim - 1) {
1776           oss << "]";
1777         }
1778       }
1779 
1780       if (i < al->size() - 1) {
1781         oss << ", ";
1782       }
1783     }
1784     oss << "]";
1785 
1786     return oss.str();
1787   }
1788   return b_show_json_basic(env, e);
1789 }
1790 
b_output_json(EnvI & env,Call * call)1791 Expression* b_output_json(EnvI& env, Call* call) {
1792   return create_json_output(env, false, false, false);
1793 }
b_output_json_parameters(EnvI & env,Call * call)1794 Expression* b_output_json_parameters(EnvI& env, Call* call) {
1795   std::vector<Expression*> outputVars;
1796   outputVars.push_back(new StringLit(Location().introduce(), "{\n"));
1797 
1798   class JSONParVisitor : public ItemVisitor {
1799   protected:
1800     EnvI& _e;
1801     std::vector<Expression*>& _outputVars;
1802     bool _firstVar;
1803 
1804   public:
1805     JSONParVisitor(EnvI& e, std::vector<Expression*>& outputVars)
1806         : _e(e), _outputVars(outputVars), _firstVar(true) {}
1807     void vVarDeclI(VarDeclI* vdi) {
1808       VarDecl* vd = vdi->e();
1809       if (vd->ann().contains(constants().ann.rhs_from_assignment)) {
1810         std::ostringstream s;
1811         if (_firstVar) {
1812           _firstVar = false;
1813         } else {
1814           s << ",\n";
1815         }
1816         s << "  \"" << vd->id()->str() << "\""
1817           << " : ";
1818         auto* sl = new StringLit(Location().introduce(), s.str());
1819         _outputVars.push_back(sl);
1820 
1821         std::vector<Expression*> showArgs(1);
1822         showArgs[0] = vd->id();
1823         Call* show = new Call(Location().introduce(), "showJSON", showArgs);
1824         show->type(Type::parstring());
1825         FunctionI* fi = _e.model->matchFn(_e, show, false);
1826         assert(fi);
1827         show->decl(fi);
1828         _outputVars.push_back(show);
1829       }
1830     }
1831   } jsonov(env, outputVars);
1832 
1833   iter_items(jsonov, env.model);
1834   outputVars.push_back(new StringLit(Location().introduce(), "\n}\n"));
1835   return new ArrayLit(Location().introduce(), outputVars);
1836 }
1837 
b_format(EnvI & env,Call * call)1838 std::string b_format(EnvI& env, Call* call) {
1839   int width = 0;
1840   int prec = -1;
1841   GCLock lock;
1842   Expression* e;
1843   if (call->argCount() > 1) {
1844     width = static_cast<int>(eval_int(env, call->arg(0)).toInt());
1845     if (call->argCount() == 2) {
1846       e = eval_par(env, call->arg(1));
1847     } else {
1848       assert(call->argCount() == 3);
1849       prec = static_cast<int>(eval_int(env, call->arg(1)).toInt());
1850       if (prec < 0) {
1851         throw EvalError(env, call->arg(1)->loc(), "output precision cannot be negative");
1852       }
1853       e = eval_par(env, call->arg(2));
1854     }
1855   } else {
1856     e = eval_par(env, call->arg(0));
1857   }
1858   if (e->type() == Type::parint()) {
1859     long long int i = eval_int(env, e).toInt();
1860     std::ostringstream formatted;
1861     if (width > 0) {
1862       formatted.width(width);
1863     } else if (width < 0) {
1864       formatted.width(-width);
1865       formatted.flags(std::ios::left);
1866     }
1867     if (prec != -1) {
1868       formatted.precision(prec);
1869     }
1870     formatted << i;
1871     return formatted.str();
1872   }
1873   if (e->type() == Type::parfloat()) {
1874     FloatVal i = eval_float(env, e);
1875     std::ostringstream formatted;
1876     if (width > 0) {
1877       formatted.width(width);
1878     } else if (width < 0) {
1879       formatted.width(-width);
1880       formatted.flags(std::ios::left);
1881     }
1882     formatted.setf(std::ios::fixed);
1883     formatted.precision(std::numeric_limits<double>::digits10 + 2);
1884     if (prec != -1) {
1885       formatted.precision(prec);
1886     }
1887     formatted << i;
1888     return formatted.str();
1889   }
1890   std::string s = show(env, e);
1891   if (prec >= 0 && prec < s.size()) {
1892     s = s.substr(0, prec);
1893   }
1894   std::ostringstream oss;
1895   if (s.size() < std::abs(width)) {
1896     int addLeft = width < 0 ? 0 : (width - static_cast<int>(s.size()));
1897     if (addLeft < 0) {
1898       addLeft = 0;
1899     }
1900     int addRight = width < 0 ? (-width - static_cast<int>(s.size())) : 0;
1901     if (addRight < 0) {
1902       addRight = 0;
1903     }
1904     for (int i = addLeft; (i--) != 0;) {
1905       oss << " ";
1906     }
1907     oss << s;
1908     for (int i = addRight; (i--) != 0;) {
1909       oss << " ";
1910     }
1911     return oss.str();
1912   }
1913   return s;
1914 }
1915 
b_format_justify_string(EnvI & env,Call * call)1916 std::string b_format_justify_string(EnvI& env, Call* call) {
1917   int width = 0;
1918   GCLock lock;
1919   Expression* e;
1920   width = static_cast<int>(eval_int(env, call->arg(0)).toInt());
1921   e = eval_par(env, call->arg(1));
1922   std::string s = eval_string(env, e);
1923   std::ostringstream oss;
1924   if (s.size() < std::abs(width)) {
1925     int addLeft = width < 0 ? 0 : (width - static_cast<int>(s.size()));
1926     if (addLeft < 0) {
1927       addLeft = 0;
1928     }
1929     int addRight = width < 0 ? (-width - static_cast<int>(s.size())) : 0;
1930     if (addRight < 0) {
1931       addRight = 0;
1932     }
1933     for (int i = addLeft; (i--) != 0;) {
1934       oss << " ";
1935     }
1936     oss << s;
1937     for (int i = addRight; (i--) != 0;) {
1938       oss << " ";
1939     }
1940     return oss.str();
1941   }
1942   return s;
1943 }
1944 
b_show_int(EnvI & env,Call * call)1945 std::string b_show_int(EnvI& env, Call* call) {
1946   assert(call->argCount() == 2);
1947   GCLock lock;
1948   Expression* e = eval_par(env, call->arg(1));
1949   std::ostringstream oss;
1950   if (auto* iv = e->dynamicCast<IntLit>()) {
1951     int justify = static_cast<int>(eval_int(env, call->arg(0)).toInt());
1952     std::ostringstream oss_length;
1953     oss_length << iv->v();
1954     int iv_length = static_cast<int>(oss_length.str().size());
1955     int addLeft = justify < 0 ? 0 : (justify - iv_length);
1956     if (addLeft < 0) {
1957       addLeft = 0;
1958     }
1959     int addRight = justify < 0 ? (-justify - iv_length) : 0;
1960     if (addRight < 0) {
1961       addRight = 0;
1962     }
1963     for (int i = addLeft; (i--) != 0;) {
1964       oss << " ";
1965     }
1966     oss << iv->v();
1967     for (int i = addRight; (i--) != 0;) {
1968       oss << " ";
1969     }
1970   } else {
1971     Printer p(oss, 0, false);
1972     p.print(e);
1973   }
1974   return oss.str();
1975 }
1976 
b_show_float(EnvI & env,Call * call)1977 std::string b_show_float(EnvI& env, Call* call) {
1978   assert(call->argCount() == 3);
1979   GCLock lock;
1980   Expression* e = eval_par(env, call->arg(2));
1981   std::ostringstream oss;
1982   if (auto* fv = e->dynamicCast<FloatLit>()) {
1983     int justify = static_cast<int>(eval_int(env, call->arg(0)).toInt());
1984     int prec = static_cast<int>(eval_int(env, call->arg(1)).toInt());
1985     if (prec < 0) {
1986       throw EvalError(env, call->arg(1)->loc(),
1987                       "number of digits in show_float cannot be negative");
1988     }
1989     std::ostringstream oss_length;
1990     oss_length << std::setprecision(prec) << std::fixed << fv->v();
1991     int fv_length = static_cast<int>(oss_length.str().size());
1992     int addLeft = justify < 0 ? 0 : (justify - fv_length);
1993     if (addLeft < 0) {
1994       addLeft = 0;
1995     }
1996     int addRight = justify < 0 ? (-justify - fv_length) : 0;
1997     if (addRight < 0) {
1998       addRight = 0;
1999     }
2000     for (int i = addLeft; (i--) != 0;) {
2001       oss << " ";
2002     }
2003     oss << std::setprecision(prec) << std::fixed << fv->v();
2004     for (int i = addRight; (i--) != 0;) {
2005       oss << " ";
2006     }
2007   } else {
2008     Printer p(oss, 0, false);
2009     p.print(e);
2010   }
2011   return oss.str();
2012 }
2013 
b_file_path(EnvI &,Call * call)2014 std::string b_file_path(EnvI& /*env*/, Call* call) {
2015   return FileUtils::file_path(
2016       std::string(call->loc().filename().c_str(), call->loc().filename().size()));
2017 }
2018 
b_concat(EnvI & env,Call * call)2019 std::string b_concat(EnvI& env, Call* call) {
2020   assert(call->argCount() == 1);
2021   GCLock lock;
2022   ArrayLit* al = eval_array_lit(env, call->arg(0));
2023   std::ostringstream oss;
2024   for (unsigned int i = 0; i < al->size(); i++) {
2025     oss << eval_string(env, (*al)[i]);
2026   }
2027   return oss.str();
2028 }
2029 
b_join(EnvI & env,Call * call)2030 std::string b_join(EnvI& env, Call* call) {
2031   assert(call->argCount() == 2);
2032   std::string sep = eval_string(env, call->arg(0));
2033   GCLock lock;
2034   ArrayLit* al = eval_array_lit(env, call->arg(1));
2035   std::ostringstream oss;
2036   for (unsigned int i = 0; i < al->size(); i++) {
2037     oss << eval_string(env, (*al)[i]);
2038     if (i < al->size() - 1) {
2039       oss << sep;
2040     }
2041   }
2042   return oss.str();
2043 }
2044 
b_array_union(EnvI & env,Call * call)2045 IntSetVal* b_array_union(EnvI& env, Call* call) {
2046   assert(call->argCount() == 1);
2047   ArrayLit* al = eval_array_lit(env, call->arg(0));
2048   if (al->size() == 0) {
2049     return IntSetVal::a();
2050   }
2051   IntSetVal* isv = eval_intset(env, (*al)[0]);
2052   for (unsigned int i = 0; i < al->size(); i++) {
2053     IntSetRanges i0(isv);
2054     IntSetRanges i1(eval_intset(env, (*al)[i]));
2055     Ranges::Union<IntVal, IntSetRanges, IntSetRanges> u(i0, i1);
2056     isv = IntSetVal::ai(u);
2057   }
2058   return isv;
2059 }
2060 
b_array_intersect(EnvI & env,Call * call)2061 IntSetVal* b_array_intersect(EnvI& env, Call* call) {
2062   assert(call->argCount() == 1);
2063   ArrayLit* al = eval_array_lit(env, call->arg(0));
2064   std::vector<IntSetVal::Range> ranges;
2065   if (al->size() > 0) {
2066     IntSetVal* i0 = eval_intset(env, (*al)[0]);
2067     if (i0->size() > 0) {
2068       IntSetRanges i0r(i0);
2069       IntVal min = i0r.min();
2070       while (i0r()) {
2071         // Initialize with last interval
2072         IntVal max = i0r.max();
2073         // Intersect with all other intervals
2074       restart:
2075         for (unsigned int j = al->size(); (j--) != 0U;) {
2076           IntSetRanges ij(eval_intset(env, (*al)[j]));
2077           // Skip intervals that are too small
2078           while (ij() && (ij.max() < min)) {
2079             ++ij;
2080           }
2081           if (!ij()) {
2082             goto done;
2083           }
2084           if (ij.min() > max) {
2085             min = ij.min();
2086             max = ij.max();
2087             goto restart;
2088           }
2089           // Now the intervals overlap
2090           if (min < ij.min()) {
2091             min = ij.min();
2092           }
2093           if (max > ij.max()) {
2094             max = ij.max();
2095           }
2096         }
2097         ranges.emplace_back(min, max);
2098         // The next interval must be at least two elements away
2099         min = max + 2;
2100       }
2101     done:
2102       return IntSetVal::a(ranges);
2103     } else {
2104       return IntSetVal::a();
2105     }
2106   } else {
2107     return IntSetVal::a();
2108   }
2109 }
2110 
b_sort_by_int(EnvI & env,Call * call)2111 Expression* b_sort_by_int(EnvI& env, Call* call) {
2112   assert(call->argCount() == 2);
2113   ArrayLit* al = eval_array_lit(env, call->arg(0));
2114   ArrayLit* order_e = eval_array_lit(env, call->arg(1));
2115   std::vector<IntVal> order(order_e->size());
2116   std::vector<int> a(order_e->size());
2117   for (unsigned int i = 0; i < order.size(); i++) {
2118     a[i] = i;
2119     order[i] = eval_int(env, (*order_e)[i]);
2120   }
2121   struct Ord {
2122     std::vector<IntVal>& order;
2123     Ord(std::vector<IntVal>& order0) : order(order0) {}
2124     bool operator()(int i, int j) { return order[i] < order[j]; }
2125   } _ord(order);
2126   std::stable_sort(a.begin(), a.end(), _ord);
2127   std::vector<Expression*> sorted(a.size());
2128   for (auto i = static_cast<unsigned int>(sorted.size()); (i--) != 0U;) {
2129     sorted[i] = (*al)[a[i]];
2130   }
2131   auto* al_sorted = new ArrayLit(al->loc(), sorted);
2132   al_sorted->type(al->type());
2133   return al_sorted;
2134 }
2135 
b_sort_by_float(EnvI & env,Call * call)2136 Expression* b_sort_by_float(EnvI& env, Call* call) {
2137   assert(call->argCount() == 2);
2138   ArrayLit* al = eval_array_lit(env, call->arg(0));
2139   ArrayLit* order_e = eval_array_lit(env, call->arg(1));
2140   std::vector<FloatVal> order(order_e->size());
2141   std::vector<int> a(order_e->size());
2142   for (unsigned int i = 0; i < order.size(); i++) {
2143     a[i] = i;
2144     order[i] = eval_float(env, (*order_e)[i]);
2145   }
2146   struct Ord {
2147     std::vector<FloatVal>& order;
2148     Ord(std::vector<FloatVal>& order0) : order(order0) {}
2149     bool operator()(int i, int j) { return order[i] < order[j]; }
2150   } _ord(order);
2151   std::stable_sort(a.begin(), a.end(), _ord);
2152   std::vector<Expression*> sorted(a.size());
2153   for (auto i = static_cast<unsigned int>(sorted.size()); (i--) != 0U;) {
2154     sorted[i] = (*al)[a[i]];
2155   }
2156   auto* al_sorted = new ArrayLit(al->loc(), sorted);
2157   al_sorted->type(al->type());
2158   return al_sorted;
2159 }
2160 
b_sort(EnvI & env,Call * call)2161 Expression* b_sort(EnvI& env, Call* call) {
2162   assert(call->argCount() == 1);
2163   ArrayLit* al = eval_array_lit(env, call->arg(0));
2164   std::vector<Expression*> sorted(al->size());
2165   for (auto i = static_cast<unsigned int>(sorted.size()); (i--) != 0U;) {
2166     sorted[i] = (*al)[i];
2167   }
2168   struct Ord {
2169     EnvI& env;
2170     Ord(EnvI& env0) : env(env0) {}
2171     bool operator()(Expression* e0, Expression* e1) {
2172       switch (e0->type().bt()) {
2173         case Type::BT_INT:
2174           return eval_int(env, e0) < eval_int(env, e1);
2175         case Type::BT_BOOL:
2176           return static_cast<int>(eval_bool(env, e0)) < static_cast<int>(eval_bool(env, e1));
2177         case Type::BT_FLOAT:
2178           return eval_float(env, e0) < eval_float(env, e1);
2179         default:
2180           throw EvalError(env, e0->loc(), "unsupported type for sorting");
2181       }
2182     }
2183   } _ord(env);
2184   std::sort(sorted.begin(), sorted.end(), _ord);
2185   auto* al_sorted = new ArrayLit(al->loc(), sorted);
2186   al_sorted->type(al->type());
2187   return al_sorted;
2188 }
2189 
b_inverse(EnvI & env,Call * call)2190 Expression* b_inverse(EnvI& env, Call* call) {
2191   assert(call->argCount() == 1);
2192   ArrayLit* al = eval_array_lit(env, call->arg(0));
2193   if (al->size() == 0) {
2194     return al;
2195   }
2196   int min_idx = al->min(0);
2197 
2198   std::vector<IntVal> ivs(al->size());
2199   IntVal minVal = eval_int(env, (*al)[0]);
2200   IntVal maxVal = minVal;
2201   ivs[0] = minVal;
2202   for (unsigned int i = 1; i < al->size(); i++) {
2203     IntVal ii = eval_int(env, (*al)[i]);
2204     ivs[i] = ii;
2205     minVal = std::min(minVal, ii);
2206     maxVal = std::max(maxVal, ii);
2207   }
2208   if (maxVal - minVal + 1 != al->size()) {
2209     throw ResultUndefinedError(env, call->loc(),
2210                                "inverse on non-contiguous set of values is undefined");
2211   }
2212 
2213   std::vector<Expression*> inv(al->size());
2214   std::vector<bool> used(al->size());
2215   for (unsigned int i = 0; i < ivs.size(); i++) {
2216     used[(ivs[i] - minVal).toInt()] = true;
2217     inv[(ivs[i] - minVal).toInt()] = IntLit::a(i + min_idx);
2218   }
2219   for (bool b : used) {
2220     if (!b) {
2221       throw ResultUndefinedError(env, call->loc(),
2222                                  "inverse on non-contiguous set of values is undefined");
2223     }
2224   }
2225   auto* al_inv = new ArrayLit(al->loc(), inv, {{minVal.toInt(), maxVal.toInt()}});
2226   al_inv->type(al->type());
2227   return al_inv;
2228 }
2229 
b_set_to_ranges_int(EnvI & env,Call * call)2230 Expression* b_set_to_ranges_int(EnvI& env, Call* call) {
2231   assert(call->argCount() == 1);
2232   IntSetVal* isv = eval_intset(env, call->arg(0));
2233   std::vector<Expression*> v(isv->size() * 2);
2234   for (unsigned int i = 0; i < isv->size(); i++) {
2235     v[2 * i] = IntLit::a(isv->min(i));
2236     v[2 * i + 1] = IntLit::a(isv->max(i));
2237   }
2238   auto* al = new ArrayLit(call->loc().introduce(), v);
2239   al->type(Type::parint(1));
2240   return al;
2241 }
2242 
b_set_to_ranges_float(EnvI & env,Call * call)2243 Expression* b_set_to_ranges_float(EnvI& env, Call* call) {
2244   assert(call->argCount() == 1);
2245   FloatSetVal* fsv = eval_floatset(env, call->arg(0));
2246   std::vector<Expression*> v(fsv->size() * 2);
2247   for (unsigned int i = 0; i < fsv->size(); i++) {
2248     v[2 * i] = FloatLit::a(fsv->min(i));
2249     v[2 * i + 1] = FloatLit::a(fsv->max(i));
2250   }
2251   auto* al = new ArrayLit(call->loc().introduce(), v);
2252   al->type(Type::parfloat(1));
2253   return al;
2254 }
2255 
rnd_generator()2256 std::default_random_engine& rnd_generator() {
2257   // TODO: initiate with seed if given as annotation/in command line
2258   static std::default_random_engine g;
2259   return g;
2260 }
2261 
b_normal_float_float(EnvI & env,Call * call)2262 FloatVal b_normal_float_float(EnvI& env, Call* call) {
2263   assert(call->argCount() == 2);
2264   const double mean = eval_float(env, call->arg(0)).toDouble();
2265   const double stdv = eval_float(env, call->arg(1)).toDouble();
2266   std::normal_distribution<double> distribution(mean, stdv);
2267   // return a sample from the distribution
2268   return distribution(rnd_generator());
2269 }
2270 
b_normal_int_float(EnvI & env,Call * call)2271 FloatVal b_normal_int_float(EnvI& env, Call* call) {
2272   assert(call->argCount() == 2);
2273   const double mean = double(eval_int(env, call->arg(0)).toInt());
2274   const double stdv = eval_float(env, call->arg(1)).toDouble();
2275   std::normal_distribution<double> distribution(mean, stdv);
2276   // return a sample from the distribution
2277   return distribution(rnd_generator());
2278 }
2279 
b_uniform_float(EnvI & env,Call * call)2280 FloatVal b_uniform_float(EnvI& env, Call* call) {
2281   assert(call->argCount() == 2);
2282   const double lb = eval_float(env, call->arg(0)).toDouble();
2283   const double ub = eval_float(env, call->arg(1)).toDouble();
2284   if (lb > ub) {
2285     std::stringstream ssm;
2286     ssm << "lowerbound of uniform distribution \"" << lb
2287         << "\" is higher than its upperbound: " << ub;
2288     throw EvalError(env, call->arg(0)->loc(), ssm.str());
2289   }
2290   std::uniform_real_distribution<double> distribution(lb, ub);
2291   // return a sample from the distribution
2292   return distribution(rnd_generator());
2293 }
2294 
b_uniform_int(EnvI & env,Call * call)2295 IntVal b_uniform_int(EnvI& env, Call* call) {
2296   assert(call->argCount() == 2);
2297   const long long int lb = eval_int(env, call->arg(0)).toInt();
2298   const long long int ub = eval_int(env, call->arg(1)).toInt();
2299   if (lb > ub) {
2300     std::stringstream ssm;
2301     ssm << "lowerbound of uniform distribution \"" << lb
2302         << "\" is higher than its upperbound: " << ub;
2303     throw EvalError(env, call->arg(0)->loc(), ssm.str());
2304   }
2305   std::uniform_int_distribution<long long int> distribution(lb, ub);
2306   // return a sample from the distribution
2307   return IntVal(distribution(rnd_generator()));
2308 }
2309 
b_poisson_int(EnvI & env,Call * call)2310 IntVal b_poisson_int(EnvI& env, Call* call) {
2311   assert(call->argCount() == 1);
2312   long long int mean = eval_int(env, call->arg(0)).toInt();
2313   std::poisson_distribution<long long int> distribution(static_cast<double>(mean));
2314   // return a sample from the distribution
2315   return IntVal(distribution(rnd_generator()));
2316 }
2317 
b_poisson_float(EnvI & env,Call * call)2318 IntVal b_poisson_float(EnvI& env, Call* call) {
2319   assert(call->argCount() == 1);
2320   double mean = eval_float(env, call->arg(0)).toDouble();
2321   std::poisson_distribution<long long int> distribution(mean);
2322   // return a sample from the distribution
2323   return IntVal(distribution(rnd_generator()));
2324 }
2325 
b_gamma_float_float(EnvI & env,Call * call)2326 FloatVal b_gamma_float_float(EnvI& env, Call* call) {
2327   assert(call->argCount() == 2);
2328   const double alpha = eval_float(env, call->arg(0)).toDouble();
2329   const double beta = eval_float(env, call->arg(1)).toDouble();
2330   std::gamma_distribution<double> distribution(alpha, beta);
2331   // return a sample from the distribution
2332   return distribution(rnd_generator());
2333 }
2334 
b_gamma_int_float(EnvI & env,Call * call)2335 FloatVal b_gamma_int_float(EnvI& env, Call* call) {
2336   assert(call->argCount() == 2);
2337   const double alpha = eval_float(env, call->arg(0)).toDouble();
2338   const double beta = eval_float(env, call->arg(1)).toDouble();
2339   std::gamma_distribution<double> distribution(alpha, beta);
2340   // return a sample from the distribution
2341   return distribution(rnd_generator());
2342 }
2343 
b_weibull_int_float(EnvI & env,Call * call)2344 FloatVal b_weibull_int_float(EnvI& env, Call* call) {
2345   assert(call->argCount() == 2);
2346   const double shape = double(eval_int(env, call->arg(0)).toInt());
2347   if (shape < 0) {
2348     std::stringstream ssm;
2349     ssm << "The shape factor for the weibull distribution \"" << shape
2350         << "\" has to be greater than zero.";
2351     throw EvalError(env, call->arg(0)->loc(), ssm.str());
2352   }
2353   const double scale = eval_float(env, call->arg(1)).toDouble();
2354   if (scale < 0) {
2355     std::stringstream ssm;
2356     ssm << "The scale factor for the weibull distribution \"" << scale
2357         << "\" has to be greater than zero.";
2358     throw EvalError(env, call->arg(1)->loc(), ssm.str());
2359   }
2360   std::weibull_distribution<double> distribution(shape, scale);
2361   // return a sample from the distribution
2362   return distribution(rnd_generator());
2363 }
2364 
b_weibull_float_float(EnvI & env,Call * call)2365 FloatVal b_weibull_float_float(EnvI& env, Call* call) {
2366   assert(call->argCount() == 2);
2367   const double shape = eval_float(env, call->arg(0)).toDouble();
2368   if (shape < 0) {
2369     std::stringstream ssm;
2370     ssm << "The shape factor for the weibull distribution \"" << shape
2371         << "\" has to be greater than zero.";
2372     throw EvalError(env, call->arg(0)->loc(), ssm.str());
2373   }
2374   const double scale = eval_float(env, call->arg(1)).toDouble();
2375   if (scale < 0) {
2376     std::stringstream ssm;
2377     ssm << "The scale factor for the weibull distribution \"" << scale
2378         << "\" has to be greater than zero.";
2379     throw EvalError(env, call->arg(1)->loc(), ssm.str());
2380   }
2381   std::weibull_distribution<double> distribution(shape, scale);
2382   // return a sample from the distribution
2383   return distribution(rnd_generator());
2384 }
2385 
b_exponential_float(EnvI & env,Call * call)2386 FloatVal b_exponential_float(EnvI& env, Call* call) {
2387   assert(call->argCount() == 1);
2388   const double lambda = eval_float(env, call->arg(0)).toDouble();
2389   if (lambda < 0) {
2390     std::stringstream ssm;
2391     ssm << "The lambda-parameter for the exponential distribution function \"" << lambda
2392         << "\" has to be greater than zero.";
2393     throw EvalError(env, call->arg(0)->loc(), ssm.str());
2394   }
2395   std::exponential_distribution<double> distribution(lambda);
2396   // return a sample from the distribution
2397   return distribution(rnd_generator());
2398 }
2399 
b_exponential_int(EnvI & env,Call * call)2400 FloatVal b_exponential_int(EnvI& env, Call* call) {
2401   assert(call->argCount() == 1);
2402   const double lambda = double(eval_int(env, call->arg(0)).toInt());
2403   if (lambda < 0) {
2404     std::stringstream ssm;
2405     ssm << "The lambda-parameter for the exponential distribution function \"" << lambda
2406         << "\" has to be greater than zero.";
2407     throw EvalError(env, call->arg(0)->loc(), ssm.str());
2408   }
2409   std::exponential_distribution<double> distribution(lambda);
2410   // return a sample from the distribution
2411   return distribution(rnd_generator());
2412 }
2413 
b_lognormal_float_float(EnvI & env,Call * call)2414 FloatVal b_lognormal_float_float(EnvI& env, Call* call) {
2415   assert(call->argCount() == 2);
2416   const double mean = eval_float(env, call->arg(0)).toDouble();
2417   const double stdv = eval_float(env, call->arg(1)).toDouble();
2418   std::lognormal_distribution<double> distribution(mean, stdv);
2419   // return a sample from the distribution
2420   return distribution(rnd_generator());
2421 }
2422 
b_lognormal_int_float(EnvI & env,Call * call)2423 FloatVal b_lognormal_int_float(EnvI& env, Call* call) {
2424   assert(call->argCount() == 2);
2425   const double mean = double(eval_int(env, call->arg(0)).toInt());
2426   const double stdv = eval_float(env, call->arg(1)).toDouble();
2427   std::lognormal_distribution<double> distribution(mean, stdv);
2428   // return a sample from the distribution
2429   return distribution(rnd_generator());
2430 }
2431 
b_chisquared_float(EnvI & env,Call * call)2432 FloatVal b_chisquared_float(EnvI& env, Call* call) {
2433   assert(call->argCount() == 1);
2434   const double lambda = eval_float(env, call->arg(0)).toDouble();
2435   std::exponential_distribution<double> distribution(lambda);
2436   // return a sample from the distribution
2437   return distribution(rnd_generator());
2438 }
2439 
b_chisquared_int(EnvI & env,Call * call)2440 FloatVal b_chisquared_int(EnvI& env, Call* call) {
2441   assert(call->argCount() == 1);
2442   const double lambda = double(eval_int(env, call->arg(0)).toInt());
2443   std::exponential_distribution<double> distribution(lambda);
2444   // return a sample from the distribution
2445   return distribution(rnd_generator());
2446 }
2447 
b_cauchy_float_float(EnvI & env,Call * call)2448 FloatVal b_cauchy_float_float(EnvI& env, Call* call) {
2449   assert(call->argCount() == 2);
2450   const double mean = eval_float(env, call->arg(0)).toDouble();
2451   const double scale = eval_float(env, call->arg(1)).toDouble();
2452   std::cauchy_distribution<double> distribution(mean, scale);
2453   // return a sample from the distribution
2454   return distribution(rnd_generator());
2455 }
2456 
b_cauchy_int_float(EnvI & env,Call * call)2457 FloatVal b_cauchy_int_float(EnvI& env, Call* call) {
2458   assert(call->argCount() == 2);
2459   const double mean = double(eval_int(env, call->arg(0)).toInt());
2460   const double scale = eval_float(env, call->arg(1)).toDouble();
2461   std::cauchy_distribution<double> distribution(mean, scale);
2462   // return a sample from the distribution
2463   return distribution(rnd_generator());
2464 }
2465 
b_fdistribution_float_float(EnvI & env,Call * call)2466 FloatVal b_fdistribution_float_float(EnvI& env, Call* call) {
2467   assert(call->argCount() == 2);
2468   const double d1 = eval_float(env, call->arg(0)).toDouble();
2469   const double d2 = eval_float(env, call->arg(1)).toDouble();
2470   std::fisher_f_distribution<double> distribution(d1, d2);
2471   // return a sample from the distribution
2472   return distribution(rnd_generator());
2473 }
2474 
b_fdistribution_int_int(EnvI & env,Call * call)2475 FloatVal b_fdistribution_int_int(EnvI& env, Call* call) {
2476   assert(call->argCount() == 2);
2477   const double d1 = double(eval_int(env, call->arg(0)).toInt());
2478   const double d2 = double(eval_int(env, call->arg(1)).toInt());
2479   std::fisher_f_distribution<double> distribution(d1, d2);
2480   // return a sample from the distribution
2481   return distribution(rnd_generator());
2482 }
2483 
b_tdistribution_float(EnvI & env,Call * call)2484 FloatVal b_tdistribution_float(EnvI& env, Call* call) {
2485   assert(call->argCount() == 1);
2486   const double sampleSize = eval_float(env, call->arg(0)).toDouble();
2487   std::student_t_distribution<double> distribution(sampleSize);
2488   // return a sample from the distribution
2489   return distribution(rnd_generator());
2490 }
2491 
b_tdistribution_int(EnvI & env,Call * call)2492 FloatVal b_tdistribution_int(EnvI& env, Call* call) {
2493   assert(call->argCount() == 1);
2494   const double sampleSize = double(eval_int(env, call->arg(0)).toInt());
2495   std::student_t_distribution<double> distribution(sampleSize);
2496   // return a sample from the distribution
2497   return distribution(rnd_generator());
2498 }
2499 
b_discrete_distribution(EnvI & env,Call * call)2500 IntVal b_discrete_distribution(EnvI& env, Call* call) {
2501   assert(call->argCount() == 1);
2502   GCLock lock;
2503   ArrayLit* al = eval_array_lit(env, call->arg(0));
2504   if (al->dims() != 1) {
2505     std::stringstream ssm;
2506     ssm << "expecting 1-dimensional array of weights for discrete distribution instead of: " << *al
2507         << std::endl;
2508     throw EvalError(env, al->loc(), ssm.str());
2509   }
2510   std::vector<long long int> weights(al->size());
2511   for (unsigned int i = 0; i < al->size(); i++) {
2512     weights[i] = eval_int(env, (*al)[i]).toInt();
2513   }
2514 #ifdef _MSC_VER
2515   std::size_t i(0);
2516   std::discrete_distribution<long long int> distribution(
2517       weights.size(), 0.0, 1.0, [&weights, &i](double d) { return weights[i++]; });
2518 #else
2519   std::discrete_distribution<long long int> distribution(weights.begin(), weights.end());
2520 #endif
2521   // return a sample from the distribution
2522   IntVal iv = IntVal(distribution(rnd_generator()));
2523   return iv;
2524 }
2525 
b_bernoulli(EnvI & env,Call * call)2526 bool b_bernoulli(EnvI& env, Call* call) {
2527   assert(call->argCount() == 1);
2528   const double p = eval_float(env, call->arg(0)).toDouble();
2529   std::bernoulli_distribution distribution(p);
2530   // return a sample from the distribution
2531   return distribution(rnd_generator());
2532 }
2533 
b_binomial(EnvI & env,Call * call)2534 IntVal b_binomial(EnvI& env, Call* call) {
2535   assert(call->argCount() == 2);
2536   double t = double(eval_int(env, call->arg(0)).toInt());
2537   double p = eval_float(env, call->arg(1)).toDouble();
2538   std::binomial_distribution<long long int> distribution(t, p);
2539   // return a sample from the distribution
2540   return IntVal(distribution(rnd_generator()));
2541 }
2542 
b_atan(EnvI & env,Call * call)2543 FloatVal b_atan(EnvI& env, Call* call) {
2544   assert(call->argCount() == 1);
2545   GCLock lock;
2546   FloatVal f = eval_float(env, call->arg(0));
2547   return std::atan(f.toDouble());
2548 }
2549 
b_cos(EnvI & env,Call * call)2550 FloatVal b_cos(EnvI& env, Call* call) {
2551   assert(call->argCount() == 1);
2552   GCLock lock;
2553   FloatVal f = eval_float(env, call->arg(0));
2554   return std::cos(f.toDouble());
2555 }
2556 
b_sin(EnvI & env,Call * call)2557 FloatVal b_sin(EnvI& env, Call* call) {
2558   assert(call->argCount() == 1);
2559   GCLock lock;
2560   FloatVal f = eval_float(env, call->arg(0));
2561   return std::sin(f.toDouble());
2562 }
2563 
b_asin(EnvI & env,Call * call)2564 FloatVal b_asin(EnvI& env, Call* call) {
2565   assert(call->argCount() == 1);
2566   GCLock lock;
2567   FloatVal f = eval_float(env, call->arg(0));
2568   return std::asin(f.toDouble());
2569 }
2570 
b_acos(EnvI & env,Call * call)2571 FloatVal b_acos(EnvI& env, Call* call) {
2572   assert(call->argCount() == 1);
2573   GCLock lock;
2574   FloatVal f = eval_float(env, call->arg(0));
2575   return std::acos(f.toDouble());
2576 }
2577 
b_tan(EnvI & env,Call * call)2578 FloatVal b_tan(EnvI& env, Call* call) {
2579   assert(call->argCount() == 1);
2580   GCLock lock;
2581   FloatVal f = eval_float(env, call->arg(0));
2582   return std::tan(f.toDouble());
2583 }
2584 
b_to_enum(EnvI & env,Call * call)2585 IntVal b_to_enum(EnvI& env, Call* call) {
2586   assert(call->argCount() == 2);
2587   IntSetVal* isv = eval_intset(env, call->arg(0));
2588   IntVal v = eval_int(env, call->arg(1));
2589   if (!isv->contains(v)) {
2590     throw ResultUndefinedError(env, call->loc(), "value outside of enum range");
2591   }
2592   return v;
2593 }
2594 
b_enum_next(EnvI & env,Call * call)2595 IntVal b_enum_next(EnvI& env, Call* call) {
2596   IntSetVal* isv = eval_intset(env, call->arg(0));
2597   IntVal v = eval_int(env, call->arg(1));
2598   if (!isv->contains(v + 1)) {
2599     throw ResultUndefinedError(env, call->loc(), "value outside of enum range");
2600   }
2601   return v + 1;
2602 }
2603 
b_enum_prev(EnvI & env,Call * call)2604 IntVal b_enum_prev(EnvI& env, Call* call) {
2605   IntSetVal* isv = eval_intset(env, call->arg(0));
2606   IntVal v = eval_int(env, call->arg(1));
2607   if (!isv->contains(v - 1)) {
2608     throw ResultUndefinedError(env, call->loc(), "value outside of enum range");
2609   }
2610   return v - 1;
2611 }
2612 
b_mzn_compiler_version(EnvI &,Call *)2613 IntVal b_mzn_compiler_version(EnvI& /*env*/, Call* /*call*/) {
2614   return atoi(MZN_VERSION_MAJOR) * 10000 + atoi(MZN_VERSION_MINOR) * 1000 + atoi(MZN_VERSION_PATCH);
2615 }
2616 
b_slice(EnvI & env,Call * call)2617 Expression* b_slice(EnvI& env, Call* call) {
2618   ArrayLit* al = eval_array_lit(env, call->arg(0));
2619 
2620   ArrayLit* slice = eval_array_lit(env, call->arg(1));
2621   std::vector<std::pair<int, int>> newSlice(slice->size());
2622   for (unsigned int i = 0; i < slice->size(); i++) {
2623     IntSetVal* isv = eval_intset(env, (*slice)[i]);
2624     if (isv->size() == 0) {
2625       newSlice[i] = std::pair<int, int>(1, 0);
2626     } else {
2627       if (isv->size() > 1) {
2628         throw ResultUndefinedError(env, call->loc(), "array slice must be contiguous");
2629       }
2630       int sl_min = isv->min().isFinite() ? static_cast<int>(isv->min().toInt()) : al->min(i);
2631       int sl_max = isv->max().isFinite() ? static_cast<int>(isv->max().toInt()) : al->max(i);
2632       if (sl_min < al->min(i) || sl_max > al->max(i)) {
2633         throw ResultUndefinedError(env, call->loc(), "array slice out of bounds");
2634       }
2635       newSlice[i] = std::pair<int, int>(sl_min, sl_max);
2636     }
2637   }
2638 
2639   std::vector<std::pair<int, int>> newDims(call->argCount() - 2);
2640   for (unsigned int i = 0; i < newDims.size(); i++) {
2641     IntSetVal* isv = eval_intset(env, call->arg(2 + i));
2642     if (isv->size() == 0) {
2643       newDims[i] = std::pair<int, int>(1, 0);
2644     } else {
2645       newDims[i] = std::pair<int, int>(static_cast<int>(isv->min().toInt()),
2646                                        static_cast<int>(isv->max().toInt()));
2647     }
2648   }
2649   auto* ret = new ArrayLit(al->loc(), al, newDims, newSlice);
2650   ret->type(call->type());
2651   return ret;
2652 }
2653 
b_regular_from_string(EnvI & env,Call * call)2654 Expression* b_regular_from_string(EnvI& env, Call* call) {
2655 #ifdef HAS_GECODE
2656   using namespace Gecode;
2657   ArrayLit* vars = eval_array_lit(env, call->arg(0));
2658   std::string expr = eval_string(env, call->arg(1));
2659 
2660   IntSetVal* dom;
2661   if (vars->size() == 0) {
2662     dom = IntSetVal::a();
2663   } else {
2664     dom = b_dom_varint(env, (*vars)[0]);
2665     for (unsigned int i = 1; i < vars->size(); i++) {
2666       IntSetRanges isr(dom);
2667       IntSetRanges r(b_dom_varint(env, (*vars)[i]));
2668       Ranges::Union<IntVal, IntSetRanges, IntSetRanges> u(isr, r);
2669       dom = IntSetVal::ai(u);
2670     }
2671   }
2672   long long int card = dom->max().toInt() - dom->min().toInt() + 1;
2673   int offset = 1 - static_cast<int>(dom->min().toInt());
2674 
2675   // Replace all occurrences of enum constructor calls
2676   std::regex constructor_call(
2677       "([A-Za-z][A-Za-z0-9_]*|'[^'\\xa\\xd\\x0]*')[[:space:]]*\\([[:space:]]*([A-Za-z][A-Za-z0-9_]*"
2678       "|'[^'\\xa\\xd\\x0]*'|([0-9]*))[[:space:]]*\\)",
2679       std::regex_constants::egrep);
2680   while (std::regex_search(expr, constructor_call)) {
2681     std::ostringstream oss;
2682     auto id_re_it =
2683         std::sregex_token_iterator(expr.begin(), expr.end(), constructor_call, {-1, 1, 2, 3});
2684     for (; id_re_it != std::sregex_token_iterator();) {
2685       std::string rest = *id_re_it;
2686       oss << rest;
2687       ++id_re_it;
2688       if (id_re_it == std::sregex_token_iterator()) {
2689         break;
2690       }
2691       std::string id1 = *id_re_it;
2692       ++id_re_it;
2693       std::string id2 = *id_re_it;
2694       ++id_re_it;
2695       std::string val3 = *id_re_it;
2696       ++id_re_it;
2697       // Enum constructor call, get both items
2698       Expression* arg;
2699       if (val3.empty()) {
2700         auto it = env.reverseEnum.find(id2);
2701         if (it == env.reverseEnum.end()) {
2702           throw std::runtime_error("Unknown identifier: " + id2);
2703         }
2704         auto* id2_vd = it->second->dynamicCast<VarDeclI>();
2705         if (id2_vd == nullptr) {
2706           throw std::runtime_error("identifier " + id2 + " is not an enum constant");
2707         }
2708         arg = id2_vd->e()->id();
2709       } else {
2710         int v = std::stoi(val3);
2711         arg = IntLit::a(v);
2712       }
2713       auto it = env.reverseEnum.find(id1);
2714       if (it == env.reverseEnum.end()) {
2715         throw std::runtime_error("Unknown identifier: " + id2);
2716       }
2717       if (auto* id1_vdi = it->second->dynamicCast<VarDeclI>()) {
2718         // this is not an enum constructor, simply output both values
2719         IntVal result1 = eval_int(env, id1_vdi->e()->id());
2720         IntVal result2 = eval_int(env, arg);
2721         oss << result1 << "(" << result2 << ")";
2722       } else {
2723         auto* fi = it->second->cast<FunctionI>();
2724         Call* c = new Call(Location().introduce(), fi->id(), {arg});
2725         c->type(fi->rtype(env, {arg->type()}, true));
2726         c->decl(fi);
2727 
2728         IntVal result = eval_int(env, c);
2729         oss << result;
2730       }
2731     }
2732     expr = oss.str();
2733   }
2734 
2735   // Replace all remaining enum identifiers
2736   std::regex enumid("[A-Za-z][A-Za-z0-9_]*|'[^'\\xa\\xd\\x0]*'", std::regex_constants::egrep);
2737   auto id_re_it = std::sregex_token_iterator(expr.begin(), expr.end(), enumid, {-1, 0});
2738   std::ostringstream oss;
2739   for (; id_re_it != std::sregex_token_iterator();) {
2740     std::string rest = *id_re_it;
2741     oss << rest;
2742     ++id_re_it;
2743     if (id_re_it == std::sregex_token_iterator()) {
2744       break;
2745     }
2746     std::string id1 = *id_re_it;
2747     ++id_re_it;
2748     auto it = env.reverseEnum.find(id1);
2749     if (it == env.reverseEnum.end()) {
2750       throw std::runtime_error("Unknown identifier: " + id1);
2751     }
2752     auto* id1_vd = it->second->dynamicCast<VarDeclI>();
2753     if (id1_vd == nullptr) {
2754       throw std::runtime_error("identifier " + id1 + " is not an enum constant");
2755     }
2756     IntVal result1 = eval_int(env, id1_vd->e()->id());
2757     oss << result1;
2758   }
2759   expr = oss.str();
2760 
2761   std::unique_ptr<REG> regex;
2762   try {
2763     regex = regex_from_string(expr, *dom);
2764   } catch (const std::exception& e) {
2765     throw SyntaxError(call->arg(1)->loc(), e.what());
2766   }
2767   DFA dfa = DFA(*regex);
2768 
2769   std::vector<std::vector<Expression*>> reg_trans(
2770       dfa.n_states(), std::vector<Expression*>(static_cast<size_t>(card), IntLit::a(IntVal(0))));
2771 
2772   DFA::Transitions trans(dfa);
2773   while (trans()) {
2774     //      std::cerr << trans.i_state() + 1 << " -- " << trans.symbol() << " --> " <<
2775     //      trans.o_state() + 1 << "\n";
2776     if (trans.symbol() >= dom->min().toInt() && trans.symbol() <= dom->max().toInt()) {
2777       reg_trans[trans.i_state()][trans.symbol() + offset - 1] =
2778           IntLit::a(IntVal(trans.o_state() + 1));
2779     }
2780     ++trans;
2781   }
2782 
2783   std::vector<Expression*> args(6);
2784   if (offset == 0) {
2785     args[0] = vars;  // x
2786   } else {
2787     std::vector<Expression*> nvars(vars->size());
2788     IntLit* loffset = IntLit::a(IntVal(offset));
2789     for (int i = 0; i < nvars.size(); ++i) {
2790       nvars[i] = new BinOp(call->loc().introduce(), (*vars)[i], BOT_PLUS, loffset);
2791       nvars[i]->type(Type::varint());
2792     }
2793     args[0] = new ArrayLit(call->loc().introduce(), nvars);  // x
2794     args[0]->type(Type::varint(1));
2795   }
2796   args[1] = IntLit::a(IntVal(dfa.n_states()));  // Q
2797   args[1]->type(Type::parint());
2798   args[2] = IntLit::a(IntVal(card));  // S
2799   args[2]->type(Type::parint());
2800   args[3] = new ArrayLit(call->loc().introduce(), reg_trans);  // d
2801   args[3]->type(Type::parint(2));
2802   args[4] = IntLit::a(IntVal(1));  // q0
2803   args[4]->type(Type::parint());
2804   args[5] = new SetLit(call->loc().introduce(),
2805                        IntSetVal::a(IntVal(dfa.final_fst() + 1), IntVal(dfa.final_lst())));  // F
2806   args[5]->type(Type::parsetint());
2807 
2808   auto* nc = new Call(call->loc().introduce(), "regular", args);
2809   nc->type(Type::varbool());
2810 
2811   return nc;
2812 #else
2813   throw FlatteningError(
2814       env, call->loc(),
2815       "MiniZinc was compiled without built-in Gecode, cannot parse regular expression");
2816 #endif
2817 }
2818 
b_show_checker_output(EnvI & env,Call * call)2819 Expression* b_show_checker_output(EnvI& env, Call* call) {
2820   // Get checker output
2821   env.checkerOutput.flush();
2822   std::string output = env.checkerOutput.str();
2823   // Reset checker output
2824   env.checkerOutput.str("");
2825   env.checkerOutput.clear();
2826   return new StringLit(call->loc().introduce(), output);
2827 }
2828 
register_builtins(Env & e)2829 void register_builtins(Env& e) {
2830   EnvI& env = e.envi();
2831   Model* m = env.model;
2832 
2833   std::vector<Type> t_intint(2);
2834   t_intint[0] = Type::parint();
2835   t_intint[1] = Type::parint();
2836 
2837   std::vector<Type> t_intarray(1);
2838   t_intarray[0] = Type::parint(-1);
2839 
2840   GCLock lock;
2841 
2842   rb(env, m, ASTString("min"), t_intint, b_int_min);
2843   rb(env, m, ASTString("min"), t_intarray, b_int_min);
2844   rb(env, m, ASTString("max"), t_intint, b_int_max);
2845   rb(env, m, ASTString("max"), t_intarray, b_int_max);
2846   rb(env, m, constants().ids.sum, t_intarray, b_sum_int);
2847   rb(env, m, ASTString("product"), t_intarray, b_product_int);
2848   rb(env, m, ASTString("pow"), t_intint, b_pow_int);
2849 
2850   rb(env, m, ASTString("'div'"), t_intint, b_idiv);
2851   rb(env, m, ASTString("'mod'"), t_intint, b_mod);
2852   rb(env, m, ASTString("'..'"), t_intint, b_dotdot);
2853   {
2854     std::vector<Type> t({Type::parfloat(), Type::parfloat()});
2855     rb(env, m, ASTString("'/'"), t, b_fdiv);
2856   }
2857   {
2858     std::vector<Type> t(2);
2859     t[0] = Type::top(-1);
2860     t[1] = Type::top(-1);
2861     rb(env, m, ASTString("index_sets_agree"), t, b_index_sets_agree);
2862   }
2863   {
2864     std::vector<Type> t_anyarray1(1);
2865     t_anyarray1[0] = Type::optvartop(1);
2866     rb(env, m, ASTString("index_set"), t_anyarray1, b_index_set1);
2867   }
2868   {
2869     std::vector<Type> t_anyarray2(1);
2870     t_anyarray2[0] = Type::optvartop(2);
2871     rb(env, m, ASTString("index_set_1of2"), t_anyarray2, b_index_set1);
2872     rb(env, m, ASTString("index_set_2of2"), t_anyarray2, b_index_set2);
2873   }
2874   {
2875     std::vector<Type> t_anyarray3(1);
2876     t_anyarray3[0] = Type::optvartop(3);
2877     rb(env, m, ASTString("index_set_1of3"), t_anyarray3, b_index_set1);
2878     rb(env, m, ASTString("index_set_2of3"), t_anyarray3, b_index_set2);
2879     rb(env, m, ASTString("index_set_3of3"), t_anyarray3, b_index_set3);
2880   }
2881   {
2882     std::vector<Type> t_anyarray4(1);
2883     t_anyarray4[0] = Type::optvartop(4);
2884     rb(env, m, ASTString("index_set_1of4"), t_anyarray4, b_index_set1);
2885     rb(env, m, ASTString("index_set_2of4"), t_anyarray4, b_index_set2);
2886     rb(env, m, ASTString("index_set_3of4"), t_anyarray4, b_index_set3);
2887     rb(env, m, ASTString("index_set_4of4"), t_anyarray4, b_index_set4);
2888   }
2889   {
2890     std::vector<Type> t_anyarray5(1);
2891     t_anyarray5[0] = Type::optvartop(5);
2892     rb(env, m, ASTString("index_set_1of5"), t_anyarray5, b_index_set1);
2893     rb(env, m, ASTString("index_set_2of5"), t_anyarray5, b_index_set2);
2894     rb(env, m, ASTString("index_set_3of5"), t_anyarray5, b_index_set3);
2895     rb(env, m, ASTString("index_set_4of5"), t_anyarray5, b_index_set4);
2896     rb(env, m, ASTString("index_set_5of5"), t_anyarray5, b_index_set5);
2897   }
2898   {
2899     std::vector<Type> t_anyarray6(1);
2900     t_anyarray6[0] = Type::optvartop(6);
2901     rb(env, m, ASTString("index_set_1of6"), t_anyarray6, b_index_set1);
2902     rb(env, m, ASTString("index_set_2of6"), t_anyarray6, b_index_set2);
2903     rb(env, m, ASTString("index_set_3of6"), t_anyarray6, b_index_set3);
2904     rb(env, m, ASTString("index_set_4of6"), t_anyarray6, b_index_set4);
2905     rb(env, m, ASTString("index_set_5of6"), t_anyarray6, b_index_set5);
2906     rb(env, m, ASTString("index_set_6of6"), t_anyarray6, b_index_set6);
2907   }
2908   {
2909     std::vector<Type> t_arrayXd(1);
2910     t_arrayXd[0] = Type::top(-1);
2911     rb(env, m, ASTString("array1d"), t_arrayXd, b_array1d_list);
2912     t_arrayXd[0].ot(Type::OT_OPTIONAL);
2913     rb(env, m, ASTString("array1d"), t_arrayXd, b_array1d_list);
2914     t_arrayXd[0] = Type::vartop(-1);
2915     rb(env, m, ASTString("array1d"), t_arrayXd, b_array1d_list);
2916     t_arrayXd[0] = Type::optvartop(-1);
2917     rb(env, m, ASTString("array1d"), t_arrayXd, b_array1d_list);
2918   }
2919   {
2920     std::vector<Type> t_arrayXd(2);
2921     t_arrayXd[0] = Type::parsetint();
2922     t_arrayXd[1] = Type::top(-1);
2923     rb(env, m, ASTString("array1d"), t_arrayXd, b_array1d);
2924     t_arrayXd[1].ot(Type::OT_OPTIONAL);
2925     rb(env, m, ASTString("array1d"), t_arrayXd, b_array1d);
2926     t_arrayXd[1] = Type::vartop(-1);
2927     rb(env, m, ASTString("array1d"), t_arrayXd, b_array1d);
2928     t_arrayXd[1] = Type::optvartop(-1);
2929     rb(env, m, ASTString("array1d"), t_arrayXd, b_array1d);
2930   }
2931   {
2932     std::vector<Type> t_arrayXd(2);
2933     t_arrayXd[0] = Type::optvartop(-1);
2934     t_arrayXd[1] = Type::top(-1);
2935     rb(env, m, ASTString("arrayXd"), t_arrayXd, b_arrayXd);
2936     t_arrayXd[1].ot(Type::OT_OPTIONAL);
2937     rb(env, m, ASTString("arrayXd"), t_arrayXd, b_arrayXd);
2938     t_arrayXd[1] = Type::vartop(-1);
2939     rb(env, m, ASTString("arrayXd"), t_arrayXd, b_arrayXd);
2940     t_arrayXd[1] = Type::optvartop(-1);
2941     rb(env, m, ASTString("arrayXd"), t_arrayXd, b_arrayXd);
2942   }
2943   {
2944     std::vector<Type> t_arrayXd(3);
2945     t_arrayXd[0] = Type::parsetint();
2946     t_arrayXd[1] = Type::parsetint();
2947     t_arrayXd[2] = Type::top(-1);
2948     rb(env, m, ASTString("array2d"), t_arrayXd, b_array2d);
2949     t_arrayXd[2].ot(Type::OT_OPTIONAL);
2950     rb(env, m, ASTString("array2d"), t_arrayXd, b_array2d);
2951     t_arrayXd[2] = Type::vartop(-1);
2952     rb(env, m, ASTString("array2d"), t_arrayXd, b_array2d);
2953     t_arrayXd[2] = Type::optvartop(-1);
2954     rb(env, m, ASTString("array2d"), t_arrayXd, b_array2d);
2955   }
2956   {
2957     std::vector<Type> t_arrayXd(4);
2958     t_arrayXd[0] = Type::parsetint();
2959     t_arrayXd[1] = Type::parsetint();
2960     t_arrayXd[2] = Type::parsetint();
2961     t_arrayXd[3] = Type::top(-1);
2962     rb(env, m, ASTString("array3d"), t_arrayXd, b_array3d);
2963     t_arrayXd[3].ot(Type::OT_OPTIONAL);
2964     rb(env, m, ASTString("array3d"), t_arrayXd, b_array3d);
2965     t_arrayXd[3] = Type::vartop(-1);
2966     rb(env, m, ASTString("array3d"), t_arrayXd, b_array3d);
2967     t_arrayXd[3] = Type::optvartop(-1);
2968     rb(env, m, ASTString("array3d"), t_arrayXd, b_array3d);
2969   }
2970   {
2971     std::vector<Type> t_arrayXd(5);
2972     t_arrayXd[0] = Type::parsetint();
2973     t_arrayXd[1] = Type::parsetint();
2974     t_arrayXd[2] = Type::parsetint();
2975     t_arrayXd[3] = Type::parsetint();
2976     t_arrayXd[4] = Type::top(-1);
2977     rb(env, m, ASTString("array4d"), t_arrayXd, b_array4d);
2978     t_arrayXd[4].ot(Type::OT_OPTIONAL);
2979     rb(env, m, ASTString("array4d"), t_arrayXd, b_array4d);
2980     t_arrayXd[4] = Type::vartop(-1);
2981     rb(env, m, ASTString("array4d"), t_arrayXd, b_array4d);
2982     t_arrayXd[4] = Type::optvartop(-1);
2983     rb(env, m, ASTString("array4d"), t_arrayXd, b_array4d);
2984   }
2985   {
2986     std::vector<Type> t_arrayXd(6);
2987     t_arrayXd[0] = Type::parsetint();
2988     t_arrayXd[1] = Type::parsetint();
2989     t_arrayXd[2] = Type::parsetint();
2990     t_arrayXd[3] = Type::parsetint();
2991     t_arrayXd[4] = Type::parsetint();
2992     t_arrayXd[5] = Type::top(-1);
2993     rb(env, m, ASTString("array5d"), t_arrayXd, b_array5d);
2994     t_arrayXd[5].ot(Type::OT_OPTIONAL);
2995     rb(env, m, ASTString("array5d"), t_arrayXd, b_array5d);
2996     t_arrayXd[5] = Type::vartop(-1);
2997     rb(env, m, ASTString("array5d"), t_arrayXd, b_array5d);
2998     t_arrayXd[5] = Type::optvartop(-1);
2999     rb(env, m, ASTString("array5d"), t_arrayXd, b_array5d);
3000   }
3001   {
3002     std::vector<Type> t_arrayXd(7);
3003     t_arrayXd[0] = Type::parsetint();
3004     t_arrayXd[1] = Type::parsetint();
3005     t_arrayXd[2] = Type::parsetint();
3006     t_arrayXd[3] = Type::parsetint();
3007     t_arrayXd[4] = Type::parsetint();
3008     t_arrayXd[5] = Type::parsetint();
3009     t_arrayXd[6] = Type::top(-1);
3010     rb(env, m, ASTString("array6d"), t_arrayXd, b_array6d);
3011     t_arrayXd[6].ot(Type::OT_OPTIONAL);
3012     rb(env, m, ASTString("array6d"), t_arrayXd, b_array6d);
3013     t_arrayXd[6] = Type::vartop(-1);
3014     rb(env, m, ASTString("array6d"), t_arrayXd, b_array6d);
3015     t_arrayXd[6] = Type::optvartop(-1);
3016     rb(env, m, ASTString("array6d"), t_arrayXd, b_array6d);
3017   }
3018   {
3019     std::vector<Type> stv(3);
3020     stv[0] = Type::partop(-1);
3021     stv[1] = Type::parsetint(1);
3022     stv[2] = Type::parsetint();
3023     rb(env, m, ASTString("slice_1d"), stv, b_slice);
3024     stv[0] = Type::vartop(-1);
3025     rb(env, m, ASTString("slice_1d"), stv, b_slice);
3026     stv[0] = Type::optvartop(-1);
3027     rb(env, m, ASTString("slice_1d"), stv, b_slice);
3028     stv[0] = Type::optpartop(-1);
3029     rb(env, m, ASTString("slice_1d"), stv, b_slice);
3030 
3031     stv.push_back(Type::parsetint());
3032     stv[0] = Type::partop(-1);
3033     rb(env, m, ASTString("slice_2d"), stv, b_slice);
3034     stv[0] = Type::vartop(-1);
3035     rb(env, m, ASTString("slice_2d"), stv, b_slice);
3036     stv[0] = Type::optvartop(-1);
3037     rb(env, m, ASTString("slice_2d"), stv, b_slice);
3038     stv[0] = Type::optpartop(-1);
3039     rb(env, m, ASTString("slice_2d"), stv, b_slice);
3040 
3041     stv.push_back(Type::parsetint());
3042     stv[0] = Type::partop(-1);
3043     rb(env, m, ASTString("slice_3d"), stv, b_slice);
3044     stv[0] = Type::vartop(-1);
3045     rb(env, m, ASTString("slice_3d"), stv, b_slice);
3046     stv[0] = Type::optvartop(-1);
3047     rb(env, m, ASTString("slice_3d"), stv, b_slice);
3048     stv[0] = Type::optpartop(-1);
3049     rb(env, m, ASTString("slice_3d"), stv, b_slice);
3050 
3051     stv.push_back(Type::parsetint());
3052     stv[0] = Type::partop(-1);
3053     rb(env, m, ASTString("slice_4d"), stv, b_slice);
3054     stv[0] = Type::vartop(-1);
3055     rb(env, m, ASTString("slice_4d"), stv, b_slice);
3056     stv[0] = Type::optvartop(-1);
3057     rb(env, m, ASTString("slice_4d"), stv, b_slice);
3058     stv[0] = Type::optpartop(-1);
3059     rb(env, m, ASTString("slice_4d"), stv, b_slice);
3060 
3061     stv.push_back(Type::parsetint());
3062     stv[0] = Type::partop(-1);
3063     rb(env, m, ASTString("slice_5d"), stv, b_slice);
3064     stv[0] = Type::vartop(-1);
3065     rb(env, m, ASTString("slice_5d"), stv, b_slice);
3066     stv[0] = Type::optvartop(-1);
3067     rb(env, m, ASTString("slice_5d"), stv, b_slice);
3068     stv[0] = Type::optpartop(-1);
3069     rb(env, m, ASTString("slice_5d"), stv, b_slice);
3070 
3071     stv.push_back(Type::parsetint());
3072     stv[0] = Type::partop(-1);
3073     rb(env, m, ASTString("slice_6d"), stv, b_slice);
3074     stv[0] = Type::vartop(-1);
3075     rb(env, m, ASTString("slice_6d"), stv, b_slice);
3076     stv[0] = Type::optvartop(-1);
3077     rb(env, m, ASTString("slice_6d"), stv, b_slice);
3078     stv[0] = Type::optpartop(-1);
3079     rb(env, m, ASTString("slice_6d"), stv, b_slice);
3080   }
3081   {
3082     std::vector<Type> t(2);
3083     t[0] = Type::parbool();
3084     t[1] = Type::parstring();
3085     rb(env, m, constants().ids.assert, t, b_assert_bool);
3086   }
3087   {
3088     std::vector<Type> t(3);
3089     t[0] = Type::parbool();
3090     t[1] = Type::parstring();
3091     t[2] = Type::top();
3092     rb(env, m, constants().ids.assert, t, b_assert);
3093     t[2] = Type::optpartop();
3094     rb(env, m, constants().ids.assert, t, b_assert);
3095     t[2] = Type::vartop();
3096     rb(env, m, constants().ids.assert, t, b_assert);
3097     t[2] = Type::optvartop();
3098     rb(env, m, constants().ids.assert, t, b_assert);
3099     t[2] = Type::top(-1);
3100     rb(env, m, constants().ids.assert, t, b_assert);
3101     t[2] = Type::optpartop(-1);
3102     rb(env, m, constants().ids.assert, t, b_assert);
3103     t[2] = Type::vartop(-1);
3104     rb(env, m, constants().ids.assert, t, b_assert);
3105     t[2] = Type::optvartop(-1);
3106     rb(env, m, constants().ids.assert, t, b_assert);
3107   }
3108   {
3109     std::vector<Type> t(4);
3110     t[0] = Type::parstring();
3111     t[1] = Type::parstring();
3112     t[2] = Type::parstring();
3113     t[3] = Type::top();
3114     rb(env, m, constants().ids.mzn_deprecate, t, b_mzn_deprecate);
3115     t[3] = Type::vartop();
3116     rb(env, m, constants().ids.mzn_deprecate, t, b_mzn_deprecate);
3117     t[3] = Type::optvartop();
3118     rb(env, m, constants().ids.mzn_deprecate, t, b_mzn_deprecate);
3119     t[3] = Type::top(-1);
3120     rb(env, m, constants().ids.mzn_deprecate, t, b_mzn_deprecate);
3121     t[3] = Type::vartop(-1);
3122     rb(env, m, constants().ids.mzn_deprecate, t, b_mzn_deprecate);
3123     t[3] = Type::optvartop(-1);
3124     rb(env, m, constants().ids.mzn_deprecate, t, b_mzn_deprecate);
3125   }
3126   {
3127     rb(env, m, constants().ids.mzn_symmetry_breaking_constraint, {Type::varbool()},
3128        b_mzn_symmetry_breaking_constraint);
3129     rb(env, m, constants().ids.mzn_redundant_constraint, {Type::varbool()},
3130        b_mzn_redundant_constraint);
3131   }
3132   {
3133     std::vector<Type> t(1);
3134     t[0] = Type::parstring();
3135     rb(env, m, ASTString("abort"), t, b_abort);
3136     rb(env, m, constants().ids.trace, t, b_trace);
3137     rb(env, m, ASTString("trace_stdout"), t, b_trace_stdout);
3138     rb(env, m, ASTString("trace_logstream"), t, b_trace_logstream);
3139   }
3140   {
3141     std::vector<Type> t;
3142     rb(env, m, ASTString("logstream_to_string"), t, b_logstream);
3143   }
3144   {
3145     std::vector<Type> t(2);
3146     t[0] = Type::parstring();
3147     t[1] = Type::top();
3148     rb(env, m, constants().ids.trace, t, b_trace);
3149     rb(env, m, ASTString("trace_stdout"), t, b_trace_stdout);
3150     rb(env, m, ASTString("trace_logstream"), t, b_trace_logstream);
3151     t[1] = Type::optpartop();
3152     rb(env, m, constants().ids.trace, t, b_trace);
3153     rb(env, m, ASTString("trace_stdout"), t, b_trace_stdout);
3154     rb(env, m, ASTString("trace_logstream"), t, b_trace_logstream);
3155     t[1] = Type::vartop();
3156     rb(env, m, constants().ids.trace, t, b_trace);
3157     rb(env, m, ASTString("trace_stdout"), t, b_trace_stdout);
3158     rb(env, m, ASTString("trace_logstream"), t, b_trace_logstream);
3159     t[1] = Type::optvartop();
3160     rb(env, m, constants().ids.trace, t, b_trace);
3161     rb(env, m, ASTString("trace_stdout"), t, b_trace_stdout);
3162     rb(env, m, ASTString("trace_logstream"), t, b_trace_logstream);
3163     t[1] = Type::top(-1);
3164     rb(env, m, constants().ids.trace, t, b_trace);
3165     rb(env, m, ASTString("trace_stdout"), t, b_trace_stdout);
3166     rb(env, m, ASTString("trace_logstream"), t, b_trace_logstream);
3167     t[1] = Type::optpartop(-1);
3168     rb(env, m, constants().ids.trace, t, b_trace);
3169     rb(env, m, ASTString("trace_stdout"), t, b_trace_stdout);
3170     rb(env, m, ASTString("trace_logstream"), t, b_trace_logstream);
3171     t[1] = Type::vartop(-1);
3172     rb(env, m, constants().ids.trace, t, b_trace);
3173     rb(env, m, ASTString("trace_stdout"), t, b_trace_stdout);
3174     rb(env, m, ASTString("trace_logstream"), t, b_trace_logstream);
3175     t[1] = Type::optvartop(-1);
3176     rb(env, m, constants().ids.trace, t, b_trace);
3177     rb(env, m, ASTString("trace_stdout"), t, b_trace_stdout);
3178     rb(env, m, ASTString("trace_logstream"), t, b_trace_logstream);
3179   }
3180   {
3181     rb(env, m, ASTString("mzn_in_redundant_constraint"), std::vector<Type>(),
3182        b_in_redundant_constraint);
3183   }
3184   {
3185     rb(env, m, ASTString("mzn_in_symmetry_breaking_constraint"), std::vector<Type>(),
3186        b_in_symmetry_breaking_constraint);
3187   }
3188   {
3189     std::vector<Type> t_length(1);
3190     t_length[0] = Type::optvartop(-1);
3191     rb(env, m, ASTString("length"), t_length, b_length);
3192   }
3193   {
3194     std::vector<Type> t(1);
3195     t[0] = Type::parbool();
3196     rb(env, m, constants().ids.bool2int, t, b_bool2int);
3197   }
3198   {
3199     std::vector<Type> t(1);
3200     t[0] = Type::parbool(-1);
3201     rb(env, m, constants().ids.forall, t, b_forall_par);
3202     rb(env, m, constants().ids.exists, t, b_exists_par);
3203     rb(env, m, ASTString("xorall"), t, b_xorall_par);
3204     rb(env, m, ASTString("iffall"), t, b_iffall_par);
3205   }
3206   { rb(env, m, constants().ids.bool_not, {Type::parbool()}, b_not_par); }
3207   {
3208     std::vector<Type> t(2);
3209     t[0] = Type::parbool(-1);
3210     t[1] = Type::parbool(-1);
3211     rb(env, m, constants().ids.clause, t, b_clause_par);
3212   }
3213   {
3214     std::vector<Type> t(1);
3215     t[0] = Type::varsetint();
3216     rb(env, m, ASTString("ub"), t, b_ub_set);
3217     rb(env, m, ASTString("lb"), t, b_lb_set);
3218   }
3219   {
3220     std::vector<Type> t(1);
3221     t[0] = Type::varsetint(1);
3222     rb(env, m, ASTString("ub_array"), t, b_array_ub_set);
3223   }
3224   {
3225     std::vector<Type> t(1);
3226     t[0] = Type::varint();
3227     rb(env, m, ASTString("dom"), t, b_dom_varint);
3228     t[0].ot(Type::OT_OPTIONAL);
3229     rb(env, m, ASTString("dom"), t, b_dom_varint);
3230   }
3231   {
3232     std::vector<Type> t(1);
3233     t[0] = Type::varint(-1);
3234     rb(env, m, ASTString("dom_array"), t, b_dom_array);
3235     rb(env, m, ASTString("dom_bounds_array"), t, b_dom_bounds_array);
3236     t[0].ot(Type::OT_OPTIONAL);
3237     rb(env, m, ASTString("dom_array"), t, b_dom_array);
3238     rb(env, m, ASTString("dom_bounds_array"), t, b_dom_bounds_array);
3239   }
3240   {
3241     std::vector<Type> t(1);
3242     t[0] = Type::parsetint();
3243     rb(env, m, ASTString("min"), t, b_min_parsetint);
3244   }
3245   {
3246     std::vector<Type> t(1);
3247     t[0] = Type::parsetint();
3248     rb(env, m, ASTString("max"), t, b_max_parsetint);
3249   }
3250   {
3251     std::vector<Type> t(1);
3252     t[0] = Type::varint();
3253     t[0].ot(Type::OT_OPTIONAL);
3254     rb(env, m, ASTString("lb"), t, b_lb_varoptint);
3255   }
3256   {
3257     std::vector<Type> t(1);
3258     t[0] = Type::varint();
3259     t[0].ot(Type::OT_OPTIONAL);
3260     rb(env, m, ASTString("ub"), t, b_ub_varoptint);
3261   }
3262   {
3263     std::vector<Type> t(1);
3264     t[0] = Type::varint();
3265     rb(env, m, ASTString("lb"), t, b_lb_varoptint);
3266   }
3267   {
3268     std::vector<Type> t(1);
3269     t[0] = Type::varint();
3270     rb(env, m, ASTString("ub"), t, b_ub_varoptint);
3271   }
3272   {
3273     std::vector<Type> t(1);
3274     t[0] = Type::varint(-1);
3275     t[0].ot(Type::OT_OPTIONAL);
3276     rb(env, m, ASTString("lb_array"), t, b_array_lb_int);
3277   }
3278   {
3279     std::vector<Type> t(1);
3280     t[0] = Type::varint(-1);
3281     t[0].ot(Type::OT_OPTIONAL);
3282     rb(env, m, ASTString("ub_array"), t, b_array_ub_int);
3283   }
3284   {
3285     std::vector<Type> t(1);
3286     t[0] = Type::varfloat();
3287     t[0].ot(Type::OT_OPTIONAL);
3288     rb(env, m, ASTString("lb"), t, b_lb_varoptfloat);
3289   }
3290   {
3291     std::vector<Type> t(1);
3292     t[0] = Type::varfloat();
3293     t[0].ot(Type::OT_OPTIONAL);
3294     rb(env, m, ASTString("ub"), t, b_ub_varoptfloat);
3295   }
3296   {
3297     std::vector<Type> t(1);
3298     t[0] = Type::varfloat();
3299     rb(env, m, ASTString("lb"), t, b_lb_varoptfloat);
3300   }
3301   {
3302     std::vector<Type> t(1);
3303     t[0] = Type::varfloat();
3304     rb(env, m, ASTString("ub"), t, b_ub_varoptfloat);
3305   }
3306   {
3307     std::vector<Type> t(1);
3308     t[0] = Type::varfloat(-1);
3309     t[0].ot(Type::OT_OPTIONAL);
3310     rb(env, m, ASTString("lb_array"), t, b_array_lb_float);
3311   }
3312   {
3313     std::vector<Type> t(1);
3314     t[0] = Type::varfloat(-1);
3315     t[0].ot(Type::OT_OPTIONAL);
3316     rb(env, m, ASTString("ub_array"), t, b_array_ub_float);
3317   }
3318   {
3319     std::vector<Type> t(1);
3320     t[0] = Type::parsetint();
3321     rb(env, m, ASTString("card"), t, b_card);
3322   }
3323   {
3324     std::vector<Type> t(1);
3325     t[0] = Type::parsetint();
3326     rb(env, m, ASTString("set_to_ranges"), t, b_set_to_ranges_int);
3327     t[0] = Type::parsetfloat();
3328     rb(env, m, ASTString("set_to_ranges"), t, b_set_to_ranges_float);
3329   }
3330   {
3331     std::vector<Type> t(1);
3332     t[0] = Type::parint();
3333     rb(env, m, ASTString("abs"), t, b_abs_int);
3334     t[0] = Type::parfloat();
3335     rb(env, m, ASTString("abs"), t, b_abs_float);
3336   }
3337   {
3338     std::vector<Type> t(1);
3339     t[0] = Type::varint();
3340     rb(env, m, ASTString("has_bounds"), t, b_has_bounds_int);
3341   }
3342   {
3343     std::vector<Type> t(1);
3344     t[0] = Type::varfloat();
3345     rb(env, m, ASTString("has_bounds"), t, b_has_bounds_float);
3346   }
3347   {
3348     std::vector<Type> t(1);
3349     t[0] = Type::varsetint();
3350     rb(env, m, ASTString("has_ub_set"), t, b_has_ub_set);
3351   }
3352   {
3353     std::vector<Type> t(1);
3354     t[0] = Type::optvartop();
3355     rb(env, m, ASTString("is_fixed"), t, b_is_fixed);
3356     t[0] = Type::varsetint();
3357     rb(env, m, ASTString("is_fixed"), t, b_is_fixed);
3358     Type setoftop;
3359     setoftop.bt(Type::BT_TOP);
3360     setoftop.st(Type::ST_SET);
3361     setoftop.ti(Type::TI_PAR);
3362     setoftop.ot(Type::OT_PRESENT);
3363     t[0] = setoftop;
3364     rb(env, m, ASTString("is_fixed"), t, b_is_fixed);
3365   }
3366   {
3367     std::vector<Type> t(1);
3368     t[0] = Type::optvartop(-1);
3369     rb(env, m, ASTString("is_fixed"), t, b_is_fixed_array);
3370   }
3371   {
3372     std::vector<Type> t(2);
3373     t[0] = t[1] = Type::optvartop();
3374     rb(env, m, ASTString("is_same"), t, b_is_same);
3375   }
3376   {
3377     std::vector<Type> t(1);
3378     t[0] = Type::optvartop();
3379     rb(env, m, ASTString("fix"), t, b_fix_bool);
3380     rb(env, m, ASTString("fix"), t, b_fix_int);
3381     rb(env, m, ASTString("fix"), t, b_fix_set);
3382     rb(env, m, ASTString("fix"), t, b_fix_float);
3383   }
3384   {
3385     std::vector<Type> t(1);
3386     t[0] = Type::optvartop(1);
3387     rb(env, m, ASTString("fix"), t, b_fix_array);
3388   }
3389   {
3390     std::vector<Type> t(2);
3391     t[0] = Type::optvartop();
3392     t[1] = Type::ann();
3393     rb(env, m, ASTString("has_ann"), t, b_has_ann);
3394     t[0] = Type::varsetint();
3395     rb(env, m, ASTString("has_ann"), t, b_has_ann);
3396     Type setoftop;
3397     setoftop.bt(Type::BT_TOP);
3398     setoftop.st(Type::ST_SET);
3399     setoftop.ti(Type::TI_PAR);
3400     setoftop.ot(Type::OT_PRESENT);
3401     t[0] = setoftop;
3402     rb(env, m, ASTString("has_ann"), t, b_has_ann);
3403   }
3404   {
3405     std::vector<Type> t(2);
3406     t[0] = Type::optvartop();
3407     t[1] = Type::ann();
3408     rb(env, m, ASTString("annotate"), t, b_annotate);
3409     t[0] = Type::varsetint();
3410     rb(env, m, ASTString("annotate"), t, b_annotate);
3411     Type setoftop;
3412     setoftop.bt(Type::BT_TOP);
3413     setoftop.st(Type::ST_SET);
3414     setoftop.ti(Type::TI_PAR);
3415     setoftop.ot(Type::OT_PRESENT);
3416     t[0] = setoftop;
3417     rb(env, m, ASTString("annotate"), t, b_annotate);
3418   }
3419   {
3420     std::vector<Type> t(1);
3421     t[0] = Type::parint();
3422     rb(env, m, ASTString("int2float"), t, b_int2float);
3423   }
3424   {
3425     std::vector<Type> t(1);
3426     t[0] = Type::parfloat();
3427     rb(env, m, ASTString("ceil"), t, b_ceil);
3428     rb(env, m, ASTString("floor"), t, b_floor);
3429     rb(env, m, ASTString("round"), t, b_round);
3430     rb(env, m, ASTString("log10"), t, b_log10);
3431     rb(env, m, ASTString("log2"), t, b_log2);
3432     rb(env, m, ASTString("ln"), t, b_ln);
3433     rb(env, m, ASTString("exp"), t, b_exp);
3434     rb(env, m, ASTString("sqrt"), t, b_sqrt);
3435     t.push_back(Type::parfloat());
3436     rb(env, m, ASTString("log"), t, b_log);
3437     rb(env, m, ASTString("pow"), t, b_pow);
3438   }
3439   {
3440     std::vector<Type> t(1);
3441     t[0] = Type::parfloat(1);
3442     rb(env, m, constants().ids.sum, t, b_sum_float);
3443     rb(env, m, ASTString("product"), t, b_product_float);
3444   }
3445   {
3446     std::vector<Type> t(1);
3447     t[0] = Type::parfloat(1);
3448     rb(env, m, ASTString("min"), t, b_float_min);
3449     rb(env, m, ASTString("max"), t, b_float_max);
3450 
3451     t[0] = Type::parfloat();
3452     t.push_back(Type::parfloat());
3453     rb(env, m, ASTString("min"), t, b_float_min);
3454     rb(env, m, ASTString("max"), t, b_float_max);
3455   }
3456   {
3457     std::vector<Type> t(1);
3458     t[0] = Type::parsetint();
3459     rb(env, m, ASTString("set2array"), t, b_set2array);
3460   }
3461   {
3462     std::vector<Type> t(1);
3463     t[0] = Type::parstring();
3464     rb(env, m, ASTString("string_length"), t, b_string_length);
3465   }
3466   { rb(env, m, ASTString("file_path"), std::vector<Type>(), b_file_path); }
3467   {
3468     std::vector<Type> t(1);
3469     t[0] = Type::vartop();
3470     rb(env, m, ASTString("show"), t, b_show);
3471     rb(env, m, ASTString("showJSON"), t, b_show_json);
3472     t[0] = Type::vartop();
3473     t[0].st(Type::ST_SET);
3474     t[0].ot(Type::OT_OPTIONAL);
3475     rb(env, m, ASTString("show"), t, b_show);
3476     rb(env, m, ASTString("showJSON"), t, b_show_json);
3477     t[0] = Type::vartop(-1);
3478     rb(env, m, ASTString("show"), t, b_show);
3479     rb(env, m, ASTString("showJSON"), t, b_show_json);
3480   }
3481   {
3482     std::vector<Type> t(1);
3483     t[0] = Type::parstring();
3484     rb(env, m, ASTString("showDznId"), t, b_show_dzn_id);
3485   }
3486   {
3487     std::vector<Type> t(3);
3488     t[0] = t[1] = Type::parint();
3489     t[2] = Type::vartop();
3490     rb(env, m, ASTString("format"), t, b_format);
3491     t[2] = Type::vartop();
3492     t[2].st(Type::ST_SET);
3493     t[2].ot(Type::OT_OPTIONAL);
3494     rb(env, m, ASTString("format"), t, b_format);
3495     t[2] = Type::vartop(-1);
3496     rb(env, m, ASTString("format"), t, b_format);
3497   }
3498   {
3499     std::vector<Type> t(2);
3500     t[0] = Type::parint();
3501     t[1] = Type::vartop();
3502     rb(env, m, ASTString("format"), t, b_format);
3503     t[1] = Type::vartop();
3504     t[1].st(Type::ST_SET);
3505     t[1].ot(Type::OT_OPTIONAL);
3506     rb(env, m, ASTString("format"), t, b_format);
3507     t[1] = Type::vartop(-1);
3508     rb(env, m, ASTString("format"), t, b_format);
3509     t[1] = Type::parstring();
3510     rb(env, m, ASTString("format_justify_string"), t, b_format_justify_string);
3511   }
3512   {
3513     std::vector<Type> t;
3514     rb(env, m, ASTString("outputJSON"), t, b_output_json);
3515     rb(env, m, ASTString("outputJSONParameters"), t, b_output_json_parameters);
3516   }
3517   {
3518     std::vector<Type> t(2);
3519     t[0] = Type::parint();
3520     t[1] = Type::varint();
3521     rb(env, m, ASTString("show_int"), t, b_show_int);
3522   }
3523   {
3524     std::vector<Type> t(3);
3525     t[0] = Type::parint();
3526     t[1] = Type::parint();
3527     t[2] = Type::varfloat();
3528     rb(env, m, ASTString("show_float"), t, b_show_float);
3529   }
3530   {
3531     std::vector<Type> t(1);
3532     t[0] = Type::parstring(1);
3533     rb(env, m, ASTString("concat"), t, b_concat);
3534   }
3535   {
3536     std::vector<Type> t(2);
3537     t[0] = Type::parstring();
3538     t[1] = Type::parstring(1);
3539     rb(env, m, ASTString("join"), t, b_join);
3540   }
3541   {
3542     std::vector<Type> t(2);
3543     t[0] = Type::varint();
3544     t[1] = Type::varint();
3545     rb(env, m, ASTString("compute_div_bounds"), t, b_compute_div_bounds);
3546   }
3547   {
3548     std::vector<Type> t(1);
3549     t[0] = Type::parsetint(1);
3550     rb(env, m, ASTString("array_intersect"), t, b_array_intersect);
3551     rb(env, m, ASTString("array_union"), t, b_array_union);
3552   }
3553   {
3554     std::vector<Type> t(1);
3555     t[0] = Type::parint();
3556     t[0].ot(Type::OT_OPTIONAL);
3557     t[0].bt(Type::BT_TOP);
3558     rb(env, m, ASTString("occurs"), t, b_occurs);
3559     rb(env, m, ASTString("deopt"), t, b_deopt_expr);
3560     t[0].bt(Type::BT_INT);
3561     rb(env, m, ASTString("deopt"), t, b_deopt_int);
3562     t[0].bt(Type::BT_BOOL);
3563     rb(env, m, ASTString("deopt"), t, b_deopt_bool);
3564     t[0].bt(Type::BT_FLOAT);
3565     rb(env, m, ASTString("deopt"), t, b_deopt_float);
3566     t[0].bt(Type::BT_STRING);
3567     rb(env, m, ASTString("deopt"), t, b_deopt_string);
3568     t[0].bt(Type::BT_INT);
3569     t[0].st(Type::ST_SET);
3570     rb(env, m, ASTString("deopt"), t, b_deopt_intset);
3571   }
3572   {
3573     std::vector<Type> t(2);
3574     t[0] = Type::varbot(1);
3575     t[1] = Type::parint(1);
3576     rb(env, m, ASTString("sort_by"), t, b_sort_by_int);
3577     t[0] = Type::bot(1);
3578     rb(env, m, ASTString("sort_by"), t, b_sort_by_int);
3579     t[0].ot(Type::OT_OPTIONAL);
3580     rb(env, m, ASTString("sort_by"), t, b_sort_by_int);
3581   }
3582   {
3583     std::vector<Type> t(2);
3584     t[0] = Type::varbot(1);
3585     t[1] = Type::parfloat(1);
3586     rb(env, m, ASTString("sort_by"), t, b_sort_by_float);
3587     t[0] = Type::bot(1);
3588     rb(env, m, ASTString("sort_by"), t, b_sort_by_float);
3589     t[0].ot(Type::OT_OPTIONAL);
3590     rb(env, m, ASTString("sort_by"), t, b_sort_by_float);
3591   }
3592   {
3593     std::vector<Type> t(1);
3594     t[0] = Type::parint(1);
3595     rb(env, m, ASTString("sort"), t, b_sort);
3596     rb(env, m, ASTString("arg_min"), t, b_arg_min_int);
3597     rb(env, m, ASTString("arg_max"), t, b_arg_max_int);
3598     t[0] = Type::parbool(1);
3599     rb(env, m, ASTString("sort"), t, b_sort);
3600     rb(env, m, ASTString("arg_min"), t, b_arg_min_bool);
3601     rb(env, m, ASTString("arg_max"), t, b_arg_max_bool);
3602     t[0] = Type::parfloat(1);
3603     rb(env, m, ASTString("sort"), t, b_sort);
3604     rb(env, m, ASTString("arg_min"), t, b_arg_min_float);
3605     rb(env, m, ASTString("arg_max"), t, b_arg_max_float);
3606   }
3607   {
3608     std::vector<Type> t(1);
3609     t[0] = Type::parint(1);
3610     rb(env, m, ASTString("inverse"), t, b_inverse, true);
3611   }
3612   {
3613     std::vector<Type> t(1);
3614     t[0] = Type::parfloat();
3615     rb(env, m, ASTString("atan"), t, b_atan);
3616   }
3617   {
3618     std::vector<Type> t(1);
3619     t[0] = Type::parfloat();
3620     rb(env, m, ASTString("cos"), t, b_cos);
3621   }
3622   {
3623     std::vector<Type> t(1);
3624     t[0] = Type::parfloat();
3625     rb(env, m, ASTString("sin"), t, b_sin);
3626   }
3627   {
3628     std::vector<Type> t(1);
3629     t[0] = Type::parfloat();
3630     rb(env, m, ASTString("asin"), t, b_asin);
3631   }
3632   {
3633     std::vector<Type> t(1);
3634     t[0] = Type::parfloat();
3635     rb(env, m, ASTString("acos"), t, b_acos);
3636   }
3637   {
3638     std::vector<Type> t(1);
3639     t[0] = Type::parfloat();
3640     rb(env, m, ASTString("tan"), t, b_tan);
3641   }
3642   {
3643     std::vector<Type> t(2);
3644     t[0] = Type::parfloat();
3645     t[1] = Type::parfloat();
3646     rb(env, m, ASTString("normal"), t, b_normal_float_float);
3647     t[0] = Type::parint();
3648     rb(env, m, ASTString("normal"), t, b_normal_int_float);
3649   }
3650   {
3651     std::vector<Type> t(2);
3652     t[0] = Type::parfloat();
3653     t[1] = Type::parfloat();
3654     rb(env, m, ASTString("uniform"), t, b_uniform_float);
3655     t[0] = Type::parint();
3656     t[1] = Type::parint();
3657     rb(env, m, ASTString("uniform"), t, b_uniform_int);
3658   }
3659   {
3660     std::vector<Type> t(1);
3661     t[0] = Type::parfloat();
3662     rb(env, m, ASTString("poisson"), t, b_poisson_float);
3663     t[0] = Type::parint();
3664     rb(env, m, ASTString("poisson"), t, b_poisson_int);
3665   }
3666   {
3667     std::vector<Type> t(2);
3668     t[0] = Type::parfloat();
3669     t[1] = Type::parfloat();
3670     rb(env, m, ASTString("gamma"), t, b_gamma_float_float);
3671     t[0] = Type::parint();
3672     rb(env, m, ASTString("gamma"), t, b_gamma_int_float);
3673   }
3674   {
3675     std::vector<Type> t(2);
3676     t[0] = Type::parfloat();
3677     t[1] = Type::parfloat();
3678     rb(env, m, ASTString("weibull"), t, b_weibull_float_float);
3679     t[0] = Type::parint();
3680     rb(env, m, ASTString("weibull"), t, b_weibull_int_float);
3681   }
3682   {
3683     std::vector<Type> t(1);
3684     t[0] = Type::parfloat();
3685     rb(env, m, ASTString("exponential"), t, b_exponential_float);
3686     t[0] = Type::parint();
3687     rb(env, m, ASTString("exponential"), t, b_exponential_int);
3688   }
3689   {
3690     std::vector<Type> t(2);
3691     t[0] = Type::parfloat();
3692     t[1] = Type::parfloat();
3693     rb(env, m, ASTString("lognormal"), t, b_lognormal_float_float);
3694     t[0] = Type::parint();
3695     rb(env, m, ASTString("lognormal"), t, b_lognormal_int_float);
3696   }
3697   {
3698     std::vector<Type> t(1);
3699     t[0] = Type::parfloat();
3700     rb(env, m, ASTString("chisquared"), t, b_chisquared_float);
3701     t[0] = Type::parint();
3702     rb(env, m, ASTString("chisquared"), t, b_chisquared_int);
3703   }
3704   {
3705     std::vector<Type> t(2);
3706     t[0] = Type::parfloat();
3707     t[1] = Type::parfloat();
3708     rb(env, m, ASTString("cauchy"), t, b_cauchy_float_float);
3709     t[0] = Type::parint();
3710     rb(env, m, ASTString("cauchy"), t, b_cauchy_int_float);
3711   }
3712   {
3713     std::vector<Type> t(2);
3714     t[0] = Type::parfloat();
3715     t[1] = Type::parfloat();
3716     rb(env, m, ASTString("fdistribution"), t, b_fdistribution_float_float);
3717     t[0] = Type::parint();
3718     t[1] = Type::parint();
3719     rb(env, m, ASTString("fdistribution"), t, b_fdistribution_int_int);
3720   }
3721   {
3722     std::vector<Type> t(1);
3723     t[0] = Type::parfloat();
3724     rb(env, m, ASTString("tdistribution"), t, b_tdistribution_float);
3725     t[0] = Type::parint();
3726     rb(env, m, ASTString("tdistribution"), t, b_tdistribution_int);
3727   }
3728   {
3729     std::vector<Type> t(1);
3730     t[0] = Type::parint(1);
3731     rb(env, m, ASTString("discrete_distribution"), t, b_discrete_distribution);
3732   }
3733   {
3734     std::vector<Type> t(1);
3735     t[0] = Type::parint();
3736     rb(env, m, ASTString("bernoulli"), t, b_bernoulli);
3737   }
3738   {
3739     std::vector<Type> t(2);
3740     t[0] = Type::parint();
3741     t[1] = Type::parfloat();
3742     rb(env, m, ASTString("binomial"), t, b_binomial);
3743   }
3744   {
3745     std::vector<Type> t(2);
3746     t[0] = Type::parsetint();
3747     t[1] = Type::parint();
3748     rb(env, m, ASTString("to_enum"), t, b_to_enum);
3749     rb(env, m, ASTString("enum_next"), t, b_enum_next);
3750     rb(env, m, ASTString("enum_prev"), t, b_enum_prev);
3751   }
3752   { rb(env, m, ASTString("mzn_compiler_version"), std::vector<Type>(), b_mzn_compiler_version); }
3753   {
3754     std::vector<Type> t(2);
3755     t[0] = Type::varint(1);
3756     t[1] = Type::parstring();
3757     rb(env, m, ASTString("fzn_regular"), t, b_regular_from_string, true);
3758   }
3759   { rb(env, m, ASTString("showCheckerOutput"), {}, b_show_checker_output); }
3760 }
3761 
3762 }  // namespace MiniZinc
3763