packages feed

cryptol 2.2.5 → 2.2.6

raw patch · 8 files changed

+260/−201 lines, 8 filesdep +base-compatdep ~basedep ~sbvPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: base-compat

Dependency ranges changed: base, sbv

API changes (from Hackage documentation)

- Cryptol.REPL.Monad: CVC4NotFound :: Smoke
+ Cryptol.REPL.Monad: Z3NotFound :: Smoke
+ Cryptol.Symbolic: AllSat :: SatNum
+ Cryptol.Symbolic: ProveQuery :: QueryType
+ Cryptol.Symbolic: ProverCommand :: QueryType -> String -> Bool -> [DeclGroup] -> Maybe FilePath -> Expr -> Schema -> ProverCommand
+ Cryptol.Symbolic: SatQuery :: SatNum -> QueryType
+ Cryptol.Symbolic: SomeSat :: Int -> SatNum
+ Cryptol.Symbolic: [pcExpr] :: ProverCommand -> Expr
+ Cryptol.Symbolic: [pcExtraDecls] :: ProverCommand -> [DeclGroup]
+ Cryptol.Symbolic: [pcProverName] :: ProverCommand -> String
+ Cryptol.Symbolic: [pcQueryType] :: ProverCommand -> QueryType
+ Cryptol.Symbolic: [pcSchema] :: ProverCommand -> Schema
+ Cryptol.Symbolic: [pcSmtFile] :: ProverCommand -> Maybe FilePath
+ Cryptol.Symbolic: [pcVerbose] :: ProverCommand -> Bool
+ Cryptol.Symbolic: data ProverCommand
+ Cryptol.Symbolic: data QueryType
+ Cryptol.Symbolic: data SatNum
+ Cryptol.Symbolic: instance GHC.Show.Show Cryptol.Symbolic.QueryType
+ Cryptol.Symbolic: instance GHC.Show.Show Cryptol.Symbolic.SatNum
+ Cryptol.Symbolic: proverError :: String -> ModuleCmd ProverResult
+ Cryptol.Symbolic: satSMTResults :: SatResult -> [SMTResult]
- Cryptol.REPL.Monad: getUserSatNum :: REPL (Maybe Int)
+ Cryptol.REPL.Monad: getUserSatNum :: REPL SatNum
- Cryptol.Symbolic: protectStack :: ModuleCmd ProverResult -> ModuleCmd ProverResult
+ Cryptol.Symbolic: protectStack :: (String -> ModuleCmd a) -> ModuleCmd a -> ModuleCmd a
- Cryptol.Symbolic: satProve :: Bool -> Maybe Int -> (String, Bool) -> [DeclGroup] -> Maybe FilePath -> (Expr, Schema) -> ModuleCmd ProverResult
+ Cryptol.Symbolic: satProve :: ProverCommand -> ModuleCmd ProverResult
- Cryptol.Symbolic: satProveOffline :: Bool -> Bool -> [DeclGroup] -> Maybe FilePath -> (Expr, Schema) -> ModuleCmd ProverResult
+ Cryptol.Symbolic: satProveOffline :: ProverCommand -> ModuleCmd (Either String String)
- Cryptol.Symbolic: smtMode :: Bool
+ Cryptol.Symbolic: smtMode :: SMTLibVersion

Files

cryptol.cabal view
@@ -1,5 +1,5 @@ Name:                cryptol-Version:             2.2.5+Version:             2.2.6 Synopsis:            Cryptol: The Language of Cryptography Description: Cryptol is a domain-specific language for specifying cryptographic algorithms. A Cryptol implementation of an algorithm resembles its mathematical specification more closely than an implementation in a general purpose language. For more, see <http://www.cryptol.net/>. License:             BSD3@@ -23,7 +23,7 @@ source-repository this   type:     git   location: https://github.com/GaloisInc/cryptol.git-  tag:      v2.2.5+  tag:      v2.2.6  flag static   default: False@@ -40,7 +40,8 @@ library   Default-language:     Haskell98-  Build-depends:       base            >= 4.6 && < 5,+  Build-depends:       base            >= 4.7 && < 5,+                       base-compat     >= 0.6,                        array           >= 0.4,                        async           >= 2.0,                        containers      >= 0.5,@@ -56,7 +57,7 @@                        process         >= 1.2,                        QuickCheck      >= 2.7,                        random          >= 1.0.1,-                       sbv             (>= 4.3 && < 5.0) || (>= 5.1 && < 5.2),+                       sbv             >= 5.7,                        smtLib          >= 1.0.7,                        syb             >= 0.4,                        text            >= 1.1,
dist/build/Cryptol/Parser/Lexer.hs view
@@ -1,3 +1,4 @@+{-# OPTIONS_GHC -fno-warn-unused-binds -fno-warn-missing-signatures #-} {-# LANGUAGE CPP,MagicHash #-} {-# LINE 1 "src/Cryptol/Parser/Lexer.x" #-} @@ -25,17 +26,17 @@ #endif #if __GLASGOW_HASKELL__ >= 503 import Data.Array-import Data.Char (ord) import Data.Array.Base (unsafeAt) #else import Array-import Char (ord) #endif #if __GLASGOW_HASKELL__ >= 503 import GHC.Exts #else import GlaExts #endif+alex_tab_size :: Int+alex_tab_size = 8 alex_base :: AlexAddr alex_base = AlexA# "\xf8\xff\xff\xff\x6d\x00\x00\x00\x63\x01\x00\x00\x59\x02\x00\x00\xe2\x00\x00\x00\xd9\x02\x00\x00\x59\x03\x00\x00\xd9\x03\x00\x00\x59\x04\x00\x00\xd9\x04\x00\x00\x59\x05\x00\x00\xd9\x05\x00\x00\x59\x06\x00\x00\xd9\x06\x00\x00\x59\x07\x00\x00\xd9\x07\x00\x00\x59\x08\x00\x00\x00\x00\x00\x00\xca\x08\x00\x00\x00\x00\x00\x00\x3b\x09\x00\x00\x00\x00\x00\x00\xac\x09\x00\x00\x00\x00\x00\x00\x1d\x0a\x00\x00\x00\x00\x00\x00\x8e\x0a\x00\x00\x00\x00\x00\x00\xff\x0a\x00\x00\x00\x00\x00\x00\x40\x0b\x00\x00\x00\x00\x00\x00\x81\x0b\x00\x00\x00\x00\x00\x00\xc2\x0b\x00\x00\x00\x00\x00\x00\x03\x0c\x00\x00\x00\x00\x00\x00\x44\x0c\x00\x00\x00\x00\x00\x00\x85\x0c\x00\x00\xe0\xff\xff\xff\xfb\x0c\x00\x00\x48\x00\x00\x00\xd7\xff\xff\xff\xdf\xff\xff\xff\xfb\x0d\x00\x00\xbb\x0d\x00\x00\x00\x00\x00\x00\xbb\x0e\x00\x00\x31\x0f\x00\x00\x7c\x0e\x00\x00\x00\x00\x00\x00\x31\x10\x00\x00\xf1\x0f\x00\x00\x00\x00\x00\x00\xf1\x10\x00\x00\x67\x11\x00\x00\xb2\x10\x00\x00\x00\x00\x00\x00\x67\x12\x00\x00\x27\x12\x00\x00\x00\x00\x00\x00\x27\x13\x00\x00\xe7\x12\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe2\xff\xff\xff\x00\x00\x00\x00\xe8\xff\xff\xff\x00\x00\x00\x00\xdd\x13\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd3\x14\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x79\x00\x00\x00\xc9\x15\x00\x00\xa2\x16\x00\x00\x13\x17\x00\x00\x84\x17\x00\x00\xf5\x17\x00\x00\x66\x18\x00\x00\xd7\x18\x00\x00\x48\x19\x00\x00\xb9\x19\x00\x00\x2a\x1a\x00\x00\x9b\x1a\x00\x00\x0c\x1b\x00\x00\x7d\x1b\x00\x00\xee\x1b\x00\x00\x5f\x1c\x00\x00\xd0\x1c\x00\x00\x41\x1d\x00\x00\xb2\x1d\x00\x00\x23\x1e\x00\x00\x94\x1e\x00\x00\x05\x1f\x00\x00\x76\x1f\x00\x00\xe7\x1f\x00\x00\x58\x20\x00\x00\xc9\x20\x00\x00\x3a\x21\x00\x00\xab\x21\x00\x00\x1c\x22\x00\x00\x8d\x22\x00\x00\xfe\x22\x00\x00\x6f\x23\x00\x00\xe0\x23\x00\x00\x51\x24\x00\x00\xc2\x24\x00\x00\x33\x25\x00\x00\xa4\x25\x00\x00\x15\x26\x00\x00\x86\x26\x00\x00\xf7\x26\x00\x00\x68\x27\x00\x00\xd9\x27\x00\x00\x4a\x28\x00\x00\xbb\x28\x00\x00\xe3\xff\xff\xff\x6a\x00\x00\x00\x7f\x00\x00\x00\x34\x02\x00\x00\x4c\x02\x00\x00\x2c\x29\x00\x00\x9d\x29\x00\x00\x0e\x2a\x00\x00\x7f\x2a\x00\x00\xf0\x2a\x00\x00\x61\x2b\x00\x00\xd2\x2b\x00\x00\x43\x2c\x00\x00\xb4\x2c\x00\x00\x25\x2d\x00\x00\x96\x2d\x00\x00\x07\x2e\x00\x00\x78\x2e\x00\x00\xe9\x2e\x00\x00\x5a\x2f\x00\x00\xcb\x2f\x00\x00\x3c\x30\x00\x00\xad\x30\x00\x00\x1e\x31\x00\x00\x8f\x31\x00\x00\x00\x32\x00\x00\x71\x32\x00\x00\xe2\x32\x00\x00\x53\x33\x00\x00\xc4\x33\x00\x00\x35\x34\x00\x00\xa6\x34\x00\x00\x17\x35\x00\x00\x88\x35\x00\x00\xf9\x35\x00\x00\x6a\x36\x00\x00\xdb\x36\x00\x00\x4c\x37\x00\x00\xbd\x37\x00\x00\x2e\x38\x00\x00\x9f\x38\x00\x00\x10\x39\x00\x00\x81\x39\x00\x00\xf2\x39\x00\x00\x63\x3a\x00\x00\xd4\x3a\x00\x00\x45\x3b\x00\x00\xb6\x3b\x00\x00\x27\x3c\x00\x00\x98\x3c\x00\x00\x09\x3d\x00\x00\x7a\x3d\x00\x00\xeb\x3d\x00\x00\x5c\x3e\x00\x00\xcd\x3e\x00\x00\x3e\x3f\x00\x00\xaf\x3f\x00\x00\x20\x40\x00\x00\x91\x40\x00\x00\x02\x41\x00\x00\x73\x41\x00\x00\xe4\x41\x00\x00\x55\x42\x00\x00\xc6\x42\x00\x00\x37\x43\x00\x00\xa8\x43\x00\x00\x19\x44\x00\x00\x8a\x44\x00\x00\xfb\x44\x00\x00\x6c\x45\x00\x00\xdd\x45\x00\x00\x4e\x46\x00\x00\xbf\x46\x00\x00\x30\x47\x00\x00\xa1\x47\x00\x00\x12\x48\x00\x00\x83\x48\x00\x00\xf4\x48\x00\x00\x65\x49\x00\x00\xd6\x49\x00\x00\x47\x4a\x00\x00\xb8\x4a\x00\x00\x29\x4b\x00\x00\x9a\x4b\x00\x00\x0b\x4c\x00\x00\x7c\x4c\x00\x00\xed\x4c\x00\x00\x5e\x4d\x00\x00\xcf\x4d\x00\x00\x40\x4e\x00\x00\xb1\x4e\x00\x00\x22\x4f\x00\x00\x93\x4f\x00\x00\x04\x50\x00\x00\x75\x50\x00\x00\xe6\x50\x00\x00\x57\x51\x00\x00\xc8\x51\x00\x00\x39\x52\x00\x00\xaa\x52\x00\x00\x1b\x53\x00\x00\x8c\x53\x00\x00\xfd\x53\x00\x00\x6e\x54\x00\x00\xdf\x54\x00\x00\x50\x55\x00\x00\xc1\x55\x00\x00\x32\x56\x00\x00\xa3\x56\x00\x00\x14\x57\x00\x00\x85\x57\x00\x00\xf6\x57\x00\x00\x67\x58\x00\x00\xd8\x58\x00\x00\x49\x59\x00\x00\xba\x59\x00\x00\x2b\x5a\x00\x00\x9c\x5a\x00\x00\x0d\x5b\x00\x00\x7e\x5b\x00\x00\xef\x5b\x00\x00\x60\x5c\x00\x00\xd1\x5c\x00\x00\x42\x5d\x00\x00\xb3\x5d\x00\x00\x24\x5e\x00\x00\x95\x5e\x00\x00\x06\x5f\x00\x00\x77\x5f\x00\x00\xe8\x5f\x00\x00\x59\x60\x00\x00\xca\x60\x00\x00\x3b\x61\x00\x00\xac\x61\x00\x00\x1d\x62\x00\x00\x8e\x62\x00\x00\xff\x62\x00\x00\x70\x63\x00\x00\x00\x00\x00\x00\xd8\xff\xff\xff\x00\x00\x00\x00\xed\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\xfa\xff\xff\xff\x4a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x52\x00\x00\x00\x5b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x53\x00\x00\x00\xd9\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x34\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x81\x00\x00\x00\x00\x00\x00\x00\x55\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x66\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x65\x00\x00\x00\x5c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x77\x00\x00\x00\x00\x00\x00\x00\x68\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"# @@ -315,8 +316,8 @@   narrow32Int# i   where    i    = word2Int# ((b3 `uncheckedShiftL#` 24#) `or#`-		     (b2 `uncheckedShiftL#` 16#) `or#`-		     (b1 `uncheckedShiftL#` 8#) `or#` b0)+                     (b2 `uncheckedShiftL#` 16#) `or#`+                     (b1 `uncheckedShiftL#` 8#) `or#` b0)    b3   = int2Word# (ord# (indexCharOffAddr# arr (off' +# 3#)))    b2   = int2Word# (ord# (indexCharOffAddr# arr (off' +# 2#)))    b1   = int2Word# (ord# (indexCharOffAddr# arr (off' +# 1#)))@@ -356,30 +357,30 @@  alexScanUser user input (I# (sc))   = case alex_scan_tkn user input 0# input sc AlexNone of-	(AlexNone, input') ->-		case alexGetByte input of-			Nothing -> +        (AlexNone, input') ->+                case alexGetByte input of+                        Nothing ->    -				   AlexEOF-			Just _ ->+                                   AlexEOF+                        Just _ ->   -				   AlexError input'+                                   AlexError input' -	(AlexLastSkip input'' len, _) ->+        (AlexLastSkip input'' len, _) ->   -		AlexSkip input'' len+                AlexSkip input'' len -	(AlexLastAcc k input''' len, _) ->+        (AlexLastAcc k input''' len, _) ->   -		AlexToken input''' len k+                AlexToken input''' len k   -- Push the input through the DFA, remembering the most recent accepting@@ -388,7 +389,7 @@ alex_scan_tkn user orig_input len input s last_acc =   input `seq` -- strict in the input   let -	new_acc = (check_accs (alex_accept `quickIndex` (I# (s))))+        new_acc = (check_accs (alex_accept `quickIndex` (I# (s))))   in   new_acc `seq`   case alexGetByte input of@@ -402,23 +403,23 @@                 base   = alexIndexInt32OffAddr alex_base s                 offset = (base +# ord_c)                 check  = alexIndexInt16OffAddr alex_check offset-		+                                 new_s = if GTE(offset,0#) && EQ(check,ord_c)-			  then alexIndexInt16OffAddr alex_table offset-			  else alexIndexInt16OffAddr alex_deflt s-	in+                          then alexIndexInt16OffAddr alex_table offset+                          else alexIndexInt16OffAddr alex_deflt s+        in         case new_s of-	    -1# -> (new_acc, input)-		-- on an error, we want to keep the input *before* the-		-- character that failed, not after.-    	    _ -> alex_scan_tkn user orig_input (if c < 0x80 || c >= 0xC0 then (len +# 1#) else len)+            -1# -> (new_acc, input)+                -- on an error, we want to keep the input *before* the+                -- character that failed, not after.+            _ -> alex_scan_tkn user orig_input (if c < 0x80 || c >= 0xC0 then (len +# 1#) else len)                                                 -- note that the length is increased ONLY if this is the 1st byte in a char encoding)-			new_input new_s new_acc+                        new_input new_s new_acc       }   where-	check_accs (AlexAccNone) = last_acc-	check_accs (AlexAcc a  ) = AlexLastAcc a input (I# (len))-	check_accs (AlexAccSkip) = AlexLastSkip  input (I# (len))+        check_accs (AlexAccNone) = last_acc+        check_accs (AlexAcc a  ) = AlexLastAcc a input (I# (len))+        check_accs (AlexAccSkip) = AlexLastSkip  input (I# (len))  {-# LINE 198 "templates/GenericTemplate.hs" #-} @@ -428,17 +429,12 @@   | AlexLastSkip  !AlexInput !Int  instance Functor AlexLastAcc where-    fmap f AlexNone = AlexNone+    fmap _ AlexNone = AlexNone     fmap f (AlexLastAcc x y z) = AlexLastAcc (f x) y z-    fmap f (AlexLastSkip x y) = AlexLastSkip x y+    fmap _ (AlexLastSkip x y) = AlexLastSkip x y  data AlexAcc a user   = AlexAccNone   | AlexAcc a   | AlexAccSkip--{-# LINE 242 "templates/GenericTemplate.hs" #-}---- used by wrappers-iUnbox (I# (i)) = i 
src/Cryptol/REPL/Command.hs view
@@ -54,6 +54,7 @@ import qualified Cryptol.Parser.AST as P import Cryptol.Prims.Doc(helpDoc) import qualified Cryptol.Transform.Specialize as S+import Cryptol.Symbolic (ProverCommand(..), QueryType(..), SatNum(..)) import qualified Cryptol.Symbolic as Symbolic  import Control.DeepSeq@@ -336,9 +337,10 @@ satCmd = cmdProveSat True proveCmd = cmdProveSat False --- | Run a SAT solver on the given expression. Binds the @it@ variable--- to a record whose form depends on the expression given. See ticket--- #66 for a discussion of this design.+-- | Console-specific version of 'proveSat'. Prints output to the+-- console, and binds the @it@ variable to a record whose form depends+-- on the expression given. See ticket #66 for a discussion of this+-- design. cmdProveSat :: Bool -> String -> REPL () cmdProveSat isSat "" =   do xs <- getPropertyNames@@ -349,81 +351,104 @@                      then rPutStr $ ":sat "   ++ x ++ "\n\t"                      else rPutStr $ ":prove " ++ x ++ "\n\t"                   cmdProveSat isSat x-cmdProveSat isSat str = do+cmdProveSat isSat expr = do+  let cexStr | isSat = "satisfying assignment"+             | otherwise = "counterexample"   EnvString proverName <- getUser "prover"   EnvString fileName <- getUser "smtfile"   let mfile = if fileName == "-" then Nothing else Just fileName   case proverName of-    "offline" -> offlineProveSat isSat str mfile-    _ -> onlineProveSat isSat str proverName mfile+    "offline" -> do+      result <- offlineProveSat isSat expr mfile+      case result of+        Left msg -> rPutStrLn msg+        Right smtlib -> do+          let filename = fromMaybe "standard output" mfile+          let satWord | isSat = "satisfiability"+                      | otherwise = "validity"+          rPutStrLn $+              "Writing to SMT-Lib file " ++ filename ++ "..."+          rPutStrLn $+            "To determine the " ++ satWord +++            " of the expression, use an external SMT solver."+          case mfile of+            Just path -> io $ writeFile path smtlib+            Nothing -> rPutStr smtlib+    _ -> do+      result <- onlineProveSat isSat expr proverName mfile+      ppOpts <- getPPValOpts+      case result of+        Symbolic.EmptyResult         ->+          panic "REPL.Command" [ "got EmptyResult for online prover query" ]+        Symbolic.ProverError msg     -> rPutStrLn msg+        Symbolic.ThmResult ts        -> do+          rPutStrLn (if isSat then "Unsatisfiable" else "Q.E.D.")+          let (t, e) = mkSolverResult cexStr (not isSat) (Left ts)+          bindItVariable t e+        Symbolic.AllSatResult tevss -> do+          let tess = map (map $ \(t,e,_) -> (t,e)) tevss+              vss  = map (map $ \(_,_,v) -> v)     tevss+              ppvs vs = do+                parseExpr <- replParseExpr expr+                let docs = map (pp . E.WithBase ppOpts) vs+                    -- function application has precedence 3+                    doc = ppPrec 3 parseExpr+                rPrint $ hsep (doc : docs) <+>+                  text (if isSat then "= True" else "= False")+              resultRecs = map (mkSolverResult cexStr isSat . Right) tess+              collectTes tes = (t, es)+                where+                  (ts, es) = unzip tes+                  t = case nub ts of+                        [t'] -> t'+                        _ -> panic "REPL.Command.onlineProveSat"+                               [ "satisfying assignments with different types" ]+              (ty, exprs) =+                case resultRecs of+                  [] -> panic "REPL.Command.onlineProveSat"+                          [ "no satisfying assignments after mkSovlerResult" ]+                  [(t, e)] -> (t, [e])+                  _        -> collectTes resultRecs+          forM_ vss ppvs+          case (ty, exprs) of+            (t, [e]) -> bindItVariable t e+            (t, es ) -> bindItVariables t es  onlineProveSat :: Bool-               -> String -> String -> Maybe FilePath -> REPL ()+               -> String -> String -> Maybe FilePath -> REPL Symbolic.ProverResult onlineProveSat isSat str proverName mfile = do   EnvBool verbose <- getUser "debug"-  mSatNum <- getUserSatNum-  let cexStr | isSat = "satisfying assignment"-             | otherwise = "counterexample"+  satNum <- getUserSatNum   parseExpr <- replParseExpr str   (expr, schema) <- replCheckExpr parseExpr-  denv <- getDynEnv-  result <- liftModuleCmd $-    Symbolic.satProve-      isSat-      mSatNum-      (proverName, verbose)-      (M.deDecls denv)-      mfile-      (expr, schema)-  ppOpts <- getPPValOpts-  case result of-    Symbolic.EmptyResult         ->-      panic "REPL.Command" [ "got EmptyResult for online prover query" ]-    Symbolic.ProverError msg     -> rPutStrLn msg-    Symbolic.ThmResult ts        -> do-      rPutStrLn (if isSat then "Unsatisfiable" else "Q.E.D.")-      let (t, e) = mkSolverResult cexStr (not isSat) (Left ts)-      bindItVariable t e-    Symbolic.AllSatResult tevss -> do-      let tess = map (map $ \(t,e,_) -> (t,e)) tevss-          vss  = map (map $ \(_,_,v) -> v)     tevss-          ppvs vs = do-            let docs = map (pp . E.WithBase ppOpts) vs-                -- function application has precedence 3-                doc = ppPrec 3 parseExpr-            rPrint $ hsep (doc : docs) <+>-              text (if isSat then "= True" else "= False")-          resultRecs = map (mkSolverResult cexStr isSat . Right) tess-          collectTes tes = (t, es)-            where-              (ts, es) = unzip tes-              t = case nub ts of-                    [t'] -> t'-                    _ -> panic "REPL.Command.onlineProveSat"-                           [ "satisfying assignments with different types" ]-          (ty, exprs) =-            case resultRecs of-              [] -> panic "REPL.Command.onlineProveSat"-                      [ "no satisfying assignments after mkSovlerResult" ]-              [(t, e)] -> (t, [e])-              _        -> collectTes resultRecs-      forM_ vss ppvs-      case (ty, exprs) of-        (t, [e]) -> bindItVariable t e-        (t, es ) -> bindItVariables t es+  decls <- fmap M.deDecls getDynEnv+  let cmd = Symbolic.ProverCommand {+          pcQueryType    = if isSat then SatQuery satNum else ProveQuery+        , pcProverName   = proverName+        , pcVerbose      = verbose+        , pcExtraDecls   = decls+        , pcSmtFile      = mfile+        , pcExpr         = expr+        , pcSchema       = schema+        }+  liftModuleCmd $ Symbolic.satProve cmd -offlineProveSat :: Bool -> String -> Maybe FilePath -> REPL ()+offlineProveSat :: Bool -> String -> Maybe FilePath -> REPL (Either String String) offlineProveSat isSat str mfile = do-  EnvBool vrb <- getUser "debug"+  EnvBool verbose <- getUser "debug"   parseExpr <- replParseExpr str-  exsch <- replCheckExpr parseExpr+  (expr, schema) <- replCheckExpr parseExpr   decls <- fmap M.deDecls getDynEnv-  result <- liftModuleCmd $-    Symbolic.satProveOffline isSat vrb decls mfile exsch-  case result of-    Symbolic.ProverError msg -> rPutStrLn msg-    Symbolic.EmptyResult -> return ()-    _ -> panic "REPL.Command" [ "unexpected prover result for offline prover" ]+  let cmd = Symbolic.ProverCommand {+          pcQueryType    = if isSat then SatQuery (SomeSat 0) else ProveQuery+        , pcProverName   = "offline"+        , pcVerbose      = verbose+        , pcExtraDecls   = decls+        , pcSmtFile      = mfile+        , pcExpr         = expr+        , pcSchema       = schema+        }+  liftModuleCmd $ Symbolic.satProveOffline cmd  -- | Make a type/expression pair that is suitable for binding to @it@ -- after running @:sat@ or @:prove@
src/Cryptol/REPL/Monad.hs view
@@ -80,7 +80,7 @@ import Cryptol.Utils.PP import Cryptol.Utils.Panic (panic) import qualified Cryptol.Parser.AST as P-import Cryptol.Symbolic (proverNames, lookupProver)+import Cryptol.Symbolic (proverNames, lookupProver, SatNum(..))  import Control.Monad (ap,unless,when) import Data.IORef@@ -527,7 +527,7 @@     "The number of random tests to try."   , simpleOpt "satNum" (EnvString "1") checkSatNum     "The maximum number of :sat solutions to display (\"all\" for no limit)."-  , simpleOpt "prover" (EnvString "cvc4") checkProver $+  , simpleOpt "prover" (EnvString "z3") checkProver $     "The external SMT solver for :prove and :sat (" ++ proverListString ++ ")."   , simpleOpt "warnDefaulting" (EnvBool True) (const $ return Nothing)     "Choose if we should display warnings when defaulting."@@ -582,12 +582,12 @@       _               -> return $ Just "must be an integer > 0 or \"all\""   _ -> return $ Just "unable to parse a value for satNum" -getUserSatNum :: REPL (Maybe Int)+getUserSatNum :: REPL SatNum getUserSatNum = do   EnvString s <- getUser "satNum"   case s of-    "all"                     -> return Nothing-    _ | Just n <- readMaybe s -> return (Just n)+    "all"                     -> return AllSat+    _ | Just n <- readMaybe s -> return (SomeSat n)     _                         -> panic "REPL.Monad.getUserSatNum"                                    [ "invalid satNum option" ] @@ -603,25 +603,25 @@ smokeTest :: REPL [Smoke] smokeTest = catMaybes <$> sequence tests   where-    tests = [ cvc4exists ]+    tests = [ z3exists ]  type SmokeTest = REPL (Maybe Smoke)  data Smoke-  = CVC4NotFound+  = Z3NotFound   deriving (Show, Eq)  instance PP Smoke where   ppPrec _ smoke =     case smoke of-      CVC4NotFound -> text . intercalate " " $ [-          "[error] cvc4 is required to run Cryptol, but was not found in the"-        , "system path. See the Cryptol README for more on how to install cvc4."+      Z3NotFound -> text . intercalate " " $ [+          "[error] z3 is required to run Cryptol, but was not found in the"+        , "system path. See the Cryptol README for more on how to install z3."         ] -cvc4exists :: SmokeTest-cvc4exists = do-  mPath <- io $ findExecutable "cvc4"+z3exists :: SmokeTest+z3exists = do+  mPath <- io $ findExecutable "z3"   case mPath of-    Nothing -> return (Just CVC4NotFound)+    Nothing -> return (Just Z3NotFound)     Just _  -> return Nothing
src/Cryptol/Symbolic.hs view
@@ -6,23 +6,24 @@ -- Stability   :  provisional -- Portability :  portable +{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE PatternGuards #-}+{-# LANGUAGE RecordWildCards #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TupleSections #-}  module Cryptol.Symbolic where  import Control.Monad (replicateM, when, zipWithM)-import Control.Monad.IO.Class import Data.List (transpose, intercalate) import qualified Data.Map as Map-import Data.Maybe import qualified Control.Exception as X  import qualified Data.SBV.Dynamic as SBV  import qualified Cryptol.ModuleSystem as M import qualified Cryptol.ModuleSystem.Env as M+import qualified Cryptol.ModuleSystem.Monad as M  import Cryptol.Symbolic.Prims import Cryptol.Symbolic.Value@@ -75,6 +76,30 @@  type SatResult = [(Type, Expr, Eval.Value)] +data SatNum = AllSat | SomeSat Int+  deriving (Show)++data QueryType = SatQuery SatNum | ProveQuery+  deriving (Show)++data ProverCommand = ProverCommand {+    pcQueryType :: QueryType+    -- ^ The type of query to run+  , pcProverName :: String+    -- ^ Which prover to use (one of the strings in 'proverConfigs')+  , pcVerbose :: Bool+    -- ^ Verbosity flag passed to SBV+  , pcExtraDecls :: [DeclGroup]+    -- ^ Extra declarations to bring into scope for symbolic+    -- simulation+  , pcSmtFile :: Maybe FilePath+    -- ^ Optionally output the SMTLIB query to a file+  , pcExpr :: Expr+    -- ^ The typechecked expression to evaluate+  , pcSchema :: Schema+    -- ^ The 'Schema' of @pcExpr@+  }+ -- | A prover result is either an error message, an empty result (eg -- for the offline prover), a counterexample or a lazy list of -- satisfying assignments.@@ -83,42 +108,65 @@                   | EmptyResult                   | ProverError  String +satSMTResults :: SBV.SatResult -> [SBV.SMTResult]+satSMTResults (SBV.SatResult r) = [r]+ allSatSMTResults :: SBV.AllSatResult -> [SBV.SMTResult] allSatSMTResults (SBV.AllSatResult (_, rs)) = rs  thmSMTResults :: SBV.ThmResult -> [SBV.SMTResult] thmSMTResults (SBV.ThmResult r) = [r] -satProve :: Bool-         -> Maybe Int -- ^ satNum-         -> (String, Bool)-         -> [DeclGroup]-         -> Maybe FilePath-         -> (Expr, Schema)-         -> M.ModuleCmd ProverResult-satProve isSat mSatNum (proverName, verbose) edecls mfile (expr, schema) = protectStack $ \modEnv -> do-  let extDgs = allDeclGroups modEnv ++ edecls+proverError :: String -> M.ModuleCmd ProverResult+proverError msg modEnv = return (Right (ProverError msg, modEnv), [])++satProve :: ProverCommand -> M.ModuleCmd ProverResult+satProve ProverCommand {..} = protectStack proverError $ \modEnv ->+  M.runModuleM modEnv $ do+  let (isSat, mSatNum) = case pcQueryType of+        ProveQuery -> (False, Nothing)+        SatQuery sn -> case sn of+          SomeSat n -> (True, Just n)+          AllSat    -> (True, Nothing)+  let extDgs = allDeclGroups modEnv ++ pcExtraDecls   provers <--    case proverName of-      "any" -> SBV.sbvAvailableSolvers-      _ -> return [(lookupProver proverName) { SBV.smtFile = mfile }]-  let provers' = [ p { SBV.timing = verbose, SBV.verbose = verbose } | p <- provers ]+    case pcProverName of+      "any" -> M.io SBV.sbvAvailableSolvers+      _ -> return [(lookupProver pcProverName) { SBV.smtFile = pcSmtFile }]+  let provers' = [ p { SBV.timing = pcVerbose, SBV.verbose = pcVerbose } | p <- provers ]   let tyFn = if isSat then existsFinType else forallFinType   let runProver fn tag e = do-        when verbose $ liftIO $+        case provers of+          [prover] -> do+            when pcVerbose $ M.io $+              putStrLn $ "Trying proof with " ++ show prover+            res <- M.io (fn prover e)+            when pcVerbose $ M.io $+              putStrLn $ "Got result from " ++ show prover+            return (tag res)+          _ ->+            return [ SBV.ProofError+                       prover+                       [":sat with option prover=any requires option satNum=1"]+                   | prover <- provers ]+      runProvers fn tag e = do+        when pcVerbose $ M.io $           putStrLn $ "Trying proof with " ++                      intercalate ", " (map show provers)-        (firstProver, res) <- fn provers' e-        when verbose $ liftIO $+        (firstProver, res) <- M.io $ fn provers' e+        when pcVerbose $ M.io $           putStrLn $ "Got result from " ++ show firstProver         return (tag res)-  let runFn | isSat     = runProver SBV.allSatWithAny allSatSMTResults-            | otherwise = runProver SBV.proveWithAny  thmSMTResults-  case predArgTypes schema of-    Left msg -> return (Right (ProverError msg, modEnv), [])-    Right ts -> do when verbose $ putStrLn "Simulating..."-                   let env = evalDecls emptyEnv extDgs-                   let v = evalExpr env expr+  let runFn = case pcQueryType of+        ProveQuery -> runProvers SBV.proveWithAny thmSMTResults+        SatQuery sn -> case sn of+          SomeSat 1 -> runProvers SBV.satWithAny satSMTResults+          _         -> runProver SBV.allSatWith allSatSMTResults+  case predArgTypes pcSchema of+    Left msg -> return (ProverError msg)+    Right ts -> do when pcVerbose $ M.io $ putStrLn "Simulating..."+                   let env = evalDecls mempty extDgs+                   let v = evalExpr env pcExpr                    results' <- runFn $ do                                  args <- mapM tyFn ts                                  b <- return $! fromVBit (foldl fromVFun v args)@@ -152,48 +200,37 @@                                         | otherwise = show . SBV.ThmResult . head                                   boom = panic "Cryptol.Symbolic.sat"                                            [ "attempted to evaluate bogus boolean for pretty-printing" ]-                   return (Right (esatexprs, modEnv), [])+                   return esatexprs -satProveOffline :: Bool-                -> Bool-                -> [DeclGroup]-                -> Maybe FilePath-                -> (Expr, Schema)-                -> M.ModuleCmd ProverResult-satProveOffline isSat vrb edecls mfile (expr, schema) =-  protectStack $ \modEnv -> do-    let extDgs = allDeclGroups modEnv ++ edecls+satProveOffline :: ProverCommand -> M.ModuleCmd (Either String String)+satProveOffline ProverCommand {..} =+  protectStack (\msg modEnv -> return (Right (Left msg, modEnv), [])) $ \modEnv -> do+    let isSat = case pcQueryType of+          ProveQuery -> False+          SatQuery _ -> True+    let extDgs = allDeclGroups modEnv ++ pcExtraDecls     let tyFn = if isSat then existsFinType else forallFinType-    let filename = fromMaybe "standard output" mfile-    case predArgTypes schema of-      Left msg -> return (Right (ProverError msg, modEnv), [])+    case predArgTypes pcSchema of+      Left msg -> return (Right (Left msg, modEnv), [])       Right ts ->-        do when vrb $ putStrLn "Simulating..."-           let env = evalDecls emptyEnv extDgs-           let v = evalExpr env expr-           let satWord | isSat = "satisfiability"-                       | otherwise = "validity"-           txt <- SBV.compileToSMTLib smtMode isSat $ do-                    args <- mapM tyFn ts-                    b <- return $! fromVBit (foldl fromVFun v args)-                    liftIO $ putStrLn $-                      "Writing to SMT-Lib file " ++ filename ++ "..."-                    return b-           liftIO $ putStrLn $-             "To determine the " ++ satWord ++-             " of the expression, use an external SMT solver."-           case mfile of-             Just path -> writeFile path txt-             Nothing -> putStr txt-           return (Right (EmptyResult, modEnv), [])+        do when pcVerbose $ putStrLn "Simulating..."+           let env = evalDecls mempty extDgs+           let v = evalExpr env pcExpr+           smtlib <- SBV.compileToSMTLib SBV.SMTLib2 isSat $ do+             args <- mapM tyFn ts+             b <- return $! fromVBit (foldl fromVFun v args)+             return b+           return (Right (Right smtlib, modEnv), []) -protectStack :: M.ModuleCmd ProverResult-             -> M.ModuleCmd ProverResult-protectStack cmd modEnv = X.catchJust isOverflow (cmd modEnv) handler+protectStack :: (String -> M.ModuleCmd a)+             -> M.ModuleCmd a+             -> M.ModuleCmd a+protectStack mkErr cmd modEnv =+  X.catchJust isOverflow (cmd modEnv) handler   where isOverflow X.StackOverflow = Just ()         isOverflow _               = Nothing         msg = "Symbolic evaluation failed to terminate."-        handler () = return (Right (ProverError msg, modEnv), [])+        handler () = mkErr msg modEnv  parseValues :: [FinType] -> [SBV.CW] -> ([Eval.Value], [SBV.CW]) parseValues [] cws = ([], cws)@@ -378,7 +415,8 @@         _ -> panic "Cryptol.Symbolic.evalSel" [ "Record selector applied to non-record" ]      ListSel n _   -> case v of-                       VWord s -> VBit (SBV.svTestBit s n)+                       VWord s -> VBit (SBV.svTestBit s i)+                                    where i = SBV.intSizeOf s - 1 - n                        _       -> fromSeq v !! n  -- 0-based indexing  -- Declarations ----------------------------------------------------------------
src/Cryptol/Symbolic/Prims.hs view
@@ -25,9 +25,8 @@  import qualified Data.SBV.Dynamic as SBV -#if __GLASGOW_HASKELL__ < 710-import Control.Applicative-#endif+import Prelude ()+import Prelude.Compat  traverseSnd :: Functor f => (a -> f b) -> (t, a) -> f (t, b) traverseSnd f (x, y) = (,) x <$> f y@@ -317,7 +316,7 @@   case v of     VStream xs -> nth err xs (fromInteger n)     VSeq _ xs  -> nth err xs (fromInteger n)-    VWord x                 -> let i = SBV.svBitSize x - 1 - fromInteger n+    VWord x                 -> let i = SBV.intSizeOf x - 1 - fromInteger n                                in if i < 0 then err else                                     VBit (SBV.svTestBit x i)     _                       -> err@@ -342,13 +341,13 @@   case xs of     VSeq b xs'  -> VSeq b (genericDrop n xs')     VStream xs' -> VStream (genericDrop n xs')-    VWord w     -> VWord $ SBV.svExtract (SBV.svBitSize w - 1 - fromInteger n) 0 w+    VWord w     -> VWord $ SBV.svExtract (SBV.intSizeOf w - 1 - fromInteger n) 0 w     _           -> panic "Cryptol.Symbolic.Prims.dropV" [ "non-droppable value" ]  takeV :: Integer -> Value -> Value takeV n xs =   case xs of-    VWord w     -> VWord $ SBV.svExtract (SBV.svBitSize w - 1) (SBV.svBitSize w - fromInteger n) w+    VWord w     -> VWord $ SBV.svExtract (SBV.intSizeOf w - 1) (SBV.intSizeOf w - fromInteger n) w     VSeq b xs'  -> VSeq b (genericTake n xs')     VStream xs' -> VSeq b (genericTake n xs')                      where b = case xs' of VBit _ : _ -> True@@ -425,7 +424,7 @@  sExp :: SWord -> SWord -> SWord sExp x y = go (reverse (unpackWord y)) -- bits in little-endian order-  where go []       = literalSWord (SBV.svBitSize x) 1+  where go []       = literalSWord (SBV.intSizeOf x) 1         go (b : bs) = SBV.svIte b (SBV.svTimes x s) s             where a = go bs                   s = SBV.svTimes a a@@ -434,8 +433,8 @@ sLg2 :: SWord -> SWord sLg2 x = go 0   where-    lit n = literalSWord (SBV.svBitSize x) n-    go i | i < SBV.svBitSize x = SBV.svIte (SBV.svLessEq x (lit (2^i))) (lit (toInteger i)) (go (i + 1))+    lit n = literalSWord (SBV.intSizeOf x) n+    go i | i < SBV.intSizeOf x = SBV.svIte (SBV.svLessEq x (lit (2^i))) (lit (toInteger i)) (go (i + 1))          | otherwise           = lit (toInteger i)  -- Cmp -------------------------------------------------------------------------
src/Cryptol/Symbolic/Value.hs view
@@ -92,7 +92,7 @@                                   [ "mergeValue: incompatible values" ]   where     mergeBit b1 b2 = svSymbolicMerge KBool f c b1 b2-    mergeWord w1 w2 = svSymbolicMerge (svKind w1) f c w1 w2+    mergeWord w1 w2 = svSymbolicMerge (kindOf w1) f c w1 w2     mergeField (n1, x1) (n2, x2)       | n1 == n2  = (n1, mergeValue f c x1 x2)       | otherwise = panic "Cryptol.Symbolic.Value"@@ -104,7 +104,7 @@  instance BitWord SBool SWord where   packWord bs = fromBitsLE (reverse bs)-  unpackWord x = [ svTestBit x i | i <- reverse [0 .. svBitSize x - 1] ]+  unpackWord x = [ svTestBit x i | i <- reverse [0 .. intSizeOf x - 1] ]  -- Errors ---------------------------------------------------------------------- 
src/Cryptol/TypeCheck/Solver/Smtlib.hs view
@@ -45,7 +45,7 @@   asmps = mapMaybe toPred (ordFactsToProps ordAsmp ++ origAsmps)    tryGoal g = case toPred (goal g) of-                Just q -> do res <- cvc4 (toScript vs asmps q)+                Just q -> do res <- z3 (toScript vs asmps q)                              return (g, res == Unsat)                               -- i.e., solved for Nats, anyway                 Nothing -> return (g, False)@@ -124,35 +124,35 @@ data SMTResult = Sat | Unsat | Unknown                   deriving (Eq,Show) --- | First look for @cvc4@ in the path, but failing that, assume that it's +-- | First look for @z3@ in the path, but failing that, assume that it's  -- installed side-by-side with Cryptol.-findCvc4 :: IO FilePath-findCvc4 = do-  mfp <- findExecutable "cvc4"+findZ3 :: IO FilePath+findZ3 = do+  mfp <- findExecutable "z3"   case mfp of     Just fp -> return fp     Nothing -> do      bindir <- takeDirectory `fmap` getExecutablePath-     return (bindir </> "cvc4")+     return (bindir </> "z3") -cvc4 :: SMT.Script -> IO SMTResult-cvc4 script =+z3 :: SMT.Script -> IO SMTResult+z3 script =   X.handle (\(_::X.IOException) -> return Unknown) $   do let txt = show (SMT.pp script)-     cvc4path <- findCvc4-     (ex,out,err) <- readProcessWithExitCode cvc4path ["--lang=smtlib2","--rewrite-divk","-"] txt+     z3path <- findZ3+     (ex,out,err) <- readProcessWithExitCode z3path ["-smt2","-in"] txt      case ex of        ExitFailure 10  -> return Sat        ExitFailure 20  -> return Unsat-       ExitFailure 127 -> return Unknown -- cvc4 program not found+       ExitFailure 127 -> return Unknown -- z3 program not found        ExitSuccess          | out == "sat\n"     -> return Sat          | out == "unsat\n"   -> return Unsat-         | out == "unknwon\n" -> return Unknown+         | out == "unknown\n" -> return Unknown         -- XXX: We should not print to STDOUT here.        -- Report to a separate logger.-       x -> do putStrLn "Called to CVC4 failed!!!"+       x -> do putStrLn "Called to Z3 failed!!!"                putStrLn ("Exit code: " ++ show x)                putStrLn "Script"                putStrLn txt