{-# LANGUAGE ScopedTypeVariables #-}
{-# OPTIONS_GHC -fno-cse -fno-full-laziness #-}
module Test.ChasingBottoms.IsBottom
  ( isBottom
  , isBottomIO
  , bottom
  , nonBottomError
  , isBottomTimeOut
  , isBottomTimeOutIO
  ) where
import Prelude hiding (catch)
import qualified Control.Exception as E
import System.IO.Unsafe (unsafePerformIO)
import qualified Test.ChasingBottoms.TimeOut as T
isBottom :: a -> Bool
isBottom :: forall a. a -> Bool
isBottom = Maybe Int -> a -> Bool
forall a. Maybe Int -> a -> Bool
isBottomTimeOut Maybe Int
forall a. Maybe a
Nothing
bottom :: a
bottom :: forall a. a
bottom = [Char] -> a
forall a. HasCallStack => [Char] -> a
error [Char]
"_|_"
nonBottomError :: String -> a
nonBottomError :: forall a. [Char] -> a
nonBottomError = AssertionFailed -> a
forall a e. Exception e => e -> a
E.throw (AssertionFailed -> a)
-> ([Char] -> AssertionFailed) -> [Char] -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> AssertionFailed
E.AssertionFailed
{-# NOINLINE isBottomTimeOut #-}
isBottomTimeOut :: Maybe Int -> a -> Bool
isBottomTimeOut :: forall a. Maybe Int -> a -> Bool
isBottomTimeOut Maybe Int
timeOutLimit a
f =
  IO Bool -> Bool
forall a. IO a -> a
unsafePerformIO (IO Bool -> Bool) -> IO Bool -> Bool
forall a b. (a -> b) -> a -> b
$ Maybe Int -> a -> IO Bool
forall a. Maybe Int -> a -> IO Bool
isBottomTimeOutIO Maybe Int
timeOutLimit a
f
isBottomIO :: a -> IO Bool
isBottomIO :: forall a. a -> IO Bool
isBottomIO = Maybe Int -> a -> IO Bool
forall a. Maybe Int -> a -> IO Bool
isBottomTimeOutIO Maybe Int
forall a. Maybe a
Nothing
isBottomTimeOutIO :: Maybe Int -> a -> IO Bool
isBottomTimeOutIO :: forall a. Maybe Int -> a -> IO Bool
isBottomTimeOutIO Maybe Int
timeOutLimit a
f =
  IO a -> IO Bool
forall {a}. IO a -> IO Bool
maybeTimeOut (a -> IO a
forall a. a -> IO a
E.evaluate a
f) IO Bool -> [Handler Bool] -> IO Bool
forall a. IO a -> [Handler a] -> IO a
`E.catches`
    [ (ArrayException -> IO Bool) -> Handler Bool
forall a e. Exception e => (e -> IO a) -> Handler a
E.Handler (\(ArrayException
_ :: E.ArrayException)   -> Bool -> IO Bool
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True)
    , (ErrorCall -> IO Bool) -> Handler Bool
forall a e. Exception e => (e -> IO a) -> Handler a
E.Handler (\(ErrorCall
_ :: E.ErrorCall)        -> Bool -> IO Bool
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True)
    , (NoMethodError -> IO Bool) -> Handler Bool
forall a e. Exception e => (e -> IO a) -> Handler a
E.Handler (\(NoMethodError
_ :: E.NoMethodError)    -> Bool -> IO Bool
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True)
    , (NonTermination -> IO Bool) -> Handler Bool
forall a e. Exception e => (e -> IO a) -> Handler a
E.Handler (\(NonTermination
_ :: E.NonTermination)   -> Bool -> IO Bool
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True)
    , (PatternMatchFail -> IO Bool) -> Handler Bool
forall a e. Exception e => (e -> IO a) -> Handler a
E.Handler (\(PatternMatchFail
_ :: E.PatternMatchFail) -> Bool -> IO Bool
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True)
    , (RecConError -> IO Bool) -> Handler Bool
forall a e. Exception e => (e -> IO a) -> Handler a
E.Handler (\(RecConError
_ :: E.RecConError)      -> Bool -> IO Bool
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True)
    , (RecSelError -> IO Bool) -> Handler Bool
forall a e. Exception e => (e -> IO a) -> Handler a
E.Handler (\(RecSelError
_ :: E.RecSelError)      -> Bool -> IO Bool
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True)
    , (RecUpdError -> IO Bool) -> Handler Bool
forall a e. Exception e => (e -> IO a) -> Handler a
E.Handler (\(RecUpdError
_ :: E.RecUpdError)      -> Bool -> IO Bool
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True)
    ]
  where
  maybeTimeOut :: IO a -> IO Bool
maybeTimeOut IO a
io = case Maybe Int
timeOutLimit of
    Maybe Int
Nothing -> do
      IO a
io
      Bool -> IO Bool
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
    Just Int
lim -> do
      Result a
result <- Int -> IO a -> IO (Result a)
forall a. Int -> IO a -> IO (Result a)
T.timeOut Int
lim IO a
io
      case Result a
result of               
        T.Value a
_        -> Bool -> IO Bool
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
        Result a
T.NonTermination -> Bool -> IO Bool
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
        T.Exception SomeException
e    -> SomeException -> IO Bool
forall a e. Exception e => e -> a
E.throw SomeException
e