package jayhorn.hornify; import java.util.Collections; import java.util.Comparator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import com.google.common.base.Verify; import jayhorn.solver.Prover; import jayhorn.solver.ProverExpr; import jayhorn.solver.ProverFun; import jayhorn.solver.ProverTupleExpr; import jayhorn.solver.ProverTupleType; import jayhorn.solver.ProverType; import soottocfg.cfg.type.BoolType; import soottocfg.cfg.type.IntType; import soottocfg.cfg.type.ReferenceType; import soottocfg.cfg.type.Type; import soottocfg.cfg.type.TypeType; import soottocfg.cfg.variable.Variable; public class HornHelper { public static final int NullValue = 0; private static HornHelper hh; public static void resetInstance() { hh = null; } public static HornHelper hh() { if (null == hh) { hh = new HornHelper(); } return hh; } private HornHelper() { } /** * Creates a ProverType from a Type. * TODO: not fully implemented. * * @param p * @param t * @return */ public ProverType getProverType(Prover p, Type t) { if (t == IntType.instance()) { return p.getIntType(); } if (t == BoolType.instance()) { return p.getBooleanType(); } if (t instanceof ReferenceType) { ReferenceType rt = (ReferenceType) t; final ProverType[] subTypes = new ProverType[rt.getElementTypeList().size()]; for (int i = 0; i < rt.getElementTypeList().size(); i++) { subTypes[i] = getProverType(p, rt.getElementTypeList().get(i)); } return p.getTupleType(subTypes); } if (t instanceof TypeType) { return p.getIntType(); } throw new IllegalArgumentException("don't know what to do with " + t); } public ProverTupleExpr mkNullExpression(Prover p, ProverType[] types) { ProverExpr[] subExprs = new ProverExpr[types.length]; for (int i = 0; i < types.length; i++) { if (types[i] instanceof jayhorn.solver.BoolType) { subExprs[i] = p.mkLiteral(false); } else if (types[i] instanceof jayhorn.solver.IntType) { subExprs[i] = p.mkLiteral(NullValue); } else if (types[i] instanceof ProverTupleType) { subExprs[i] = mkNullExpression(p, ((ProverTupleType)types[i]).getSubTypes()); } else { throw new RuntimeException("Not implemented " + types[i].getClass()); } } return (ProverTupleExpr) p.mkTuple(subExprs); } public ProverFun genHornPredicate(Prover p, String name, List<Variable> sortedVars) { final List<ProverType> types = new LinkedList<ProverType>(); for (Variable v : sortedVars) { types.add(getProverType(p, v.getType())); } return p.mkHornPredicate(name, types.toArray(new ProverType[types.size()])); } private int varNum = 0; public int newVarNum() { return varNum++; } public List<ProverExpr> findOrCreateProverVar(Prover p, List<Variable> cfgVars, Map<Variable, ProverExpr> varMap) { List<ProverExpr> res = new LinkedList<ProverExpr>(); for (Variable v : cfgVars) { res.add(findOrCreateProverVar(p, v, varMap)); } return res; } public ProverExpr findOrCreateProverVar(Prover p, Variable v, Map<Variable, ProverExpr> varMap) { if (!varMap.containsKey(v)) { varMap.put(v, createVariable(p, v)); } return varMap.get(v); } public ProverExpr createVariable(Prover p, Variable v) { ProverType pt = getProverType(p, v.getType()); if (pt instanceof ProverTupleType) { ProverTupleType ptt = (ProverTupleType) pt; ProverExpr[] subExprs = new ProverExpr[ptt.getArity()]; Verify.verify(v.getType() instanceof ReferenceType); for (int i = 0; i < ptt.getArity(); i++) { subExprs[i] = createVariable(p, new Variable(v.getName() + "#" + i, ((ReferenceType) v.getType()).getElementTypeList().get(i))); } return p.mkTuple(subExprs); } else { return p.mkHornVariable(v.getName() + "_" + newVarNum(), pt); } } public ProverExpr createVariable(Prover p, String prefix, Type tp) { return p.mkHornVariable(prefix + newVarNum(), getProverType(p, tp)); } public List<Variable> setToSortedList(Set<Variable> set) { List<Variable> res = new LinkedList<Variable>(set); if (!res.isEmpty()) { Collections.sort(res, new Comparator<Variable>() { @Override public int compare(final Variable object1, final Variable object2) { return object1.getName().compareTo(object2.getName()); } }); } return res; } public ProverExpr findOrCreateUniqueVariable(Prover p, Variable v, Map<Variable, ProverExpr> varMap, int uniqueNumber) { if (!varMap.containsKey(v)) { varMap.put(v, createVariable(p, v)); } return varMap.get(v); } public ProverExpr createUniqueVariable(Prover p, Variable v, int number) { ProverType pt = getProverType(p, v.getType()); if (pt instanceof ProverTupleType) { ProverTupleType ptt = (ProverTupleType) pt; ProverExpr[] subExprs = new ProverExpr[ptt.getArity()]; Verify.verify(v.getType() instanceof ReferenceType); subExprs[0] = p.mkLiteral(number); for (int i = 1; i < ptt.getArity(); i++) { subExprs[i] = createVariable(p, new Variable(v.getName() + "#" + i, ((ReferenceType) v.getType()).getElementTypeList().get(i))); } return p.mkTuple(subExprs); } else if (pt instanceof jayhorn.solver.IntType) { return p.mkLiteral(number); } else { return p.mkHornVariable(v.getName() + "_" + newVarNum(), pt); } } }