/** * translate boogie statement to prover expression * * @param s * @return */ protected ProverExpr statement2ProverExpr(Statement s) { if (s instanceof AssignStatement) { AssignStatement st = (AssignStatement) s; if (st.getLeft() instanceof SimpleHeapAccess || st.getLeft() instanceof ArrayReadExpression) { return arrayWrite2ProverExpr(st.getLeft(), expression2ProverExpr(st.getRight())); } else { return theoremProver.mkEq( expression2ProverExpr(st.getLeft()), expression2ProverExpr(st.getRight())); } } else if (s instanceof AssumeStatement) { AssumeStatement st = (AssumeStatement) s; return guardExpression2ProverExpr(st.getExpression()); } else if (s instanceof AssertStatement) { AssertStatement st = (AssertStatement) s; return guardExpression2ProverExpr(st.getExpression()); } else if (s instanceof InvokeStatement) { InvokeStatement st = (InvokeStatement) s; if (st.getReturnTargets().size() > 1) { Log.error("A method with too many return parameters! Should have been removed in SSA"); return null; } ProverFun fun = procedure2ProverExpr(st.getInvokedProcedure()); Log.error( "This should not happen as calls are removed by SSA: " + fun.toString()); // TODO: proper error handling? // This can never happen. LinkedList<ProverExpr> args = new LinkedList<ProverExpr>(); for (Expression e : st.getArguments()) { args.add(expression2ProverExpr(e)); } ProverExpr ret = fun.mkExpr((ProverExpr[]) args.toArray(new ProverExpr[args.size()])); if (st.getReturnTargets().size() > 0) { ProverExpr lhs = expression2ProverExpr(st.getReturnTargets().get(0)); if (st.getReturnTargets().get(0) instanceof SimpleHeapAccess || st.getReturnTargets().get(0) instanceof ArrayReadExpression) { ret = arrayWrite2ProverExpr(st.getReturnTargets().get(0), ret); // ((NAryExpression)lhs).addArgument(ret); // ret = VCExpressionGenerator.binOp(TmpConstants.Eq, // ((NAryExpression)lhs).getArgument(0),lhs); } else { ret = theoremProver.mkEq(lhs, ret); } } return ret; } else if (s instanceof ExpressionStatement) { ExpressionStatement es = (ExpressionStatement) s; return expression2ProverExpr(es.getExpression()); } else { Log.error("Unmatched Statement " + s.toString()); return null; } }
/** * generates a prover expression from an expression e * * @param e * @param boundvars * @return */ private ProverExpr expression2ProverExpr(Expression e, HashMap<Variable, ProverExpr> boundvars) { try { if (e instanceof ArrayReadExpression) { ArrayReadExpression exp = (ArrayReadExpression) e; return arrayExpression2ProverExpr( exp.getBaseExpression(), new LinkedList<Expression>(Arrays.asList(new Expression[] {exp.getIndexExpression()})), null, boundvars); } else if (e instanceof InvokeExpression) { InvokeExpression exp = (InvokeExpression) e; ProverFun fun = procedure2ProverExpr(exp.getInvokedProcedure()); LinkedList<ProverExpr> args = new LinkedList<ProverExpr>(); for (Expression e2 : exp.getArguments()) { args.add(expression2ProverExpr(e2, boundvars)); } return fun.mkExpr((ProverExpr[]) args.toArray(new ProverExpr[args.size()])); } else if (e instanceof SimpleHeapAccess) { SimpleHeapAccess exp = (SimpleHeapAccess) e; return arrayExpression2ProverExpr( exp.getHeapVariable(), new LinkedList<Expression>( Arrays.asList( new Expression[] {exp.getBaseExpression(), exp.getFieldExpression()})), null, boundvars); } else if (e instanceof TypeExpression) { TypeExpression exp = (TypeExpression) e; return expression2ProverExpr(exp.getTypeVariable(), boundvars); } else if (e instanceof Variable) { Variable exp = (Variable) e; if (boundvars.containsKey(exp)) { return boundvars.get(exp); } if (!usedVariable.containsKey(exp)) { ProverExpr pe = theoremProver.mkVariable( getProverFriendlyName(exp.getName()), type2ProverSort(exp.getType())); usedVariable.put(exp, pe); } return usedVariable.get(exp); } else if (e instanceof UboundedIntConstant) { UboundedIntConstant exp = (UboundedIntConstant) e; return theoremProver.mkLiteral(BigInteger.valueOf(exp.getValue())); } else if (e instanceof Constant) { Log.error("DEBUG-ERROR, there should not be any constant but Integers! VC will be wrong!"); return expression2ProverExpr(BoogieProgram.v().getNullReference(), boundvars); } else if (e instanceof QuantifiedExpression) { // TODO: right now, Quantifiers can only be used in Axioms QuantifiedExpression qe = (QuantifiedExpression) e; HashMap<Variable, ProverExpr> bvars = new HashMap<Variable, ProverExpr>(boundvars); // LinkedList<ProverExpr> localBound = new // LinkedList<ProverExpr>(); int idx = 0; for (Variable v : qe.getBoundVariables()) { ProverExpr boundvar = theoremProver.mkBoundVariable(idx++, type2ProverSort(v.getType())); bvars.put(v, boundvar); // localBound.add(boundvar); } ProverExpr boundExp = expression2ProverExpr(qe.getExpression(), bvars); if (qe.getQuantifier() == Quantifier.ForAll) { return theoremProver.mkAll(boundExp, theoremProver.getBooleanType()); } else { return theoremProver.mkEx(boundExp, theoremProver.getBooleanType()); } } else if (e instanceof BinOpExpression) { BinOpExpression be = (BinOpExpression) e; ProverExpr left = (expression2ProverExpr(be.getLhs(), boundvars)); ProverExpr right = (expression2ProverExpr(be.getRhs(), boundvars)); switch (be.getOp()) { case Eq: { return theoremProver.mkEq(left, right); } case Lt: { return theoremProver.mkLt(left, right); } case Le: { return theoremProver.mkLeq(left, right); } case Gt: { return theoremProver.mkGt(left, right); } case Ge: { return theoremProver.mkGeq(left, right); } case Neq: { return theoremProver.mkNot(theoremProver.mkEq(left, right)); } case Implies: { return theoremProver.mkOr(theoremProver.mkNot(left), right); } case LAnd: { return theoremProver.mkAnd(left, right); } case LOr: { return theoremProver.mkOr(left, right); } case Plus: { return theoremProver.mkPlus(left, right); } case Minus: { return theoremProver.mkMinus(left, right); } case Mul: { return theoremProver.mkMult(left, right); } default: { throw new RuntimeException("Unmatched binop: " + be.getOp().toString()); // TODO: a proper exception might be nice. // However, this case can only occur if we screw up the // implementation } } } else if (e instanceof IteExpression) { IteExpression ite = (IteExpression) e; ProverExpr condE = expression2ProverExpr(ite.getCond(), boundvars); ProverExpr thenE = expression2ProverExpr(ite.getThen(), boundvars); ProverExpr elseE = expression2ProverExpr(ite.getElse(), boundvars); return theoremProver.mkIte(condE, thenE, elseE); } else { Log.error("Unmatched Expression " + e.toString()); return null; } } catch (Exception exc) { Log.error("expression2ProverExpr failed: " + exc.toString()); Log.error("Called on expression: " + e.toString()); if (e instanceof BinOpExpression) { BinOpExpression boe = (BinOpExpression) e; Log.error(boe.getLhs().getType().toString() + " and " + boe.getRhs().getType()); } return null; } }