module Copilot.Core.Analysis
( exprIsConstant )
where
import qualified Copilot.Core as Core
import Copilot.Theorem.What4 (SatResult (..), Solver (Z3), prove)
import Data.List (lookup)
exprIsConstant :: Core.Spec
-> Core.Name
-> Core.Expr Bool
-> IO (Bool, Bool)
exprIsConstant :: Spec -> Name -> Expr Bool -> IO (Bool, Bool)
exprIsConstant Spec
spec Name
name Expr Bool
expr = do
r1 <- Spec -> Name -> Prop -> IO Bool
propIsValid Spec
spec Name
name (Expr Bool -> Prop
Core.Forall Expr Bool
expr)
r2 <- propIsValid spec name (Core.Forall (Core.Op1 Core.Not expr))
pure (r1, r2)
propIsValid :: Core.Spec
-> Core.Name
-> Core.Prop
-> IO Bool
propIsValid :: Spec -> Name -> Prop -> IO Bool
propIsValid Spec
spec Name
name Prop
expr =
Bool -> (SatResult -> Bool) -> Maybe SatResult -> Bool
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
False SatResult -> Bool
isValid (Maybe SatResult -> Bool)
-> ([(Name, SatResult)] -> Maybe SatResult)
-> [(Name, SatResult)]
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Name -> [(Name, SatResult)] -> Maybe SatResult
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup Name
name ([(Name, SatResult)] -> Bool) -> IO [(Name, SatResult)] -> IO Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Solver -> Spec -> IO [(Name, SatResult)]
prove Solver
Z3 Spec
spec'
where
spec' :: Spec
spec' = Spec
spec { Core.specProperties = prop' : Core.specProperties spec }
prop' :: Property
prop' = Name -> Prop -> Property
Core.Property Name
name Prop
expr
isValid :: SatResult -> Bool
isValid :: SatResult -> Bool
isValid SatResult
Valid = Bool
True
isValid SatResult
_ = Bool
False