z3 / src / ast / shared_occs.cpp

/*++
Copyright (c) 2011 Microsoft Corporation

Module Name:

    shared_occs.cpp

Abstract:

    Functor for computing the shared subterms in a given
    term.

Author:

    Leonardo de Moura (leonardo) 2011-04-01.

Revision History:
--*/
#include"shared_occs.h"
#include"ast_smt2_pp.h"
#include"ref_util.h"

inline void shared_occs::insert(expr * t) {
    obj_hashtable<expr>::entry * dummy;
    if (m_shared.insert_if_not_there_core(t, dummy))
        m.inc_ref(t);
}

void shared_occs::reset() { 
    dec_ref_collection_values(m, m_shared);
    m_shared.reset(); 
}

void shared_occs::cleanup() { 
    reset();
    m_shared.finalize();
    m_stack.finalize(); 
}

shared_occs::~shared_occs() {
    reset();
}

inline bool shared_occs::process(expr * t, shared_occs_mark & visited) {
    switch (t->get_kind()) {
    case AST_APP: {
        unsigned num_args = to_app(t)->get_num_args();
        if (t->get_ref_count() > 1 && (m_track_atomic || num_args > 0)) {
            if (visited.is_marked(t)) {
                insert(t);
                return true;
            }
            visited.mark(t);
        }
        if (num_args == 0)
            return true; // done with t
        m_stack.push_back(frame(t, 0)); // need to create frame if num_args > 0
        return false; 
    }
    case AST_VAR:
        if (m_track_atomic && t->get_ref_count() > 1) {
            if (visited.is_marked(t))
                insert(t);
            else
                visited.mark(t);
        }
        return true; // done with t
    case AST_QUANTIFIER:
        if (t->get_ref_count() > 1) {
            if (visited.is_marked(t)) {
                insert(t);
                return true; // done with t
            }
            visited.mark(t);
        }
        if (!m_visit_quantifiers)
            return true; 
        m_stack.push_back(frame(t, 0));
        return false; 
    default:
        UNREACHABLE();
        return true;
    }
}

void shared_occs::operator()(expr * t, shared_occs_mark & visited) {
    SASSERT(m_stack.empty());
    if (process(t, visited)) {
        return;
    }
    SASSERT(!m_stack.empty());
    while (!m_stack.empty()) {
    start:
        frame & fr  = m_stack.back();
        expr * curr = fr.first;
        switch (curr->get_kind()) {
        case AST_APP: {
            unsigned num_args = to_app(curr)->get_num_args();
            while (fr.second < num_args) {
                expr * arg = to_app(curr)->get_arg(fr.second);
                fr.second++;
                if (!process(arg, visited))
                    goto start;
            }
            break;
        }
        case AST_QUANTIFIER: {
            SASSERT(m_visit_quantifiers);
            unsigned num_children = m_visit_patterns ? to_quantifier(curr)->get_num_children() : 1;
            while (fr.second < num_children) {
                expr * child = to_quantifier(curr)->get_child(fr.second);
                fr.second++;
                if (!process(child, visited))
                    goto start;
            }
            break;
        }
        default:
            UNREACHABLE();
            break;
        }
        m_stack.pop_back();
    }
}


void shared_occs::operator()(expr * t) {
    SASSERT(m_stack.empty());
    shared_occs_mark visited;
    reset();
    operator()(t, visited);
}

void shared_occs::display(std::ostream & out, ast_manager & m) const {
    iterator it =  begin_shared();
    iterator end = end_shared();
    for (; it != end; ++it) {
        out << mk_ismt2_pp(*it, m) << "\n";
    }
}
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.