<commit_before>{-# Language DeriveDataTypeable #-} -- for GHC <= 7.8
-- |
-- Module      : Test.Speculate.CondReason
-- Copyright   : (c) 2016-2017 <NAME>
-- License     : 3-Clause BSD  (see the file LICENSE)
-- Maintainer  : <NAME> <<EMAIL>>
--
-- This module is part o Speculate.
--
-- Arguments to the 'speculate' function and parsing of command line arguments.
module Test.Speculate.Args
  ( Args (..)
  , args

  , foreground
  , background

  , getArgs
  , computeMaxSemiSize
  , computeMaxCondSize
  , computeInstances
  , types
  , atoms
  , compareExpr
  , keepExpr
  , timeout
  , shouldShowEquation
  , shouldShowConditionalEquation
  , reallyShowConditions

  -- TODO: remove the following exports eventually:
  , prepareArgs
  , module System.Console.CmdArgs.Explicit
  )
where

import Test.Speculate.Expr
import Test.Speculate.Utils
import System.Console.CmdArgs.Explicit

import qualified Data.List as L (insert)
import Data.List hiding (insert)
import Data.Maybe (catMaybes)
import Data.Monoid ((<>))


-- | Arguments to Speculate
data Args = Args
  { maxSize     :: Int         -- ^ maximum size of considered expressions
  , maxTests    :: Int         -- ^ maximum number of test for each law
  , constants   :: [Expr]      -- ^ constants considered when generating expressions
  , instances   :: [Instances] -- ^ typeclass instance information for @Eq@, @Ord@ and @Listable@
  , maxSemiSize :: Int         -- ^ maximum size of inqualities RHS/LHS
  , maxCondSize :: Int         -- ^ maximum size of considered condition
  , maxVars     :: Int         -- ^ maximum number of variables allowed in inequalities and conditional equations

  , showConstants     :: Bool  -- ^ repeat constants on output
  , showEquations     :: Bool  -- ^ whether to show equations
  , showSemiequations :: Bool  -- ^ whether to show inequalties
  , showConditions    :: Bool  -- ^ whether to show conditional equations
  , showConstantLaws  :: Bool  -- ^ whether to show laws with no variables

  , minTests    :: Int -> Int  -- ^ __(intermediary)__ minimum number of tests
                               --   for passing postconditions in function of
                               --   maximum number of tests
  , maxConstants :: Maybe Int  -- ^ __(intermediary)__ maximum nubmer of constants allowed when considering expressions
  , maxDepth     :: Maybe Int  -- ^ __(intermediary)__ maximum depth of considered expressions
  , showCounts   :: Bool       -- ^ __(intermediary)__ show counts of equations, inequalities and conditional equations
  , showTheory   :: Bool       -- ^ __(debug)__ whether to show raw theory
  , showArgs     :: Bool       -- ^ __(debug)__ show _this_ args before running
  , showHelp     :: Bool       -- ^ __(advanced)__ whether to show the command line help
  , evalTimeout :: Maybe Double -- ^ __(advanced)__ timeout when evaluating ground expressions
  , force        :: Bool       -- ^ __(advanced)__ ignore errors
  , extra        :: [String]   -- ^ __(advanced)__ unused, user-defined meaning
  , exclude      :: [String]   -- ^ __(advanced)__ exclude this symbols from signature before running
  , onlyTypes    :: [String]   -- ^ __(advanced)__ only allow those types at top-level equations / semi-equations
  , showClassesFor :: [Int]    -- ^ __(advanced)__ show equivalence classes of expressions
  , showDot      :: Bool       -- ^ __(advanced)__ whether to show a Graphviz dotfile with an Ord lattice
  , quietDot     :: Bool       -- ^ __(advanced)__ whether to show a Graphviz dotfiel with an Ord lattice (less verbose)
  }
  deriving Typeable -- for GHC <= 7.8
-- TODO: future options:
--, closureLimit      :: Int
--, order             :: OptOrder  -- data OptOrder = Dershowitz | KnuthBendix
--, maxRuleSize       :: Maybe Int
--, maxEquationSize   :: Maybe Int
--, keepRewriteRules  :: Bool
-- Maybe add an empty Thy here.

-- | Default arguments to Speculate
args :: Args
args = Args
  { maxSize              = 5
  , maxTests             = 500
  , minTests             = \n -> n `div` 20 -- defaults to 5% of maxTests
  , maxSemiSize          = -1
  , maxCondSize          = -1
  , maxDepth             = Nothing
  , instances            = []
  , showConstants        = True
  , showArgs             = True
  , showTheory           = False
  , showEquations        = True
  , showSemiequations    = True
  , showConditions       = True
  , showConstantLaws     = False
  , showCounts           = False
  , showDot              = False
  , quietDot             = False
  , showClassesFor       = []
  , maxVars              = 2
  , maxConstants         = Nothing
  , evalTimeout          = Nothing
--, closureLimit         = 2
--, order                = Dershowitz
--, maxRuleSize          = Nothing
--, maxEquationSize      = Nothing
--, keepRewriteRules     = False
  , showHelp             = False
  , force                = False
  , extra                = []
  , constants            = []
  , exclude              = []
  , onlyTypes            = []
  }


computeMaxSemiSize :: Args -> Int
computeMaxSemiSize args
  | maxSemiSize args > 0 = maxSemiSize args
  | otherwise            = maxSize args + maxSemiSize args

computeMaxCondSize :: Args -> Int
computeMaxCondSize args
  | maxCondSize args > 0 = maxCondSize args
  | otherwise            = maxSize args + maxCondSize args

computeInstances :: Args -> Instances
computeInstances args = concat (instances args) ++ preludeInstances

shouldShow2 :: Args -> (Expr,Expr) -> Bool
shouldShow2 args (e1,e2) = showConstantLaws args || hasVar e1 || hasVar e2
-- `allAbout` constants // (conditionAtoms `union` equationAtoms)

shouldShowEquation :: Args -> (Expr,Expr) -> Bool
shouldShowEquation args (e1,e2) =
  shouldShow2 args (e1,e2) && (e1 `about` fore || e2 `about` fore)
  where
  fore = foregroundConstants args

shouldShow3 :: Args -> (Expr,Expr,Expr) -> Bool
shouldShow3 args (e1,e2,e3) = showConstantLaws args
                           || hasVar e1 || hasVar e2 || hasVar e3

shouldShowConditionalEquation :: Args -> (Expr,Expr,Expr) -> Bool
shouldShowConditionalEquation args (ce,e1,e2) = shouldShow3 args (ce,e1,e2)
                                             && cem ce e1 e2
                                             && (ce `about` fore
                                              || e1 `about` fore
                                              || e2 `about` fore)
  where
  cem = condEqualM (computeInstances args) (maxTests args) (minTests args (maxTests args))
  fore = foregroundConstants args

keepExpr :: Args -> Expr -> Bool
keepExpr Args{maxConstants = Just n} e | length (consts e) > n = False
keepExpr Args{maxDepth     = Just n} e |         depthE e  > n = False
keepExpr _                           _                         = True

reallyShowConditions :: Args -> Bool
reallyShowConditions args = showConditions args
                         && boolTy `elem` map (finalResultTy . typ) (allConstants args)

atoms :: Args -> [Expr]
atoms args = nubSort (map holeOfTy ts)
     `union` allConstants args
     `union` [showConstant True  | showConds || showDot args]
     `union` [showConstant False | showConds || showDot args]
     `union` (nubSort . catMaybes) [eqE is t | showConds, t <- ts]
  where
  ts = types args
  is = computeInstances args<commit_msg>Speculate.Args.atoms: add TODO<commit_after>{-# Language DeriveDataTypeable #-} -- for GHC <= 7.8
-- |
-- Module      : Test.Speculate.CondReason
-- Copyright   : (c) 2016-2017 <NAME>
-- License     : 3-Clause BSD  (see the file LICENSE)
-- Maintainer  : <NAME> <<EMAIL>>
--
-- This module is part o Speculate.
--
-- Arguments to the 'speculate' function and parsing of command line arguments.
module Test.Speculate.Args
  ( Args (..)
  , args

  , foreground
  , background

  , getArgs
  , computeMaxSemiSize
  , computeMaxCondSize
  , computeInstances
  , types
  , atoms
  , compareExpr
  , keepExpr
  , timeout
  , shouldShowEquation
  , shouldShowConditionalEquation
  , reallyShowConditions

  -- TODO: remove the following exports eventually:
  , prepareArgs
  , module System.Console.CmdArgs.Explicit
  )
where

import Test.Speculate.Expr
import Test.Speculate.Utils
import System.Console.CmdArgs.Explicit

import qualified Data.List as L (insert)
import Data.List hiding (insert)
import Data.Maybe (catMaybes)
import Data.Monoid ((<>))


-- | Arguments to Speculate
data Args = Args
  { maxSize     :: Int         -- ^ maximum size of considered expressions
  , maxTests    :: Int         -- ^ maximum number of test for each law
  , constants   :: [Expr]      -- ^ constants considered when generating expressions
  , instances   :: [Instances] -- ^ typeclass instance information for @Eq@, @Ord@ and @Listable@
  , maxSemiSize :: Int         -- ^ maximum size of inqualities RHS/LHS
  , maxCondSize :: Int         -- ^ maximum size of considered condition
  , maxVars     :: Int         -- ^ maximum number of variables allowed in inequalities and conditional equations

  , showConstants     :: Bool  -- ^ repeat constants on output
  , showEquations     :: Bool  -- ^ whether to show equations
  , showSemiequations :: Bool  -- ^ whether to show inequalties
  , showConditions    :: Bool  -- ^ whether to show conditional equations
  , showConstantLaws  :: Bool  -- ^ whether to show laws with no variables

  , minTests    :: Int -> Int  -- ^ __(intermediary)__ minimum number of tests
                               --   for passing postconditions in function of
                               --   maximum number of tests
  , maxConstants :: Maybe Int  -- ^ __(intermediary)__ maximum nubmer of constants allowed when considering expressions
  , maxDepth     :: Maybe Int  -- ^ __(intermediary)__ maximum depth of considered expressions
  , showCounts   :: Bool       -- ^ __(intermediary)__ show counts of equations, inequalities and conditional equations
  , showTheory   :: Bool       -- ^ __(debug)__ whether to show raw theory
  , showArgs     :: Bool       -- ^ __(debug)__ show _this_ args before running
  , showHelp     :: Bool       -- ^ __(advanced)__ whether to show the command line help
  , evalTimeout :: Maybe Double -- ^ __(advanced)__ timeout when evaluating ground expressions
  , force        :: Bool       -- ^ __(advanced)__ ignore errors
  , extra        :: [String]   -- ^ __(advanced)__ unused, user-defined meaning
  , exclude      :: [String]   -- ^ __(advanced)__ exclude this symbols from signature before running
  , onlyTypes    :: [String]   -- ^ __(advanced)__ only allow those types at top-level equations / semi-equations
  , showClassesFor :: [Int]    -- ^ __(advanced)__ show equivalence classes of expressions
  , showDot      :: Bool       -- ^ __(advanced)__ whether to show a Graphviz dotfile with an Ord lattice
  , quietDot     :: Bool       -- ^ __(advanced)__ whether to show a Graphviz dotfiel with an Ord lattice (less verbose)
  }
  deriving Typeable -- for GHC <= 7.8
-- TODO: future options:
--, closureLimit      :: Int
--, order             :: OptOrder  -- data OptOrder = Dershowitz | KnuthBendix
--, maxRuleSize       :: Maybe Int
--, maxEquationSize   :: Maybe Int
--, keepRewriteRules  :: Bool
-- Maybe add an empty Thy here.

-- | Default arguments to Speculate
args :: Args
args = Args
  { maxSize              = 5
  , maxTests             = 500
  , minTests             = \n -> n `div` 20 -- defaults to 5% of maxTests
  , maxSemiSize          = -1
  , maxCondSize          = -1
  , maxDepth             = Nothing
  , instances            = []
  , showConstants        = True
  , showArgs             = True
  , showTheory           = False
  , showEquations        = True
  , showSemiequations    = True
  , showConditions       = True
  , showConstantLaws     = False
  , showCounts           = False
  , showDot              = False
  , quietDot             = False
  , showClassesFor       = []
  , maxVars              = 2
  , maxConstants         = Nothing
  , evalTimeout          = Nothing
--, closureLimit         = 2
--, order                = Dershowitz
--, maxRuleSize          = Nothing
--, maxEquationSize      = Nothing
--, keepRewriteRules     = False
  , showHelp             = False
  , force                = False
  , extra                = []
  , constants            = []
  , exclude              = []
  , onlyTypes            = []
  }


computeMaxSemiSize :: Args -> Int
computeMaxSemiSize args
  | maxSemiSize args > 0 = maxSemiSize args
  | otherwise            = maxSize args + maxSemiSize args

computeMaxCondSize :: Args -> Int
computeMaxCondSize args
  | maxCondSize args > 0 = maxCondSize args
  | otherwise            = maxSize args + maxCondSize args

computeInstances :: Args -> Instances
computeInstances args = concat (instances args) ++ preludeInstances

shouldShow2 :: Args -> (Expr,Expr) -> Bool
shouldShow2 args (e1,e2) = showConstantLaws args || hasVar e1 || hasVar e2
-- `allAbout` constants // (conditionAtoms `union` equationAtoms)

shouldShowEquation :: Args -> (Expr,Expr) -> Bool
shouldShowEquation args (e1,e2) =
  shouldShow2 args (e1,e2) && (e1 `about` fore || e2 `about` fore)
  where
  fore = foregroundConstants args

shouldShow3 :: Args -> (Expr,Expr,Expr) -> Bool
shouldShow3 args (e1,e2,e3) = showConstantLaws args
                           || hasVar e1 || hasVar e2 || hasVar e3

shouldShowConditionalEquation :: Args -> (Expr,Expr,Expr) -> Bool
shouldShowConditionalEquation args (ce,e1,e2) = shouldShow3 args (ce,e1,e2)
                                             && cem ce e1 e2
                                             && (ce `about` fore
                                              || e1 `about` fore
                                              || e2 `about` fore)
  where
  cem = condEqualM (computeInstances args) (maxTests args) (minTests args (maxTests args))
  fore = foregroundConstants args

keepExpr :: Args -> Expr -> Bool
keepExpr Args{maxConstants = Just n} e | length (consts e) > n = False
keepExpr Args{maxDepth     = Just n} e |         depthE e  > n = False
keepExpr _                           _                         = True

reallyShowConditions :: Args -> Bool
reallyShowConditions args = showConditions args
                         && boolTy `elem` map (finalResultTy . typ) (allConstants args)

atoms :: Args -> [Expr]
atoms args = nubSort (map holeOfTy ts)
     `union` allConstants args
     `union` [showConstant True  | showConds || showDot args]
     `union` [showConstant False | showConds || showDot args]
     `union` (nubSort . catMaybes) [eqE is t | showConds, t <- ts]
-- TODO:
--        \/ foldr (\/) [tiersE is t | t <- ts]
-- somehow discard repetitions here, make it not very slow
-- but I don't have to care that much, we aren't going past tier 7 anytime
-- soon.
  where
  ts = types args
  is = computeInstances args
{'fraction_non_alphanumeric': 0.09788413438788617, 'fraction_numerical': 0.007638748056513216, 'mean_word_length': 2.1658463513802695, 'pattern_counts': {'":': 0, '<': 20, '<?xml version=': 0, '>': 55, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 24, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1330799', 'n_tokens_mistral': 4232, 'n_tokens_neox': 4110, 'n_words': 1337}