From 9d196e432c2cb49179428490bd20b1d186dd0efe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ali=20Sinan=20K=C3=B6ksal?= <alisinan@gmail.com> Date: Mon, 23 May 2011 20:43:26 +0000 Subject: [PATCH] we now generate VCs for map accesses --- src/funcheck/CodeExtraction.scala | 7 +++-- src/purescala/DefaultTactic.scala | 31 ++++++++++++++++++++++- src/purescala/FairZ3Solver.scala | 5 +--- src/purescala/VerificationCondition.scala | 1 + 4 files changed, 37 insertions(+), 7 deletions(-) diff --git a/src/funcheck/CodeExtraction.scala b/src/funcheck/CodeExtraction.scala index 2b89efb9a..49174d469 100644 --- a/src/funcheck/CodeExtraction.scala +++ b/src/funcheck/CodeExtraction.scala @@ -543,13 +543,16 @@ trait CodeExtraction extends Extractors { case ExMapApply(m,f) => { val rm = rec(m) val rf = rec(f) - MapGet(rm, rf).setType(rm.getType match { + val tpe = rm.getType match { case MapType(_,toType) => toType case _ => { if (!silent) unit.error(tree.pos, "apply on non-map expression") throw ImpureCodeEncounteredException(tree) } - }) + } + val mg = MapGet(rm, rf).setType(tpe) + val ida = MapIsDefinedAt(rm, rf) + IfExpr(ida, mg, Error("key not found for map access").setType(tpe)).setType(tpe) } case ExMapIsDefinedAt(m,k) => { val rm = rec(m) diff --git a/src/purescala/DefaultTactic.scala b/src/purescala/DefaultTactic.scala index 0b4cb1924..e4797d1be 100644 --- a/src/purescala/DefaultTactic.scala +++ b/src/purescala/DefaultTactic.scala @@ -155,8 +155,37 @@ class DefaultTactic(reporter: Reporter) extends Tactic(reporter) { toRet } + def generateMapAccessChecks(function: FunDef) : Seq[VerificationCondition] = { + val toRet = if (function.hasBody) { + val cleanBody = matchToIfThenElse(function.body.get) + + val allPathConds = collectWithPathCondition((t => t match { + case Error("key not found for map access") => true + case _ => false + }), cleanBody) + + def withPrecIfDefined(conds: Seq[Expr]) : Expr = if (function.hasPrecondition) { + Not(And(matchToIfThenElse(function.precondition.get), And(conds))) + } else { + Not(And(conds)) + } + + allPathConds.map(pc => + new VerificationCondition( + withPrecIfDefined(pc._1), + function, + VCKind.MapAccess, + this.asInstanceOf[DefaultTactic]).setPosInfo(pc._2.asInstanceOf[Error]) + ).toSeq + } else { + Seq.empty + } + + toRet + } + def generateMiscCorrectnessConditions(function: FunDef) : Seq[VerificationCondition] = { - Seq.empty + generateMapAccessChecks(function) } // prec: there should be no lets and no pattern-matching in this expression diff --git a/src/purescala/FairZ3Solver.scala b/src/purescala/FairZ3Solver.scala index d40e54ed8..c1a61b698 100644 --- a/src/purescala/FairZ3Solver.scala +++ b/src/purescala/FairZ3Solver.scala @@ -886,11 +886,8 @@ class FairZ3Solver(val reporter: Reporter) extends Solver(reporter) with Abstrac } case mg @ MapGet(m,k) => m.getType match { case MapType(fromType, toType) => - val errorAST = z3.mkFreshConst("errorValue", typeToSort(toType)) - // exprToZ3Id += (e -> errorAST) - // z3IdToExpr += (errorAST -> e) val selected = z3.mkSelect(rec(m), rec(k)) - z3.mkITE(z3.mkDistinct(selected, mapRangeNoneConstructors(toType)()), mapRangeValueSelectors(toType)(selected), errorAST) + mapRangeValueSelectors(toType)(selected) case errorType => scala.Predef.error("Unexpected type for map: " + (ex, errorType)) } case MapUnion(m1,m2) => m1.getType match { diff --git a/src/purescala/VerificationCondition.scala b/src/purescala/VerificationCondition.scala index b62c5f176..7c6710fa2 100644 --- a/src/purescala/VerificationCondition.scala +++ b/src/purescala/VerificationCondition.scala @@ -48,4 +48,5 @@ object VCKind extends Enumeration { val Precondition = Value("precond.") val Postcondition = Value("postcond.") val ExhaustiveMatch = Value("match.") + val MapAccess = Value("map acc.") } -- GitLab