packages feed

liquidhaskell-0.8.10.7: benchmarks/cse230/src/Week10/Expressions.hs

{-@ LIQUID "--reflection" @-}
{-@ LIQUID "--ple"        @-}
{-@ LIQUID "--diff"       @-}

{-# LANGUAGE PartialTypeSignatures #-}

module Expressions where

import qualified State as S 
import ProofCombinators 

--------------------------------------------------------------------------------
-- | Arithmetic Expressions 
--------------------------------------------------------------------------------
type Vname = String

data AExp  
  = N Val 
  | V Vname 
  | Plus  AExp AExp 
  | Minus AExp AExp 
  | Times AExp AExp 
  deriving (Show)

type Val   = Int 
type State = S.GState Vname Val 

{-@ reflect aval @-}
aval                :: AExp -> State -> Val 
aval (N n) _         = n 
aval (V x) s         = S.get s x 
aval (Plus  e1 e2) s = aval e1 s + aval e2 s
aval (Minus e1 e2) s = aval e1 s - aval e2 s
aval (Times e1 e2) s = aval e1 s * aval e2 s

{-@ reflect asgn @-}
asgn :: Vname -> AExp -> State -> State
asgn x a s = S.set s x (aval a s)

{-@ reflect subst @-}
subst :: Vname -> AExp -> AExp -> AExp
subst x e (Plus  a1 a2)  = Plus  (subst x e a1) (subst x e a2)
subst x e (Minus a1 a2)  = Minus (subst x e a1) (subst x e a2)
subst x e (Times a1 a2)  = Times (subst x e a1) (subst x e a2)
subst x e (V y) | x == y = e
subst _ _ a              = a

{-@ lem_subst :: x:_ -> a:_ -> e:_ -> s:_ -> 
      { aval (subst x a e) s = aval e (asgn x a s) } 
  @-}
lem_subst :: Vname -> AExp -> AExp -> State -> Proof
lem_subst x a (V y) s
  | x == y                    = ()
  | otherwise                 = S.lemma_get_not_set y x (aval a s) s
lem_subst x a (N i) s         = ()
lem_subst x a (Plus  e1 e2) s = lem_subst x a e1 s &&& lem_subst x a e2 s
lem_subst x a (Minus e1 e2) s = lem_subst x a e1 s &&& lem_subst x a e2 s
lem_subst x a (Times e1 e2) s = lem_subst x a e1 s &&& lem_subst x a e2 s



--------------------------------------------------------------------------------
-- | Boolean Expressions 
--------------------------------------------------------------------------------

data BExp 
  = Bc    Bool       -- true, false 
  | Not   BExp       -- not b 
  | And   BExp BExp  -- b1 && b2
  | Leq   AExp AExp  -- a1 <= a2 
  | Equal AExp AExp  -- a1 == a2 
  deriving (Show)

{-@ reflect .&&. @-}
(.&&.) :: BExp -> BExp -> BExp 
b1 .&&. b2 = And b1 b2 

{-@ reflect .=>. @-}
(.=>.) :: BExp -> BExp -> BExp 
b1 .=>. b2 = bImp b1 b2 

{-@ reflect bAnd @-}
bAnd :: BExp -> BExp -> BExp 
bAnd b1 b2 = And b1 b2 

{-@ reflect bIte @-}
bIte :: BExp -> BExp -> BExp -> BExp 
bIte p b1 b2 = And (bImp p b1) (bImp (Not p) b2)

{-@ reflect .==. @-}
(.==.) :: AExp -> AExp -> BExp 
b1 .==. b2 = Equal b1 b2 

{-@ reflect .<=. @-}
(.<=.) :: AExp -> AExp -> BExp 
b1 .<=. b2 = Leq b1 b2 

{-@ reflect bOr @-}
bOr :: BExp -> BExp -> BExp 
bOr b1 b2 = Not ((Not b1) `And` (Not b2))
       
{-@ reflect bImp @-}
bImp :: BExp -> BExp -> BExp 
bImp b1 b2 = bOr (Not b1) b2

{-@ reflect bLess @-}
bLess :: AExp -> AExp -> BExp 
bLess a1 a2 = And (Leq a1 a2) (Not (Equal a1 a2))

{-@ reflect tt @-}
tt :: BExp 
tt = Bc True 

{-@ reflect ff @-}
ff :: BExp 
ff = Bc False 

{-@ reflect bval @-}
bval :: BExp -> State -> Bool
bval (Bc   b)      _ = b 
bval (Not  b)      s = not (bval b s) 
bval (And  b1 b2)  s = bval b1 s && bval b2 s 
bval (Leq  a1 a2)  s = aval a1 s <= aval a2 s 
bval (Equal a1 a2) s = aval a1 s == aval a2 s 


{-@ reflect bsubst @-}
bsubst :: Vname -> AExp -> BExp -> BExp
bsubst x a (Bc    b)     = Bc    b
bsubst x a (Not   b)     = Not   (bsubst x a b)
bsubst x a (And   b1 b2) = And   (bsubst x a b1) (bsubst x a b2)
bsubst x a (Leq   a1 a2) = Leq   (subst  x a a1) (subst  x a a2)
bsubst x a (Equal a1 a2) = Equal (subst  x a a1) (subst  x a a2)

{-@ lem_bsubst :: x:_ -> a:_ -> b:_ -> s:_ -> 
      { bval (bsubst x a b) s = bval b (asgn x a s) } 
  @-}
lem_bsubst :: Vname -> AExp -> BExp -> State -> Proof 
lem_bsubst x a (Bc _) _        = () 
lem_bsubst x a (Not b)       s = lem_bsubst x a b  s 
lem_bsubst x a (And b1 b2)   s = lem_bsubst x a b1 s &&& lem_bsubst x a b2 s 
lem_bsubst x a (Leq a1 a2)   s = lem_subst  x a a1 s &&& lem_subst  x a a2 s 
lem_bsubst x a (Equal a1 a2) s = lem_subst  x a a1 s &&& lem_subst  x a a2 s