packages feed

g2-0.2.0.0: src/G2/Liquid/Config.hs

module G2.Liquid.Config ( LHConfig (..)
                        , Counterfactual (..)
                        , CFModules (..)
                        , BlockErrorsMethod (..)
                        , getLHConfig
                        , mkLHConfig
                        , mkLHConfigDirect) where

import G2.Config.Config

import qualified Data.HashSet as S
import qualified Data.Map.Lazy as M
import Data.Monoid ((<>))
import qualified Data.Text as T
import Options.Applicative
import System.Directory

data Counterfactual = Counterfactual CFModules | NotCounterfactual deriving (Eq, Show, Read)

data CFModules = CFAll | CFOnly (S.HashSet (T.Text, Maybe T.Text)) deriving (Eq, Show, Read)

data BlockErrorsMethod = ArbBlock
                       | AssumeBlock deriving (Eq, Show, Read)

data LHConfig = LHConfig {
      cut_off :: Int -- ^ How many steps to take after finding an equally good equiv state, in LH mode
    , switch_after :: Int --- ^ How many steps to take in a single step, in LH mode
    , counterfactual :: Counterfactual -- ^ Which functions should be able to generate abstract counterexamples
    , only_top :: Bool -- ^ Only try to find counterexamples in the very first function definition, or directly called functions?
    , block_errors_in :: (S.HashSet (T.Text, Maybe T.Text)) -- ^ Prevents calls from errors occuring in the indicated functions
    , block_errors_method :: BlockErrorsMethod -- ^ Should errors be blocked with an Assume or with an arbitrarily inserted value
    , reduce_abs :: Bool
    , add_tyvars :: Bool
    }

getLHConfig :: IO (String, String, Config, LHConfig)
getLHConfig = do
    homedir <- getHomeDirectory
    execParser (mkConfigInfo homedir)

mkConfigInfo :: String -> ParserInfo (String, String, Config, LHConfig)
mkConfigInfo homedir =
    info (((,,,) <$> getFileName <*> getFunctionName <*> mkConfig homedir <*> mkLHConfig) <**> helper)
          ( fullDesc
          <> progDesc "Allows symbolically executing LiquidHaskell code"
          <> header "The G2 Symbolic Execution Engine" )

getFileName :: Parser String
getFileName = argument str (metavar "FILE")

getFunctionName :: Parser String
getFunctionName = argument str (metavar "FUNCTION")

mkLHConfig :: Parser LHConfig
mkLHConfig = LHConfig
    <$> option auto (long "cut-off"
                   <> metavar "N"
                   <> value 600
                   <> help "how many steps to take after finding an equally good equivalent state, in LH mode ")
    <*> option auto (long "switch-after"
                   <> metavar "N"
                   <> value 300
                   <> help "how many steps to take before switching states, in LH mode ")
    <*> flag (Counterfactual CFAll) (NotCounterfactual) (long "no-counterfactual" <> help "disable counterfactual counterexamples")
    <*> pure False
    <*> pure S.empty
    <*> pure AssumeBlock
    <*> pure True
    <*> pure False


mkLHConfigDirect :: [String] -> M.Map String [String] -> LHConfig
mkLHConfigDirect as m = LHConfig {
      cut_off = strArg "cut-off" as m read 600
    , switch_after = strArg "switch-after" as m read 300
    , counterfactual = boolArg' "counterfactual" as
                        (Counterfactual CFAll) (Counterfactual CFAll) NotCounterfactual
    , only_top = False
    , block_errors_in = S.empty
    , block_errors_method = AssumeBlock
    , reduce_abs = True
    , add_tyvars = False
}