/*
* 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.math.BigDecimal;
import java.math.BigInteger;
import java.util.Map;
import de.uni_freiburg.informatik.ultimate.logic.Theory.SolverSetup;
/**
* Simple implementation of a script, that supports building terms and sorts,
* but does not support setting and getting options, checking for satisfiabilty,
* or getting any other results.
*
* This can be used as base class for implementing the script interface.
*
* @author Jürgen Christ, Jochen Hoenicke
*/
public class NoopScript implements Script {
private Theory mTheory;
protected int mStackLevel = 0;
protected SolverSetup mSolverSetup;
public NoopScript() {
this(null, null);
}
protected NoopScript(Theory theory) {
this(theory, null);
}
protected NoopScript(Theory theory, SolverSetup setup) {
mTheory = theory;
mSolverSetup = setup;
}
public Theory getTheory() {
return mTheory;
}
/**
* Check that the symbol does not contain characters that would make
* it impossible to use it in a LoggingScript. These are | and \.
* @param symbol the symbol to check
* @throws SMTLibException if symbol contains | or \.
*/
private void checkSymbol(String symbol) throws SMTLIBException {
if (symbol.indexOf('|') >= 0 || symbol.indexOf('\\') >= 0) {
throw new SMTLIBException("Symbol must not contain | or \\");
}
}
@Override
public void setLogic(String logic) throws UnsupportedOperationException {
try {
setLogic(Logics.valueOf(logic));
} catch (final IllegalArgumentException eLogicUnsupported) {
/* Logic is not in enumeration */
throw new UnsupportedOperationException("Logic " + logic
+ " not supported");
}
}
@Override
public void setLogic(Logics logic) throws UnsupportedOperationException {
if (mTheory != null) {
throw new SMTLIBException("Logic already set!");
}
mTheory = new Theory(logic, mSolverSetup);
}
@Override
public void setOption(String opt, Object value)
throws UnsupportedOperationException, SMTLIBException {
// Nothing to do
}
@Override
public void setInfo(String info, Object value) {
// Nothing to do
}
@Override
public void declareSort(String sort, int arity) throws SMTLIBException {
if (mTheory == null) {
throw new SMTLIBException("No logic set!");
}
checkSymbol(sort);
try {
mTheory.declareSort(sort, arity);
} catch (final IllegalArgumentException eiae) {
throw new SMTLIBException(eiae.getMessage());
}
}
@Override
public void defineSort(String sort, Sort[] sortParams, Sort definition)
throws SMTLIBException {
if (mTheory == null) {
throw new SMTLIBException("No logic set!");
}
checkSymbol(sort);
try {
mTheory.defineSort(sort, sortParams.length, definition);
} catch (final IllegalArgumentException eiae) {
throw new SMTLIBException(eiae.getMessage());
}
}
@Override
public void declareFun(String fun, Sort[] paramSorts, Sort resultSort)
throws SMTLIBException {
if (mTheory == null) {
throw new SMTLIBException("No logic set!");
}
checkSymbol(fun);
try {
mTheory.declareFunction(fun, paramSorts, resultSort);
} catch (final IllegalArgumentException eiae) {
throw new SMTLIBException(eiae.getMessage());
}
}
@Override
public void defineFun(String fun, TermVariable[] params,
Sort resultSort, Term definition) throws SMTLIBException {
checkSymbol(fun);
defineFunInternal(fun, params, resultSort, definition);
}
private void defineFunInternal(String fun, TermVariable[] params,
Sort resultSort, Term definition) throws SMTLIBException {
if (mTheory == null) {
throw new SMTLIBException("No logic set!");
}
if (!resultSort.equalsSort(definition.getSort())) {
throw new SMTLIBException("Sort mismatch");
}
try {
mTheory.defineFunction(fun, params, definition);
} catch (final IllegalArgumentException eiae) {
throw new SMTLIBException(eiae.getMessage());
}
}
@Override
public void push(int levels) {
if (mTheory == null) {
throw new SMTLIBException("No logic set!");
}
mStackLevel += levels;
for (int i = 0; i < levels; i++) {
mTheory.push();
}
}
@Override
public void pop(int levels) throws SMTLIBException {
if (mTheory == null) {
throw new SMTLIBException("No logic set!");
}
if (levels > mStackLevel) {
throw new SMTLIBException("Not enough levels on assertion stack");
}
mStackLevel -= levels;
for (int i = 0; i < levels; i++) {
mTheory.pop();
}
}
@Override
public LBool assertTerm(Term term) throws SMTLIBException {
return LBool.UNKNOWN;
}
@Override
public LBool checkSat() {
return LBool.UNKNOWN;
}
@Override
public LBool checkSatAssuming(Term... assumptions) {
return LBool.UNKNOWN;
}
@Override
public Term[] getAssertions() throws SMTLIBException {
throw new UnsupportedOperationException();
}
@Override
public Term getProof() throws SMTLIBException,
UnsupportedOperationException {
throw new UnsupportedOperationException();
}
@Override
public Term[] getUnsatCore() throws SMTLIBException,
UnsupportedOperationException {
throw new UnsupportedOperationException();
}
@Override
public Map<Term, Term> getValue(Term[] terms) throws SMTLIBException,
UnsupportedOperationException {
throw new UnsupportedOperationException();
}
@Override
public Assignments getAssignment() throws SMTLIBException,
UnsupportedOperationException {
throw new UnsupportedOperationException();
}
@Override
public Object getOption(String opt)
throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
@Override
public Object getInfo(String info)
throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
@Override
public Term simplify(Term term) throws SMTLIBException {
throw new UnsupportedOperationException();
}
@Override
public void reset() {
mTheory = null;
mStackLevel = 0;
}
@Override
public Term[] getInterpolants(Term[] partition) throws SMTLIBException,
UnsupportedOperationException {
// The default startOfSubtrees is an array with 0's.
final int[] startOfSubtrees = new int[partition.length];
return getInterpolants(partition, startOfSubtrees);
}
@Override
public Term[] getInterpolants(Term[] partition, int[] startOfSubtree)
throws SMTLIBException, UnsupportedOperationException {
throw new UnsupportedOperationException();
}
@Override
public void exit() {
// Nothing to do
}
@Override
public Sort sort(String sortname, Sort... params) throws SMTLIBException {
return sort(sortname, null, params);
}
@Override
public Sort sort(String sortname, BigInteger[] indices, Sort... params)
throws SMTLIBException {
if (mTheory == null) {
throw new SMTLIBException("No logic set!");
}
final Sort res = mTheory.getSort(sortname, indices, params);
if (res == null) {
throw new SMTLIBException("Sort " + sortname + " not declared");
}
return res;
}
@Override
public Term term(String funcname, Term... params) throws SMTLIBException {
return term(funcname, null, null, params);
}
@Override
public Term term(String funcname, BigInteger[] indices,
Sort returnSort, Term... params) throws SMTLIBException {
if (mTheory == null) {
throw new SMTLIBException("No logic set!");
}
final Sort[] sorts =
params.length == 0 ? Script.EMPTY_SORT_ARRAY : new Sort[params.length];
for (int i = 0; i < sorts.length; i++) {
sorts[i] = params[i].getSort();
}
final FunctionSymbol fsym = mTheory
.getFunctionWithResult(funcname, indices, returnSort, sorts);
if (fsym == null) {
final StringBuilder sb = new StringBuilder();
final PrintTerm pt = new PrintTerm();
sb.append("Undeclared function symbol (").append(funcname);
for (final Sort s: sorts) {
sb.append(' ');
pt.append(sb, s);
}
sb.append(')');
throw new SMTLIBException(sb.toString());
}
return mTheory.term(fsym, params);
}
@Override
public TermVariable variable(String varname, Sort sort)
throws SMTLIBException {
if (sort == null || varname == null) {
throw new SMTLIBException(
"Invalid input to create a term variable");
}
checkSymbol(varname);
return mTheory.createTermVariable(varname, sort);
}
@Override
public Term quantifier(int quantor, TermVariable[] vars, Term body,
Term[]... patterns) throws SMTLIBException {
if (vars.length == 0) {
throw new SMTLIBException("No quantified variables given");
}
if (body == null) {
throw new SMTLIBException("Empty quantifier body");
}
if (patterns != null && patterns.length > 0) {
final Annotation[] annots = new Annotation[patterns.length];
int i = 0;
for (final Term[] p : patterns) {
annots[i++] = new Annotation(":pattern", p);
}
body = mTheory.annotatedTerm(annots, body);
}
if (quantor == Script.EXISTS) {
return mTheory.exists(vars, body);
}
if (quantor == Script.FORALL) {
return mTheory.forall(vars, body);
}
throw new SMTLIBException("Unknown Quantifier");
}
@Override
public Term let(TermVariable[] vars, Term[] values, Term body)
throws SMTLIBException {
if (vars.length != values.length) {
throw new SMTLIBException(
"Need exactly one value for every variable");
}
return mTheory.let(vars, values, body);
}
@Override
public Term annotate(Term t, Annotation... annotations)
throws SMTLIBException {
if (annotations.length > 0) {
for (final Annotation a : annotations) {
if (a.getKey().equals(":named")) {
if (!(a.getValue() instanceof String)) {
throw new SMTLIBException(
"Need a string value for :named");
}
checkSymbol((String) a.getValue());
if (t.getFreeVars().length != 0) {
throw new SMTLIBException("Cannot name open terms");
} else {
defineFunInternal((String) a.getValue(),
Theory.EMPTY_TERM_VARIABLE_ARRAY, t.getSort(), t);
}
}
}
return mTheory.annotatedTerm(annotations, t);
} else {
return t;
}
}
@Override
public Term numeral(String num) throws SMTLIBException {
if (mTheory == null) {
throw new SMTLIBException("No logic set!");
}
if (mTheory.getNumericSort() == null) {
throw new SMTLIBException("Logic does not allow numerals");
}
try {
return mTheory.numeral(num);
} catch (final NumberFormatException enfe) {
throw new SMTLIBException("Not a numeral: " + num);
}
}
@Override
public Term numeral(BigInteger num) throws SMTLIBException {
if (mTheory == null) {
throw new SMTLIBException("No logic set!");
}
if (mTheory.getNumericSort() == null) {
throw new SMTLIBException("Logic does not allow numerals");
}
return mTheory.numeral(num);
}
@Override
public Term decimal(String decimal) throws SMTLIBException {
if (mTheory == null) {
throw new SMTLIBException("No logic set!");
}
if (mTheory.getRealSort() == null) {
throw new SMTLIBException("Logic does not allow reals");
}
try {
return mTheory.decimal(decimal);
} catch (final NumberFormatException enfe) {
throw new SMTLIBException("Not a decimal: " + decimal);
}
}
@Override
public Term decimal(BigDecimal decimal) throws SMTLIBException {
if (mTheory == null) {
throw new SMTLIBException("No logic set!");
}
if (mTheory.getRealSort() == null) {
throw new SMTLIBException("Logic does not allow reals");
}
return mTheory.decimal(decimal);
}
@Override
public Term string(String str) throws SMTLIBException {
if (mTheory == null) {
throw new SMTLIBException("No logic set!");
}
if (mTheory.getStringSort() == null) {
throw new SMTLIBException("Logic does not allow strings");
}
return mTheory.string(str);
}
@Override
public Term hexadecimal(String hex) throws SMTLIBException {
if (mTheory == null) {
throw new SMTLIBException("No logic set!");
}
final Term res = mTheory.hexadecimal(hex);
if (res == null) {
throw new SMTLIBException("No bitvector logic");
}
return res;
}
@Override
public Term binary(String bin) throws SMTLIBException {
if (mTheory == null) {
throw new SMTLIBException("No logic set!");
}
final Term res = mTheory.binary(bin);
if (res == null) {
throw new SMTLIBException("No bitvector logic");
}
return res;
}
@Override
public Sort[] sortVariables(String... names) throws SMTLIBException {
if (mTheory == null) {
throw new SMTLIBException("No logic set!");
}
return mTheory.createSortVariables(names);
}
@Override
public Model getModel() throws SMTLIBException,
UnsupportedOperationException {
throw new UnsupportedOperationException();
}
@Override
public Iterable<Term[]> checkAllsat(Term[] predicates)
throws SMTLIBException, UnsupportedOperationException {
throw new UnsupportedOperationException();
}
@Override
public Term[] findImpliedEquality(Term[] x, Term[] y)
throws SMTLIBException, UnsupportedOperationException {
throw new UnsupportedOperationException();
}
@Override
public QuotedObject echo(QuotedObject msg) {
return msg;
}
@Override
public void resetAssertions() {
if (mTheory == null) {
throw new SMTLIBException("No logic set!");
}
mTheory.resetAssertions();
mStackLevel = 0;
}
@Override
public Term[] getUnsatAssumptions() throws SMTLIBException,
UnsupportedOperationException {
throw new UnsupportedOperationException();
}
}