    {-# LANGUAGE CPP #-}
    module Runner (
      runModules
    , Summary(..)

    #ifdef TEST
    , Report
    , ReportState (..)
    , report
    , report_
    #endif
    ) where

    import           Prelude hiding (putStr, putStrLn, error)

    #if __GLASGOW_HASKELL__ < 710
    import           Data.Monoid hiding ((<>))
    import           Control.Applicative
    #endif

    import           Control.Monad hiding (forM_)
    import           Text.Printf (printf)
    import           System.IO (hPutStrLn, hPutStr, stderr, hIsTerminalDevice)
    import           Data.Foldable (forM_)

    import           Control.Monad.Trans.State
    import           Control.Monad.IO.Class

    import           Interpreter (Interpreter)
    import qualified Interpreter
    import           Parse
    import           Location
    import           Property
    import           Runner.Example

    -- | Summary of a test run.
    data Summary = Summary {
      Summary -> Int
    sExamples :: Int
    , Summary -> Int
    sTried    :: Int
    , Summary -> Int
    sErrors   :: Int
    , Summary -> Int
    sFailures :: Int
    } deriving Summary -> Summary -> Bool
    (Summary -> Summary -> Bool)
    -> (Summary -> Summary -> Bool) -> Eq Summary
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    /= :: Summary -> Summary -> Bool
    $c/= :: Summary -> Summary -> Bool
    == :: Summary -> Summary -> Bool
    $c== :: Summary -> Summary -> Bool
    Eq

    -- | Format a summary.
    instance Show Summary where
      show :: Summary -> String
    show (Summary examples :: Int
    examples tried :: Int
    tried errors :: Int
    errors failures :: Int
    failures) =
        String -> Int -> Int -> Int -> Int -> String
    forall r. PrintfType r => String -> r
    printf "Examples: %d  Tried: %d  Errors: %d  Failures: %d" Int
    examples Int
    tried Int
    errors Int
    failures

    -- | Sum up summaries.
    instance Monoid Summary where
      mempty :: Summary
    mempty = Int -> Int -> Int -> Int -> Summary
    Summary 0 0 0 0
    #if MIN_VERSION_base(4,11,0)
    instance Semigroup Summary where
      <> :: Summary -> Summary -> Summary
    (<>)
    #else
      mappend
    #endif
        (Summary x1 :: Int
    x1 x2 :: Int
    x2 x3 :: Int
    x3 x4 :: Int
    x4) (Summary y1 :: Int
    y1 y2 :: Int
    y2 y3 :: Int
    y3 y4 :: Int
    y4) = Int -> Int -> Int -> Int -> Summary
    Summary (Int
    x1 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    y1) (Int
    x2 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    y2) (Int
    x3 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    y3) (Int
    x4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    y4)

    -- | Run all examples from a list of modules.
    runModules :: Bool -> Bool -> Bool -> Interpreter -> [Module [Located DocTest]] -> IO Summary
    runModules :: Bool
    -> Bool
    -> Bool
    -> Interpreter
    -> [Module [Located DocTest]]
    -> IO Summary
    runModules fastMode :: Bool
    fastMode preserveIt :: Bool
    preserveIt verbose :: Bool
    verbose repl :: Interpreter
    repl modules :: [Module [Located DocTest]]
    modules = do
      Bool
    isInteractive <- Handle -> IO Bool
    hIsTerminalDevice Handle
    stderr
      ReportState _ _ _ s :: Summary
    s <- (StateT ReportState IO () -> ReportState -> IO ReportState
    forall (m :: * -> *) s a. Monad m => StateT s m a -> s -> m s
    `execStateT` Int -> Bool -> Bool -> Summary -> ReportState
    ReportState 0 Bool
    isInteractive Bool
    verbose Summary
    forall a. Monoid a => a
    mempty {sExamples :: Int
    sExamples = Int
    c}) (StateT ReportState IO () -> IO ReportState)
    -> StateT ReportState IO () -> IO ReportState
    forall a b. (a -> b) -> a -> b
    $ do
        [Module [Located DocTest]]
    -> (Module [Located DocTest] -> StateT ReportState IO ())
    -> StateT ReportState IO ()
    forall (t :: * -> *) (m :: * -> *) a b.
    (Foldable t, Monad m) =>
    t a -> (a -> m b) -> m ()
    forM_ [Module [Located DocTest]]
    modules ((Module [Located DocTest] -> StateT ReportState IO ())
     -> StateT ReportState IO ())
    -> (Module [Located DocTest] -> StateT ReportState IO ())
    -> StateT ReportState IO ()
    forall a b. (a -> b) -> a -> b
    $ Bool
    -> Bool
    -> Interpreter
    -> Module [Located DocTest]
    -> StateT ReportState IO ()
    runModule Bool
    fastMode Bool
    preserveIt Interpreter
    repl

        String -> StateT ReportState IO ()
    verboseReport "# Final summary:"
        (ReportState -> String) -> StateT ReportState IO String
    forall (m :: * -> *) s a. Monad m => (s -> a) -> StateT s m a
    gets (Summary -> String
    forall a. Show a => a -> String
    show (Summary -> String)
    -> (ReportState -> Summary) -> ReportState -> String
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ReportState -> Summary
    reportStateSummary) StateT ReportState IO String
    -> (String -> StateT ReportState IO ()) -> StateT ReportState IO ()
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= String -> StateT ReportState IO ()
    report

      Summary -> IO Summary
    forall (m :: * -> *) a. Monad m => a -> m a
    return Summary
    s
      where
        c :: Int
    c = ([Int] -> Int
    forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
    sum ([Int] -> Int)
    -> ([Module [Located DocTest]] -> [Int])
    -> [Module [Located DocTest]]
    -> Int
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Module [Located DocTest] -> Int)
    -> [Module [Located DocTest]] -> [Int]
    forall a b. (a -> b) -> [a] -> [b]
    map Module [Located DocTest] -> Int
    count) [Module [Located DocTest]]
    modules

    -- | Count number of expressions in given module.
    count :: Module [Located DocTest] -> Int
    count :: Module [Located DocTest] -> Int
    count (Module _ setup :: Maybe [Located DocTest]
    setup tests :: [[Located DocTest]]
    tests) = [Int] -> Int
    forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
    sum (([Located DocTest] -> Int) -> [[Located DocTest]] -> [Int]
    forall a b. (a -> b) -> [a] -> [b]
    map [Located DocTest] -> Int
    forall (t :: * -> *) a. Foldable t => t a -> Int
    length [[Located DocTest]]
    tests) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int -> ([Located DocTest] -> Int) -> Maybe [Located DocTest] -> Int
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe 0 [Located DocTest] -> Int
    forall (t :: * -> *) a. Foldable t => t a -> Int
    length Maybe [Located DocTest]
    setup

    -- | A monad for generating test reports.
    type Report = StateT ReportState IO

    data ReportState = ReportState {
      ReportState -> Int
    reportStateCount        :: Int     -- ^ characters on the current line
    , ReportState -> Bool
    reportStateInteractive  :: Bool    -- ^ should intermediate results be printed?
    , ReportState -> Bool
    reportStateVerbose      :: Bool
    , ReportState -> Summary
    reportStateSummary      :: Summary -- ^ test summary
    }

    -- | Add output to the report.
    report :: String -> Report ()
    report :: String -> StateT ReportState IO ()
    report msg :: String
    msg = do
      String -> StateT ReportState IO ()
    overwrite String
    msg

      -- add a newline, this makes the output permanent
      IO () -> StateT ReportState IO ()
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> StateT ReportState IO ())
    -> IO () -> StateT ReportState IO ()
    forall a b. (a -> b) -> a -> b
    $ Handle -> String -> IO ()
    hPutStrLn Handle
    stderr ""
      (ReportState -> ReportState) -> StateT ReportState IO ()
    forall (m :: * -> *) s. Monad m => (s -> s) -> StateT s m ()
    modify (\st :: ReportState
    st -> ReportState
    st {reportStateCount :: Int
    reportStateCount = 0})

    -- | Add intermediate output to the report.
    --
    -- This will be overwritten by subsequent calls to `report`/`report_`.
    -- Intermediate out may not contain any newlines.
    report_ :: String -> Report ()
    report_ :: String -> StateT ReportState IO ()
    report_ msg :: String
    msg = do
      Bool
    f <- (ReportState -> Bool) -> StateT ReportState IO Bool
    forall (m :: * -> *) s a. Monad m => (s -> a) -> StateT s m a
    gets ReportState -> Bool
    reportStateInteractive
      Bool -> StateT ReportState IO () -> StateT ReportState IO ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    when Bool
    f (StateT ReportState IO () -> StateT ReportState IO ())
    -> StateT ReportState IO () -> StateT ReportState IO ()
    forall a b. (a -> b) -> a -> b
    $ do
        String -> StateT ReportState IO ()
    overwrite String
    msg
        (ReportState -> ReportState) -> StateT ReportState IO ()
    forall (m :: * -> *) s. Monad m => (s -> s) -> StateT s m ()
    modify (\st :: ReportState
    st -> ReportState
    st {reportStateCount :: Int
    reportStateCount = String -> Int
    forall (t :: * -> *) a. Foldable t => t a -> Int
    length String
    msg})

    -- | Add output to the report, overwrite any intermediate out.
    overwrite :: String -> Report ()
    overwrite :: String -> StateT ReportState IO ()
    overwrite msg :: String
    msg = do
      Int
    n <- (ReportState -> Int) -> StateT ReportState IO Int
    forall (m :: * -> *) s a. Monad m => (s -> a) -> StateT s m a
    gets ReportState -> Int
    reportStateCount
      let str :: String
    str | 0 Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    < Int
    n     = "\r" String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    msg String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ Int -> Char -> String
    forall a. Int -> a -> [a]
    replicate (Int
    n Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - String -> Int
    forall (t :: * -> *) a. Foldable t => t a -> Int
    length String
    msg) ' '
              | Bool
    otherwise = String
    msg
      IO () -> StateT ReportState IO ()
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (Handle -> String -> IO ()
    hPutStr Handle
    stderr String
    str)

    -- | Run all examples from given module.
    runModule :: Bool -> Bool -> Interpreter -> Module [Located DocTest] -> Report ()
    runModule :: Bool
    -> Bool
    -> Interpreter
    -> Module [Located DocTest]
    -> StateT ReportState IO ()
    runModule fastMode :: Bool
    fastMode preserveIt :: Bool
    preserveIt repl :: Interpreter
    repl (Module module_ :: String
    module_ setup :: Maybe [Located DocTest]
    setup examples :: [[Located DocTest]]
    examples) = do

      Summary _ _ e0 :: Int
    e0 f0 :: Int
    f0 <- (ReportState -> Summary) -> StateT ReportState IO Summary
    forall (m :: * -> *) s a. Monad m => (s -> a) -> StateT s m a
    gets ReportState -> Summary
    reportStateSummary

      Maybe [Located DocTest]
    -> ([Located DocTest] -> StateT ReportState IO ())
    -> StateT ReportState IO ()
    forall (t :: * -> *) (m :: * -> *) a b.
    (Foldable t, Monad m) =>
    t a -> (a -> m b) -> m ()
    forM_ Maybe [Located DocTest]
    setup (([Located DocTest] -> StateT ReportState IO ())
     -> StateT ReportState IO ())
    -> ([Located DocTest] -> StateT ReportState IO ())
    -> StateT ReportState IO ()
    forall a b. (a -> b) -> a -> b
    $
        Bool
    -> Interpreter
    -> IO ()
    -> [Located DocTest]
    -> StateT ReportState IO ()
    runTestGroup Bool
    preserveIt Interpreter
    repl IO ()
    reload

      Summary _ _ e1 :: Int
    e1 f1 :: Int
    f1 <- (ReportState -> Summary) -> StateT ReportState IO Summary
    forall (m :: * -> *) s a. Monad m => (s -> a) -> StateT s m a
    gets ReportState -> Summary
    reportStateSummary

      -- only run tests, if setup does not produce any errors/failures
      Bool -> StateT ReportState IO () -> StateT ReportState IO ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    when (Int
    e0 Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == Int
    e1 Bool -> Bool -> Bool
    && Int
    f0 Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == Int
    f1) (StateT ReportState IO () -> StateT ReportState IO ())
    -> StateT ReportState IO () -> StateT ReportState IO ()
    forall a b. (a -> b) -> a -> b
    $
        [[Located DocTest]]
    -> ([Located DocTest] -> StateT ReportState IO ())
    -> StateT ReportState IO ()
    forall (t :: * -> *) (m :: * -> *) a b.
    (Foldable t, Monad m) =>
    t a -> (a -> m b) -> m ()
    forM_ [[Located DocTest]]
    examples (([Located DocTest] -> StateT ReportState IO ())
     -> StateT ReportState IO ())
    -> ([Located DocTest] -> StateT ReportState IO ())
    -> StateT ReportState IO ()
    forall a b. (a -> b) -> a -> b
    $
          Bool
    -> Interpreter
    -> IO ()
    -> [Located DocTest]
    -> StateT ReportState IO ()
    runTestGroup Bool
    preserveIt Interpreter
    repl IO ()
    setup_
      where
        reload :: IO ()
        reload :: IO ()
    reload = do
          Bool -> IO () -> IO ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    unless Bool
    fastMode (IO () -> IO ()) -> IO () -> IO ()
    forall a b. (a -> b) -> a -> b
    $
            -- NOTE: It is important to do the :reload first! See
            -- https://ghc.haskell.org/trac/ghc/ticket/5904, which results in a
            -- panic on GHC 7.4.1 if you do the :reload second.
            IO (Either String String) -> IO ()
    forall (f :: * -> *) a. Functor f => f a -> f ()
    void (IO (Either String String) -> IO ())
    -> IO (Either String String) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ Interpreter -> String -> IO (Either String String)
    Interpreter.safeEval Interpreter
    repl ":reload"
          IO (Either String String) -> IO ()
    forall (f :: * -> *) a. Functor f => f a -> f ()
    void (IO (Either String String) -> IO ())
    -> IO (Either String String) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ Interpreter -> String -> IO (Either String String)
    Interpreter.safeEval Interpreter
    repl (String -> IO (Either String String))
    -> String -> IO (Either String String)
    forall a b. (a -> b) -> a -> b
    $ ":m *" String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    module_

          Bool -> IO () -> IO ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    when Bool
    preserveIt (IO () -> IO ()) -> IO () -> IO ()
    forall a b. (a -> b) -> a -> b
    $
            -- Evaluate a dumb expression to populate the 'it' variable NOTE: This is
            -- one reason why we cannot have safeEval = safeEvalIt: 'it' isn't set in
            -- a fresh GHCi session.
            IO (Either String String) -> IO ()
    forall (f :: * -> *) a. Functor f => f a -> f ()
    void (IO (Either String String) -> IO ())
    -> IO (Either String String) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ Interpreter -> String -> IO (Either String String)
    Interpreter.safeEval Interpreter
    repl (String -> IO (Either String String))
    -> String -> IO (Either String String)
    forall a b. (a -> b) -> a -> b
    $ "()"

        setup_ :: IO ()
        setup_ :: IO ()
    setup_ = do
          IO ()
    reload
          Maybe [Located DocTest] -> ([Located DocTest] -> IO ()) -> IO ()
    forall (t :: * -> *) (m :: * -> *) a b.
    (Foldable t, Monad m) =>
    t a -> (a -> m b) -> m ()
    forM_ Maybe [Located DocTest]
    setup (([Located DocTest] -> IO ()) -> IO ())
    -> ([Located DocTest] -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \l :: [Located DocTest]
    l -> [Located DocTest] -> (Located DocTest -> IO ()) -> IO ()
    forall (t :: * -> *) (m :: * -> *) a b.
    (Foldable t, Monad m) =>
    t a -> (a -> m b) -> m ()
    forM_ [Located DocTest]
    l ((Located DocTest -> IO ()) -> IO ())
    -> (Located DocTest -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \(Located _ x :: DocTest
    x) -> case DocTest
    x of
            Property _  -> () -> IO ()
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
            Example e :: String
    e _ -> IO (Either String String) -> IO ()
    forall (f :: * -> *) a. Functor f => f a -> f ()
    void (IO (Either String String) -> IO ())
    -> IO (Either String String) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ Bool -> Interpreter -> String -> IO (Either String String)
    safeEvalWith Bool
    preserveIt Interpreter
    repl String
    e

    reportStart :: Location -> Expression -> String -> Report ()
    reportStart :: Location -> String -> String -> StateT ReportState IO ()
    reportStart loc :: Location
    loc expression :: String
    expression testType :: String
    testType = do
      String -> StateT ReportState IO ()
    verboseReport (String -> String -> String -> ShowS
    forall r. PrintfType r => String -> r
    printf "### Started execution at %s.\n### %s:\n%s" (Location -> String
    forall a. Show a => a -> String
    show Location
    loc) String
    testType String
    expression)

    reportFailure :: Location -> Expression -> [String] -> Report ()
    reportFailure :: Location -> String -> [String] -> StateT ReportState IO ()
    reportFailure loc :: Location
    loc expression :: String
    expression err :: [String]
    err = do
      String -> StateT ReportState IO ()
    report (String -> String -> ShowS
    forall r. PrintfType r => String -> r
    printf "%s: failure in expression `%s'" (Location -> String
    forall a. Show a => a -> String
    show Location
    loc) String
    expression)
      (String -> StateT ReportState IO ())
    -> [String] -> StateT ReportState IO ()
    forall (t :: * -> *) (m :: * -> *) a b.
    (Foldable t, Monad m) =>
    (a -> m b) -> t a -> m ()
    mapM_ String -> StateT ReportState IO ()
    report [String]
    err
      String -> StateT ReportState IO ()
    report ""
      Summary -> StateT ReportState IO ()
    updateSummary (Int -> Int -> Int -> Int -> Summary
    Summary 0 1 0 1)

    reportError :: Location -> Expression -> String -> Report ()
    reportError :: Location -> String -> String -> StateT ReportState IO ()
    reportError loc :: Location
    loc expression :: String
    expression err :: String
    err = do
      String -> StateT ReportState IO ()
    report (String -> String -> ShowS
    forall r. PrintfType r => String -> r
    printf "%s: error in expression `%s'" (Location -> String
    forall a. Show a => a -> String
    show Location
    loc) String
    expression)
      String -> StateT ReportState IO ()
    report String
    err
      String -> StateT ReportState IO ()
    report ""
      Summary -> StateT ReportState IO ()
    updateSummary (Int -> Int -> Int -> Int -> Summary
    Summary 0 1 1 0)

    reportSuccess :: Report ()
    reportSuccess :: StateT ReportState IO ()
    reportSuccess = do
      String -> StateT ReportState IO ()
    verboseReport "### Successful!\n"
      Summary -> StateT ReportState IO ()
    updateSummary (Int -> Int -> Int -> Int -> Summary
    Summary 0 1 0 0)

    verboseReport :: String -> Report ()
    verboseReport :: String -> StateT ReportState IO ()
    verboseReport xs :: String
    xs = do
      Bool
    verbose <- (ReportState -> Bool) -> StateT ReportState IO Bool
    forall (m :: * -> *) s a. Monad m => (s -> a) -> StateT s m a
    gets ReportState -> Bool
    reportStateVerbose
      Bool -> StateT ReportState IO () -> StateT ReportState IO ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    when Bool
    verbose (StateT ReportState IO () -> StateT ReportState IO ())
    -> StateT ReportState IO () -> StateT ReportState IO ()
    forall a b. (a -> b) -> a -> b
    $ String -> StateT ReportState IO ()
    report String
    xs

    updateSummary :: Summary -> Report ()
    updateSummary :: Summary -> StateT ReportState IO ()
    updateSummary summary :: Summary
    summary = do
      ReportState n :: Int
    n f :: Bool
    f v :: Bool
    v s :: Summary
    s <- StateT ReportState IO ReportState
    forall (m :: * -> *) s. Monad m => StateT s m s
    get
      ReportState -> StateT ReportState IO ()
    forall (m :: * -> *) s. Monad m => s -> StateT s m ()
    put (Int -> Bool -> Bool -> Summary -> ReportState
    ReportState Int
    n Bool
    f Bool
    v (Summary -> ReportState) -> Summary -> ReportState
    forall a b. (a -> b) -> a -> b
    $ Summary
    s Summary -> Summary -> Summary
    forall a. Monoid a => a -> a -> a
    `mappend` Summary
    summary)

    reportProgress :: Report ()
    reportProgress :: StateT ReportState IO ()
    reportProgress = do
      Bool
    verbose <- (ReportState -> Bool) -> StateT ReportState IO Bool
    forall (m :: * -> *) s a. Monad m => (s -> a) -> StateT s m a
    gets ReportState -> Bool
    reportStateVerbose
      Bool -> StateT ReportState IO () -> StateT ReportState IO ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    when (Bool -> Bool
    not Bool
    verbose) (StateT ReportState IO () -> StateT ReportState IO ())
    -> StateT ReportState IO () -> StateT ReportState IO ()
    forall a b. (a -> b) -> a -> b
    $ (ReportState -> String) -> StateT ReportState IO String
    forall (m :: * -> *) s a. Monad m => (s -> a) -> StateT s m a
    gets (Summary -> String
    forall a. Show a => a -> String
    show (Summary -> String)
    -> (ReportState -> Summary) -> ReportState -> String
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ReportState -> Summary
    reportStateSummary) StateT ReportState IO String
    -> (String -> StateT ReportState IO ()) -> StateT ReportState IO ()
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= String -> StateT ReportState IO ()
    report_

    -- | Run given test group.
    --
    -- The interpreter state is zeroed with @:reload@ first.  This means that you
    -- can reuse the same 'Interpreter' for several test groups.
    runTestGroup :: Bool -> Interpreter -> IO () -> [Located DocTest] -> Report ()
    runTestGroup :: Bool
    -> Interpreter
    -> IO ()
    -> [Located DocTest]
    -> StateT ReportState IO ()
    runTestGroup preserveIt :: Bool
    preserveIt repl :: Interpreter
    repl setup :: IO ()
    setup tests :: [Located DocTest]
    tests = do

      StateT ReportState IO ()
    reportProgress

      IO () -> StateT ReportState IO ()
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO IO ()
    setup
      Bool
    -> Interpreter -> [Located Interaction] -> StateT ReportState IO ()
    runExampleGroup Bool
    preserveIt Interpreter
    repl [Located Interaction]
    examples

      [(Location, String)]
    -> ((Location, String) -> StateT ReportState IO ())
    -> StateT ReportState IO ()
    forall (t :: * -> *) (m :: * -> *) a b.
    (Foldable t, Monad m) =>
    t a -> (a -> m b) -> m ()
    forM_ [(Location, String)]
    properties (((Location, String) -> StateT ReportState IO ())
     -> StateT ReportState IO ())
    -> ((Location, String) -> StateT ReportState IO ())
    -> StateT ReportState IO ()
    forall a b. (a -> b) -> a -> b
    $ \(loc :: Location
    loc, expression :: String
    expression) -> do
        PropertyResult
    r <- do
          IO () -> StateT ReportState IO ()
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO IO ()
    setup
          Location -> String -> String -> StateT ReportState IO ()
    reportStart Location
    loc String
    expression "property"
          IO PropertyResult -> StateT ReportState IO PropertyResult
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO PropertyResult -> StateT ReportState IO PropertyResult)
    -> IO PropertyResult -> StateT ReportState IO PropertyResult
    forall a b. (a -> b) -> a -> b
    $ Interpreter -> String -> IO PropertyResult
    runProperty Interpreter
    repl String
    expression
        case PropertyResult
    r of
          Success ->
            StateT ReportState IO ()
    reportSuccess
          Error err :: String
    err -> do
            Location -> String -> String -> StateT ReportState IO ()
    reportError Location
    loc String
    expression String
    err
          Failure msg :: String
    msg -> do
            Location -> String -> [String] -> StateT ReportState IO ()
    reportFailure Location
    loc String
    expression [String
    msg]
      where
        properties :: [(Location, String)]
    properties = [(Location
    loc, String
    p) | Located loc :: Location
    loc (Property p :: String
    p) <- [Located DocTest]
    tests]

        examples :: [Located Interaction]
        examples :: [Located Interaction]
    examples = [Location -> Interaction -> Located Interaction
    forall a. Location -> a -> Located a
    Located Location
    loc (String
    e, ExpectedResult
    r) | Located loc :: Location
    loc (Example e :: String
    e r :: ExpectedResult
    r) <- [Located DocTest]
    tests]

    -- |
    -- Execute all expressions from given example in given 'Interpreter' and verify
    -- the output.
    runExampleGroup :: Bool -> Interpreter -> [Located Interaction] -> Report ()
    runExampleGroup :: Bool
    -> Interpreter -> [Located Interaction] -> StateT ReportState IO ()
    runExampleGroup preserveIt :: Bool
    preserveIt repl :: Interpreter
    repl = [Located Interaction] -> StateT ReportState IO ()
    go
      where
        go :: [Located Interaction] -> StateT ReportState IO ()
    go ((Located loc :: Location
    loc (expression :: String
    expression, expected :: ExpectedResult
    expected)) : xs :: [Located Interaction]
    xs) = do
          Location -> String -> String -> StateT ReportState IO ()
    reportStart Location
    loc String
    expression "example"
          Either String [String]
    r <- (String -> [String])
    -> Either String String -> Either String [String]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap String -> [String]
    lines (Either String String -> Either String [String])
    -> StateT ReportState IO (Either String String)
    -> StateT ReportState IO (Either String [String])
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> IO (Either String String)
    -> StateT ReportState IO (Either String String)
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (Bool -> Interpreter -> String -> IO (Either String String)
    safeEvalWith Bool
    preserveIt Interpreter
    repl String
    expression)
          case Either String [String]
    r of
            Left err :: String
    err -> do
              Location -> String -> String -> StateT ReportState IO ()
    reportError Location
    loc String
    expression String
    err
            Right actual :: [String]
    actual -> case ExpectedResult -> [String] -> Result
    mkResult ExpectedResult
    expected [String]
    actual of
              NotEqual err :: [String]
    err -> do
                Location -> String -> [String] -> StateT ReportState IO ()
    reportFailure Location
    loc String
    expression [String]
    err
              Equal -> do
                StateT ReportState IO ()
    reportSuccess
                [Located Interaction] -> StateT ReportState IO ()
    go [Located Interaction]
    xs
        go [] = () -> StateT ReportState IO ()
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()

    safeEvalWith :: Bool -> Interpreter -> String -> IO (Either String String)
    safeEvalWith :: Bool -> Interpreter -> String -> IO (Either String String)
    safeEvalWith preserveIt :: Bool
    preserveIt
      | Bool
    preserveIt = Interpreter -> String -> IO (Either String String)
    Interpreter.safeEvalIt
      | Bool
    otherwise  = Interpreter -> String -> IO (Either String String)
    Interpreter.safeEval