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.
Jip J. Dekker f2a1c4e389 Squashed 'software/mza/' content from commit f970a59b17
git-subtree-dir: software/mza
git-subtree-split: f970a59b177c13ca3dd8aaef8cc6681d83b7e813
2021-07-11 16:34:30 +10:00

357 lines
11 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/. */
#ifndef __MINIZINC_ASTITERATOR_HH__
#define __MINIZINC_ASTITERATOR_HH__
#include <minizinc/ast.hh>
#include <minizinc/hash.hh>
namespace MiniZinc {
/**
* \brief Bottom-up iterator for expressions
*/
template <class T>
class BottomUpIterator {
protected:
/// The visitor to call back during iteration
T& _t;
/// Stack item
struct C {
/// Expression on the stack
Expression* _e;
/// Whether this expression has been visited before
bool _done;
/// If part of a generator expression, which one it is
int _gen_i;
/// Constructor
C(Expression* e) : _e(e), _done(false), _gen_i(-1) {}
/// Constructor for generator expression
C(Expression* e, int gen_i) : _e(e), _done(true), _gen_i(gen_i) {}
};
/// Push all elements of \a v onto \a stack
template <class E>
void pushVec(std::vector<C>& stack, ASTExprVec<E> v) {
for (unsigned int i = 0; i < v.size(); i++) stack.push_back(C(v[i]));
}
public:
/// Constructor
BottomUpIterator(T& t) : _t(t) {}
/// Run iterator on expression \a e
void run(Expression* e);
};
template <class T>
void bottomUp(T& t, Expression* e) {
BottomUpIterator<T>(t).run(e);
}
/**
* \brief Leaf iterator for expressions
*/
template <class T>
class TopDownIterator {
protected:
/// The visitor to call back during iteration
T& _t;
/// Push all elements of \a v onto \a stack
template <class E>
static void pushVec(std::vector<Expression*>& stack, ASTExprVec<E> v) {
for (unsigned int i = 0; i < v.size(); i++) stack.push_back(v[i]);
}
public:
/// Constructor
TopDownIterator(T& t) : _t(t) {}
/// Run iterator on expression \a e
void run(Expression* e);
};
template <class T>
void topDown(T& t, Expression* e) {
TopDownIterator<T>(t).run(e);
}
/* IMPLEMENTATION */
template <class T>
void BottomUpIterator<T>::run(Expression* root) {
std::vector<C> stack;
if (_t.enter(root)) stack.push_back(C(root));
while (!stack.empty()) {
C& c = stack.back();
if (c._e == NULL) {
stack.pop_back();
continue;
}
if (c._done) {
switch (c._e->eid()) {
case Expression::E_INTLIT:
_t.vIntLit(*c._e->template cast<IntLit>());
break;
case Expression::E_FLOATLIT:
_t.vFloatLit(*c._e->template cast<FloatLit>());
break;
case Expression::E_SETLIT:
_t.vSetLit(*c._e->template cast<SetLit>());
break;
case Expression::E_BOOLLIT:
_t.vBoolLit(*c._e->template cast<BoolLit>());
break;
case Expression::E_STRINGLIT:
_t.vStringLit(*c._e->template cast<StringLit>());
break;
case Expression::E_ID:
_t.vId(*c._e->template cast<Id>());
break;
case Expression::E_ANON:
_t.vAnonVar(*c._e->template cast<AnonVar>());
break;
case Expression::E_ARRAYLIT:
_t.vArrayLit(*c._e->template cast<ArrayLit>());
break;
case Expression::E_ARRAYACCESS:
_t.vArrayAccess(*c._e->template cast<ArrayAccess>());
break;
case Expression::E_COMP:
if (c._gen_i >= 0) {
_t.vComprehensionGenerator(*c._e->template cast<Comprehension>(), c._gen_i);
} else {
_t.vComprehension(*c._e->template cast<Comprehension>());
}
break;
case Expression::E_ITE:
_t.vITE(*c._e->template cast<ITE>());
break;
case Expression::E_BINOP:
_t.vBinOp(*c._e->template cast<BinOp>());
break;
case Expression::E_UNOP:
_t.vUnOp(*c._e->template cast<UnOp>());
break;
case Expression::E_CALL:
_t.vCall(*c._e->template cast<Call>());
break;
case Expression::E_VARDECL:
_t.vVarDecl(*c._e->template cast<VarDecl>());
break;
case Expression::E_LET:
_t.vLet(*c._e->template cast<Let>());
break;
case Expression::E_TI:
_t.vTypeInst(*c._e->template cast<TypeInst>());
break;
case Expression::E_TIID:
_t.vTIId(*c._e->template cast<TIId>());
break;
}
_t.exit(c._e);
stack.pop_back();
} else {
c._done = true;
Expression* ce = c._e;
for (ExpressionSetIter it = ce->ann().begin(); it != ce->ann().end(); ++it) {
if (_t.enter(*it)) stack.push_back(C(*it));
}
if (_t.enter(ce)) {
switch (ce->eid()) {
case Expression::E_INTLIT:
case Expression::E_FLOATLIT:
case Expression::E_BOOLLIT:
case Expression::E_STRINGLIT:
case Expression::E_ANON:
case Expression::E_ID:
case Expression::E_TIID:
break;
case Expression::E_SETLIT:
pushVec(stack, ce->template cast<SetLit>()->v());
break;
case Expression::E_ARRAYLIT: {
for (unsigned int i = 0; i < ce->cast<ArrayLit>()->size(); i++)
stack.push_back((*ce->cast<ArrayLit>())[i]);
} break;
case Expression::E_ARRAYACCESS:
pushVec(stack, ce->template cast<ArrayAccess>()->idx());
stack.push_back(C(ce->template cast<ArrayAccess>()->v()));
break;
case Expression::E_COMP: {
Comprehension* comp = ce->template cast<Comprehension>();
stack.push_back(C(comp->e()));
for (unsigned int i = comp->n_generators(); i--;) {
for (unsigned int j = comp->n_decls(i); j--;) {
stack.push_back(C(comp->decl(i, j)));
}
if (comp->in(i)) {
stack.push_back(C(comp->where(i)));
stack.push_back(C(comp, i));
stack.push_back(C(comp->in(i)));
} else {
stack.push_back(C(comp, i));
stack.push_back(C(comp->where(i)));
}
}
} break;
case Expression::E_ITE: {
ITE* ite = ce->template cast<ITE>();
stack.push_back(C(ite->e_else()));
for (int i = 0; i < ite->size(); i++) {
stack.push_back(C(ite->e_if(i)));
stack.push_back(C(ite->e_then(i)));
}
} break;
case Expression::E_BINOP:
stack.push_back(C(ce->template cast<BinOp>()->rhs()));
stack.push_back(C(ce->template cast<BinOp>()->lhs()));
break;
case Expression::E_UNOP:
stack.push_back(C(ce->template cast<UnOp>()->e()));
break;
case Expression::E_CALL:
for (unsigned int i = 0; i < ce->template cast<Call>()->n_args(); i++)
stack.push_back(ce->template cast<Call>()->arg(i));
break;
case Expression::E_VARDECL:
stack.push_back(C(ce->template cast<VarDecl>()->e()));
stack.push_back(C(ce->template cast<VarDecl>()->ti()));
break;
case Expression::E_LET:
stack.push_back(C(ce->template cast<Let>()->in()));
pushVec(stack, ce->template cast<Let>()->let());
break;
case Expression::E_TI:
stack.push_back(C(ce->template cast<TypeInst>()->domain()));
pushVec(stack, ce->template cast<TypeInst>()->ranges());
break;
}
} else {
c._e = NULL;
}
}
}
}
template <class T>
void TopDownIterator<T>::run(Expression* root) {
std::vector<Expression*> stack;
if (_t.enter(root)) stack.push_back(root);
while (!stack.empty()) {
Expression* e = stack.back();
stack.pop_back();
if (e == NULL) {
continue;
}
if (!_t.enter(e)) continue;
for (ExpressionSetIter it = e->ann().begin(); it != e->ann().end(); ++it) {
stack.push_back(*it);
}
switch (e->eid()) {
case Expression::E_INTLIT:
_t.vIntLit(*e->template cast<IntLit>());
break;
case Expression::E_FLOATLIT:
_t.vFloatLit(*e->template cast<FloatLit>());
break;
case Expression::E_SETLIT:
_t.vSetLit(*e->template cast<SetLit>());
pushVec(stack, e->template cast<SetLit>()->v());
break;
case Expression::E_BOOLLIT:
_t.vBoolLit(*e->template cast<BoolLit>());
break;
case Expression::E_STRINGLIT:
_t.vStringLit(*e->template cast<StringLit>());
break;
case Expression::E_ID:
_t.vId(*e->template cast<Id>());
break;
case Expression::E_ANON:
_t.vAnonVar(*e->template cast<AnonVar>());
break;
case Expression::E_ARRAYLIT:
_t.vArrayLit(*e->template cast<ArrayLit>());
for (unsigned int i = 0; i < e->cast<ArrayLit>()->size(); i++)
stack.push_back((*e->cast<ArrayLit>())[i]);
break;
case Expression::E_ARRAYACCESS:
_t.vArrayAccess(*e->template cast<ArrayAccess>());
pushVec(stack, e->template cast<ArrayAccess>()->idx());
stack.push_back(e->template cast<ArrayAccess>()->v());
break;
case Expression::E_COMP:
_t.vComprehension(*e->template cast<Comprehension>());
{
Comprehension* comp = e->template cast<Comprehension>();
for (unsigned int i = comp->n_generators(); i--;) {
stack.push_back(comp->where(i));
stack.push_back(comp->in(i));
for (unsigned int j = comp->n_decls(i); j--;) {
stack.push_back(comp->decl(i, j));
}
}
stack.push_back(comp->e());
}
break;
case Expression::E_ITE:
_t.vITE(*e->template cast<ITE>());
{
ITE* ite = e->template cast<ITE>();
stack.push_back(ite->e_else());
for (int i = 0; i < ite->size(); i++) {
stack.push_back(ite->e_if(i));
stack.push_back(ite->e_then(i));
}
}
break;
case Expression::E_BINOP:
_t.vBinOp(*e->template cast<BinOp>());
stack.push_back(e->template cast<BinOp>()->rhs());
stack.push_back(e->template cast<BinOp>()->lhs());
break;
case Expression::E_UNOP:
_t.vUnOp(*e->template cast<UnOp>());
stack.push_back(e->template cast<UnOp>()->e());
break;
case Expression::E_CALL:
_t.vCall(*e->template cast<Call>());
for (unsigned int i = 0; i < e->template cast<Call>()->n_args(); i++)
stack.push_back(e->template cast<Call>()->arg(i));
break;
case Expression::E_VARDECL:
_t.vVarDecl(*e->template cast<VarDecl>());
stack.push_back(e->template cast<VarDecl>()->e());
stack.push_back(e->template cast<VarDecl>()->ti());
break;
case Expression::E_LET:
_t.vLet(*e->template cast<Let>());
stack.push_back(e->template cast<Let>()->in());
pushVec(stack, e->template cast<Let>()->let());
break;
case Expression::E_TI:
_t.vTypeInst(*e->template cast<TypeInst>());
stack.push_back(e->template cast<TypeInst>()->domain());
pushVec(stack, e->template cast<TypeInst>()->ranges());
break;
case Expression::E_TIID:
_t.vTIId(*e->template cast<TIId>());
break;
}
}
}
} // namespace MiniZinc
#endif