-- | Simple (i.e., non-compound) generators
module Test.Falsify.Reexported.Generator.Simple (
    bool
  , inRange
  , integral
  , enum
  , int
  ) where

import Prelude hiding (properFraction)

import Data.Bits
import Data.Word

import Test.Falsify.Internal.Generator
import Test.Falsify.Internal.Range
import Test.Falsify.Internal.SampleTree (Sample(..), sampleValue)
import Test.Falsify.Reexported.Generator.Precision

import qualified Test.Falsify.Range as Range

{-------------------------------------------------------------------------------
  Simple generators
-------------------------------------------------------------------------------}

-- | Generate random bool, shrink towards the given value
--
-- Chooses with equal probability between 'True' and 'False'.
bool :: Bool -> Gen Bool
bool :: Bool -> Gen Bool
bool Bool
target = Word64 -> Bool
aux forall b c a. (b -> c) -> (a -> b) -> a -> c
. Sample -> Word64
sampleValue forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Sample -> [Word64]) -> Gen Sample
primWith Sample -> [Word64]
shrinker
  where
    aux :: Word64 -> Bool
    aux :: Word64 -> Bool
aux Word64
x | forall a. FiniteBits a => a -> Bool
msbSet Word64
x  = Bool -> Bool
not Bool
target
          | Bool
otherwise = Bool
target

    msbSet :: forall a. FiniteBits a => a -> Bool
    msbSet :: forall a. FiniteBits a => a -> Bool
msbSet a
x = forall a. Bits a => a -> Int -> Bool
testBit a
x (forall b. FiniteBits b => b -> Int
finiteBitSize (forall a. HasCallStack => a
undefined :: a) forall a. Num a => a -> a -> a
- Int
1)

    shrinker :: Sample -> [Word64]
    shrinker :: Sample -> [Word64]
shrinker (Shrunk Word64
0) = []
    shrinker Sample
_          = [Word64
0]

{-------------------------------------------------------------------------------
  Integral ranges
-------------------------------------------------------------------------------}

-- | Generate value in the specified range
inRange :: Range a -> Gen a
inRange :: forall a. Range a -> Gen a
inRange Range a
r = forall (f :: * -> *) a.
Applicative f =>
(Precision -> f ProperFraction) -> Range a -> f a
Range.eval HasCallStack => Precision -> Gen ProperFraction
properFraction Range a
r

-- | Deprecated alias for 'inRange'
integral :: Range a -> Gen a
{-# DEPRECATED integral "Use inRange instead" #-}
integral :: forall a. Range a -> Gen a
integral = forall a. Range a -> Gen a
inRange

-- | Deprecated alias for 'inRange'
enum :: Range a -> Gen a
{-# DEPRECATED enum "Use inRange instead" #-}
enum :: forall a. Range a -> Gen a
enum = forall a. Range a -> Gen a
inRange

-- | Type-specialization of 'inRange'
int :: Range Int -> Gen Int
int :: Range Int -> Gen Int
int = forall a. Range a -> Gen a
inRange