private String z3_printSMT2Declarations() { StringBuilder sb = new StringBuilder(); sb.append("(set-logic AUFLIA)\n\n"); for (String s : z3_helperVars) { sb.append("(declare-fun "); sb.append(getProverFriendlyName(s)); sb.append(" () Bool"); sb.append(")\n"); } for (Entry<Variable, ProverExpr> entry : usedVariable.entrySet()) { sb.append("(declare-fun "); sb.append(getProverFriendlyName(entry.getKey().getName())); sb.append(" () "); sb.append(z3_type2SMT2(entry.getKey().getType())); sb.append(")\n"); } for (Entry<BoogieProcedure, ProverFun> entry : usedFunctions.entrySet()) { // distinguish between prelude functions that have exactly one // statement and are pure // and all the rest. if (proc.isPure() && proc.getRootBlock() != null && proc.getRootBlock().getStatements().size() == 1) { // TODO: for some reason this does not happen, // as princess already inlines those functions and they // are not added to the list of used functions. throw new RuntimeException("SMT2 Printer, unexpected prelude function"); } else { sb.append("(declare-fun "); sb.append(getProverFriendlyName(entry.getKey().getName())); sb.append("( "); // now the params for (Variable param : entry.getKey().getParameterList()) { sb.append("("); sb.append(z3_type2SMT2(param.getType())); sb.append(") "); } sb.append(") "); // done with params // not the regular return value: if (entry.getKey().getReturnVariable() != null) { sb.append(z3_type2SMT2(entry.getKey().getReturnVariable().getType())); sb.append(" "); } // TODO: at this point, the SSA should have removed all // calls to non-pure functions already, so no need to // worry about exception handling sb.append(")\n"); } } return sb.toString(); }
// TODO fix BoogieHelperFunctions s.t. we can remove qual_name and // returntype because they are already in proc public InvokeExpression(BoogieProcedure proc, LinkedList<Expression> args) { invokedProcedure = proc; qualifiedName = proc.getName(); if (proc.getReturnVariable() != null) { returnType = proc.getReturnVariable().getType(); } else { returnType = BoogieBaseTypes.getVoidType(); } arguments = args; }
/** * @param base * @param indices * @param rhs is null if we have Select operation, otherwise it is the value E on the right hand * side of an assignment a[x]=E. * @param boundvars * @return This is needed here only for one purpose: a[x] = 5 in Boogie is translated to * a__i[x__j] = 5 in SSA-Boogie but in the VC we have to write (= a__i (store a__(i-1) x__j * 5), so we need to be able to access the previous incarnation of array typed variables * Probably, we should settle this already during SSA and introduce uninterpreted procedures * for store and select. */ private ProverExpr arrayExpression2ProverExpr( Expression base, LinkedList<Expression> indices, ProverExpr rhs, HashMap<Variable, ProverExpr> boundvars) { LinkedList<ProverExpr> args = new LinkedList<ProverExpr>(); if (rhs != null) { if (base instanceof SSAVariable) { SSAVariable var = (SSAVariable) base; SSAVariable tmp = null; for (Variable v : proc.getVarIncarnationMap().get(((SSAVariable) base).getOriginalVar())) { if (v instanceof SSAVariable) { if (((SSAVariable) v).getIncarnation() == ((SSAVariable) base).getIncarnation() - 1) { tmp = (SSAVariable) v; break; } } } if (tmp == null) { tmp = new SSAVariable(var.getOriginalVar(), var.getIncarnation() - 1); proc.getVarIncarnationMap().get(((SSAVariable) base).getOriginalVar()).addFirst(tmp); } base = tmp; } else { Log.error( "org.joogie.vcgen.VCGeneration.arrayaccess2VCExpression: this case has not been considered ... Joogie will crash!"); } } ProverExpr arr = expression2ProverExpr(base, boundvars); for (Expression idx : indices) { args.add(expression2ProverExpr(idx, boundvars)); } if (rhs != null) return theoremProver.mkStore( arr, (ProverExpr[]) (args.toArray(new ProverExpr[args.size()])), rhs); else return theoremProver.mkSelect( arr, (ProverExpr[]) (args.toArray(new ProverExpr[args.size()]))); }
private ProverFun procedure2ProverExpr(BoogieProcedure proc) { HashMap<Variable, ProverExpr> localbound = new HashMap<Variable, ProverExpr>(); if (!usedFunctions.containsKey(proc)) { LinkedList<ProverType> args = new LinkedList<ProverType>(); int idx = 0; for (Variable v : proc.getParameterList()) { ProverExpr arg = theoremProver.mkBoundVariable(idx++, type2ProverSort(v.getType())); args.add(arg.getType()); localbound.put(v, arg); } ProverFun vcf = null; ProverType[] arr = args.toArray(new ProverType[args.size()]); if (proc.isPure() && proc.getRootBlock() != null && proc.getRootBlock().getStatements().size() == 1) { // TODO: this is a hack: // we assume that this case only occurs for prelude functions // which have only one statement // this will not work in any other case Statement stmt = proc.getRootBlock().getStatements().get(0); ProverExpr b = null; if (stmt instanceof ExpressionStatement) { ExpressionStatement es = (ExpressionStatement) stmt; b = expression2ProverExpr(es.getExpression(), localbound); } else { throw new RuntimeException("procedure2ProverExpr failed"); } vcf = theoremProver.mkDefinedFunction(getProverFriendlyName(proc.getName()), arr, b); } else { vcf = theoremProver.mkUnintFunction( getProverFriendlyName(proc.getName()), arr, type2ProverSort(proc.getReturnVariable().getType())); // TODO: uninterpreted functions? } usedFunctions.put(proc, vcf); } return usedFunctions.get(proc); }