this repo has no description
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2
3/*
4 * Main authors:
5 * Guido Tack <guido.tack@monash.edu>
6 */
7
8/* This Source Code Form is subject to the terms of the Mozilla Public
9 * License, v. 2.0. If a copy of the MPL was not distributed with this
10 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
11
12#include <minizinc/flat_exp.hh>
13
14namespace MiniZinc {
15
16EE flatten_vardecl(EnvI& env, const Ctx& ctx, Expression* e, VarDecl* r, VarDecl* b) {
17 CallStackItem _csi(env, e);
18 EE ret;
19 GCLock lock;
20 if (ctx.b != C_ROOT) {
21 throw FlatteningError(env, e->loc(), "not in root context");
22 }
23 auto* v = e->cast<VarDecl>();
24 VarDecl* it = v->flat();
25 if (it == nullptr) {
26 TypeInst* ti = eval_typeinst(env, ctx, v);
27 if ((ti->domain() != nullptr) && ti->domain()->isa<SetLit>()) {
28 if (ti->type().bt() == Type::BT_INT && ti->type().st() == Type::ST_PLAIN) {
29 if (eval_intset(env, ti->domain())->size() == 0) {
30 env.fail("domain is empty");
31 }
32 } else if (ti->type().bt() == Type::BT_FLOAT) {
33 if (eval_floatset(env, ti->domain())->size() == 0) {
34 env.fail("domain is empty");
35 }
36 }
37 }
38 bool reuseVarId =
39 v->type().isAnn() || (v->toplevel() && v->id()->idn() == -1 &&
40 v->id()->v().c_str()[0] != '\'' && v->id()->v().c_str()[0] != '_');
41 VarDecl* vd = new_vardecl(env, ctx, ti, reuseVarId ? v->id() : nullptr, v, nullptr);
42 v->flat(vd);
43 Ctx nctx;
44 if ((v->e() != nullptr) && v->e()->type().bt() == Type::BT_BOOL) {
45 nctx.b = C_MIX;
46 }
47 if (v->e() != nullptr) {
48 (void)flat_exp(env, nctx, v->e(), vd, constants().varTrue);
49 if (v->e()->type().dim() > 0) {
50 Expression* ee = follow_id_to_decl(vd->e());
51 if (ee->isa<VarDecl>()) {
52 ee = ee->cast<VarDecl>()->e();
53 }
54 assert(ee && ee->isa<ArrayLit>());
55 auto* al = ee->cast<ArrayLit>();
56 if (vd->ti()->domain() != nullptr) {
57 for (unsigned int i = 0; i < al->size(); i++) {
58 if (Id* ali_id = (*al)[i]->dynamicCast<Id>()) {
59 if (ali_id != constants().absent && ali_id->decl()->ti()->domain() == nullptr) {
60 ali_id->decl()->ti()->domain(vd->ti()->domain());
61 }
62 }
63 }
64 }
65 }
66 }
67
68 ret.r = bind(env, Ctx(), r, vd->id());
69 } else {
70 ret.r = bind(env, Ctx(), r, it);
71 }
72 ret.b = bind(env, Ctx(), b, constants().literalTrue);
73 return ret;
74}
75} // namespace MiniZinc