/**
* Author: Georg Hofferek <georg.hofferek@iaik.tugraz.at>
*/
package at.iaik.suraq.smtlib.formula;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import sun.reflect.generics.reflectiveObjects.NotImplementedException;
import at.iaik.suraq.exceptions.InvalidParametersException;
import at.iaik.suraq.sexp.SExpression;
import at.iaik.suraq.sexp.Token;
import at.iaik.suraq.smtlib.SMTLibObject;
import at.iaik.suraq.util.FormulaCache;
/**
* @author Georg Hofferek <georg.hofferek@iaik.tugraz.at>
*
*/
public class TermFunctionMacro extends FunctionMacro {
/**
*
*/
private static final long serialVersionUID = 1L;
/**
* The body of this macro.
*/
private final Term body;
/**
* Constructs a new <code>TermFunctionMacro</code> with the given values.
*
* @param name
* the name of this macro.
* @param a
* list of parameters
* @param paramMap
* the map from parameters to types.
* @param body
* the actual body.
* @throws InvalidParametersException
* if the size of the parameter list and the type map do not
* match.
*/
private TermFunctionMacro(Token name, List<Token> parameters,
Map<Token, SExpression> paramMap, Term body)
throws InvalidParametersException {
super(name, parameters, paramMap);
this.body = body;
}
public static TermFunctionMacro create(Token name, List<Token> parameters,
Map<Token, SExpression> paramMap, Term body)
throws InvalidParametersException {
return (TermFunctionMacro) FormulaCache.functionMacro
.put(new TermFunctionMacro(name, parameters, paramMap, body));
}
/**
* Constructs a new <code>PropositionalFunctionMacro</code>, which is a deep
* copy of the given one
*
* @param macro
* the macro to (deep) copy.
*/
/*
* public TermFunctionMacro(TermFunctionMacro macro) { super(macro);
* this.body = macro.body.deepTermCopy(); }
*/
/**
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!(obj instanceof TermFunctionMacro))
return false;
if (this.hashCode() != obj.hashCode())
return false;
TermFunctionMacro other = (TermFunctionMacro) obj;
if (!other.name.equals(name))
return false;
if (!other.parameters.equals(parameters))
return false;
if (!other.paramMap.equals(paramMap))
return false;
if (!other.body.equals(body))
return false;
return true;
}
/**
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
return name.hashCode() * 31 * 31 * 31 + parameters.hashCode() * 31 * 31
+ paramMap.hashCode() * 31 + body.hashCode();
}
/**
* Returns the function body of this macro.
*
* @return the <code>body</code>
*/
public Term getBody() {
return body;
}
/**
* @see at.iaik.suraq.smtlib.formula.FunctionMacro#removeArrayEqualities()
*/
@Override
public FunctionMacro removeArrayEqualities() {
try {
return TermFunctionMacro.create(name, parameters, paramMap,
body.removeArrayEqualitiesTerm());
} catch (InvalidParametersException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
/**
* @see at.iaik.suraq.smtlib.formula.FunctionMacro#arrayPropertiesToFiniteConjunctions(java.util.Set)
*/
@Override
public FunctionMacro arrayPropertiesToFiniteConjunctions(
Set<DomainTerm> indexSet) {
try {
return TermFunctionMacro.create(name, parameters, paramMap,
body.arrayPropertiesToFiniteConjunctionsTerm(indexSet));
} catch (InvalidParametersException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
/**
* Returns the type of the term of this macro's body.
*
* @return the type of the term of this macro's body.
*/
@Override
public SExpression getType() {
return body.getType();
}
/**
* @see at.iaik.suraq.smtlib.formula.EqualityFormula#removeArrayWrites(at.iaik.suraq.smtlib.formula.Formula,
* java.util.Set, java.util.Set)
*/
public Set<Formula> removeArrayWrites(Formula topLevelFormula,
Set<Token> noDependenceVars) {
Set<Formula> constraints = new HashSet<Formula>();
body.removeArrayWritesTerm(topLevelFormula, constraints,
noDependenceVars);
return constraints;
}
/**
* Replaces array-read expressions with uninterpreted function instances
*/
public FunctionMacro arrayReadsToUninterpretedFunctions(
Set<Token> noDependenceVars) {
Term body = this.body
.arrayReadsToUninterpretedFunctionsTerm(noDependenceVars);
try {
return TermFunctionMacro.create(name, parameters, paramMap, body);
} catch (InvalidParametersException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
/**
* @see at.iaik.suraq.smtlib.formula.Term#getUninterpretedFunctions()
*/
@Override
public void getUninterpretedFunctions(Set<UninterpretedFunction> result,
Set<SMTLibObject> done) {
body.getUninterpretedFunctions(result, done);
}
/**
* @see at.iaik.suraq.smtlib.formula.FunctionMacro#getBodyExpression()
*/
@Override
public SExpression getBodyExpression() {
return body.toSmtlibV2();
}
/**
* @see at.iaik.suraq.smtlib.formula.Term#substituteUninterpretedFunction(Token,
* at.iaik.suraq.smtlib.formula.UninterpretedFunction)
*/
@Override
public FunctionMacro substituteUninterpretedFunction(
Map<Token, UninterpretedFunction> substitutions,
Map<SMTLibObject, SMTLibObject> done) {
if (done.get(this) != null) {
assert (done.get(this) instanceof FunctionMacro);
return (FunctionMacro) done.get(this);
}
try {
Term tmp = body
.substituteUninterpretedFunction(substitutions, done);
FunctionMacro result = TermFunctionMacro.create(name, parameters,
paramMap, tmp);
done.put(this, result);
return result;
} catch (InvalidParametersException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
/**
* @param topLevelFormula
* @param noDependenceVars
* @return
*/
public Set<Formula> makeArrayReadsSimple(Formula topLevelFormula,
Set<Token> noDependenceVars) {
Set<Formula> constraints = new HashSet<Formula>();
body.makeArrayReadsSimpleTerm(topLevelFormula, constraints,
noDependenceVars);
return constraints;
}
/**
* @see at.iaik.suraq.smtlib.formula.Formula#uninterpretedPredicatesToAuxiliaryVariables(at.iaik.suraq.smtlib.formula.Formula,
* java.util.Set, java.util.Set)
*/
/*
* public TermFunctionMacro uninterpretedPredicatesToAuxiliaryVariables(
* Formula topLeveFormula, Set<Formula> constraints, Set<Token>
* noDependenceVars) {
*
* Term newBody = body.uninterpretedPredicatesToAuxiliaryVariables(
* topLeveFormula, constraints, noDependenceVars); try { return new
* TermFunctionMacro(name, parameters, paramMap, newBody); } catch
* (InvalidParametersException exc) { throw new RuntimeException(
* "Unexpectedly unable to create TermFunctionMacro.", exc); }
*
* }
*/
/**
* Returns the elements assert-partition.
*
* @return assert-partition of the element.
*/
@Override
public Set<Integer> getAssertPartition() {
return body.getPartitionsFromSymbols();
}
/**
* @see at.iaik.suraq.formula.Formula#uninterpretedPredicatesToAuxiliaryVariables(at.iaik.suraq.formula.Formula,
* java.util.Map, java.util.Map)
*/
public FunctionMacro uninterpretedPredicatesToAuxiliaryVariables(
Formula topLeveFormula,
Map<String, List<PropositionalVariable>> predicateInstances,
Map<PropositionalVariable, List<DomainTerm>> instanceParameters,
Set<Token> noDependenceVars) {
Term tmp = body.uninterpretedPredicatesToAuxiliaryVariablesTerm(
topLeveFormula, predicateInstances, instanceParameters,
noDependenceVars);
try {
return TermFunctionMacro.create(name, parameters, paramMap, tmp);
} catch (InvalidParametersException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
/**
* @see at.iaik.suraq.formula.Formula#uninterpretedFunctionsToAuxiliaryVariables(at.iaik.suraq.formula.Formula,
* java.util.Map, java.util.Map)
*/
public FunctionMacro uninterpretedFunctionsToAuxiliaryVariables(
Formula topLeveFormula,
Map<String, List<DomainVariable>> functionInstances,
Map<DomainVariable, List<DomainTerm>> instanceParameters,
Set<Token> noDependenceVars) {
Term tmp = body.uninterpretedFunctionsToAuxiliaryVariablesTerm(
topLeveFormula, functionInstances, instanceParameters,
noDependenceVars);
try {
return TermFunctionMacro.create(name, parameters, paramMap, tmp);
} catch (InvalidParametersException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
/**
* @param arrayVars
* @return
*/
@Override
public TermFunctionMacro uninterpretedFunctionsBackToArrayReads(
Set<ArrayVariable> arrayVars, Map<SMTLibObject, SMTLibObject> done) {
if (done.get(this) != null)
return (TermFunctionMacro) done.get(this);
Term newBody = (Term) body.uninterpretedFunctionsBackToArrayReads(
arrayVars, done);
try {
TermFunctionMacro result = TermFunctionMacro.create(name,
parameters, paramMap, newBody);
done.put(this, result);
return result;
} catch (InvalidParametersException exc) {
throw new RuntimeException(
"Unexpected InvalidParametersException while back-substituting array reads.",
exc);
}
}
/**
* @see at.iaik.suraq.smtlib.SMTLibObject#getPartitionsFromSymbols()
*/
@Override
public Set<Integer> getPartitionsFromSymbols() {
throw new NotImplementedException();
}
/**
* @see at.iaik.suraq.smtlib.SMTLibObject#getArrayVariables(java.util.Set,
* java.util.Set)
*/
@Override
public void getArrayVariables(Set<ArrayVariable> result,
Set<SMTLibObject> done) {
throw new NotImplementedException();
}
/**
* @see at.iaik.suraq.smtlib.SMTLibObject#getDomainVariables(java.util.Set,
* java.util.Set)
*/
@Override
public void getDomainVariables(Set<DomainVariable> result,
Set<SMTLibObject> done) {
throw new NotImplementedException();
}
/**
* @see at.iaik.suraq.smtlib.SMTLibObject#getPropositionalVariables(java.util.Set,
* java.util.Set)
*/
@Override
public void getPropositionalVariables(Set<PropositionalVariable> result,
Set<SMTLibObject> done) {
throw new NotImplementedException();
}
/**
* @see at.iaik.suraq.smtlib.SMTLibObject#getUninterpretedFunctionNames(java.util.Set,
* java.util.Set)
*/
@Override
public void getUninterpretedFunctionNames(Set<String> result,
Set<SMTLibObject> done) {
throw new NotImplementedException();
}
/**
* @see at.iaik.suraq.smtlib.SMTLibObject#getFunctionMacroNames(java.util.Set,
* java.util.Set)
*/
@Override
public void getFunctionMacroNames(Set<String> result, Set<SMTLibObject> done) {
result.add(this.name.toString());
}
/**
* @see at.iaik.suraq.smtlib.SMTLibObject#getFunctionMacros(java.util.Set,
* java.util.Set)
*/
@Override
public void getFunctionMacros(Set<FunctionMacro> result,
Set<SMTLibObject> done) {
result.add(this);
}
}