package jayhorn.solver.princess;
import ap.parser.IAtom;
import ap.parser.ITerm;
import ap.terfor.preds.Predicate;
import jayhorn.solver.ProverExpr;
import jayhorn.solver.ProverFun;
import jayhorn.solver.ProverTupleExpr;
import jayhorn.solver.ProverType;
import scala.collection.mutable.ArrayBuffer;
class PredicateFun implements ProverFun {
private final Predicate pred;
private final ProverType[] argTypes;
PredicateFun(Predicate pred, ProverType[] argTypes) {
this.pred = pred;
this.argTypes = argTypes;
}
public ProverExpr mkExpr(ProverExpr[] args) {
try {
checkArgTypes(argTypes, args);
} catch(RuntimeException e) {
System.err.println("Warning: " + e);
e.printStackTrace();
}
ProverExpr[] flatArgs = ProverTupleExpr.flatten(args);
final ArrayBuffer<ITerm> argsBuf = new ArrayBuffer<ITerm>();
for (int i = 0; i < flatArgs.length; ++i) {
argsBuf.$plus$eq(((PrincessProverExpr)flatArgs[i]).toTerm());
}
return new FormulaExpr(new IAtom(pred, argsBuf.toSeq()));
}
protected static void checkArgTypes(ProverType[] argTypes,
ProverExpr[] args) {
if (argTypes == null)
return;
if (argTypes.length != args.length)
throw new RuntimeException("Wrong number of arguments: expected " +
argTypes.length + " but got " +
args.length);
for (int i = 0; i < argTypes.length; ++i)
if (!argTypes[i].equals(args[i].getType()))
throw new RuntimeException("Wrong argument type: expected " +
argTypes[i] + " but got " +
args[i] + " of type " +
args[i].getType());
}
public String toString() {
return pred.toString();
}
public String toSMTLIBDeclaration() {
StringBuffer res = new StringBuffer();
res.append("(declare-fun " + pred.name() + "(");
String sep = "";
for (int i = 0; i < pred.arity(); ++i) {
res.append(sep);
res.append("Int");
sep = " ";
}
res.append(") Bool)");
return res.toString();
}
public int hashCode() {
return pred.hashCode() + 13;
}
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
PredicateFun other = (PredicateFun) obj;
if (pred == null) {
if (other.pred != null)
return false;
} else if (!pred.equals(other.pred))
return false;
return true;
}
}