copilot-theorem 2.2.0 → 2.2.1
raw patch · 35 files changed
+306/−316 lines, 35 filesdep ~copilot-coredep ~smtlib2new-uploaderPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependency ranges changed: copilot-core, smtlib2
API changes (from Hackage documentation)
- Copilot.Theorem.Prove: Admit :: Action
- Copilot.Theorem.Prove: Assume :: PropId -> Action
- Copilot.Theorem.Prove: Check :: Prover -> Action
- Copilot.Theorem.Prove: Proof :: Writer [Action] b -> ProofScheme a b
- Copilot.Theorem.Prove: PropRef :: PropId -> PropRef a
+ Copilot.Theorem.Prove: [Admit] :: Action
+ Copilot.Theorem.Prove: [Assume] :: PropId -> Action
+ Copilot.Theorem.Prove: [Check] :: Prover -> Action
+ Copilot.Theorem.Prove: [Proof] :: Writer [Action] b -> ProofScheme a b
+ Copilot.Theorem.Prove: [PropRef] :: PropId -> PropRef a
+ Copilot.Theorem.Prove: combine :: Prover -> Prover -> Prover
Files
- README.md +41/−41
- copilot-theorem.cabal +20/−12
- src/Copilot/Theorem.hs +2/−0
- src/Copilot/Theorem/IL.hs +2/−0
- src/Copilot/Theorem/IL/PrettyPrint.hs +1/−0
- src/Copilot/Theorem/IL/Spec.hs +1/−0
- src/Copilot/Theorem/IL/Transform.hs +1/−0
- src/Copilot/Theorem/IL/Translate.hs +19/−7
- src/Copilot/Theorem/Kind2.hs +2/−0
- src/Copilot/Theorem/Kind2/AST.hs +2/−0
- src/Copilot/Theorem/Kind2/Output.hs +1/−0
- src/Copilot/Theorem/Kind2/PrettyPrint.hs +2/−0
- src/Copilot/Theorem/Kind2/Prover.hs +1/−0
- src/Copilot/Theorem/Kind2/Translate.hs +1/−0
- src/Copilot/Theorem/Misc/Error.hs +2/−0
- src/Copilot/Theorem/Misc/SExpr.hs +1/−1
- src/Copilot/Theorem/Misc/Utils.hs +2/−0
- src/Copilot/Theorem/Prove.hs +10/−8
- src/Copilot/Theorem/Prover/Backend.hs +1/−0
- src/Copilot/Theorem/Prover/SMT.hs +5/−5
- src/Copilot/Theorem/Prover/SMTIO.hs +1/−1
- src/Copilot/Theorem/Prover/SMTLib.hs +1/−0
- src/Copilot/Theorem/Prover/TPTP.hs +1/−0
- src/Copilot/Theorem/Prover/Z3.hs +160/−222
- src/Copilot/Theorem/Tactics.hs +2/−1
- src/Copilot/Theorem/TransSys.hs +2/−0
- src/Copilot/Theorem/TransSys/Cast.hs +1/−0
- src/Copilot/Theorem/TransSys/Invariants.hs +1/−0
- src/Copilot/Theorem/TransSys/Operators.hs +1/−2
- src/Copilot/Theorem/TransSys/PrettyPrint.hs +1/−0
- src/Copilot/Theorem/TransSys/Renaming.hs +7/−12
- src/Copilot/Theorem/TransSys/Spec.hs +2/−1
- src/Copilot/Theorem/TransSys/Transform.hs +1/−0
- src/Copilot/Theorem/TransSys/Translate.hs +7/−3
- src/Copilot/Theorem/TransSys/Type.hs +1/−0
README.md view
@@ -7,7 +7,7 @@ a partial answer to one of its main issue which is scalability. *copilot-theorem* is a Copilot library aimed at checking automatically some safety-properties on Copilot programs. It includes :+properties on Copilot programs. It includes: * A general interface for *provers* and a *proof scheme* mechanism aimed at splitting the task of proving a complex property into checking a sequence of@@ -26,12 +26,12 @@ ### Installation instructions -*copilot-theorem* needs the following dependencies to be installed :+*copilot-theorem* needs the following dependencies to be installed: * The *copilot-core* and *copilot-language* Haskell libraries-* The *Yices2* SMT-solver : `yices-smt2` must be in your `$PATH`-* The *Z3* SMT-solver : `z3` must be in your `$PATH`-* The *Kind2* model checker : `kind2` must be in your `$PATH`+* The *Yices2* SMT-solver: `yices-smt2` must be in your `$PATH`+* The *Z3* SMT-solver: `z3` must be in your `$PATH`+* The *Kind2* model checker: `kind2` must be in your `$PATH` To build it, just clone this repository and use `cabal install`. You will find some examples in the `examples` folder, which can be built with `cabal install`@@ -53,7 +53,7 @@ boolean stream to a property name with the `prop` construct in the specification. -For instance, here is a straightforward specification declaring one property :+For instance, here is a straightforward specification declaring one property: ```haskell spec :: Spec@@ -65,7 +65,7 @@ Let's say we want to check that `gt0` holds. For this, we use the `prove :: Prover -> ProofScheme -> Spec -> IO ()` function exported by `Copilot.Theorem`.-This function takes three arguments :+This function takes three arguments: * The prover we want to use. For now, two provers are available, exported by the `Copilot.Theorem.Light` and `Copilot.Theorem.Kind2` module.@@ -86,7 +86,7 @@ The `Copilot.Theorem.Prover` defines a general interface for provers. Therefore, it is really easy to add a new prover by creating a new object of type-`Prover`. The latter is defined like this :+`Prover`. The latter is defined like this: ```haskell data Cex = Cex@@ -120,13 +120,13 @@ and checks if the assumptions logically entail the conclusion. -Two provers are provided by default : `Light` and `Kind2`.+Two provers are provided by default: `Light` and `Kind2`. #### The light prover The *light prover* is a really simple prover which uses the Yices SMT solver with the `QF_UFLIA` theory and is limited to prove *k-inductive* properties,-that is properties such that there exists some *k* such that :+that is properties such that there exists some *k* such that: * The property holds during the first *k* steps of the algorithm. * From the hypothesis the property has held during *k* consecutive steps, we@@ -166,7 +166,7 @@ * If `debugMode` is set to `True`, the SMTLib queries produced by the prover are displayed in the standard output. -`Options` is an instance of the `Data.Default` typeclass :+`Options` is an instance of the `Data.Default` typeclass: ```haskell instance Default Options where@@ -202,7 +202,7 @@ in the future. For instance, a *lazy* one such that C launches B only if A has returns *unknown* or *error*. -As an example, the following prover is used in `Driver.hs` :+As an example, the following prover is used in `Driver.hs`: ```haskell prover =@@ -215,7 +215,7 @@ ### Proof schemes -Let's consider again this example :+Let's consider again this example: ```haskell spec :: Spec@@ -235,7 +235,7 @@ assert "gt0" >> check "neq0" ``` instead of just `check "neq0"`. A proof scheme is chain of primitives schemes-glued by the `>>` operator. For now, the available primitives are :+glued by the `>>` operator. For now, the available primitives are: * `check "prop"` checks whether or not a given property is true in the current context.@@ -256,7 +256,7 @@ `spec` and a proof scheme `scheme`. You can change the example being run just by changing one *import* directive in `Driver.hs`. -These examples include :+These examples include: * `Incr.hs` : a straightforward example in the style of the previous one. * `Grey.hs` : an example where two different implementations of a periodical@@ -277,21 +277,21 @@ set of slides. You can find some additional readings in the *References* section. -### Architecture of copilot-kind+### Architecture of copilot-theorem #### An overview of the proving process Each prover first translates the Copilot specification into an intermediate representation best suited for model checking. Two representations are-available :+available: -* The **IL** format : a Copilot program is translated into a list of+* The **IL** format: a Copilot program is translated into a list of quantifier-free equations over integer sequences, implicitly universally quantified by a free variable *n*. Each sequence roughly corresponds to a stream. This format is the one used in G. Hagen's thesis [4]. The *light prover* works with this format. -* The **TransSys** format : a Copilot program is *flattened* and translated+* The **TransSys** format: a Copilot program is *flattened* and translated into a *state transition system* [1]. Moreover, in order to keep some structure in this representation, the variables of this system are grouped by *nodes*, each node exporting and importing variables. The *Kind2 prover* uses@@ -308,7 +308,7 @@ ##### An example -The following program :+The following program: ```haskell spec = do@@ -319,7 +319,7 @@ fib = [1, 1] ++ (fib + drop 1 fib) ``` -can be translated into this IL specification :+can be translated into this IL specification: ``` SEQUENCES@@ -336,7 +336,7 @@ 'pos' : s0[n] > 0 ``` -or this modular transition system :+or this modular transition system: ``` NODE 's0' DEPENDS ON []@@ -399,9 +399,9 @@ #### The Light prover As said in the tutorial, the *light prover* is a simple tool implementing the-basic *k-induction* algorithm [1]. The `Light` directory contains three files :+basic *k-induction* algorithm [1]. The `Light` directory contains three files: -* `Prover.hs` : the prover and the *k-induction* algorithm are implemented in+* `Prover.hs`: the prover and the *k-induction* algorithm are implemented in this file. * `SMT.hs` contains some functions to interact with the Yices SMT provers. * `SMTLib.hs` is a set of functions to output SMTLib directives. It uses the@@ -417,16 +417,16 @@ Therefore, each stream definition directly gives us a recurrence equation and initial conditions for the associated sequence. -The translation process mostly :+The translation process mostly: -* onverts the types and operators, using uninterpreted functions to handle+* converts the types and operators, using uninterpreted functions to handle non-linear operators and external functions. * creates a sequence for each stream, local stream ands external stream. The reader is invited to use the *light prover* on the examples with `debugMode = true`, in order to have a look at the SMTLib code produced. For instance, if we check the property `"pos"` on the previous example involving the Fibonacci-sequence, we get :+sequence, we get: ``` <step> (set-logic QF_UFLIA)@@ -468,7 +468,7 @@ ##### Modular transition systems Let's look at the definition of a *modular transition systems*, in the-`TransSys.Spec` module :+`TransSys.Spec` module: ```haskell type NodeId = String@@ -513,7 +513,7 @@ is just a set of variables living in a local namespace and corresponding to the `Var` type. The `ExtVar` type is used to identify a variable in the global namespace by specifying both a node name and a variable. A node contains two-types of variables :+types of variables: * Some variables imported from other nodes. The structure `nodeImportedVars` binds each imported variable to its local name. The set of nodes from which a@@ -534,12 +534,12 @@ to *flatten* the copilot specification so the value of all streams at time *n* only depends on the values of all the streams at time *n - 1*, which is not the case in the `Fib` example shown earlier. This is done by a simple program-transformation which turns this :+transformation which turns this: ```haskell fib = [1, 1] ++ (fib + drop 1 fib) ```-into this :+into this: ```haskell fib0 = [1] ++ fib1@@ -607,7 +607,7 @@ which discards all the structure of a *modular transition system* and turns it into a *non-modular transition system* with only one node. In fact, when-translating a copilot specification to a kind2 file, two styles are available :+translating a copilot specification to a kind2 file, two styles are available: the `Kind2.toKind2` function takes a `Style` argument which can take the value `Inlined` or `Modular`. The only difference is that in the first case, a call to `removeCycles` is replaced by a call to `inline`.@@ -615,7 +615,7 @@ ### Limitations of copilot-theorem Now, we will discuss some limitations of the *copilot-theorem* tool. These-limitations are organized in two categories : the limitations related to the+limitations are organized in two categories: the limitations related to the Copilot language itself and its implementation, and the limitations related to the model-checking techniques we are using. @@ -625,7 +625,7 @@ informations about the structure of the original Copilot program. In fact, a stream is kept in the reified program only if it is recursively defined. Otherwise, all its occurences will be inlined. Moreover, let's look at the-`intCounter` function defined in the example `Grey.hs` :+`intCounter` function defined in the example `Grey.hs`: ```haskell intCounter :: Stream Bool -> Stream Word64@@ -638,7 +638,7 @@ If *n* counters are created with this function, the same code will be inlined *n* times and the structure of the original code will be lost. -There are many problems with this :+There are many problems with this: * It makes some optimizations of the model-checking based on a static analysis of the program more difficult (for instance *structural abstraction* - see@@ -679,7 +679,7 @@ ##### Limitations related to the SMT solvers -The use of SMT solvers introduces two kind of limitations :+The use of SMT solvers introduces two kind of limitations: 1. We are limited by the computing power needed by the SMT solvers 2. SMT solvers can't handle quantifiers efficiently@@ -710,7 +710,7 @@ why we have no other solution than replacing universal quantification by *bounded* universal quantification by assuming all the elements of the input stream are in the finite list `allowed` and using the function `forAllCst`-defined in `Copilot.Kind.Lib` :+defined in `Copilot.Kind.Lib`: ```haskell conj :: [Stream Bool] -> Stream Bool@@ -730,7 +730,7 @@ is hard to follow in our case because of * The difficulty to deal with universal quantification.-* The lack of *true* functions in Copilot : the latter offers metaprogramming+* The lack of *true* functions in Copilot: the latter offers metaprogramming facilities but no concept of functions like *Lustre* does with its *nodes*). * The inlining policy of the reification process. This point is related to the previous one.@@ -824,7 +824,7 @@ To be honest, I'm not sure producing a modular *Kind2* output is worth the complexity added. It's especially true at the time I write this in the sense-that :+that: * Each predicate introduced is used only one time (which is true because copilot doesn't handle functions or parametrized streams like Lustre does and@@ -843,7 +843,7 @@ ## References -1. *An insight into An insight into SMT-based model checking techniques for+1. *An insight into SMT-based model checking techniques for formal software verification of synchronous dataflow programs*, talk, Jonathan Laurent (see the `doc` folder of this repository) @@ -853,7 +853,7 @@ 3. *SMT-based Unbounded Model Checking with IC3 and Approximate Quantifier Elimination*, C. Sticksel, C. Tinelli -4. *Verifying safety properties of Lustre programs : an SMT-based approach*,+4. *Verifying safety properties of Lustre programs: an SMT-based approach*, PhD thesis, G. Hagen 5. *Understanding IC3*, Aaron R. Bradley
copilot-theorem.cabal view
@@ -6,7 +6,7 @@ Some tools to prove properties on Copilot programs with k-induction model checking. -version : 2.2.0+version : 2.2.1 license : BSD3 license-file : LICENSE maintainer : jonathan.laurent@ens.fr@@ -27,8 +27,19 @@ -fno-warn-missing-signatures -fcontext-stack=100 + -fpackage-trust+ -trust=array+ -trust=base+ -trust=containers+ -trust=copilot-core+ -trust=directory+ -trust=exceptions+ -trust=process+ -trust=random+ -trust=unix+ build-depends : base >= 4.0 && < 5- , copilot-core == 2.2.0+ , copilot-core == 2.2.1 , mtl , containers , pretty@@ -40,7 +51,7 @@ , xml , random , transformers- , smtlib2 >= 0.3+ , smtlib2 >= 0.3 && < 1.0 , ansi-terminal exposed-modules : Copilot.Theorem@@ -49,29 +60,29 @@ , Copilot.Theorem.Prover.SMT , Copilot.Theorem.Prover.Z3 , Copilot.Theorem.Kind2.Prover- + other-modules : Copilot.Theorem.Tactics- + , Copilot.Theorem.IL , Copilot.Theorem.IL.PrettyPrint , Copilot.Theorem.IL.Spec , Copilot.Theorem.IL.Translate , Copilot.Theorem.IL.Transform- + , Copilot.Theorem.Kind2.AST , Copilot.Theorem.Kind2.Output , Copilot.Theorem.Kind2.PrettyPrint , Copilot.Theorem.Kind2.Translate- + , Copilot.Theorem.Prover.SMTIO , Copilot.Theorem.Prover.SMTLib , Copilot.Theorem.Prover.TPTP , Copilot.Theorem.Prover.Backend- + , Copilot.Theorem.Misc.Error , Copilot.Theorem.Misc.SExpr , Copilot.Theorem.Misc.Utils- + , Copilot.Theorem.TransSys , Copilot.Theorem.TransSys.Cast , Copilot.Theorem.TransSys.PrettyPrint@@ -82,6 +93,3 @@ , Copilot.Theorem.TransSys.Invariants , Copilot.Theorem.TransSys.Operators , Copilot.Theorem.TransSys.Type- --
src/Copilot/Theorem.hs view
@@ -1,5 +1,7 @@ -------------------------------------------------------------------------------- +{-# LANGUAGE Safe #-}+ module Copilot.Theorem ( module X , Proof
src/Copilot/Theorem/IL.hs view
@@ -1,5 +1,7 @@ -------------------------------------------------------------------------------- +{-# LANGUAGE Safe #-}+ module Copilot.Theorem.IL (module X) where import Copilot.Theorem.IL.Spec as X
src/Copilot/Theorem/IL/PrettyPrint.hs view
@@ -1,6 +1,7 @@ --------------------------------------------------------------------------------- {-# LANGUAGE NamedFieldPuns, GADTs #-}+{-# LANGUAGE Safe #-} module Copilot.Theorem.IL.PrettyPrint (prettyPrint, printConstraint) where
src/Copilot/Theorem/IL/Spec.hs view
@@ -1,6 +1,7 @@ -------------------------------------------------------------------------------- {-# LANGUAGE ExistentialQuantification, GADTs, LambdaCase #-}+{-# LANGUAGE Safe #-} module Copilot.Theorem.IL.Spec ( Type (..)
src/Copilot/Theorem/IL/Transform.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE LambdaCase #-}+{-# LANGUAGE Safe #-} module Copilot.Theorem.IL.Transform ( bsimpl ) where
src/Copilot/Theorem/IL/Translate.hs view
@@ -2,8 +2,9 @@ {-# LANGUAGE RankNTypes, NamedFieldPuns, ScopedTypeVariables, GADTs, LambdaCase #-}+{-# LANGUAGE Safe #-} -module Copilot.Theorem.IL.Translate ( translate ) where+module Copilot.Theorem.IL.Translate ( translate, translateWithBounds ) where import Copilot.Theorem.IL.Spec @@ -11,7 +12,6 @@ import qualified Data.Map.Strict as Map -import Control.Applicative ((<$>), (<*)) import Control.Monad.State import Data.Char@@ -48,8 +48,14 @@ -- | Translates a Copilot specification to an IL specification translate :: C.Spec -> IL-translate (C.Spec {C.specStreams, C.specProperties}) = runTrans $ do+translate = translate' False +translateWithBounds :: C.Spec -> IL+translateWithBounds = translate' True++translate' :: Bool -> C.Spec -> IL+translate' b (C.Spec {C.specStreams, C.specProperties}) = runTrans b $ do+ let modelInit = concatMap streamInit specStreams mainConstraints <- mapM streamRec specStreams@@ -81,7 +87,9 @@ C.Word64 -> bound' C.Word64 _ -> return () where bound' :: (Bounded a, Integral a) => C.Type a -> Trans ()- bound' t = localConstraint (Op2 Bool And+ bound' t = do+ b <- addBounds <$> get+ when b $ localConstraint (Op2 Bool And (Op2 Bool Le (trConst t minBound) s) (Op2 Bool Ge (trConst t maxBound) s)) @@ -181,6 +189,9 @@ e2' <- expr e2 newMux cond' (trType t) e1' e2' +expr (C.ExternStruct _ _ _ _) = undefined+expr (C.GetField _ _ _ _) = undefined+ trConst :: C.Type a -> a -> Expr trConst t v = case t of C.Bool -> ConstB v@@ -245,7 +256,7 @@ C.Pow t -> (Pow, trType t) -- C.Logb t -> - C.Eq t -> (Eq, Bool)+ C.Eq _ -> (Eq, Bool) -- C.Ne t -> C.Le t -> (Le, trType t)@@ -281,6 +292,7 @@ { localConstraints :: [Expr] , muxes :: [(Expr, (Expr, Type, Expr, Expr))] , nextFresh :: Integer+ , addBounds :: Bool } newMux :: Expr -> Type -> Expr -> Expr -> Trans Expr@@ -317,8 +329,8 @@ popLocalConstraints = liftM2 (++) (localConstraints <$> get) getMuxes <* (modify $ \st -> st {localConstraints = [], muxes = []}) -runTrans :: Trans a -> a-runTrans m = evalState m $ TransST [] [] 0+runTrans :: Bool -> Trans a -> a+runTrans b m = evalState m $ TransST [] [] 0 b --------------------------------------------------------------------------------
src/Copilot/Theorem/Kind2.hs view
@@ -1,5 +1,7 @@ -------------------------------------------------------------------------------- +{-# LANGUAGE Safe #-}+ module Copilot.Theorem.Kind2 (module X) where import Copilot.Theorem.Kind2.AST as X
src/Copilot/Theorem/Kind2/AST.hs view
@@ -1,5 +1,7 @@ -------------------------------------------------------------------------------- +{-# LANGUAGE Safe #-}+ module Copilot.Theorem.Kind2.AST where --------------------------------------------------------------------------------
src/Copilot/Theorem/Kind2/Output.hs view
@@ -1,6 +1,7 @@ -------------------------------------------------------------------------------- {-# LANGUAGE RankNTypes #-}+{-# LANGUAGE Safe #-} module Copilot.Theorem.Kind2.Output (parseOutput) where
src/Copilot/Theorem/Kind2/PrettyPrint.hs view
@@ -1,5 +1,7 @@ -------------------------------------------------------------------------------- +{-# LANGUAGE Safe #-}+ module Copilot.Theorem.Kind2.PrettyPrint ( prettyPrint ) where import Copilot.Theorem.Misc.SExpr
src/Copilot/Theorem/Kind2/Prover.hs view
@@ -1,6 +1,7 @@ -------------------------------------------------------------------------------- {-# LANGUAGE LambdaCase #-}+{-# LANGUAGE Trustworthy #-} module Copilot.Theorem.Kind2.Prover ( module Data.Default
src/Copilot/Theorem/Kind2/Translate.hs view
@@ -1,6 +1,7 @@ -------------------------------------------------------------------------------- {-# LANGUAGE RankNTypes, ViewPatterns, NamedFieldPuns, GADTs #-}+{-# LANGUAGE Safe #-} module Copilot.Theorem.Kind2.Translate ( toKind2
src/Copilot/Theorem/Misc/Error.hs view
@@ -1,5 +1,7 @@ -------------------------------------------------------------------------------- +{-# LANGUAGE Safe #-}+ module Copilot.Theorem.Misc.Error ( badUse , impossible
src/Copilot/Theorem/Misc/SExpr.hs view
@@ -1,12 +1,12 @@ -------------------------------------------------------------------------------- {-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE Safe #-} module Copilot.Theorem.Misc.SExpr where import Text.ParserCombinators.Parsec import Text.PrettyPrint.HughesPJ as PP hiding (char, Str)-import Control.Applicative hiding ((<|>), empty) import Control.Monad
src/Copilot/Theorem/Misc/Utils.hs view
@@ -1,5 +1,7 @@ -------------------------------------------------------------------------------- +{-# LANGUAGE Safe #-}+ module Copilot.Theorem.Misc.Utils ( isSublistOf, nub', nubBy', nubEq , openTempFile
src/Copilot/Theorem/Prove.hs view
@@ -1,6 +1,7 @@ -------------------------------------------------------------------------------- {-# LANGUAGE NamedFieldPuns, ViewPatterns, ExistentialQuantification, GADTs #-}+{-# LANGUAGE Safe #-} module Copilot.Theorem.Prove ( Output (..)@@ -12,13 +13,13 @@ , Universal, Existential , check , prove+ , combine ) where import qualified Copilot.Core as Core import Data.List (intercalate)-import Control.Applicative (liftA2, Applicative(..))-import Control.Monad (liftM, ap)+import Control.Applicative (liftA2) import Control.Monad.Writer --------------------------------------------------------------------------------@@ -64,12 +65,12 @@ (<*>) = ap instance Monad (ProofScheme a) where- (Proof p) >>= f = Proof $ p >>= (\a -> case f a of Proof p -> p)+ (Proof p) >>= f = Proof $ p >>= (\a -> case f a of Proof p' -> p') return a = Proof (return a) data Action where- Check :: Prover -> Action- Assume :: PropId -> Action+ Check :: Prover -> Action+ Assume :: PropId -> Action Admit :: Action --------------------------------------------------------------------------------@@ -109,9 +110,9 @@ putStrLn $ propId ++ ": unknown " ++ "(" ++ intercalate ", " infos ++ ")" processActions context nextActions - Assume propId -> do- putStrLn $ propId ++ ": assumption"- processActions (propId : context) nextActions+ Assume propId' -> do+ putStrLn $ propId' ++ ": assumption"+ processActions (propId' : context) nextActions Admit -> do putStrLn $ propId ++ ": admitted"@@ -148,6 +149,7 @@ closeProverR stR } +combineOutputs :: [Char] -> [Char] -> Output -> Output -> Output combineOutputs nameL nameR (Output stL msgL) (Output stR msgR) = Output (combineSt stL stR) infos
src/Copilot/Theorem/Prover/Backend.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE RankNTypes #-}+{-# LANGUAGE Safe #-} module Copilot.Theorem.Prover.Backend (SmtFormat(..), Backend(..), SatResult(..)) where
src/Copilot/Theorem/Prover/SMT.hs view
@@ -1,6 +1,7 @@ -------------------------------------------------------------------------------- {-# LANGUAGE LambdaCase, NamedFieldPuns, FlexibleInstances, RankNTypes, GADTs #-}+{-# LANGUAGE Trustworthy #-} module Copilot.Theorem.Prover.SMT ( module Data.Default@@ -24,7 +25,6 @@ import qualified Copilot.Theorem.Prover.SMTLib as SMTLib import qualified Copilot.Theorem.Prover.TPTP as TPTP -import Control.Applicative ((<$>), (<*)) import Control.Monad (msum, unless, mzero) import Control.Monad.State (StateT, runStateT, lift, get, modify) import Control.Monad.IO.Class (liftIO)@@ -65,7 +65,7 @@ onlySat :: SmtFormat a => Options -> Backend a -> Proof Existential onlySat opts backend = check P.Prover { P.proverName = "OnlySat"- , P.startProver = return . ProofState opts backend Map.empty . translate+ , P.startProver = return . ProofState opts backend Map.empty . translateWithBounds , P.askProver = onlySat' , P.closeProver = const $ return () }@@ -73,7 +73,7 @@ onlyValidity :: SmtFormat a => Options -> Backend a -> Proof Universal onlyValidity opts backend = check P.Prover { P.proverName = "OnlyValidity"- , P.startProver = return . ProofState opts backend Map.empty . translate+ , P.startProver = return . ProofState opts backend Map.empty . translateWithBounds , P.askProver = onlyValidity' , P.closeProver = const $ return () }@@ -81,7 +81,7 @@ induction :: SmtFormat a => Options -> Backend a -> Proof Universal induction opts backend = check P.Prover { P.proverName = "Induction"- , P.startProver = return . ProofState opts backend Map.empty . translate+ , P.startProver = return . ProofState opts backend Map.empty . translateWithBounds , P.askProver = kInduction' 0 0 , P.closeProver = const $ return () }@@ -89,7 +89,7 @@ kInduction :: SmtFormat a => Options -> Backend a -> Proof Universal kInduction opts backend = check P.Prover { P.proverName = "K-Induction"- , P.startProver = return . ProofState opts backend Map.empty . translate+ , P.startProver = return . ProofState opts backend Map.empty . translateWithBounds , P.askProver = kInduction' (startK opts) (maxK opts) , P.closeProver = const $ return () }
src/Copilot/Theorem/Prover/SMTIO.hs view
@@ -1,6 +1,7 @@ -------------------------------------------------------------------------------- {-# LANGUAGE LambdaCase, NamedFieldPuns, RankNTypes, ViewPatterns #-}+{-# LANGUAGE Safe #-} module Copilot.Theorem.Prover.SMTIO ( Solver@@ -15,7 +16,6 @@ import Control.Monad import Control.Monad.Trans import Control.Monad.Trans.Maybe-import Control.Applicative ((<$>)) import Data.Maybe import Data.Set ((\\), fromList, Set, union, empty, elems)
src/Copilot/Theorem/Prover/SMTLib.hs view
@@ -1,6 +1,7 @@ -------------------------------------------------------------------------------- {-# LANGUAGE GADTs, FlexibleInstances #-}+{-# LANGUAGE Safe #-} module Copilot.Theorem.Prover.SMTLib (SmtLib, interpret) where
src/Copilot/Theorem/Prover/TPTP.hs view
@@ -1,6 +1,7 @@ -------------------------------------------------------------------------------- {-# LANGUAGE GADTs, LambdaCase #-}+{-# LANGUAGE Safe #-} module Copilot.Theorem.Prover.TPTP (Tptp, interpret) where
src/Copilot/Theorem/Prover/Z3.hs view
@@ -2,6 +2,7 @@ {-# LANGUAGE LambdaCase, NamedFieldPuns, FlexibleInstances, RankNTypes, GADTs, MultiParamTypeClasses, FlexibleContexts #-}+{-# LANGUAGE Trustworthy #-} module Copilot.Theorem.Prover.Z3 ( module Data.Default@@ -15,13 +16,12 @@ import Copilot.Theorem.Prove (Output (..), check, Proof, Universal, Existential) import qualified Copilot.Theorem.Prove as P -import Control.Applicative ((<$>), (<*)) import Control.Monad (msum, mzero, when, void, unless) import Control.Monad.State (StateT, runStateT, get, modify) import Control.Monad.Trans.Maybe (MaybeT (..)) import Data.Word-import Data.Unit+import Data.Unit (Unit(..)) import Data.Maybe (fromJust, fromMaybe) import Data.Default (Default(..)) import Data.List (foldl')@@ -120,13 +120,12 @@ data SolverId = Base | Step deriving (Show, Ord, Eq) -getModels :: [PropId] -> [PropId] -> ProofScript ([Expr], [Expr], [Expr], Bool)+getModels :: [PropId] -> [PropId] -> ProofScript ([Expr], [Expr], [Expr], [Expr], Bool) getModels assumptionIds toCheckIds = do IL {modelInit, modelRec, properties, inductive} <- spec <$> get let (as, as') = selectProps assumptionIds properties (as'', toCheck) = selectProps toCheckIds properties- modelRec' = modelRec ++ as ++ as' ++ as''- return (modelInit, modelRec', toCheck, inductive)+ return (as ++ as', modelInit, modelRec ++ as ++ as' ++ as'', toCheck, inductive) getSolver :: SolverId -> ProofScript Solver getSolver sid = do@@ -231,11 +230,11 @@ valid msg = return $ Output P.Valid [msg] kInduction' :: Word32 -> Word32 -> ProofState -> [PropId] -> [PropId] -> IO Output-kInduction' startK maxK s as ps = (fromMaybe (Output P.Unknown ["proof by k-induction failed"]) . fst)+kInduction' startK maxK s as ps = (fromMaybe (Output P.Unknown ["proof by " ++ proofKind (toInteger maxK) ++ " failed"]) . fst) <$> runPS (msum (map induction [(toInteger startK) .. (toInteger maxK)]) <* stopSolvers) s where induction k = do- (modelInit, modelRec, toCheck, inductive) <- getModels as ps+ (assumps, modelInit, modelRec, toCheck, inductive) <- getModels as ps let base = [evalAt (Fixed i) m | m <- modelRec, i <- [0 .. k]] baseInv = [evalAt (Fixed k) m | m <- toCheck]@@ -244,47 +243,56 @@ ++ [evalAt (_n_plus i) m | m <- toCheck, i <- [0 .. k]] stepInv = [evalAt (_n_plus $ k + 1) m | m <- toCheck] - entailment Base (modelInit ++ base) baseInv >>= \case- Sat -> invalid $ "base case failed for " ++ proofKind k+ entailment Base assumps [ConstB False] >>= \case Unknown -> unknown- Unsat ->- if not inductive then valid ("proved without induction")- else entailment Step step stepInv >>= \case- Sat -> unknown- Unknown -> unknown- Unsat -> valid $ "proved with " ++ proofKind k+ Unsat -> invalid $ "inconsistent assumptions"+ Sat -> entailment Base (modelInit ++ base) baseInv >>= \case+ Sat -> invalid $ "base case failed for " ++ proofKind k+ Unknown -> unknown+ Unsat ->+ if not inductive then valid ("proved without induction")+ else entailment Step step stepInv >>= \case+ Sat -> unknown+ Unknown -> unknown+ Unsat -> valid $ "proved with " ++ proofKind k onlySat' :: ProofState -> [PropId] -> [PropId] -> IO Output onlySat' s as ps = (fromJust . fst) <$> runPS (script <* stopSolvers) s where script = do- (modelInit, modelRec, toCheck, inductive) <- getModels as ps+ (assumps, modelInit, modelRec, toCheck, inductive) <- getModels as ps let base = map (evalAt (Fixed 0)) modelRec baseInv = map (evalAt (Fixed 0)) toCheck - if inductive- then unknown' "proposition requires induction to prove."- else entailment Base (modelInit ++ base) (map (Op1 Bool Not) baseInv) >>= \case- Unsat -> invalid "prop not satisfiable"- Unknown -> unknown' "failed to find a satisfying model"- Sat -> sat "prop is satisfiable"+ entailment Base assumps [ConstB False] >>= \case+ Unknown -> unknown+ Unsat -> invalid $ "inconsistent assumptions"+ Sat -> if inductive+ then unknown' "proposition requires induction to prove."+ else entailment Base (modelInit ++ base) (map (Op1 Bool Not) baseInv) >>= \case+ Unsat -> invalid "prop not satisfiable"+ Unknown -> unknown' "failed to find a satisfying model"+ Sat -> sat "prop is satisfiable" onlyValidity' :: ProofState -> [PropId] -> [PropId] -> IO Output onlyValidity' s as ps = (fromJust . fst) <$> runPS (script <* stopSolvers) s where script = do- (modelInit, modelRec, toCheck, inductive) <- getModels as ps+ (assumps, modelInit, modelRec, toCheck, inductive) <- getModels as ps let base = map (evalAt (Fixed 0)) modelRec baseInv = map (evalAt (Fixed 0)) toCheck - if inductive- then unknown' "proposition requires induction to prove."- else entailment Base (modelInit ++ base) baseInv >>= \case- Unsat -> valid "proof by Z3"- Unknown -> unknown- Sat -> invalid "Z3 found a counter-example."+ entailment Base assumps [ConstB False] >>= \case+ Unknown -> unknown+ Unsat -> invalid $ "inconsistent assumptions"+ Sat -> if inductive+ then unknown' "proposition requires induction to prove."+ else entailment Base (modelInit ++ base) baseInv >>= \case+ Unsat -> valid "proof by Z3"+ Unknown -> unknown+ Sat -> invalid "Z3 found a counter-example." selectProps :: [PropId] -> Map PropId ([Expr], Expr) -> ([Expr], [Expr]) selectProps propIds properties =@@ -306,6 +314,7 @@ , ratVars :: Map String (SMTExpr Rational) } +noVars :: TransState noVars = TransState Map.empty Map.empty Map.empty Map.empty Map.empty Map.empty getBoolVar :: String -> Trans (SMTExpr Bool)@@ -326,234 +335,163 @@ getRatVar :: String -> Trans (SMTExpr Rational) getRatVar = getVar ratVars (\v s -> s {ratVars = v}) -getVar proj mod v = do+getVar :: (Unit (SMTAnnotation t), SMTType t) => (TransState -> Map String (SMTExpr t)) -> (Map String (SMTExpr t) -> TransState -> TransState) -> String -> Trans (SMTExpr t)+getVar proj upd v = do vs <- proj <$> get case Map.lookup v vs of Nothing -> do newVar <- lift $ varNamed v- modify $ mod $ Map.insert v newVar vs+ modify $ upd $ Map.insert v newVar vs return newVar Just x -> return x transB :: Expr -> Trans (SMTExpr Bool) transB = \case- ConstB b -> return $ constant b-- Ite _ c e1 e2 -> do- c' <- transB c- trans2B e1 e2 (ite c')-- Op1 _ Not e -> transB e >>= return . not'-- Op2 _ And e1 e2 -> do- e1' <- transB e1- e2' <- transB e2- return $ e1' .&&. e2'- Op2 _ Or e1 e2 -> do- e1' <- transB e1- e2' <- transB e2- return $ e1' .||. e2'-- Op2 _ Eq e1 e2 -> case typeOf e1 of- Bool -> trans2B e1 e2 (.==.)- Real -> trans2R e1 e2 (.==.)- BV8 -> trans2BV8 e1 e2 (.==.)- BV16 -> trans2BV16 e1 e2 (.==.)- BV32 -> trans2BV32 e1 e2 (.==.)- BV64 -> trans2BV64 e1 e2 (.==.)- SBV8 -> trans2BV8 e1 e2 (.==.)- SBV16 -> trans2BV16 e1 e2 (.==.)- SBV32 -> trans2BV32 e1 e2 (.==.)- SBV64 -> trans2BV64 e1 e2 (.==.)-- Op2 _ Le e1 e2 -> case typeOf e1 of- Real -> trans2R e1 e2 (.<=.)- BV8 -> trans2BV8 e1 e2 bvule- BV16 -> trans2BV16 e1 e2 bvule- BV32 -> trans2BV32 e1 e2 bvule- BV64 -> trans2BV64 e1 e2 bvule- SBV8 -> trans2BV8 e1 e2 bvsle- SBV16 -> trans2BV16 e1 e2 bvsle- SBV32 -> trans2BV32 e1 e2 bvsle- SBV64 -> trans2BV64 e1 e2 bvsle- _ -> undefined- Op2 _ Ge e1 e2 -> case typeOf e1 of- Real -> trans2R e1 e2 (.>=.)- BV8 -> trans2BV8 e1 e2 bvuge- BV16 -> trans2BV16 e1 e2 bvuge- BV32 -> trans2BV32 e1 e2 bvuge- BV64 -> trans2BV64 e1 e2 bvuge- SBV8 -> trans2BV8 e1 e2 bvsge- SBV16 -> trans2BV16 e1 e2 bvsge- SBV32 -> trans2BV32 e1 e2 bvsge- SBV64 -> trans2BV64 e1 e2 bvsge- _ -> undefined- Op2 _ Lt e1 e2 -> case typeOf e1 of- Real -> trans2R e1 e2 (.<.)- BV8 -> trans2BV8 e1 e2 bvult- BV16 -> trans2BV16 e1 e2 bvult- BV32 -> trans2BV32 e1 e2 bvult- BV64 -> trans2BV64 e1 e2 bvult- SBV8 -> trans2BV8 e1 e2 bvslt- SBV16 -> trans2BV16 e1 e2 bvslt- SBV32 -> trans2BV32 e1 e2 bvslt- SBV64 -> trans2BV64 e1 e2 bvslt- _ -> undefined- Op2 _ Gt e1 e2 -> case typeOf e1 of- Real -> trans2R e1 e2 (.>.)- BV8 -> trans2BV8 e1 e2 bvugt- BV16 -> trans2BV16 e1 e2 bvugt- BV32 -> trans2BV32 e1 e2 bvugt- BV64 -> trans2BV64 e1 e2 bvugt- SBV8 -> trans2BV8 e1 e2 bvsgt- SBV16 -> trans2BV16 e1 e2 bvsgt- SBV32 -> trans2BV32 e1 e2 bvsgt- SBV64 -> trans2BV64 e1 e2 bvsgt- _ -> undefined-- SVal _ s i -> getBoolVar $ ncVar s i-- e -> error $ "Encountered unhandled expression (Bool): " ++ show e+ ConstB b -> return $ constant b+ Ite _ c e1 e2 -> ite <$> transB c <*> transB e1 <*> transB e2+ Op1 _ Not e -> not' <$> transB e+ Op2 _ And e1 e2 -> (.&&.) <$> transB e1 <*> transB e2+ Op2 _ Or e1 e2 -> (.||.) <$> transB e1 <*> transB e2+ Op2 _ Eq e1 e2 -> case typeOf e1 of+ Bool -> (.==.) <$> transB e1 <*> transB e2+ Real -> (.==.) <$> transR e1 <*> transR e2+ BV8 -> (.==.) <$> transBV8 e1 <*> transBV8 e2+ BV16 -> (.==.) <$> transBV16 e1 <*> transBV16 e2+ BV32 -> (.==.) <$> transBV32 e1 <*> transBV32 e2+ BV64 -> (.==.) <$> transBV64 e1 <*> transBV64 e2+ SBV8 -> (.==.) <$> transBV8 e1 <*> transBV8 e2+ SBV16 -> (.==.) <$> transBV16 e1 <*> transBV16 e2+ SBV32 -> (.==.) <$> transBV32 e1 <*> transBV32 e2+ SBV64 -> (.==.) <$> transBV64 e1 <*> transBV64 e2+ e@(Op2 _ Le e1 e2) -> case typeOf e1 of+ Bool -> error $ "Comparing Bools: " ++ show e+ Real -> (.<=.) <$> transR e1 <*> transR e2+ BV8 -> bvule <$> transBV8 e1 <*> transBV8 e2+ BV16 -> bvule <$> transBV16 e1 <*> transBV16 e2+ BV32 -> bvule <$> transBV32 e1 <*> transBV32 e2+ BV64 -> bvule <$> transBV64 e1 <*> transBV64 e2+ SBV8 -> bvule <$> transBV8 e1 <*> transBV8 e2+ SBV16 -> bvule <$> transBV16 e1 <*> transBV16 e2+ SBV32 -> bvule <$> transBV32 e1 <*> transBV32 e2+ SBV64 -> bvule <$> transBV64 e1 <*> transBV64 e2+ e@(Op2 _ Ge e1 e2) -> case typeOf e1 of+ Bool -> error $ "Comparing Bools: " ++ show e+ Real -> (.>=.) <$> transR e1 <*> transR e2+ BV8 -> bvuge <$> transBV8 e1 <*> transBV8 e2+ BV16 -> bvuge <$> transBV16 e1 <*> transBV16 e2+ BV32 -> bvuge <$> transBV32 e1 <*> transBV32 e2+ BV64 -> bvuge <$> transBV64 e1 <*> transBV64 e2+ SBV8 -> bvuge <$> transBV8 e1 <*> transBV8 e2+ SBV16 -> bvuge <$> transBV16 e1 <*> transBV16 e2+ SBV32 -> bvuge <$> transBV32 e1 <*> transBV32 e2+ SBV64 -> bvuge <$> transBV64 e1 <*> transBV64 e2+ e@(Op2 _ Lt e1 e2) -> case typeOf e1 of+ Bool -> error $ "Comparing Bools: " ++ show e+ Real -> (.<.) <$> transR e1 <*> transR e2+ BV8 -> bvult <$> transBV8 e1 <*> transBV8 e2+ BV16 -> bvult <$> transBV16 e1 <*> transBV16 e2+ BV32 -> bvult <$> transBV32 e1 <*> transBV32 e2+ BV64 -> bvult <$> transBV64 e1 <*> transBV64 e2+ SBV8 -> bvult <$> transBV8 e1 <*> transBV8 e2+ SBV16 -> bvult <$> transBV16 e1 <*> transBV16 e2+ SBV32 -> bvult <$> transBV32 e1 <*> transBV32 e2+ SBV64 -> bvult <$> transBV64 e1 <*> transBV64 e2+ e@(Op2 _ Gt e1 e2) -> case typeOf e1 of+ Bool -> error $ "Comparing Bools: " ++ show e+ Real -> (.>.) <$> transR e1 <*> transR e2+ BV8 -> bvugt <$> transBV8 e1 <*> transBV8 e2+ BV16 -> bvugt <$> transBV16 e1 <*> transBV16 e2+ BV32 -> bvugt <$> transBV32 e1 <*> transBV32 e2+ BV64 -> bvugt <$> transBV64 e1 <*> transBV64 e2+ SBV8 -> bvugt <$> transBV8 e1 <*> transBV8 e2+ SBV16 -> bvugt <$> transBV16 e1 <*> transBV16 e2+ SBV32 -> bvugt <$> transBV32 e1 <*> transBV32 e2+ SBV64 -> bvugt <$> transBV64 e1 <*> transBV64 e2+ SVal _ s i -> getBoolVar $ ncVar s i+ e -> error $ "Encountered unhandled expression (Bool): " ++ show e +ncVar :: [Char] -> SeqIndex -> [Char] ncVar s (Fixed i) = s ++ "_" ++ show i ncVar s (Var i) = s ++ "_n" ++ show i transR :: Expr -> Trans (SMTExpr Rational) transR = \case- ConstR n -> return $ constant $ toRational n- Ite _ c e1 e2 -> do- c' <- transB c- trans2R e1 e2 (ite c')-- Op1 _ Neg e -> transR e >>= return . (app neg)- Op1 _ Abs e -> transR e >>= return . (app SMTAbs)+ ConstR n -> return $ constant $ toRational n+ Ite _ c e1 e2 -> ite <$> transB c <*> transR e1 <*> transR e2 - Op2 _ Add e1 e2 -> trans2R e1 e2 $ \x y -> app plus [x, y]- Op2 _ Sub e1 e2 -> trans2R e1 e2 $ \x y -> app minus (x, y)- Op2 _ Mul e1 e2 -> trans2R e1 e2 $ \x y -> app mult [x, y]- Op2 _ Fdiv e1 e2 -> trans2R e1 e2 divide+ Op1 _ Neg e -> app neg <$> transR e+ Op1 _ Abs e -> app SMTAbs <$> transR e - Op2 _ Pow e1 e2 -> do- let pow = SMTBuiltIn "^" unit :: SMTFunction (SMTExpr Rational, SMTExpr Rational) Rational- trans2R e1 e2 $ \x y -> app pow (x, y)+ Op2 _ Add e1 e2 -> (\x y -> app plus [x, y]) <$> transR e1 <*> transR e2+ Op2 _ Sub e1 e2 -> (\x y -> app minus (x, y)) <$> transR e1 <*> transR e2+ Op2 _ Mul e1 e2 -> (\x y -> app mult [x, y]) <$> transR e1 <*> transR e2+ Op2 _ Fdiv e1 e2 -> divide <$> transR e1 <*> transR e2 - SVal _ s i -> getRatVar $ ncVar s i+ Op2 _ Pow e1 e2 -> do+ let pow = SMTBuiltIn "^" () :: SMTFunction (SMTExpr Rational, SMTExpr Rational) Rational+ (\x y -> app pow (x, y)) <$> transR e1 <*> transR e2 - e -> error $ "Encountered unhandled expression (Rat): " ++ show e+ SVal _ s i -> getRatVar $ ncVar s i+ e -> error $ "Encountered unhandled expression (Rat): " ++ show e -- TODO(chathhorn): bleghh transBV8 :: Expr -> Trans (SMTExpr BV8) transBV8 = \case- ConstI _ n -> return $ constant $ BitVector n- Ite _ c e1 e2 -> do- c' <- transB c- trans2BV8 e1 e2 (ite c')-- Op1 _ Abs e -> transBV8 e >>= return . abs- Op1 _ Neg e -> transBV8 e >>= return . negate- Op2 _ Add e1 e2 -> trans2BV8 e1 e2 (+)- Op2 _ Sub e1 e2 -> trans2BV8 e1 e2 (-)- Op2 _ Mul e1 e2 -> trans2BV8 e1 e2 (*)- SVal _ s i -> getBV8Var $ ncVar s i-- e -> error $ "Encountered unhandled expression (BV8): " ++ show e+ ConstI _ n -> return $ constant $ BitVector n+ Ite _ c e1 e2 -> ite <$> transB c <*> transBV8 e1 <*> transBV8 e2+ Op1 _ Abs e -> abs <$> transBV8 e+ Op1 _ Neg e -> negate <$> transBV8 e+ Op2 _ Add e1 e2 -> (+) <$> transBV8 e1 <*> transBV8 e2+ Op2 _ Sub e1 e2 -> (-) <$> transBV8 e1 <*> transBV8 e2+ Op2 _ Mul e1 e2 -> (*) <$> transBV8 e1 <*> transBV8 e2+ SVal _ s i -> getBV8Var $ ncVar s i+ e -> error $ "Encountered unhandled expression (BV8): " ++ show e transBV16 :: Expr -> Trans (SMTExpr BV16) transBV16 = \case- ConstI _ n -> return $ constant $ BitVector n- Ite _ c e1 e2 -> do- c' <- transB c- trans2BV16 e1 e2 (ite c')-- Op1 _ Abs e -> transBV16 e >>= return . abs- Op1 _ Neg e -> transBV16 e >>= return . negate- Op2 _ Add e1 e2 -> trans2BV16 e1 e2 (+)- Op2 _ Sub e1 e2 -> trans2BV16 e1 e2 (-)- Op2 _ Mul e1 e2 -> trans2BV16 e1 e2 (*)- SVal _ s i -> getBV16Var $ ncVar s i-- e -> error $ "Encountered unhandled expression (BV16): " ++ show e+ ConstI _ n -> return $ constant $ BitVector n+ Ite _ c e1 e2 -> ite <$> transB c <*> transBV16 e1 <*> transBV16 e2+ Op1 _ Abs e -> abs <$> transBV16 e+ Op1 _ Neg e -> negate <$> transBV16 e+ Op2 _ Add e1 e2 -> (+) <$> transBV16 e1 <*> transBV16 e2+ Op2 _ Sub e1 e2 -> (-) <$> transBV16 e1 <*> transBV16 e2+ Op2 _ Mul e1 e2 -> (*) <$> transBV16 e1 <*> transBV16 e2+ SVal _ s i -> getBV16Var $ ncVar s i+ e -> error $ "Encountered unhandled expression (BV16): " ++ show e transBV32 :: Expr -> Trans (SMTExpr BV32) transBV32 = \case- ConstI _ n -> return $ constant $ BitVector n- Ite _ c e1 e2 -> do- c' <- transB c- trans2BV32 e1 e2 (ite c')-- Op1 _ Abs e -> transBV32 e >>= return . abs- Op1 _ Neg e -> transBV32 e >>= return . negate- Op2 _ Add e1 e2 -> trans2BV32 e1 e2 (+)- Op2 _ Sub e1 e2 -> trans2BV32 e1 e2 (-)- Op2 _ Mul e1 e2 -> trans2BV32 e1 e2 (*)- SVal _ s i -> getBV32Var $ ncVar s i-- e -> error $ "Encountered unhandled expression (BV32): " ++ show e+ ConstI _ n -> return $ constant $ BitVector n+ Ite _ c e1 e2 -> ite <$> transB c <*> transBV32 e1 <*> transBV32 e2+ Op1 _ Abs e -> abs <$> transBV32 e+ Op1 _ Neg e -> negate <$> transBV32 e+ Op2 _ Add e1 e2 -> (+) <$> transBV32 e1 <*> transBV32 e2+ Op2 _ Sub e1 e2 -> (-) <$> transBV32 e1 <*> transBV32 e2+ Op2 _ Mul e1 e2 -> (*) <$> transBV32 e1 <*> transBV32 e2+ SVal _ s i -> getBV32Var $ ncVar s i+ e -> error $ "Encountered unhandled expression (BV32): " ++ show e transBV64 :: Expr -> Trans (SMTExpr BV64) transBV64 = \case- ConstI _ n -> return $ constant $ BitVector n- Ite _ c e1 e2 -> do- c' <- transB c- trans2BV64 e1 e2 (ite c')-- Op1 _ Abs e -> transBV64 e >>= return . abs- Op1 _ Neg e -> transBV64 e >>= return . negate- Op2 _ Add e1 e2 -> trans2BV64 e1 e2 (+)- Op2 _ Sub e1 e2 -> trans2BV64 e1 e2 (-)- Op2 _ Mul e1 e2 -> trans2BV64 e1 e2 (*)- SVal _ s i -> getBV64Var $ ncVar s i-- e -> error $ "Encountered unhandled expression (BV64): " ++ show e--trans2BV8 :: Expr -> Expr -> (SMTExpr BV8 -> SMTExpr BV8 -> SMTExpr a) -> Trans (SMTExpr a)-trans2BV8 e1 e2 f = do- e1' <- transBV8 e1- e2' <- transBV8 e2- return $ f e1' e2'--trans2BV16 :: Expr -> Expr -> (SMTExpr BV16 -> SMTExpr BV16 -> SMTExpr a) -> Trans (SMTExpr a)-trans2BV16 e1 e2 f = do- e1' <- transBV16 e1- e2' <- transBV16 e2- return $ f e1' e2'--trans2BV32 :: Expr -> Expr -> (SMTExpr BV32 -> SMTExpr BV32 -> SMTExpr a) -> Trans (SMTExpr a)-trans2BV32 e1 e2 f = do- e1' <- transBV32 e1- e2' <- transBV32 e2- return $ f e1' e2'--trans2BV64 :: Expr -> Expr -> (SMTExpr BV64 -> SMTExpr BV64 -> SMTExpr a) -> Trans (SMTExpr a)-trans2BV64 e1 e2 f = do- e1' <- transBV64 e1- e2' <- transBV64 e2- return $ f e1' e2'--trans2R :: Expr -> Expr -> (SMTExpr Rational -> SMTExpr Rational -> SMTExpr a) -> Trans (SMTExpr a)-trans2R e1 e2 f = do- e1' <- transR e1- e2' <- transR e2- return $ f e1' e2'--trans2B :: Expr -> Expr -> (SMTExpr Bool -> SMTExpr Bool -> SMTExpr a) -> Trans (SMTExpr a)-trans2B e1 e2 f = do- e1' <- transB e1- e2' <- transB e2- return $ f e1' e2'+ ConstI _ n -> return $ constant $ BitVector n+ Ite _ c e1 e2 -> ite <$> transB c <*> transBV64 e1 <*> transBV64 e2+ Op1 _ Abs e -> abs <$> transBV64 e+ Op1 _ Neg e -> negate <$> transBV64 e+ Op2 _ Add e1 e2 -> (+) <$> transBV64 e1 <*> transBV64 e2+ Op2 _ Sub e1 e2 -> (-) <$> transBV64 e1 <*> transBV64 e2+ Op2 _ Mul e1 e2 -> (*) <$> transBV64 e1 <*> transBV64 e2+ SVal _ s i -> getBV64Var $ ncVar s i+ e -> error $ "Encountered unhandled expression (BV64): " ++ show e ----------------------------------------------------- -- Debug stuff from the the smtlib2 library github -- ----------------------------------------------------- -debugBackend :: Bool -> b -> DebugBackend b-debugBackend mute b = DebugBackend b stderr (Just 0) Nothing True mute- namedDebugBackend :: String -> Bool -> b -> DebugBackend b namedDebugBackend name mute b = DebugBackend b stderr (Just 0) (Just name) True mute data DebugBackend b = DebugBackend- { debugBackend' :: b+ { debugBackend :: b , debugHandle :: Handle , debugLines :: Maybe Integer , debugPrefix :: Maybe String@@ -562,12 +500,12 @@ } instance (SMTBackend b m,MonadIO m) => SMTBackend (DebugBackend b) m where- smtGetNames b = smtGetNames (debugBackend' b)- smtNextName b = smtNextName (debugBackend' b)+ smtGetNames b = smtGetNames (debugBackend b)+ smtNextName b = smtNextName (debugBackend b) smtHandle b req = do- getName <- smtGetNames (debugBackend' b)- nxtName <- smtNextName (debugBackend' b)- (dts,b1) <- smtHandle (debugBackend' b) SMTDeclaredDataTypes+ getName <- smtGetNames (debugBackend b)+ nxtName <- smtNextName (debugBackend b)+ (dts,b1) <- smtHandle (debugBackend b) SMTDeclaredDataTypes let rendering = renderSMTRequest nxtName getName dts req case debugPrefix b of Nothing -> return ()@@ -603,6 +541,6 @@ when (debugUseColor b) $ liftIO $ hSetSGR (debugHandle b) [Reset,SetColor Foreground Dull Blue] liftIO $ unless (mute b) $ hPutStrLn (debugHandle b) str when (debugUseColor b) $ liftIO $ hSetSGR (debugHandle b) [Reset]- return (resp,b { debugBackend' = b2 , debugLines = nline })+ return (resp,b { debugBackend = b2 , debugLines = nline })
src/Copilot/Theorem/Tactics.hs view
@@ -1,10 +1,11 @@+{-# LANGUAGE Safe #-}+ module Copilot.Theorem.Tactics ( instantiate, assume, admit ) where import Copilot.Theorem.Prove -import Data.Word import Control.Monad.Writer instantiate :: Proof Universal -> Proof Existential
src/Copilot/Theorem/TransSys.hs view
@@ -1,5 +1,7 @@ -------------------------------------------------------------------------------- +{-# LANGUAGE Safe #-}+ module Copilot.Theorem.TransSys (module X) where import Copilot.Theorem.TransSys.Spec as X
src/Copilot/Theorem/TransSys/Cast.hs view
@@ -1,6 +1,7 @@ -------------------------------------------------------------------------------- {-# LANGUAGE RankNTypes, ScopedTypeVariables, GADTs #-}+{-# LANGUAGE Safe #-} module Copilot.Theorem.TransSys.Cast ( Dyn
src/Copilot/Theorem/TransSys/Invariants.hs view
@@ -1,4 +1,5 @@ {-# OPTIONS_GHC -O0 #-}+{-# LANGUAGE Safe #-} module Copilot.Theorem.TransSys.Invariants ( HasInvariants (..)
src/Copilot/Theorem/TransSys/Operators.hs view
@@ -2,6 +2,7 @@ {-# LANGUAGE GADTs, ExistentialQuantification, LambdaCase, ScopedTypeVariables, RankNTypes #-}+{-# LANGUAGE Safe #-} module Copilot.Theorem.TransSys.Operators where @@ -10,8 +11,6 @@ import Copilot.Theorem.TransSys.Type import Copilot.Theorem.Misc.Error as Err--import Control.Applicative ((<$>)) --------------------------------------------------------------------------------
src/Copilot/Theorem/TransSys/PrettyPrint.hs view
@@ -1,6 +1,7 @@ -------------------------------------------------------------------------------- {-# LANGUAGE NamedFieldPuns, GADTs #-}+{-# LANGUAGE Safe #-} module Copilot.Theorem.TransSys.PrettyPrint ( prettyPrint ) where
src/Copilot/Theorem/TransSys/Renaming.hs view
@@ -1,6 +1,6 @@ -------------------------------------------------------------------------------- -{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE Safe #-} module Copilot.Theorem.TransSys.Renaming ( Renaming@@ -14,7 +14,6 @@ import Copilot.Theorem.TransSys.Spec import Control.Monad.State.Lazy-import Control.Applicative import Data.Maybe (fromMaybe) import Data.Map (Map)@@ -26,8 +25,7 @@ -------------------------------------------------------------------------------- -newtype Renaming a = Renaming (State RenamingST a)- deriving (Applicative, Monad, Functor)+type Renaming = State RenamingST data RenamingST = RenamingST { _reservedNames :: Set Var@@ -36,14 +34,12 @@ -------------------------------------------------------------------------------- addReservedName :: Var -> Renaming ()-addReservedName v =- Renaming $ modify $ \st ->+addReservedName v = modify $ \st -> st {_reservedNames = Set.insert v (_reservedNames st)} - getFreshName :: [Var] -> Renaming Var getFreshName vs = do- usedNames <- _reservedNames <$> Renaming get+ usedNames <- _reservedNames <$> get let varAppend (Var s) = Var $ s ++ "_" applicants = vs ++ List.iterate varAppend (head vs) v = case dropWhile (`member` usedNames) applicants of@@ -53,20 +49,19 @@ return v rename :: NodeId -> Var -> Var -> Renaming ()-rename n v v' =- Renaming $ modify $ \st ->+rename n v v' = modify $ \st -> st {_renaming = Map.insert (ExtVar n v) v' (_renaming st)} getRenamingF :: Renaming (ExtVar -> Var) getRenamingF = do- mapping <- _renaming <$> Renaming get+ mapping <- _renaming <$> get return $ \extv -> fromMaybe (extVarLocalPart extv) (Map.lookup extv mapping) runRenaming :: Renaming a -> (a, ExtVar -> Var) runRenaming m = evalState st' (RenamingST Set.empty Map.empty) where- Renaming st' = do+ st' = do r <- m f <- getRenamingF return (r, f)
src/Copilot/Theorem/TransSys/Spec.hs view
@@ -1,6 +1,7 @@ -------------------------------------------------------------------------------- {-# LANGUAGE ExistentialQuantification, GADTs, RankNTypes #-}+{-# LANGUAGE Safe #-} module Copilot.Theorem.TransSys.Spec ( module Copilot.Theorem.TransSys.Operators@@ -32,7 +33,7 @@ import Control.Monad (foldM, guard) import Data.Maybe-import Data.Monoid (Monoid, (<>), mempty, mconcat)+import Data.Monoid ((<>)) import Data.Map (Map) import Data.Set (Set, isSubsetOf, member) import Data.Bimap (Bimap)
src/Copilot/Theorem/TransSys/Transform.hs view
@@ -1,6 +1,7 @@ -------------------------------------------------------------------------------- {-# LANGUAGE RankNTypes #-}+{-# LANGUAGE Safe #-} module Copilot.Theorem.TransSys.Transform ( mergeNodes
src/Copilot/Theorem/TransSys/Translate.hs view
@@ -2,6 +2,7 @@ {-# LANGUAGE RankNTypes, NamedFieldPuns, ViewPatterns, ScopedTypeVariables, GADTs, FlexibleContexts #-}+{-# LANGUAGE Safe #-} module Copilot.Theorem.TransSys.Translate ( translate ) where @@ -9,7 +10,6 @@ import Copilot.Theorem.TransSys.Cast import Copilot.Theorem.Misc.Utils -import Control.Applicative ((<$>)) import Control.Monad.State.Lazy import Data.Char (isNumber)@@ -203,9 +203,13 @@ notHandled (UnhandledOp2 _opName _ta _tb _tc) = newUnconstrainedVar t -expr t (C.ExternFun _ta _name _args _ _mtag) = newUnconstrainedVar t+expr t (C.ExternFun _ _ _ _ _) = newUnconstrainedVar t -expr t (C.ExternArray _ _tb _name _ _ind _ _) = newUnconstrainedVar t+expr t (C.ExternArray _ _ _ _ _ _ _) = newUnconstrainedVar t++expr t (C.ExternStruct _ _ _ _) = newUnconstrainedVar t++expr t (C.GetField _ _ _ _) = undefined newUnconstrainedVar :: Type t -> Trans (Expr t) newUnconstrainedVar t = do
src/Copilot/Theorem/TransSys/Type.hs view
@@ -1,6 +1,7 @@ -------------------------------------------------------------------------------- {-# LANGUAGE ExistentialQuantification, GADTs #-}+{-# LANGUAGE Safe #-} module Copilot.Theorem.TransSys.Type ( Type (..)