/*++ Copyright (c) 2006 Microsoft Corporation Module Name: recurse_expr_def.h Abstract: Traverse an expression applying a visitor. Author: Leonardo de Moura (leonardo) 2008-01-11. Revision History: --*/ #ifndef _RECURSE_EXPR_DEF_H_ #define _RECURSE_EXPR_DEF_H_ #include"recurse_expr.h" template inline void recurse_expr::visit(expr * n, bool & visited) { if (!is_cached(n)) { m_todo.push_back(n); visited = false; } } template bool recurse_expr::visit_children(expr * n) { bool visited = true; unsigned num; switch (n->get_kind()) { case AST_APP: num = to_app(n)->get_num_args(); for (unsigned j = 0; j < num; j++) visit(to_app(n)->get_arg(j), visited); break; case AST_QUANTIFIER: if (!IgnorePatterns) { num = to_quantifier(n)->get_num_patterns(); for (unsigned j = 0; j < num; j++) visit(to_quantifier(n)->get_pattern(j), visited); num = to_quantifier(n)->get_num_no_patterns(); for (unsigned j = 0; j < num; j++) visit(to_quantifier(n)->get_no_pattern(j), visited); } visit(to_quantifier(n)->get_expr(), visited); break; default: break; } return visited; } template void recurse_expr::process(expr * n) { unsigned num; switch (n->get_kind()) { case AST_APP: m_results1.reset(); num = to_app(n)->get_num_args(); for (unsigned j = 0; j < num; j++) m_results1.push_back(get_cached(to_app(n)->get_arg(j))); cache_result(n, this->Visitor::visit(to_app(n), m_results1.c_ptr())); break; case AST_VAR: cache_result(n, this->Visitor::visit(to_var(n))); break; case AST_QUANTIFIER: if (IgnorePatterns) { cache_result(n, this->Visitor::visit(to_quantifier(n), get_cached(to_quantifier(n)->get_expr()), 0, 0)); } else { m_results1.reset(); m_results2.reset(); num = to_quantifier(n)->get_num_patterns(); for (unsigned j = 0; j < num; j++) m_results1.push_back(get_cached(to_quantifier(n)->get_pattern(j))); num = to_quantifier(n)->get_num_no_patterns(); for (unsigned j = 0; j < num; j++) m_results2.push_back(get_cached(to_quantifier(n)->get_no_pattern(j))); cache_result(n, this->Visitor::visit(to_quantifier(n), get_cached(to_quantifier(n)->get_expr()), m_results1.c_ptr(), m_results2.c_ptr())); } break; default: UNREACHABLE(); } } template T recurse_expr::operator()(expr * r) { m_todo.push_back(r); while (!m_todo.empty()) { expr * n = m_todo.back(); if (is_cached(n)) m_todo.pop_back(); else if (visit_children(n)) { m_todo.pop_back(); process(n); } } return get_cached(r); } #endif /* _RECURSE_EXPR_DEF_H_ */