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/flat_exp.hh>
13 
14 namespace MiniZinc {
15 
flatten_setlit(EnvI & env,const Ctx & ctx,Expression * e,VarDecl * r,VarDecl * b)16 EE flatten_setlit(EnvI& env, const Ctx& ctx, Expression* e, VarDecl* r, VarDecl* b) {
17   CallStackItem _csi(env, e);
18   EE ret;
19   auto* sl = e->cast<SetLit>();
20   assert(sl->isv() == nullptr && sl->fsv() == nullptr);
21   std::vector<EE> elems_ee(sl->v().size());
22   for (unsigned int i = sl->v().size(); (i--) != 0U;) {
23     elems_ee[i] = flat_exp(env, ctx, sl->v()[i], nullptr, nullptr);
24   }
25   std::vector<Expression*> elems(elems_ee.size());
26   bool allPar = true;
27   bool hadOpt = false;
28   for (auto i = static_cast<unsigned int>(elems.size()); (i--) != 0U;) {
29     elems[i] = elems_ee[i].r();
30     allPar = allPar && elems[i]->type().isPar();
31     hadOpt = hadOpt || elems[i]->type().isOpt();
32   }
33 
34   ret.b = conj(env, b, Ctx(), elems_ee);
35   if (allPar) {
36     GCLock lock;
37     auto* nsl = new SetLit(Location().introduce(), elems);
38     Type nsl_t(e->type());
39     nsl_t.ti(Type::TI_PAR);
40     nsl->type(nsl_t);
41     Expression* ee = eval_set_lit(env, nsl);
42     ret.r = bind(env, Ctx(), r, ee);
43   } else {
44     GCLock lock;
45     auto* al = new ArrayLit(sl->loc(), elems);
46     Type al_t = Type::varint(1);
47     if (hadOpt) {
48       al_t.ot(Type::OT_OPTIONAL);
49     }
50     al->type(al_t);
51     std::vector<Expression*> args(1);
52     args[0] = al;
53     Call* cc = new Call(sl->loc().introduce(), "array2set", args);
54     cc->type(Type::varsetint());
55     FunctionI* fi = env.model->matchFn(env, cc->id(), args, false);
56     if (fi == nullptr) {
57       throw FlatteningError(env, cc->loc(), "cannot find matching declaration");
58     }
59     assert(fi);
60     assert(env.isSubtype(fi->rtype(env, args, false), cc->type(), false));
61     cc->decl(fi);
62     EE ee = flat_exp(env, Ctx(), cc, nullptr, constants().varTrue);
63     ret.r = bind(env, Ctx(), r, ee.r());
64   }
65   return ret;
66 }
67 }  // namespace MiniZinc
68