137 lines
4.7 KiB
C++
137 lines
4.7 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 {
|
|
|
|
CallArgItem::CallArgItem(EnvI& env0) : env(env0) {
|
|
env.idStack.push_back(static_cast<int>(env.callStack.size()));
|
|
}
|
|
CallArgItem::~CallArgItem() { env.idStack.pop_back(); }
|
|
|
|
Expression* create_dummy_value(EnvI& env, const Type& t) {
|
|
if (t.dim() > 0) {
|
|
Expression* ret = new ArrayLit(Location().introduce(), std::vector<Expression*>());
|
|
Type ret_t = t;
|
|
ret_t.ti(Type::TI_PAR);
|
|
ret->type(ret_t);
|
|
return ret;
|
|
}
|
|
if (t.st() == Type::ST_SET) {
|
|
Expression* ret = new SetLit(Location().introduce(), std::vector<Expression*>());
|
|
Type ret_t = t;
|
|
ret_t.ti(Type::TI_PAR);
|
|
ret->type(ret_t);
|
|
return ret;
|
|
}
|
|
switch (t.bt()) {
|
|
case Type::BT_INT:
|
|
return IntLit::a(0);
|
|
case Type::BT_BOOL:
|
|
return constants().boollit(false);
|
|
case Type::BT_FLOAT:
|
|
return FloatLit::a(0);
|
|
case Type::BT_STRING:
|
|
return new StringLit(Location().introduce(), "");
|
|
case Type::BT_ANN:
|
|
return constants().ann.promise_total;
|
|
default:
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
EE flatten_error(EnvI& env, const Ctx& ctx, Expression* e, VarDecl* r, VarDecl* b) {
|
|
throw InternalError("invalid expression encountered during compilation");
|
|
}
|
|
|
|
#ifndef NDEBUG
|
|
void mzn_break_here(Expression* e) { std::cerr << "% mzn_break_here: " << *e << "\n"; }
|
|
#endif
|
|
|
|
typedef EE (*ExprFlattener)(EnvI& env, const Ctx& ctx, Expression* e, VarDecl* r, VarDecl* b);
|
|
|
|
EE flatten_setlit(EnvI& env, const Ctx& ctx, Expression* e, VarDecl* r, VarDecl* b);
|
|
EE flatten_id(EnvI& env, const Ctx& ctx, Expression* e, VarDecl* r, VarDecl* b);
|
|
EE flatten_anon(EnvI& env, const Ctx& ctx, Expression* e, VarDecl* r, VarDecl* b);
|
|
EE flatten_arraylit(EnvI& env, const Ctx& ctx, Expression* e, VarDecl* r, VarDecl* b);
|
|
EE flatten_arrayaccess(EnvI& env, const Ctx& ctx, Expression* e, VarDecl* r, VarDecl* b);
|
|
EE flatten_comp(EnvI& env, const Ctx& ctx, Expression* e, VarDecl* r, VarDecl* b);
|
|
EE flatten_ite(EnvI& env, const Ctx& ctx, Expression* e, VarDecl* r, VarDecl* b);
|
|
EE flatten_binop(EnvI& env, const Ctx& ctx, Expression* e, VarDecl* r, VarDecl* b);
|
|
EE flatten_unop(EnvI& env, const Ctx& ctx, Expression* e, VarDecl* r, VarDecl* b);
|
|
EE flatten_call(EnvI& env, const Ctx& ctx, Expression* e, VarDecl* r, VarDecl* b);
|
|
EE flatten_vardecl(EnvI& env, const Ctx& ctx, Expression* e, VarDecl* r, VarDecl* b);
|
|
EE flatten_let(EnvI& env, const Ctx& ctx, Expression* e, VarDecl* r, VarDecl* b);
|
|
EE flatten_par(EnvI& env, const Ctx& ctx, Expression* e, VarDecl* r, VarDecl* b);
|
|
|
|
EE flat_exp(EnvI& env, const Ctx& ctx, Expression* e, VarDecl* r, VarDecl* b) {
|
|
if (e == nullptr) {
|
|
return EE();
|
|
}
|
|
|
|
#ifndef NDEBUG
|
|
Annotation& e_ann = e->ann();
|
|
if (e_ann.contains(constants().ann.mzn_break_here)) {
|
|
mzn_break_here(e);
|
|
}
|
|
#endif
|
|
|
|
assert(!e->type().isunknown());
|
|
|
|
static const ExprFlattener flattener_dispatch[] = {
|
|
&flatten_par, // par expressions
|
|
&flatten_error, // E_INTLIT
|
|
&flatten_error, // E_FLOATLIT
|
|
&flatten_setlit, // E_SETLIT
|
|
&flatten_error, // E_BOOLLIT
|
|
&flatten_error, // E_STRINGLIT
|
|
&flatten_id, // E_ID
|
|
&flatten_anon, // E_ANON
|
|
&flatten_arraylit, // E_ARRAYLIT
|
|
&flatten_arrayaccess, // E_ARRAYACCESS
|
|
&flatten_comp, // E_COMP
|
|
&flatten_ite, // E_ITE
|
|
&flatten_binop, // E_BINOP
|
|
&flatten_unop, // E_UNOP
|
|
&flatten_call, // E_CALL
|
|
&flatten_vardecl, // E_VARDECL
|
|
&flatten_let, // E_LET
|
|
&flatten_error, // E_TI
|
|
&flatten_error // E_TIID
|
|
};
|
|
|
|
bool is_par = e->type().isPar() &&
|
|
(!e->type().cv() || !e->type().isbool() || ctx.b != C_ROOT || e->isa<BoolLit>()) &&
|
|
!e->isa<Let>() && !e->isa<VarDecl>() && e->type().bt() != Type::BT_ANN;
|
|
|
|
#ifdef OUTPUT_CALLTREE
|
|
if (auto* call = e->dynamicCast<Call>()) {
|
|
for (int i = 0; i < env.callDepth; ++i) {
|
|
std::cerr << "──";
|
|
}
|
|
std::cerr << *call << std::endl;
|
|
env.callDepth++;
|
|
|
|
EE ee = flatten_call(env, ctx, e, r, b);
|
|
|
|
env.callDepth--;
|
|
return ee;
|
|
}
|
|
#endif
|
|
|
|
int dispatch = is_par ? 0 : e->eid() - Expression::E_INTLIT + 1;
|
|
|
|
return flattener_dispatch[dispatch](env, ctx, e, r, b);
|
|
}
|
|
|
|
} // namespace MiniZinc
|