/** * @param arrexp * @param rhs * @return */ private ProverExpr arrayWrite2ProverExpr(Expression arrexp, ProverExpr rhs) { if (arrexp instanceof SimpleHeapAccess || arrexp instanceof ArrayReadExpression) { /* * 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 */ Expression base; LinkedList<Expression> args = new LinkedList<Expression>(); if (arrexp instanceof SimpleHeapAccess) { SimpleHeapAccess exp = (SimpleHeapAccess) arrexp; base = exp.getHeapVariable(); args.add(exp.getBaseExpression()); args.add(exp.getFieldExpression()); } else { ArrayReadExpression exp = (ArrayReadExpression) arrexp; base = exp.getBaseExpression(); args.add(exp.getIndexExpression()); } ProverExpr newbase = expression2ProverExpr(base); ProverExpr lhs = arrayExpression2ProverExpr(base, args, rhs, new HashMap<Variable, ProverExpr>()); return theoremProver.mkEq(newbase, lhs); } Log.error("CRAAAAAAAAAASH"); 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; } }