{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE DoAndIfThenElse #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Language.Fixpoint.Solver (
solve
, solveFQ
, resultExit
, resultExitCode
, parseFInfo
, simplifyFInfo
) where
import Control.Concurrent (setNumCapabilities)
import qualified Data.HashMap.Strict as HashMap
import qualified Data.HashSet as HashSet
import qualified Data.Store as S
import Data.Aeson (ToJSON, encode)
import qualified Data.Text.Lazy.IO as LT
import qualified Data.Text.Lazy.Encoding as LT
import System.Exit (ExitCode (..))
import System.Console.CmdArgs.Verbosity (whenNormal, whenLoud)
import Control.Monad (when)
import Control.Exception (SomeException, catch)
import Control.Exception.Compat
(ExceptionWithContext(..), displayExceptionContext, wrapExceptionWithContext)
import Language.Fixpoint.Solver.EnvironmentReduction
(reduceEnvironments, simplifyBindings)
import Language.Fixpoint.Solver.Sanitize (symbolEnv, sanitize)
import Language.Fixpoint.Solver.UniqifyBinds (renameAll)
import Language.Fixpoint.Defunctionalize (defunctionalize)
import Language.Fixpoint.SortCheck (ElabParam (..), Elaborate (..), unElab, unElabFSetBagZ3)
import Language.Fixpoint.Solver.Extensionality (expand)
import Language.Fixpoint.Solver.Prettify (savePrettifiedQuery)
import Language.Fixpoint.Solver.UniqifyKVars (wfcUniqify)
import qualified Language.Fixpoint.Solver.Solve as Sol
import qualified Language.Fixpoint.Solver.Solution as Sol
import Language.Fixpoint.Types.Config
import Language.Fixpoint.Types.Errors
import Language.Fixpoint.Utils.Files hiding (Result)
import Language.Fixpoint.Misc
import Language.Fixpoint.Utils.Statistics (statistics)
import Language.Fixpoint.Graph
import Language.Fixpoint.Parse (rr')
import Language.Fixpoint.Types hiding (GInfo(..), fi)
import qualified Language.Fixpoint.Types as Types (GInfo(..))
import Language.Fixpoint.Minimize (minQuery, minQuals, minKvars)
import Control.DeepSeq
import qualified Data.ByteString as B
import Data.Maybe (catMaybes)
import qualified Text.PrettyPrint.HughesPJ as PJ
solveFQ :: Config -> IO ExitCode
solveFQ :: Config -> IO ExitCode
solveFQ Config
cfg = do
(FInfo ()
fi, [[Char]]
opts) <- [Char] -> IO (FInfo (), [[Char]])
readFInfo [Char]
file
Config
cfg' <- Config -> [[Char]] -> IO Config
withPragmas Config
cfg [[Char]]
opts
let fi' :: FInfo ()
fi' = Config -> FInfo () -> FInfo ()
forall a. Config -> FInfo a -> FInfo a
ignoreQualifiers Config
cfg' FInfo ()
fi
Result (Integer, ())
r <- Config -> FInfo () -> IO (Result (Integer, ()))
forall a.
(PPrint a, NFData a, Fixpoint a, Show a, Loc a) =>
Config -> FInfo a -> IO (Result (Integer, a))
solve Config
cfg' FInfo ()
fi'
Config -> Result Integer -> IO ExitCode
forall a.
(Fixpoint a, NFData a, ToJSON a) =>
Config -> Result a -> IO ExitCode
resultExitCode Config
cfg ((Integer, ()) -> Integer
forall a b. (a, b) -> a
fst ((Integer, ()) -> Integer)
-> Result (Integer, ()) -> Result Integer
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Result (Integer, ())
r)
where
file :: [Char]
file = Config -> [Char]
srcFile Config
cfg
resultExitCode :: (Fixpoint a, NFData a, ToJSON a) => Config -> Result a
-> IO ExitCode
resultExitCode :: forall a.
(Fixpoint a, NFData a, ToJSON a) =>
Config -> Result a -> IO ExitCode
resultExitCode Config
cfg Result a
r = do
IO () -> IO ()
whenNormal (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ Moods -> [Char] -> IO ()
colorStrLn (FixResult a -> Moods
forall a. FixResult a -> Moods
colorResult FixResult a
stat) (FixResult a -> [Char]
statStr (FixResult a -> [Char]) -> FixResult a -> [Char]
forall a b. NFData a => (a -> b) -> a -> b
$!! FixResult a
stat)
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Config -> Bool
json Config
cfg) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ Text -> IO ()
LT.putStrLn Text
jStr
ExitCode -> IO ExitCode
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Result a -> ExitCode
forall {a}. Result a -> ExitCode
eCode Result a
r)
where
jStr :: Text
jStr = ByteString -> Text
LT.decodeUtf8 (ByteString -> Text)
-> (Result a -> ByteString) -> Result a -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Result a -> ByteString
forall a. ToJSON a => a -> ByteString
encode (Result a -> Text) -> Result a -> Text
forall a b. (a -> b) -> a -> b
$ Result a
r
stat :: FixResult a
stat = Result a -> FixResult a
forall a. Result a -> FixResult a
resStatus (Result a -> FixResult a) -> Result a -> FixResult a
forall a b. NFData a => (a -> b) -> a -> b
$!! Result a
r
eCode :: Result a -> ExitCode
eCode = FixResult a -> ExitCode
forall a. FixResult a -> ExitCode
resultExit (FixResult a -> ExitCode)
-> (Result a -> FixResult a) -> Result a -> ExitCode
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Result a -> FixResult a
forall a. Result a -> FixResult a
resStatus
statStr :: FixResult a -> [Char]
statStr = Doc -> [Char]
PJ.render (Doc -> [Char]) -> (FixResult a -> Doc) -> FixResult a -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FixResult a -> Doc
forall a. Fixpoint a => FixResult a -> Doc
resultDoc
ignoreQualifiers :: Config -> FInfo a -> FInfo a
ignoreQualifiers :: forall a. Config -> FInfo a -> FInfo a
ignoreQualifiers Config
cfg FInfo a
fi
| Config -> Eliminate
eliminate Config
cfg Eliminate -> Eliminate -> Bool
forall a. Eq a => a -> a -> Bool
== Eliminate
All = FInfo a
fi { Types.quals = [] }
| Bool
otherwise = FInfo a
fi
solve
:: (PPrint a, NFData a, Fixpoint a, Show a, Loc a)
=> Config -> FInfo a -> IO (Result (Integer, a))
solve :: forall a.
(PPrint a, NFData a, Fixpoint a, Show a, Loc a) =>
Config -> FInfo a -> IO (Result (Integer, a))
solve Config
cfg GInfo SubC a
q
| Config -> Bool
parts Config
cfg = Config -> GInfo SubC a -> IO (Result (Integer, a))
forall a (c :: * -> *).
(Fixpoint a, Fixpoint (c a), TaggedC c a) =>
Config -> GInfo c a -> IO (Result (Integer, a))
partition Config
cfg (GInfo SubC a -> IO (Result (Integer, a)))
-> GInfo SubC a -> IO (Result (Integer, a))
forall a b. NFData a => (a -> b) -> a -> b
$!! GInfo SubC a
q
| Config -> Bool
stats Config
cfg = Config -> GInfo SubC a -> IO (Result (Integer, a))
forall a. Config -> FInfo a -> IO (Result (Integer, a))
statistics Config
cfg (GInfo SubC a -> IO (Result (Integer, a)))
-> GInfo SubC a -> IO (Result (Integer, a))
forall a b. NFData a => (a -> b) -> a -> b
$!! GInfo SubC a
q
| Config -> Bool
minimize Config
cfg = Config
-> (Config -> GInfo SubC a -> IO (Result (Integer, a)))
-> GInfo SubC a
-> IO (Result (Integer, a))
forall a.
(NFData a, Fixpoint a) =>
Config -> Solver a -> FInfo a -> IO (Result (Integer, a))
minQuery Config
cfg Config -> GInfo SubC a -> IO (Result (Integer, a))
forall a.
(PPrint a, NFData a, Fixpoint a, Show a, Loc a) =>
Config -> FInfo a -> IO (Result (Integer, a))
solve' (GInfo SubC a -> IO (Result (Integer, a)))
-> GInfo SubC a -> IO (Result (Integer, a))
forall a b. NFData a => (a -> b) -> a -> b
$!! GInfo SubC a
q
| Config -> Bool
minimizeQs Config
cfg = Config
-> (Config -> GInfo SubC a -> IO (Result (Integer, a)))
-> GInfo SubC a
-> IO (Result (Integer, a))
forall a.
(NFData a, Fixpoint a) =>
Config -> Solver a -> FInfo a -> IO (Result (Integer, a))
minQuals Config
cfg Config -> GInfo SubC a -> IO (Result (Integer, a))
forall a.
(PPrint a, NFData a, Fixpoint a, Show a, Loc a) =>
Config -> FInfo a -> IO (Result (Integer, a))
solve' (GInfo SubC a -> IO (Result (Integer, a)))
-> GInfo SubC a -> IO (Result (Integer, a))
forall a b. NFData a => (a -> b) -> a -> b
$!! GInfo SubC a
q
| Config -> Bool
minimizeKs Config
cfg = Config
-> (Config -> GInfo SubC a -> IO (Result (Integer, a)))
-> GInfo SubC a
-> IO (Result (Integer, a))
forall a.
(NFData a, Fixpoint a) =>
Config -> Solver a -> FInfo a -> IO (Result (Integer, a))
minKvars Config
cfg Config -> GInfo SubC a -> IO (Result (Integer, a))
forall a.
(PPrint a, NFData a, Fixpoint a, Show a, Loc a) =>
Config -> FInfo a -> IO (Result (Integer, a))
solve' (GInfo SubC a -> IO (Result (Integer, a)))
-> GInfo SubC a -> IO (Result (Integer, a))
forall a b. NFData a => (a -> b) -> a -> b
$!! GInfo SubC a
q
| Bool
otherwise = Config -> GInfo SubC a -> IO (Result (Integer, a))
forall a.
(PPrint a, NFData a, Fixpoint a, Show a, Loc a) =>
Config -> FInfo a -> IO (Result (Integer, a))
solve' Config
cfg (GInfo SubC a -> IO (Result (Integer, a)))
-> GInfo SubC a -> IO (Result (Integer, a))
forall a b. NFData a => (a -> b) -> a -> b
$!! GInfo SubC a
q
solve'
:: (PPrint a, NFData a, Fixpoint a, Show a, Loc a)
=> Config -> FInfo a -> IO (Result (Integer, a))
solve' :: forall a.
(PPrint a, NFData a, Fixpoint a, Show a, Loc a) =>
Config -> FInfo a -> IO (Result (Integer, a))
solve' Config
cfg FInfo a
q = do
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Config -> Bool
save Config
cfg) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ Config -> FInfo a -> IO ()
forall a. Fixpoint a => Config -> FInfo a -> IO ()
saveQuery Config
cfg FInfo a
q
if Config -> Bool
multicore Config
cfg then
Config -> FInfo a -> IO (Result (Integer, a))
forall a.
(Loc a, NFData a, PPrint a, Show a, Fixpoint a) =>
Config -> FInfo a -> IO (Result (Integer, a))
solvePar Config
cfg FInfo a
q
else
Config -> FInfo a -> IO (Result (Integer, a))
forall a.
(NFData a, Fixpoint a, Show a, Loc a, PPrint a) =>
Config -> FInfo a -> IO (Result (Integer, a))
solveNative Config
cfg (Config -> FInfo a -> FInfo a
forall (c :: * -> *) a.
TaggedC c a =>
Config -> GInfo c a -> GInfo c a
slice Config
cfg FInfo a
q)
readFInfo :: FilePath -> IO (FInfo (), [String])
readFInfo :: [Char] -> IO (FInfo (), [[Char]])
readFInfo [Char]
f
| [Char] -> Bool
isBinary [Char]
f = (,) (FInfo () -> [[Char]] -> (FInfo (), [[Char]]))
-> IO (FInfo ()) -> IO ([[Char]] -> (FInfo (), [[Char]]))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Char] -> IO (FInfo ())
readBinFq [Char]
f IO ([[Char]] -> (FInfo (), [[Char]]))
-> IO [[Char]] -> IO (FInfo (), [[Char]])
forall a b. IO (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> [[Char]] -> IO [[Char]]
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return []
| Bool
otherwise = [Char] -> IO (FInfo (), [[Char]])
readFq [Char]
f
readFq :: FilePath -> IO (FInfo (), [String])
readFq :: [Char] -> IO (FInfo (), [[Char]])
readFq [Char]
file = do
[Char]
str <- [Char] -> IO [Char]
readFile [Char]
file
let q :: FInfoWithOpts ()
q = [Char] -> [Char] -> FInfoWithOpts ()
forall a. Inputable a => [Char] -> [Char] -> a
rr' [Char]
file [Char]
str :: FInfoWithOpts ()
(FInfo (), [[Char]]) -> IO (FInfo (), [[Char]])
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (FInfoWithOpts () -> FInfo ()
forall a. FInfoWithOpts a -> FInfo a
fioFI FInfoWithOpts ()
q, FInfoWithOpts () -> [[Char]]
forall a. FInfoWithOpts a -> [[Char]]
fioOpts FInfoWithOpts ()
q)
readBinFq :: FilePath -> IO (FInfo ())
readBinFq :: [Char] -> IO (FInfo ())
readBinFq [Char]
file = {-# SCC "parseBFq" #-} do
ByteString
bs <- [Char] -> IO ByteString
B.readFile [Char]
file
case ByteString -> Either PeekException (FInfo ())
forall a. Store a => ByteString -> Either PeekException a
S.decode ByteString
bs of
Right FInfo ()
fi -> FInfo () -> IO (FInfo ())
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return FInfo ()
fi
Left PeekException
err' -> [Char] -> IO (FInfo ())
forall a. HasCallStack => [Char] -> a
error ([Char]
"Error decoding .bfq: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ PeekException -> [Char]
forall a. Show a => a -> [Char]
show PeekException
err')
solvePar
:: (Loc a, NFData a, PPrint a, Show a, Fixpoint a)
=> Config -> FInfo a -> IO (Result (Integer, a))
solvePar :: forall a.
(Loc a, NFData a, PPrint a, Show a, Fixpoint a) =>
Config -> FInfo a -> IO (Result (Integer, a))
solvePar Config
c FInfo a
fi0 = do
let fi :: FInfo a
fi = Config -> FInfo a -> FInfo a
forall (c :: * -> *) a.
TaggedC c a =>
Config -> GInfo c a -> GInfo c a
slice Config
c FInfo a
fi0
MCInfo
mci <- Config -> IO MCInfo
mcInfo Config
c
let fis :: [FInfo a]
fis = Maybe MCInfo -> FInfo a -> [FInfo a]
forall (c :: * -> *) a.
TaggedC c a =>
Maybe MCInfo -> GInfo c a -> [GInfo c a]
partition' (MCInfo -> Maybe MCInfo
forall a. a -> Maybe a
Just MCInfo
mci) FInfo a
fi
[Char] -> IO ()
writeLoud ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
"Number of partitions : " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show ([FInfo a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [FInfo a]
fis)
[Char] -> IO ()
writeLoud ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
"number of cores : " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Maybe Int -> [Char]
forall a. Show a => a -> [Char]
show (Config -> Maybe Int
cores Config
c)
[Char] -> IO ()
writeLoud ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
"minimum part size : " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show (Config -> Int
minPartSize Config
c)
[Char] -> IO ()
writeLoud ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
"maximum part size : " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show (Config -> Int
maxPartSize Config
c)
case [FInfo a]
fis of
[] -> [Char] -> IO (Result (Integer, a))
forall a. HasCallStack => [Char] -> a
errorstar [Char]
"partiton' returned empty list!"
[FInfo a
onePart] -> Config -> FInfo a -> IO (Result (Integer, a))
forall a.
(NFData a, Fixpoint a, Show a, Loc a, PPrint a) =>
Config -> FInfo a -> IO (Result (Integer, a))
solveNative Config
c FInfo a
onePart
[FInfo a]
_ -> ((Int, FInfo a) -> IO (Result (Integer, a)))
-> [(Int, FInfo a)] -> IO (Result (Integer, a))
forall a b. (a -> IO (Result b)) -> [a] -> IO (Result b)
inParallelUsing (Config -> (Int, FInfo a) -> IO (Result (Integer, a))
forall {a}.
(NFData a, Fixpoint a, Show a, Loc a, PPrint a) =>
Config -> (Int, FInfo a) -> IO (Result (Integer, a))
f Config
c) ([(Int, FInfo a)] -> IO (Result (Integer, a)))
-> [(Int, FInfo a)] -> IO (Result (Integer, a))
forall a b. (a -> b) -> a -> b
$ [Int] -> [FInfo a] -> [(Int, FInfo a)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Int
1..] [FInfo a]
fis
where
f :: Config -> (Int, FInfo a) -> IO (Result (Integer, a))
f Config
c' (Int
j, FInfo a
fi) = Config -> FInfo a -> IO (Result (Integer, a))
forall a.
(NFData a, Fixpoint a, Show a, Loc a, PPrint a) =>
Config -> FInfo a -> IO (Result (Integer, a))
solveNative (Config
c {srcFile = queryFile (Part j) c'}) FInfo a
fi
inParallelUsing :: (a -> IO (Result b)) -> [a] -> IO (Result b)
inParallelUsing :: forall a b. (a -> IO (Result b)) -> [a] -> IO (Result b)
inParallelUsing a -> IO (Result b)
f [a]
xs = do
Int -> IO ()
setNumCapabilities ([a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
xs)
[Result b]
rs <- (a -> IO (Result b)) -> [a] -> IO [Result b]
forall a b. (a -> IO b) -> [a] -> IO [b]
asyncMapM a -> IO (Result b)
f [a]
xs
Result b -> IO (Result b)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Result b -> IO (Result b)) -> Result b -> IO (Result b)
forall a b. (a -> b) -> a -> b
$ [Result b] -> Result b
forall a. Monoid a => [a] -> a
mconcat [Result b]
rs
solveNative, solveNative'
:: (NFData a, Fixpoint a, Show a, Loc a, PPrint a)
=> Config -> FInfo a -> IO (Result (Integer, a))
solveNative :: forall a.
(NFData a, Fixpoint a, Show a, Loc a, PPrint a) =>
Config -> FInfo a -> IO (Result (Integer, a))
solveNative !Config
cfg !FInfo a
fi0 = Config -> FInfo a -> IO (Result (Integer, a))
forall a.
(NFData a, Fixpoint a, Show a, Loc a, PPrint a) =>
Config -> FInfo a -> IO (Result (Integer, a))
solveNative' Config
cfg FInfo a
fi0
IO (Result (Integer, a))
-> (Error -> IO (Result (Integer, a))) -> IO (Result (Integer, a))
forall e a. Exception e => IO a -> (e -> IO a) -> IO a
`catch`
(Result (Integer, a) -> IO (Result (Integer, a))
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Result (Integer, a) -> IO (Result (Integer, a)))
-> (Error -> Result (Integer, a))
-> Error
-> IO (Result (Integer, a))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ErrorMap a -> ExceptionWithContext Error -> Result (Integer, a)
forall a.
PPrint a =>
ErrorMap a -> ExceptionWithContext Error -> Result (Integer, a)
crashResult (FInfo a -> ErrorMap a
forall a. Loc a => FInfo a -> ErrorMap a
errorMap FInfo a
fi0) (ExceptionWithContext Error -> Result (Integer, a))
-> (Error -> ExceptionWithContext Error)
-> Error
-> Result (Integer, a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Error -> ExceptionWithContext Error
forall a. a -> ExceptionWithContext a
wrapExceptionWithContext)
IO (Result (Integer, a))
-> (SomeException -> IO (Result (Integer, a)))
-> IO (Result (Integer, a))
forall e a. Exception e => IO a -> (e -> IO a) -> IO a
`catch`
(Result (Integer, a) -> IO (Result (Integer, a))
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Result (Integer, a) -> IO (Result (Integer, a)))
-> (SomeException -> Result (Integer, a))
-> SomeException
-> IO (Result (Integer, a))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ExceptionWithContext SomeException -> Result (Integer, a)
forall a. ExceptionWithContext SomeException -> Result (Integer, a)
crashResultOther (ExceptionWithContext SomeException -> Result (Integer, a))
-> (SomeException -> ExceptionWithContext SomeException)
-> SomeException
-> Result (Integer, a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SomeException -> ExceptionWithContext SomeException
forall a. a -> ExceptionWithContext a
wrapExceptionWithContext)
crashResult :: (PPrint a) => ErrorMap a -> ExceptionWithContext Error -> Result (Integer, a)
crashResult :: forall a.
PPrint a =>
ErrorMap a -> ExceptionWithContext Error -> Result (Integer, a)
crashResult ErrorMap a
m (ExceptionWithContext ExceptionContext
ectx Error
ex) = FixResult (Integer, a)
-> FixSolution
-> FixDelayedSolution
-> ResultSorts
-> Result (Integer, a)
forall a.
FixResult a
-> FixSolution -> FixDelayedSolution -> ResultSorts -> Result a
Result FixResult (Integer, a)
res FixSolution
forall a. Monoid a => a
mempty FixDelayedSolution
forall a. Monoid a => a
mempty ResultSorts
forall a. Monoid a => a
mempty
where
res :: FixResult (Integer, a)
res = [((Integer, a), Maybe [Char])] -> [Char] -> FixResult (Integer, a)
forall a. [(a, Maybe [Char])] -> [Char] -> FixResult a
Crash [((Integer, a), Maybe [Char])]
es [Char]
msg
es :: [((Integer, a), Maybe [Char])]
es = [Maybe ((Integer, a), Maybe [Char])]
-> [((Integer, a), Maybe [Char])]
forall a. [Maybe a] -> [a]
catMaybes [ ErrorMap a -> Error1 -> Maybe ((Integer, a), Maybe [Char])
forall a.
ErrorMap a -> Error1 -> Maybe ((Integer, a), Maybe [Char])
findError ErrorMap a
m Error1
e | Error1
e <- [Error1]
ers ]
ers :: [Error1]
ers = Error -> [Error1]
errs Error
ex
msg :: [Char]
msg = ExceptionContext -> [Char]
displayExceptionContext ExceptionContext
ectx [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"\n" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
msg0
msg0 :: [Char]
msg0 | [Error1] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Error1]
ers = [Char]
"Sorry, unexpected panic in liquid-fixpoint!\n"
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Error -> [Char]
forall a. PPrint a => a -> [Char]
showpp Error
ex
| Bool
otherwise = Error -> [Char]
forall a. PPrint a => a -> [Char]
showpp Error
ex
crashResultOther
:: ExceptionWithContext SomeException -> Result (Integer, a)
crashResultOther :: forall a. ExceptionWithContext SomeException -> Result (Integer, a)
crashResultOther (ExceptionWithContext ExceptionContext
ectx SomeException
ex) =
FixResult (Integer, a)
-> FixSolution
-> FixDelayedSolution
-> ResultSorts
-> Result (Integer, a)
forall a.
FixResult a
-> FixSolution -> FixDelayedSolution -> ResultSorts -> Result a
Result FixResult (Integer, a)
forall {a}. FixResult a
res FixSolution
forall a. Monoid a => a
mempty FixDelayedSolution
forall a. Monoid a => a
mempty ResultSorts
forall a. Monoid a => a
mempty
where
res :: FixResult a
res = [(a, Maybe [Char])] -> [Char] -> FixResult a
forall a. [(a, Maybe [Char])] -> [Char] -> FixResult a
Crash [] [Char]
msg
msg :: [Char]
msg = ExceptionContext -> [Char]
displayExceptionContext ExceptionContext
ectx [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"\n" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
msg0
msg0 :: [Char]
msg0 = [Char]
"Sorry, unexpected panic in liquid-fixpoint!\n" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ SomeException -> [Char]
forall a. Show a => a -> [Char]
show SomeException
ex
type ErrorMap a = HashMap.HashMap SrcSpan a
findError :: ErrorMap a -> Error1 -> Maybe ((Integer, a), Maybe String)
findError :: forall a.
ErrorMap a -> Error1 -> Maybe ((Integer, a), Maybe [Char])
findError ErrorMap a
m Error1
e = do
a
ann <- SrcSpan -> ErrorMap a -> Maybe a
forall k v. Hashable k => k -> HashMap k v -> Maybe v
HashMap.lookup (Error1 -> SrcSpan
errLoc Error1
e) ErrorMap a
m
let str :: [Char]
str = Doc -> [Char]
PJ.render (Error1 -> Doc
errMsg Error1
e)
((Integer, a), Maybe [Char]) -> Maybe ((Integer, a), Maybe [Char])
forall a. a -> Maybe a
forall (m :: * -> *) a. Monad m => a -> m a
return ((-Integer
1, a
ann), [Char] -> Maybe [Char]
forall a. a -> Maybe a
Just [Char]
str)
errorMap :: (Loc a) => FInfo a -> ErrorMap a
errorMap :: forall a. Loc a => FInfo a -> ErrorMap a
errorMap FInfo a
fi = [(SrcSpan, a)] -> HashMap SrcSpan a
forall k v. Hashable k => [(k, v)] -> HashMap k v
HashMap.fromList [ (a -> SrcSpan
forall a. Loc a => a -> SrcSpan
srcSpan a
a, a
a) | a
a <- [a]
anns ]
where
anns :: [a]
anns = [ SubC a -> a
forall (c :: * -> *) a. TaggedC c a => c a -> a
sinfo SubC a
c | (Integer
_, SubC a
c) <- HashMap Integer (SubC a) -> [(Integer, SubC a)]
forall k v. HashMap k v -> [(k, v)]
HashMap.toList (FInfo a -> HashMap Integer (SubC a)
forall (c :: * -> *) a. GInfo c a -> HashMap Integer (c a)
Types.cm FInfo a
fi) ]
[a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
++ [ WfC a -> a
forall a. WfC a -> a
winfo WfC a
w | (KVar
_, WfC a
w) <- HashMap KVar (WfC a) -> [(KVar, WfC a)]
forall k v. HashMap k v -> [(k, v)]
HashMap.toList (FInfo a -> HashMap KVar (WfC a)
forall (c :: * -> *) a. GInfo c a -> HashMap KVar (WfC a)
Types.ws FInfo a
fi) ]
[a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
++ [ a
a | (Int
_, (Symbol
_,SortedReft
_, a
a)) <- BindEnv a -> [(Int, (Symbol, SortedReft, a))]
forall a. BindEnv a -> [(Int, (Symbol, SortedReft, a))]
bindEnvToList (FInfo a -> BindEnv a
forall (c :: * -> *) a. GInfo c a -> BindEnv a
Types.bs FInfo a
fi) ]
loudDump :: (Fixpoint a) => Int -> Config -> SInfo a -> IO ()
loudDump :: forall a. Fixpoint a => Int -> Config -> SInfo a -> IO ()
loudDump Int
i Config
cfg SInfo a
si = Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
False ([Char] -> IO ()
writeLoud ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
msg [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Doc -> [Char]
PJ.render (Config -> SInfo a -> Doc
forall a (c :: * -> *).
(Fixpoint a, Fixpoint (c a)) =>
Config -> GInfo c a -> Doc
toFixpoint Config
cfg SInfo a
si))
where
msg :: [Char]
msg = [Char]
"fq file after Uniqify & Rename " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show Int
i [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"\n"
{-# SCC simplifyFInfo #-}
simplifyFInfo :: (NFData a, Fixpoint a, Show a, Loc a)
=> Config -> FInfo a -> IO (ElabParam, SInfo a)
simplifyFInfo :: forall a.
(NFData a, Fixpoint a, Show a, Loc a) =>
Config -> FInfo a -> IO (ElabParam, SInfo a)
simplifyFInfo !Config
cfg !FInfo a
fi0 = do
FInfo a
reducedFi <- Config -> FInfo a -> IO (FInfo a)
forall a. Fixpoint a => Config -> FInfo a -> IO (FInfo a)
reduceFInfo Config
cfg FInfo a
fi0
let fi1 :: FInfo a
fi1 = FInfo a
reducedFi { Types.quals = remakeQual <$> Types.quals reducedFi }
let si0 :: SInfo a
si0 = FInfo a -> SInfo a
forall a. Fixpoint a => FInfo a -> SInfo a
convertFormat FInfo a
fi1
let si1 :: SInfo a
si1 = (Error -> SInfo a)
-> (SInfo a -> SInfo a) -> Either Error (SInfo a) -> SInfo a
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either Error -> SInfo a
forall a. HasCallStack => Error -> a
die SInfo a -> SInfo a
forall a. a -> a
id ( Config -> SInfo a -> Either Error (SInfo a)
forall a. Show a => Config -> SInfo a -> SanitizeM (SInfo a)
sanitize Config
cfg (SInfo a -> Either Error (SInfo a))
-> SInfo a -> Either Error (SInfo a)
forall a b. NFData a => (a -> b) -> a -> b
$!! SInfo a
si0)
Config -> SInfo a -> IO ()
forall (c :: * -> *) a. TaggedC c a => Config -> GInfo c a -> IO ()
graphStatistics Config
cfg SInfo a
si1
let si2 :: SInfo a
si2 = SInfo a -> SInfo a
forall a. SInfo a -> SInfo a
wfcUniqify (SInfo a -> SInfo a) -> SInfo a -> SInfo a
forall a b. NFData a => (a -> b) -> a -> b
$!! SInfo a
si1
let si3 :: SInfo a
si3 = SInfo a -> SInfo a
forall a. NFData a => SInfo a -> SInfo a
renameAll (SInfo a -> SInfo a) -> SInfo a -> SInfo a
forall a b. NFData a => (a -> b) -> a -> b
$!! SInfo a
si2
SInfo a -> ()
forall a. NFData a => a -> ()
rnf SInfo a
si3 () -> IO () -> IO ()
forall a b. a -> b -> b
`seq` IO () -> IO ()
whenLoud (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ Moods -> [Char] -> IO ()
donePhase Moods
Loud [Char]
"Uniqify & Rename"
Int -> Config -> SInfo a -> IO ()
forall a. Fixpoint a => Int -> Config -> SInfo a -> IO ()
loudDump Int
1 Config
cfg SInfo a
si3
let si4 :: SInfo a
si4 = Config -> SInfo a -> SInfo a
forall a. Fixpoint a => Config -> SInfo a -> SInfo a
defunctionalize Config
cfg (SInfo a -> SInfo a) -> SInfo a -> SInfo a
forall a b. NFData a => (a -> b) -> a -> b
$!! SInfo a
si3
Int -> Config -> SInfo a -> IO ()
forall a. Fixpoint a => Int -> Config -> SInfo a -> IO ()
loudDump Int
2 Config
cfg SInfo a
si4
let ef :: ElabFlags
ef = Config -> ElabFlags
solverFlags Config
cfg
elabParam :: ElabParam
elabParam = ElabFlags -> Located [Char] -> SymEnv -> ElabParam
ElabParam
ElabFlags
ef
(SrcSpan -> [Char] -> Located [Char]
forall l b. Loc l => l -> b -> Located b
atLoc SrcSpan
dummySpan [Char]
"solver")
(ElabFlags -> SymEnv -> SymEnv
coerceEnv ElabFlags
ef (Config -> SInfo a -> SymEnv
forall a. HasCallStack => Config -> SInfo a -> SymEnv
symbolEnv Config
cfg SInfo a
si4))
si5 :: SInfo a
si5 = ElabParam -> SInfo a -> SInfo a
forall a. (Elaborate a, HasCallStack) => ElabParam -> a -> a
elaborate ElabParam
elabParam SInfo a
si4
Int -> Config -> SInfo a -> IO ()
forall a. Fixpoint a => Int -> Config -> SInfo a -> IO ()
loudDump Int
3 Config
cfg SInfo a
si5
let si6 :: SInfo a
si6 = if Config -> Bool
extensionality Config
cfg then Config -> SInfo a -> SInfo a
forall a. Config -> SInfo a -> SInfo a
expand Config
cfg SInfo a
si5 else SInfo a
si5
(ElabParam, SInfo a) -> IO (ElabParam, SInfo a)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (ElabParam
elabParam, SInfo a
si6)
reduceFInfo :: Fixpoint a => Config -> FInfo a -> IO (FInfo a)
reduceFInfo :: forall a. Fixpoint a => Config -> FInfo a -> IO (FInfo a)
reduceFInfo Config
cfg FInfo a
fi = do
let simplifiedFi :: FInfo a
simplifiedFi = Config -> FInfo a -> FInfo a
forall a. Config -> FInfo a -> FInfo a
simplifyBindings Config
cfg FInfo a
fi
reducedFi :: FInfo a
reducedFi = FInfo a -> FInfo a
forall a. FInfo a -> FInfo a
reduceEnvironments FInfo a
simplifiedFi
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Config -> Bool
save Config
cfg) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
Config -> FInfo a -> IO ()
forall a. Fixpoint a => Config -> FInfo a -> IO ()
savePrettifiedQuery Config
cfg FInfo a
reducedFi
if Config -> Bool
noEnvReduction Config
cfg then
FInfo a -> IO (FInfo a)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return FInfo a
fi
else
FInfo a -> IO (FInfo a)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return FInfo a
reducedFi
solveNative' :: forall a.
(NFData a, Fixpoint a, Show a, Loc a, PPrint a) =>
Config -> FInfo a -> IO (Result (Integer, a))
solveNative' !Config
cfg !FInfo a
fi0 = do
(ElabParam
elabParam, SInfo a
si6) <- Config -> FInfo a -> IO (ElabParam, SInfo a)
forall a.
(NFData a, Fixpoint a, Show a, Loc a) =>
Config -> FInfo a -> IO (ElabParam, SInfo a)
simplifyFInfo Config
cfg FInfo a
fi0
Result (Integer, a)
res0 <- Config -> ElabParam -> SInfo a -> IO (Result (Integer, a))
forall a.
(NFData a, Fixpoint a, Show a, Loc a) =>
Config -> ElabParam -> SInfo a -> IO (Result (Integer, a))
Sol.solve Config
cfg ElabParam
elabParam (SInfo a -> IO (Result (Integer, a)))
-> SInfo a -> IO (Result (Integer, a))
forall a b. NFData a => (a -> b) -> a -> b
$!! SInfo a
si6
let res :: Result (Integer, a)
res = Config -> Result (Integer, a) -> Result (Integer, a)
forall a. Config -> Result a -> Result a
simplifyResult Config
cfg Result (Integer, a)
res0
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Config -> Bool
save Config
cfg) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ Config -> Result (Integer, a) -> IO ()
forall a. Config -> Result a -> IO ()
saveSolution Config
cfg Result (Integer, a)
res
Result (Integer, a) -> IO (Result (Integer, a))
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Result (Integer, a)
res
parseFInfo :: [FilePath] -> IO (FInfo a)
parseFInfo :: forall a. [[Char]] -> IO (FInfo a)
parseFInfo [[Char]]
fs = [FInfo a] -> FInfo a
forall a. Monoid a => [a] -> a
mconcat ([FInfo a] -> FInfo a) -> IO [FInfo a] -> IO (FInfo a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ([Char] -> IO (FInfo a)) -> [[Char]] -> IO [FInfo a]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM [Char] -> IO (FInfo a)
forall a. [Char] -> IO (FInfo a)
parseFI [[Char]]
fs
parseFI :: FilePath -> IO (FInfo a)
parseFI :: forall a. [Char] -> IO (FInfo a)
parseFI [Char]
f = do
[Char]
str <- [Char] -> IO [Char]
readFile [Char]
f
let fi :: FInfo ()
fi = [Char] -> [Char] -> FInfo ()
forall a. Inputable a => [Char] -> [Char] -> a
rr' [Char]
f [Char]
str :: FInfo ()
GInfo SubC a -> IO (GInfo SubC a)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (GInfo SubC a -> IO (GInfo SubC a))
-> GInfo SubC a -> IO (GInfo SubC a)
forall a b. (a -> b) -> a -> b
$ GInfo SubC a
forall a. Monoid a => a
mempty { Types.quals = Types.quals fi
, Types.gLits = Types.gLits fi
, Types.dLits = Types.dLits fi }
saveSolution :: Config -> Result a -> IO ()
saveSolution :: forall a. Config -> Result a -> IO ()
saveSolution Config
cfg Result a
res = Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Config -> Bool
save Config
cfg) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
let f :: [Char]
f = Ext -> Config -> [Char]
queryFile Ext
Out Config
cfg
[Char] -> IO ()
putStrLn ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
"Saving Solution: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
f [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"\n"
[Char] -> IO ()
ensurePath [Char]
f
[Char] -> [Char] -> IO ()
writeFile [Char]
f ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [[Char]] -> [Char]
unlines ([[Char]] -> [Char]) -> [[Char]] -> [Char]
forall a b. (a -> b) -> a -> b
$
[ [Char]
""
, [Char]
"Solution:"
, FixSolution -> [Char]
scopedRender (Result a -> FixSolution
forall a. Result a -> FixSolution
resSolution Result a
res)
] [[Char]] -> [[Char]] -> [[Char]]
forall a. [a] -> [a] -> [a]
++
[ [Char]
""
, [Char]
""
, [Char]
"Non-cut kvars:"
, [Char]
""
, FixSolution -> [Char]
scopedRender ((Delayed Expr -> Expr) -> FixDelayedSolution -> FixSolution
forall v1 v2 k. (v1 -> v2) -> HashMap k v1 -> HashMap k v2
HashMap.map Delayed Expr -> Expr
forall a. Delayed a -> a
forceDelayed (FixDelayedSolution -> FixSolution)
-> FixDelayedSolution -> FixSolution
forall a b. (a -> b) -> a -> b
$ Result a -> FixDelayedSolution
forall a. Result a -> FixDelayedSolution
resNonCutsSolution Result a
res)
]
where
scopedRender :: FixSolution -> [Char]
scopedRender = Doc -> [Char]
PJ.render (Doc -> [Char]) -> (FixSolution -> Doc) -> FixSolution -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Doc] -> Doc
PJ.vcat ([Doc] -> Doc) -> (FixSolution -> [Doc]) -> FixSolution -> Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((KVar, [(Symbol, Sort)], Expr) -> Doc)
-> [(KVar, [(Symbol, Sort)], Expr)] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map (KVar, [(Symbol, Sort)], Expr) -> Doc
forall {a} {a} {a}.
(PPrint a, PPrint a, PPrint a) =>
(a, a, a) -> Doc
ncDoc ([(KVar, [(Symbol, Sort)], Expr)] -> [Doc])
-> (FixSolution -> [(KVar, [(Symbol, Sort)], Expr)])
-> FixSolution
-> [Doc]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FixSolution -> [(KVar, [(Symbol, Sort)], Expr)]
forall {c}. HashMap KVar c -> [(KVar, [(Symbol, Sort)], c)]
scoped
scoped :: HashMap KVar c -> [(KVar, [(Symbol, Sort)], c)]
scoped HashMap KVar c
sol = [ (KVar
k, KVar -> [(Symbol, Sort)]
scope KVar
k, c
e) | (KVar
k, c
e) <- HashMap KVar c -> [(KVar, c)]
forall k v. HashMap k v -> [(k, v)]
HashMap.toList HashMap KVar c
sol]
scope :: KVar -> [(Symbol, Sort)]
scope KVar
k = [(Symbol, Sort)] -> KVar -> ResultSorts -> [(Symbol, Sort)]
forall k v. Hashable k => v -> k -> HashMap k v -> v
HashMap.lookupDefault [] KVar
k (ResultSorts -> [(Symbol, Sort)])
-> ResultSorts -> [(Symbol, Sort)]
forall a b. (a -> b) -> a -> b
$ Result a -> ResultSorts
forall a. Result a -> ResultSorts
resSorts Result a
res
ncDoc :: (a, a, a) -> Doc
ncDoc (a
k, a
xts, a
e) = [Doc] -> Doc
PJ.hsep [ a -> Doc
forall a. PPrint a => a -> Doc
pprint a
k Doc -> Doc -> Doc
PJ.<> a -> Doc
forall a. PPrint a => a -> Doc
pprint a
xts, Doc
":=", a -> Doc
forall a. PPrint a => a -> Doc
pprint a
e ]
simplifyResult :: Config -> Result a -> Result a
simplifyResult :: forall a. Config -> Result a -> Result a
simplifyResult Config
cfg Result a
res =
Result a
res
{ resSolution = HashMap.map simplifyKVar' (resSolution res)
, resNonCutsSolution = HashMap.map (fmap simplifyKVar') (resNonCutsSolution res)
}
where
simplifyKVar' :: Expr -> Expr
simplifyKVar' = Expr -> Expr
unElabSets (Expr -> Expr) -> (Expr -> Expr) -> Expr -> Expr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Expr -> Expr
unElab (Expr -> Expr) -> (Expr -> Expr) -> Expr -> Expr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HashSet Symbol -> Expr -> Expr
Sol.simplifyKVar HashSet Symbol
forall a. HashSet a
HashSet.empty
sets :: Bool
sets = ElabFlags -> Bool
elabSetBag (ElabFlags -> Bool) -> (Config -> ElabFlags) -> Config -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Config -> ElabFlags
solverFlags (Config -> Bool) -> Config -> Bool
forall a b. (a -> b) -> a -> b
$ Config
cfg
unElabSets :: Expr -> Expr
unElabSets = if Bool
sets then Expr -> Expr
unElabFSetBagZ3 else Expr -> Expr
forall a. a -> a
id