/*
* 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.BigInteger;
import java.util.Arrays;
import de.uni_freiburg.informatik.ultimate.util.datastructures.UnifyHash;
/**
* Factory for overloaded and/or polymorphic function symbols.
* @author hoenicke
*/
public abstract class FunctionSymbolFactory {
String mFuncName;
UnifyHash<FunctionSymbol> mInstances;
public FunctionSymbolFactory(String name) {
mFuncName = name;
mInstances = new UnifyHash<FunctionSymbol>();
}
public abstract Sort getResultSort(
BigInteger[] indices, Sort[] paramSorts, Sort resultSort);
public int getFlags(BigInteger[] indices, Sort[] paramSorts, Sort result) {
return FunctionSymbol.INTERNAL;
}
private static boolean isReal(Sort[] sorts) {
for (final Sort s : sorts) {
if (s.getRealSort() != s) {
return false;
}
}
return true;
}
public Term getDefinition(TermVariable[] tvs, Sort resultSort) { // NOPMD
return null;
}
public FunctionSymbol getFunctionWithResult(
Theory theory, BigInteger[] indices, Sort[] paramSorts,
Sort resultSort) {
assert isReal(paramSorts);
final int flags = getFlags(indices, paramSorts, resultSort);
if ((flags & (FunctionSymbol.ASSOCMASK)) != 0) {
if (paramSorts.length < 2) {
return null;
}
final Sort[] realParams = new Sort[] {
paramSorts[0], paramSorts[paramSorts.length - 1]
};
final Sort otherSort =
(flags & (FunctionSymbol.ASSOCMASK)) == FunctionSymbol.LEFTASSOC
? realParams[1] : realParams[0];
for (int i = 1; i < paramSorts.length - 1; i++) {
if (paramSorts[i] != otherSort) {
return null;
}
}
paramSorts = realParams;
}
if (((flags & (FunctionSymbol.RETURNOVERLOAD)) == 0)
!= (resultSort == null)) {
/* According to standard the return type must be given
* if and only if the function is overloaded on the return type.
*/
return null;
}
final int hash = Arrays.hashCode(indices)
^ Arrays.hashCode(paramSorts)
^ (resultSort == null ? 0 : resultSort.hashCode());
for (final FunctionSymbol func : mInstances.iterateHashCode(hash)) {
if (Arrays.equals(func.mIndices, indices)
&& Arrays.equals(func.mParamSort, paramSorts)
&& (resultSort == null
|| func.mReturnSort == resultSort)) {
return func;
}
}
resultSort = getResultSort(indices, paramSorts, resultSort);
if (resultSort == null) {
return null;
}
TermVariable[] defVars = new TermVariable[paramSorts.length];
for (int i = 0; i < paramSorts.length; i++) {
defVars[i] = theory.createTermVariable("x" + i, paramSorts[i]);
}
Term definition;
if (((flags & (FunctionSymbol.RETURNOVERLOAD)) != 0)// NOPMD
&& resultSort != resultSort.getRealSort()) {
final FunctionSymbol realFunc =
getFunctionWithResult(theory, indices, paramSorts,
resultSort.getRealSort());
definition = theory.term(realFunc, defVars);
} else {
definition = getDefinition(defVars, resultSort);
}
if (definition == null) {
defVars = null;
}
final FunctionSymbol func = new FunctionSymbol(
mFuncName, indices, paramSorts, resultSort,
defVars, definition, flags);
mInstances.put(hash, func);
return func;
}
@Override
public String toString() {
return mFuncName;
}
}