/*
* Copyright (C) 2012 University of Freiburg
*
* This file is part of SMTInterpol.
*
* SMTInterpol is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* SMTInterpol is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with SMTInterpol. If not, see <http://www.gnu.org/licenses/>.
*/
package de.uni_freiburg.informatik.ultimate.smtinterpol.convert;
import de.uni_freiburg.informatik.ultimate.logic.AnnotatedTerm;
import de.uni_freiburg.informatik.ultimate.logic.ApplicationTerm;
import de.uni_freiburg.informatik.ultimate.logic.ConstantTerm;
import de.uni_freiburg.informatik.ultimate.logic.LetTerm;
import de.uni_freiburg.informatik.ultimate.logic.NonRecursive;
import de.uni_freiburg.informatik.ultimate.logic.QuantifiedFormula;
import de.uni_freiburg.informatik.ultimate.logic.Term;
import de.uni_freiburg.informatik.ultimate.logic.TermVariable;
public class OccurrenceCounter extends NonRecursive {
private static class CountWalker extends InternAbstractTermWalker {
public CountWalker(Term term) {
super(term);
}
@Override
public void walk(NonRecursive walker, SMTAffineTerm term) {
final OccurrenceCounter occ = (OccurrenceCounter) walker;
if (++term.mTmpCtr == 1) {
for (final Term t : term.getSummands().keySet()) {
occ.enqueueWalker(new CountWalker(t));
}
}
}
@Override
public void walk(NonRecursive walker, ConstantTerm term) {
// TODO Do we need counts for constants???
}
@Override
public void walk(NonRecursive walker, AnnotatedTerm term) {
// just skip
walker.enqueueWalker(new CountWalker(term.getSubterm()));
}
@Override
public void walk(NonRecursive walker, ApplicationTerm term) {
final OccurrenceCounter occ = (OccurrenceCounter) walker;
if (++term.mTmpCtr == 1) {
for (final Term t : term.getParameters()) {
occ.enqueueWalker(new CountWalker(t));
}
}
}
@Override
public void walk(NonRecursive walker, LetTerm term) {
throw new InternalError("Term should be unletted before counting");
}
@Override
public void walk(NonRecursive walker, QuantifiedFormula term) {
// TODO Do we really want to descent into quantified formulas???
final OccurrenceCounter occ = (OccurrenceCounter) walker;
if (++term.mTmpCtr == 1) {
occ.enqueueWalker(new CountWalker(term.getSubformula()));
}
}
@Override
public void walk(NonRecursive walker, TermVariable term) {
++term.mTmpCtr;
}
}
private static class ResetWalker extends InternAbstractTermWalker {
public ResetWalker(Term term) {
super(term);
}
@Override
public void walk(NonRecursive walker, SMTAffineTerm term) {
final OccurrenceCounter occ = (OccurrenceCounter) walker;
if (term.mTmpCtr != 0) {
for (final Term t : term.getSummands().keySet()) {
occ.enqueueWalker(new ResetWalker(t));
}
term.mTmpCtr = 0;
}
}
@Override
public void walk(NonRecursive walker, ConstantTerm term) {
// TODO Do we need counts for constants???
}
@Override
public void walk(NonRecursive walker, AnnotatedTerm term) {
// just skip
walker.enqueueWalker(new ResetWalker(term.getSubterm()));
}
@Override
public void walk(NonRecursive walker, ApplicationTerm term) {
final OccurrenceCounter occ = (OccurrenceCounter) walker;
if (term.mTmpCtr != 0) {
for (final Term t : term.getParameters()) {
occ.enqueueWalker(new ResetWalker(t));
}
term.mTmpCtr = 0;
}
}
@Override
public void walk(NonRecursive walker, LetTerm term) {
throw new InternalError("Term should be unletted before counting");
}
@Override
public void walk(NonRecursive walker, QuantifiedFormula term) {
// TODO Do we really want to descent into quantified formulas???
final OccurrenceCounter occ = (OccurrenceCounter) walker;
if (term.mTmpCtr != 0) {
occ.enqueueWalker(new ResetWalker(term.getSubformula()));
term.mTmpCtr = 0;
}
}
@Override
public void walk(NonRecursive walker, TermVariable term) {
term.mTmpCtr = 0;
}
}
/**
* Compute the occurrence counter for the sub terms. This method does not
* keep any state in this object. This should prevent memory leaks since
* this object can be kept alive and the garbage collector is still free to
* collect the counter map.
* @param t The term to count.
*/
public void count(Term t) {
run(new CountWalker(t));
}
public void reset(Term t) {
run(new ResetWalker(t));
}
}