/*
* Copyright (C) 2009-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.logic;
import java.util.ArrayDeque;
/**
* This is the base class for representing SMTLIB 2 terms.
* You can assume that every term is one of the following sub-classes:
* <ul>
* <li>{@link ApplicationTerm} represents a function application
* <code>(name ...)</code>.</li>
* <li>{@link AnnotatedTerm} represents an annotated term
* <code>(! term ...)</code>.</li>
* <li>{@link ConstantTerm} represents a numeral, decimal, bit vector, or string
* literal.</li>
* <li>{@link LetTerm} represents a let term
* <code>(let ((var term)...) term)</code>.</li>
* <li>{@link TermVariable} represents a term variable <code>var</code> used in
* quantifier or let term.
* Note that constants are represented by ApplicationTerm.</li>
* <li>{@link QuantifiedFormula} represents a quantified formula
* <code>(exists/forall ...)</code>.</li>
* </ul>
*
* In principle it is possible to write your own sub-classes, but that is
* dangerous and only recommend for the advanced SMTInterpol hacker.
*
* @author Juergen Christ, Jochen Hoenicke
*/
public abstract class Term {
private final int mHash;
/**
* A temporary counter used e.g. to count the number of occurrences of this
* term in a bigger term.
* Don't use this!!!!
*/
public int mTmpCtr;
TermVariable[] mFreeVars;
/**
* Create a term.
* @param hash the hash code of the term. This should be stable.
*/
protected Term(int hash) {
mHash = hash;
}
/**
* Returns the SMTLIB sort of this term.
* @return the sort of the term.
*/
public abstract Sort getSort();
/**
* Computes and returns the free variables occurring in this term.
* @return the free variables.
*/
public TermVariable[] getFreeVars() {
if (mFreeVars == null) {
new NonRecursive().run(new ComputeFreeVariables(this));
}
return mFreeVars;
}
public Theory getTheory() {
return getSort().mSymbol.mTheory;
}
/**
* Prints an SMTLIB representation of this term. This
* {@link FormulaLet introduces lets for common subexpressions}
* to prevent exponential blow-up when printing
* a term with lots of sharing.
* @return an SMTLIB representation.
*/
@Override
public String toString() {
final Term letted = new FormulaLet().let(this);
return letted.toStringDirect();
}
/**
* Prints the canonical SMTLIB representation of this term.
* This does not eliminate common sub-expressions and can cause
* exponential blow-up.
* @return the canonical SMTLIB representation.
*/
public String toStringDirect() {
final StringBuilder sb = new StringBuilder();
new PrintTerm().append(sb, this);
return sb.toString();
}
@Override
public int hashCode() {
return mHash;
}
/**
* Convert a term to a string in a stack based fashion. This is used
* for internal purposes. External users can just use toString()
* or toStringDirect().
* @param mTodo The stack where to put the strings and sub terms.
* @see PrintTerm
*/
protected abstract void toStringHelper(ArrayDeque<Object> mTodo);
}