From b84323ed942e63f49d5227bb5f418a9257ae8da2 Mon Sep 17 00:00:00 2001 From: koen <koenwermer@gmail.com> Date: Sat, 28 Jan 2017 20:05:40 +0100 Subject: [PATCH] fixed the interaction between the return statement and loops/ite's --- Settings.hs | 2 +- WLP.hs | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Settings.hs b/Settings.hs index 1a9629b..2fd9358 100644 --- a/Settings.hs +++ b/Settings.hs @@ -6,7 +6,7 @@ testFile = "arrays1" -- The post condition may depend on the type of the method we are looking at postCondVoid = "true" postCondRefType = "returnValue != null" -postCondPrimType = "returnValue == returnValueVar" +postCondPrimType = "returnValueVar == returnValue" -- When ignoreLibMethods is true, library calls will simply be ignored. When false, we consider library methods but make no assumptions about them (so the WLP will be true) -- To prevent insanely long calculation times, we may decide to not calculate the wlp of the main method when ignoring library methods diff --git a/WLP.hs b/WLP.hs index 08ef61d..c856bec 100644 --- a/WLP.hs +++ b/WLP.hs @@ -35,13 +35,13 @@ type Syn = Exp -> Exp -- The wlp transformer wlpStmtAlgebra :: StmtAlgebra (Inh -> Syn) wlpStmtAlgebra = (fStmtBlock, fIfThen, fIfThenElse, fWhile, fBasicFor, fEnhancedFor, fEmpty, fExpStmt, fAssert, fSwitch, fDo, fBreak, fContinue, fReturn, fSynchronized, fThrow, fTry, fLabeled) where fStmtBlock (Block bs) inh = foldr (\b r -> wlpBlock inh {acc = r} b) (acc inh) bs -- The result of the last block-statement will be the accumulated transformer for the second-last etc. The type environment is build from the left, so it has to be done seperately. - fIfThen e s1 = fIfThenElse e s1 (const id) -- if-then is just an if-then-else with an empty else-block + fIfThen e s1 = fIfThenElse e s1 acc -- if-then is just an if-then-else with an empty else-block fIfThenElse e s1 s2 inh = let (e', trans) = foldExp wlpExpAlgebra e inh {acc = id} var = getVar - in trans . substVar' inh var e' . (\q -> (ExpName (Name [var]) &* s1 inh {acc = id} q) |* (neg (ExpName (Name [var])) &* s2 inh {acc = id} q)) . acc inh + in trans . substVar' inh var e' . (\q -> (ExpName (Name [var]) &* s1 inh q) |* (neg (ExpName (Name [var])) &* s2 inh q)) fWhile e s inh = let (e', trans) = foldExp wlpExpAlgebra e inh {acc = id} var = getVar - in (\q -> unrollLoopOpt inh nrOfUnroll e' trans (s (inh {acc = id, br = const q})) q) . acc inh + in (\q -> unrollLoopOpt inh {br = const q} nrOfUnroll e' trans s q) fBasicFor init me incr s inh = let loop = (fWhile (fromMaybeGuard me) (\inh' -> s (inh' {acc = (wlp' inh' {acc = id} (incrToStmt incr))})) inh) in wlp' (inh {acc = loop}) (initToStmt init) fEnhancedFor = error "EnhancedFor" fEmpty inh = (acc inh) -- Empty does nothing, but still passes control to the next statement @@ -82,15 +82,15 @@ wlpStmtAlgebra = (fStmtBlock, fIfThen, fIfThenElse, fWhile, fBasicFor, fEnhanced wlpDeclAssignment _ _ _ = error "ArrayCreateInit is not supported" -- Unrolls a while-loop a finite amount of times - unrollLoop :: Inh -> Int -> Exp -> (Exp -> Exp) -> (Exp -> Exp) -> Exp -> Exp + unrollLoop :: Inh -> Int -> Exp -> (Exp -> Exp) -> (Inh -> Exp -> Exp) -> Exp -> Exp unrollLoop inh 0 g gTrans _ = let var = getVar - in gTrans . substVar' inh var g . (neg (ExpName (Name [var])) `imp`) + in gTrans . substVar' inh var g . (neg (ExpName (Name [var])) `imp`) . acc inh unrollLoop inh n g gTrans bodyTrans = let var = getVar - in gTrans . substVar' inh var g . (\q -> (neg (ExpName (Name [var])) `imp` q) &* ((ExpName (Name [var])) `imp` bodyTrans (unrollLoop inh (n-1) g gTrans bodyTrans q))) + in gTrans . substVar' inh var g . (\q -> (neg (ExpName (Name [var])) `imp` acc inh q) &* ((ExpName (Name [var])) `imp` bodyTrans inh {acc = (unrollLoop inh (n-1) g gTrans bodyTrans)} q)) -- An optimized version of unroll loop to reduce the size of the wlp - unrollLoopOpt :: Inh -> Int -> Exp -> (Exp -> Exp) -> (Exp -> Exp) -> Exp -> Exp - unrollLoopOpt inh n g gTrans bodyTrans q | gTrans (bodyTrans q) == q = q -- q is not affected by the loop + unrollLoopOpt :: Inh -> Int -> Exp -> (Exp -> Exp) -> (Inh -> Exp -> Exp) -> Exp -> Exp + unrollLoopOpt inh n g gTrans bodyTrans q | gTrans (bodyTrans inh q) == acc inh q = acc inh q -- q is not affected by the loop | otherwise = unrollLoop inh n g gTrans bodyTrans q -- default to the standard version of unroll loop -- Converts initialization code of a for loop to a statement -- GitLab