1
0
This repository has been archived on 2025-03-06. You can view files and clone it, but cannot push or open issues or pull requests.

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