z3-z3-4.13.0.src.ast.occurs.cpp Maven / Gradle / Ivy
The newest version!
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
occurs.cpp
Abstract:
Author:
Leonardo de Moura (leonardo) 2007-06-07.
Revision History:
--*/
#include "ast/occurs.h"
#include "ast/for_each_expr.h"
#include "ast/for_each_ast.h"
// -----------------------------------
//
// Occurs check
//
// -----------------------------------
namespace {
struct found {};
struct proc {
expr * m_n;
#define CHECK() { if (n == m_n) throw found(); }
proc(expr * n):m_n(n) {}
void operator()(var const * n) { CHECK(); }
void operator()(app const * n) { CHECK(); }
void operator()(quantifier const * n) { CHECK(); }
};
struct decl_proc {
func_decl * m_d;
decl_proc(func_decl * d):m_d(d) {}
void operator()(var const * n) { }
void operator()(app const * n) { if (n->get_decl() == m_d) throw found(); }
void operator()(quantifier const * n) { }
};
struct sort_proc {
sort* m_s;
sort_proc(sort* s) :m_s(s) {}
void operator()(sort const* s2) { if (m_s == s2) throw found(); }
void operator()(ast*) {}
};
}
// Return true if n1 occurs in n2
bool occurs(expr * n1, expr * n2) {
proc p(n1);
try {
quick_for_each_expr(p, n2);
}
catch (const found &) {
return true;
}
return false;
}
bool occurs(func_decl * d, expr * n) {
decl_proc p(d);
try {
quick_for_each_expr(p, n);
}
catch (const found &) {
return true;
}
return false;
}
bool occurs(sort* s1, sort* s2) {
sort_proc p(s1);
try {
for_each_ast(p, s2, true);
}
catch (const found&) {
return true;
}
return false;
}
void mark_occurs(ptr_vector& to_check, expr* v, expr_mark& occ) {
expr_fast_mark2 visited;
occ.mark(v, true);
visited.mark(v, true);
while (!to_check.empty()) {
expr* e = to_check.back();
if (visited.is_marked(e)) {
to_check.pop_back();
continue;
}
if (is_app(e)) {
bool does_occur = false;
bool all_visited = true;
for (expr* arg : *to_app(e)) {
if (!visited.is_marked(arg)) {
to_check.push_back(arg);
all_visited = false;
}
else
does_occur |= occ.is_marked(arg);
}
if (all_visited) {
occ.mark(e, does_occur);
visited.mark(e, true);
to_check.pop_back();
}
}
else if (is_quantifier(e)) {
expr* body = to_quantifier(e)->get_expr();
if (visited.is_marked(body)) {
visited.mark(e, true);
occ.mark(e, occ.is_marked(body));
to_check.pop_back();
}
else
to_check.push_back(body);
}
else {
visited.mark(e, true);
to_check.pop_back();
}
}
}