-- | This module implements the top-level API for interfacing with Fixpoint
--   In particular it exports the functions that solve constraints supplied
--   either as .fq files or as FInfo.
{-# LANGUAGE BangPatterns        #-}
{-# LANGUAGE DoAndIfThenElse     #-}
{-# LANGUAGE OverloadedStrings   #-}
{-# LANGUAGE ScopedTypeVariables #-}

module Language.Fixpoint.Solver (
    -- * Invoke Solver on an FInfo
    solve

    -- * Invoke Solver on a .fq file
  , solveFQ

    -- * Function to determine outcome
  , resultExit
  , resultExitCode

    -- * Parse Qualifiers from File
  , parseFInfo

    -- * Simplified Info
  , 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

---------------------------------------------------------------------------
-- | Solve an .fq file ----------------------------------------------------
---------------------------------------------------------------------------
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 FInfo system of horn-clause constraints -----------------------------
--------------------------------------------------------------------------------
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  = {- SCC "parsefq" -} [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')

--------------------------------------------------------------------------------
-- | Solve in parallel after partitioning an FInfo to indepdendant parts
--------------------------------------------------------------------------------
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
  -- putStrLn "Using Parallel Solver \n"
  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

--------------------------------------------------------------------------------
-- | Solve a list of FInfos using the provided solver function in parallel
--------------------------------------------------------------------------------
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


--------------------------------------------------------------------------------
-- | Native Haskell Solver -----------------------------------------------------
--------------------------------------------------------------------------------
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

-- | Unpleasant hack to save meta-data that can be recovered from SrcSpan
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)

-- The order is important here: we want the "binders" to get the "precedence"
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
  -- writeLoud $ "fq file in: \n" ++ render (toFixpoint cfg fi)
  -- rnf fi0 `seq` donePhase Loud "Read Constraints"
  -- let qs   = quals fi0
  -- whenLoud $ print qs
  -- whenLoud $ putStrLn $ showFix (quals fi1)
  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   = {- SCC "convertFormat" -} FInfo a -> SInfo a
forall a. Fixpoint a => FInfo a -> SInfo a
convertFormat FInfo a
fi1
  -- writeLoud $ "fq file after format convert: \n" ++ render (toFixpoint cfg si0)
  -- rnf si0 `seq` donePhase Loud "Format Conversion"
  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 ({- SCC "sanitize" -} 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)
  -- writeLoud $ "fq file after sanitize: \n" ++ render (toFixpoint cfg si1)
  -- rnf si1 `seq` donePhase Loud "Validated Constraints"
  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  = {- SCC "wfcUniqify" -} 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
  -- writeLoud $ "fq file after wfcUniqify: \n" ++ render (toFixpoint cfg si2)
  let si3 :: SInfo a
si3  = {- SCC "renameAll"  -} 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  = {- SCC "defunction" -} 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
  -- writeLoud $ "fq file after defunc: \n" ++ render (toFixpoint cfg si4)
  -- putStrLn $ "AXIOMS: " ++ showpp (asserts si4)
  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
  -- writeLoud $ "fq file after elaborate: \n" ++ render (toFixpoint cfg si5)
  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 {- SCC "expand" -} 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){- SCC "elaborate" -}

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 = {- SCC "simplifyFInfo" -} Config -> FInfo a -> FInfo a
forall a. Config -> FInfo a -> FInfo a
simplifyBindings Config
cfg FInfo a
fi
      reducedFi :: FInfo a
reducedFi = {- SCC "reduceEnvironments" -} 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 <- {- SCC "Sol.solve" -} 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
  -- rnf soln `seq` donePhase Loud "Solve2"
  --let stat = resStatus res
  -- saveSolution cfg 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
$ Config -> Result (Integer, a) -> IO ()
forall a. Config -> Result a -> IO ()
saveSolution Config
cfg Result (Integer, a)
res
  -- writeLoud $ "\nSolution:\n"  ++ showpp (resSolution res)
  -- colorStrLn (colorResult stat) (show stat)
  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

--------------------------------------------------------------------------------
-- | Parse External Qualifiers -------------------------------------------------
--------------------------------------------------------------------------------
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