From c54ffb12b95887cb42750e9316b9814e40948b6b Mon Sep 17 00:00:00 2001
From: koen <koenwermer@gmail.com>
Date: Sat, 17 Dec 2016 18:29:58 +0100
Subject: [PATCH] binary operators being applied on expressions with
 side-effects are now being handled correctly

---
 Settings.hs             |  4 ++--
 Tests/side-effects.java |  8 ++++----
 WLP.hs                  | 14 ++++++++------
 3 files changed, 14 insertions(+), 12 deletions(-)

diff --git a/Settings.hs b/Settings.hs
index 4c43c93..2b7ac5a 100644
--- a/Settings.hs
+++ b/Settings.hs
@@ -2,7 +2,7 @@ module Settings where
 
 testFile, postCond :: String
 testFile = "side-effects"
-postCond = "(x == 6)"
+postCond = "(x == 2)"
 
 nrOfUnroll :: Int
-nrOfUnroll = 4
\ No newline at end of file
+nrOfUnroll = 2
\ No newline at end of file
diff --git a/Tests/side-effects.java b/Tests/side-effects.java
index 683e22d..d26692b 100644
--- a/Tests/side-effects.java
+++ b/Tests/side-effects.java
@@ -6,12 +6,12 @@ public static class Main
         x = 0;
         y = 0;
         int i = 0;
-        
-        while(i < f())
+        if((i++) + (i++) < 1)
         {
-            x += y;
-            i++;
+            x++;
         }
+        x++; 
+        x++;
     }
     
     
diff --git a/WLP.hs b/WLP.hs
index 433a759..f187e86 100644
--- a/WLP.hs
+++ b/WLP.hs
@@ -39,14 +39,16 @@ wlpStmtAlgebra = (fStmtBlock, fIfThen, fIfThenElse, fWhile, fBasicFor, fEnhanced
     fStmtBlock (Block bs) inh       = fst $ foldr (\b ((r, env'), varNr') -> (wlpBlock (inh {acc = r, env = env', varNr = varNr'}) b, varNr' + 1)) ((acc inh, envBlock bs (env inh)), varNr 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
     fIfThenElse e s1 s2 inh         = let e' = getExp (foldExp wlpExpAlgebra e) inh 
-                                      in (getTrans (foldExp wlpExpAlgebra e) inh  . (\q -> (e' &* fst (s1 inh) q) |* (neg e' &* fst (s2 inh) q)) . acc inh, env inh)
+                                          eTrans = getTrans (foldExp wlpExpAlgebra e) inh {acc = id} -- The guard might also have side effects
+                                      in ((\q -> (e' &* eTrans (fst (s1 inh {acc = id}) q)) |* (neg e' &* eTrans (fst (s2 inh {acc = id}) q))) . acc inh, env inh)
     fWhile e s inh                  = let e' = getExp (foldExp wlpExpAlgebra e) inh 
-                                      in ((\q -> unrollLoop nrOfUnroll e' (getTrans (foldExp wlpExpAlgebra e) inh) (fst (s (inh {br = const q}))) q) . acc inh, env inh)
+                                      in ((\q -> unrollLoop nrOfUnroll e' (getTrans (foldExp wlpExpAlgebra e) inh {acc = id}) (fst (s (inh {acc = id, br = const q}))) q) . acc inh, env inh)
     fBasicFor init me incr s inh    = let loop = fst (fWhile (fromMaybeGuard me) (\inh' -> s (inh {acc = fst (wlp' inh' (incrToStmt incr))})) inh) in wlp' (inh {acc = loop}) (initToStmt init)
     fEnhancedFor                    = error "EnhancedFor"
     fEmpty inh                      = (acc inh, env inh) -- Empty does nothing, but still passes control to the next statement
     fExpStmt e inh                  = snd $ foldExp wlpExpAlgebra e inh
-    fAssert e _ inh                 = ((e &*) . getTrans (foldExp wlpExpAlgebra e) inh, env inh)
+    fAssert e _ inh                 = let e' = getExp (foldExp wlpExpAlgebra e) inh 
+                                      in ((e' &*) . getTrans (foldExp wlpExpAlgebra e) inh, env inh)
     fSwitch e bs inh                = let (e', s1, s2) = desugarSwitch e bs in fIfThenElse e' (flip wlp' s1) (flip wlp' s2) (inh {acc = id, br = acc inh})
     fDo s e inh                     = (fst (s (inh {acc = fst (fWhile e s inh)})), env inh) -- Do is just a while with the statement block executed one additional time. Break and continue still have to be handled in this additional execution.
     fBreak _ inh                    = (br inh, env inh) -- wlp of the breakpoint. Control is passed to the statement after the loop
@@ -89,8 +91,8 @@ wlpStmtAlgebra = (fStmtBlock, fIfThen, fIfThenElse, fWhile, fBasicFor, fEnhanced
               
     -- Unrolls a while-loop a finite amount of times
     unrollLoop :: Int -> Exp -> (Exp -> Exp) -> (Exp -> Exp) -> Exp -> Exp
-    unrollLoop 0 g gTrans _ q           = gTrans (neg g `imp` q)
-    unrollLoop n g gTrans bodyTrans q   = gTrans (neg g `imp` q) &* gTrans (g `imp` bodyTrans (unrollLoop (n - 1) g gTrans bodyTrans q))
+    unrollLoop 0 g gTrans _ q           = (neg g `imp` gTrans q)
+    unrollLoop n g gTrans bodyTrans q   = (neg g `imp` gTrans q) &* (g `imp` gTrans (bodyTrans (unrollLoop (n - 1) g gTrans bodyTrans q)))
     
     
     -- Converts initialization code of a for loop to a statement
@@ -184,7 +186,7 @@ wlpExpAlgebra = (fLit, fClassLit, fThis, fThisClass, fInstanceCreation, fQualIns
     fPreBitCompl e inh                                  = (PreBitCompl $ getExp e inh, (getTrans e inh, env inh))
     fPreNot e inh                                       = (PreNot $ getExp e inh, (getTrans e inh, env inh))
     fCast t e inh                                       = (getExp e inh, (getTrans e inh, env inh))
-    fBinOp e1 op e2 inh                                 = (BinOp (getExp e1 inh) op (getExp e2 inh), (getTrans e1 (inh {acc = getTrans e2 inh}), env inh)) 
+    fBinOp e1 op e2 inh                                 = (BinOp (getExp e1 inh) op (getTrans e1 (inh {acc = id}) (getExp e2 inh)), (getTrans e1 (inh {acc = getTrans e2 inh}), env inh)) -- Side effects of the first expression are applied before the second is evaluated, so we have to apply the transformer
     fInstanceOf                                         = error "instanceOf"
     fCond g e1 e2 inh                                   = (Cond (getExp g inh) (getExp e1 inh) (getExp e2 inh), (getTrans g (inh {acc = id}) . (\q -> (getExp g inh &* getTrans e1 (inh {acc = id}) q) |* (neg (getExp g inh) &* getTrans e2 (inh {acc = id}) q)) . acc inh, env inh))
     fAssign lhs op e inh                                = let lhs' = foldLhs inh lhs
-- 
GitLab