/** * Author: Georg Hofferek <georg.hofferek@iaik.tugraz.at> */ package at.iaik.suraq.smtlib.formula; import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import at.iaik.suraq.exceptions.InvalidParametersException; import at.iaik.suraq.sexp.SExpression; import at.iaik.suraq.sexp.SExpressionConstants; import at.iaik.suraq.sexp.Token; import at.iaik.suraq.smtlib.SMTLibObject; import at.iaik.suraq.util.IdGenerator; import at.iaik.suraq.util.ImmutableArrayList; import at.iaik.suraq.util.ImmutableHashMap; /** * @author Georg Hofferek <georg.hofferek@iaik.tugraz.at> * */ public abstract class FunctionMacro implements Serializable, SMTLibObject { /** * */ private static final long serialVersionUID = 1L; /** * The name of this macro. */ protected final Token name; protected final List<Token> parameters; private final long id = IdGenerator.getId(); /** * The map of parameters to their types. */ protected final ImmutableHashMap<Token, SExpression> paramMap; /** * Constructs a new <code>FunctionMacro</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. * @throws InvalidParametersException * if the size of the parameter list and the type map do not * match. */ protected FunctionMacro(Token name, List<Token> parameters, Map<Token, SExpression> paramMap) throws InvalidParametersException { if (parameters.size() != paramMap.size()) throw new InvalidParametersException(); for (Token parameter : parameters) { if (!paramMap.containsKey(parameter)) throw new InvalidParametersException(); if (paramMap.get(parameter) == null) throw new InvalidParametersException(); } this.name = name; this.parameters = new ImmutableArrayList<Token>(parameters); this.paramMap = new ImmutableHashMap<Token, SExpression>(paramMap); } @Override public final long getId() { return id; } /** * @see java.lang.Comparable#compareTo(java.lang.Object) */ @Override public final int compareTo(SMTLibObject o) { long otherId = o.getId(); if (this.id < otherId) return -1; if (this.id == otherId) return 0; if (this.id > otherId) return 1; throw new RuntimeException("Something is TERRIBLY wrong!!"); } /** * @return the <code>name</code> */ public Token getName() { return name; } /** * Returns a copy of the list of parameters. * * @return the <code>parameters</code> (copy) */ public List<Token> getParameters() { return new ArrayList<Token>(parameters); } /** * Returns a copy of the map from parameters to values. * * @return the <code>paramMap</code> */ public Map<Token, SExpression> getParamMap() { return new HashMap<Token, SExpression>(paramMap); } /** * Returns the number of parameters of this macro. * * @return the number of parameters. */ public int getNumParams() { assert (parameters.size() == paramMap.size()); return parameters.size(); } /** * Returns the type of the parameter with index <code>count</code>, or * <code>null</code> if the index is out of bounds. * * @param index * the index of the parameter to look up. * @return the type of the parameter with the given index, or * <code>null</code> if no such parameter exists. */ public SExpression getParamType(int index) { try { return paramMap.get(parameters.get(index)); } catch (IndexOutOfBoundsException exc) { return null; } } /** * Returns the type of the parameter with the given name, or * <code>null</code> if no such parameter exists.. * * @param param * the name of the parameter to look up. * @return the type of the parameter with the given name, or * <code>null</code> if no such parameter exists. */ public SExpression getParamType(Token param) { return paramMap.get(param); } /** * Returns the parameter name with the given index. * * @param index * the index to look up * @return the parameter name with the given index. */ public Token getParam(int index) { return parameters.get(index); } /** * Removes array equalities from the body of the macro. */ public abstract FunctionMacro removeArrayEqualities(); /** * Converts array properties in the body of the macro to finite conjunctions * * @param indexSet * the index set. */ public abstract FunctionMacro arrayPropertiesToFiniteConjunctions( Set<DomainTerm> indexSet); /** * Returns an <code>SExpression</code> representing the body of the macro. * * @return an <code>SExpression</code> representing the body of the macro. */ public abstract SExpression getBodyExpression(); /** * Returns the type of this macro. * * @return the type of this macro. */ public abstract SExpression getType(); /** * Creates a define-fun expression for this macro. * * @return a define-fun expression for this macro. */ @Override public SExpression toSmtlibV2() { ArrayList<SExpression> tmp = new ArrayList<SExpression>(); tmp.add(SExpressionConstants.DEFINE_FUN); tmp.add(name); ArrayList<SExpression> allParametersExpression = new ArrayList<SExpression>(); for (Token currentParam : parameters) { ArrayList<SExpression> tmp2 = new ArrayList<SExpression>(); tmp2.add(currentParam); tmp2.add(paramMap.get(currentParam)); allParametersExpression.add(new SExpression(tmp2)); } tmp.add(new SExpression(allParametersExpression)); tmp.add(getType()); tmp.add(getBodyExpression()); return new SExpression(tmp); } /** * Returns the elements assert-partition. * * @return assert-partition of the element. */ public abstract Set<Integer> getAssertPartition(); }