111 lines
3.6 KiB
C++
111 lines
3.6 KiB
C++
/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
|
|
|
/*
|
|
* Main authors:
|
|
* Guido Tack <guido.tack@monash.edu>
|
|
*/
|
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include <minizinc/flat_exp.hh>
|
|
|
|
namespace MiniZinc {
|
|
|
|
EE flatten_par(EnvI& env, const Ctx& ctx, Expression* e, VarDecl* r, VarDecl* b) {
|
|
EE ret;
|
|
if (e->type().cv()) {
|
|
Ctx nctx;
|
|
nctx.b = ctx.b == C_ROOT ? C_ROOT : C_MIX;
|
|
|
|
try {
|
|
KeepAlive ka = flat_cv_exp(env, nctx, e);
|
|
ret.r = bind(env, ctx, r, ka());
|
|
ret.b = bind(env, Ctx(), b, constants().literalTrue);
|
|
} catch (ResultUndefinedError&) {
|
|
if (e->type().isbool()) {
|
|
ret.r = bind(env, ctx, r, constants().literalFalse);
|
|
ret.b = bind(env, Ctx(), b, constants().literalTrue);
|
|
} else {
|
|
ret.r = create_dummy_value(env, e->type());
|
|
ret.b = bind(env, Ctx(), b, constants().literalFalse);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
if (e->type().dim() > 0) {
|
|
EnvI::CSEMap::iterator it;
|
|
Id* id = e->dynamicCast<Id>();
|
|
if ((id != nullptr) && (id->decl()->flat() == nullptr || id->decl()->toplevel())) {
|
|
VarDecl* vd = id->decl()->flat();
|
|
if (vd == nullptr) {
|
|
vd = flat_exp(env, Ctx(), id->decl(), nullptr, constants().varTrue).r()->cast<Id>()->decl();
|
|
id->decl()->flat(vd);
|
|
auto* al = follow_id(vd->id())->cast<ArrayLit>();
|
|
if (al->size() == 0) {
|
|
if (r == nullptr) {
|
|
ret.r = al;
|
|
} else {
|
|
ret.r = bind(env, ctx, r, al);
|
|
}
|
|
ret.b = bind(env, Ctx(), b, constants().literalTrue);
|
|
return ret;
|
|
}
|
|
}
|
|
ret.r = bind(env, ctx, r, e->cast<Id>()->decl()->flat()->id());
|
|
ret.b = bind(env, Ctx(), b, constants().literalTrue);
|
|
return ret;
|
|
}
|
|
if ((it = env.cseMapFind(e)) != env.cseMapEnd()) {
|
|
ret.r = bind(env, ctx, r, it->second.r()->cast<VarDecl>()->id());
|
|
ret.b = bind(env, Ctx(), b, constants().literalTrue);
|
|
return ret;
|
|
}
|
|
GCLock lock;
|
|
auto* al = follow_id(eval_par(env, e))->cast<ArrayLit>();
|
|
if (al->size() == 0 || ((r != nullptr) && r->e() == nullptr)) {
|
|
if (r == nullptr) {
|
|
ret.r = al;
|
|
} else {
|
|
ret.r = bind(env, ctx, r, al);
|
|
}
|
|
ret.b = bind(env, Ctx(), b, constants().literalTrue);
|
|
return ret;
|
|
}
|
|
if ((it = env.cseMapFind(al)) != env.cseMapEnd()) {
|
|
ret.r = bind(env, ctx, r, it->second.r()->cast<VarDecl>()->id());
|
|
ret.b = bind(env, Ctx(), b, constants().literalTrue);
|
|
return ret;
|
|
}
|
|
std::vector<TypeInst*> ranges(al->dims());
|
|
for (unsigned int i = 0; i < ranges.size(); i++) {
|
|
ranges[i] =
|
|
new TypeInst(e->loc(), Type(),
|
|
new SetLit(Location().introduce(), IntSetVal::a(al->min(i), al->max(i))));
|
|
}
|
|
ASTExprVec<TypeInst> ranges_v(ranges);
|
|
assert(!al->type().isbot());
|
|
auto* ti = new TypeInst(e->loc(), al->type(), ranges_v, nullptr);
|
|
VarDecl* vd = new_vardecl(env, ctx, ti, nullptr, nullptr, al);
|
|
EE ee(vd, nullptr);
|
|
env.cseMapInsert(al, ee);
|
|
env.cseMapInsert(vd->e(), ee);
|
|
|
|
ret.r = bind(env, ctx, r, vd->id());
|
|
ret.b = bind(env, Ctx(), b, constants().literalTrue);
|
|
return ret;
|
|
}
|
|
GCLock lock;
|
|
try {
|
|
ret.r = bind(env, ctx, r, eval_par(env, e));
|
|
ret.b = bind(env, Ctx(), b, constants().literalTrue);
|
|
} catch (ResultUndefinedError&) {
|
|
ret.r = create_dummy_value(env, e->type());
|
|
ret.b = bind(env, Ctx(), b, constants().literalFalse);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
} // namespace MiniZinc
|