module Language.Lean.Internal.Exception
( LeanException(..)
, LeanExceptionKind(..)
, ExceptionPtr
, OutExceptionPtr
, throwLeanException
, leanKernelException
, leanOtherException
, LeanPartialAction
, runLeanPartialAction
, LeanPartialFn
, runLeanPartialFn
, runLeanMaybeFn
, IsLeanValue(..)
, tryAllocLeanValue
) where
import Control.Exception
import Control.Monad (when)
import Data.Typeable
import Foreign
import Foreign.C
import Language.Lean.Internal.String
data LeanExceptionKind
= LeanSystemException
| LeanOutOfMemory
| LeanInterrupted
| LeanKernelException
| LeanOtherException
deriving (Show)
data LeanException
= LeanException { leanExceptionKind :: !LeanExceptionKind
, leanExceptionName :: !String
}
deriving (Typeable, Show)
instance Exception LeanException
type ExceptionPtr = Ptr (LeanException)
type OutExceptionPtr = Ptr (ExceptionPtr)
lean_exception_del :: (ExceptionPtr) -> IO ()
lean_exception_del a1 =
let {a1' = id a1} in
lean_exception_del'_ a1' >>
return ()
lean_exception_get_message :: (ExceptionPtr) -> IO ((String))
lean_exception_get_message a1 =
let {a1' = id a1} in
lean_exception_get_message'_ a1' >>= \res ->
getLeanString res >>= \res' ->
return (res')
data ExceptionKind = LEAN_NULL_EXCEPTION
| LEAN_SYSTEM_EXCEPTION
| LEAN_OUT_OF_MEMORY
| LEAN_INTERRUPTED
| LEAN_KERNEL_EXCEPTION
| LEAN_OTHER_EXCEPTION
deriving (Enum,Eq)
lean_exception_get_kind :: (ExceptionPtr) -> IO ((ExceptionKind))
lean_exception_get_kind a1 =
let {a1' = id a1} in
lean_exception_get_kind'_ a1' >>= \res ->
let {res' = (toEnum . fromIntegral) res} in
return (res')
throwLeanException :: ExceptionPtr -> IO a
throwLeanException ptr = do
(throwIO =<< leanExceptionFromPtr ptr)
`finally` lean_exception_del ptr
leanExceptionFromPtr :: ExceptionPtr -> IO LeanException
leanExceptionFromPtr ptr = do
k <- lean_exception_get_kind ptr
msg <- lean_exception_get_message ptr
return $! LeanException (getLeanExceptionKind k) msg
leanKernelException :: String -> LeanException
leanKernelException = LeanException LeanKernelException
leanOtherException :: String -> LeanException
leanOtherException = LeanException LeanOtherException
getLeanExceptionKind :: ExceptionKind -> LeanExceptionKind
getLeanExceptionKind k = do
case k of
LEAN_NULL_EXCEPTION -> error "getLeanException not given an exception"
LEAN_SYSTEM_EXCEPTION -> LeanSystemException
LEAN_OUT_OF_MEMORY -> LeanOutOfMemory
LEAN_INTERRUPTED -> LeanOutOfMemory
LEAN_KERNEL_EXCEPTION -> LeanKernelException
LEAN_OTHER_EXCEPTION -> LeanOtherException
type LeanPartialAction = (Ptr ExceptionPtr -> IO Bool)
runLeanPartialAction :: LeanPartialAction
-> IO ()
runLeanPartialAction action =
alloca $ \ex_ptr -> do
poke ex_ptr nullPtr
success <- action ex_ptr
when (not success) $ do
throwLeanException =<< peek ex_ptr
type LeanPartialFn a = (Ptr a -> LeanPartialAction)
runLeanPartialFn :: Storable a
=> LeanPartialFn a
-> IO a
runLeanPartialFn alloc_fn =
alloca $ \ret_ptr -> do
runLeanPartialAction (alloc_fn ret_ptr)
peek ret_ptr
runLeanMaybeFn :: Storable p
=> LeanPartialFn p
-> IO (Maybe p)
runLeanMaybeFn alloc_fn =
alloca $ \ret_ptr -> do
alloca $ \ex_ptr -> do
poke ex_ptr nullPtr
success <- alloc_fn ret_ptr ex_ptr
if success then do
r <- peek ret_ptr
return $! Just r
else do
ptr <- peek ex_ptr
if ptr == nullPtr then
return $! Nothing
else
throwLeanException ptr
class Storable p => IsLeanValue v p | v -> p where
mkLeanValue :: p -> IO v
instance IsLeanValue Bool CInt where
mkLeanValue = return . toEnum . fromIntegral
instance IsLeanValue Word32 CUInt where
mkLeanValue (CUInt x) = return x
instance IsLeanValue Int32 CInt where
mkLeanValue (CInt x) = return x
instance IsLeanValue Double CDouble where
mkLeanValue (CDouble d) = return d
instance IsLeanValue String CString where
mkLeanValue = getLeanString
tryAllocLeanValue :: IsLeanValue a p
=> LeanPartialFn p
-> IO a
tryAllocLeanValue = \alloc_fn -> mkLeanValue =<< runLeanPartialFn alloc_fn
foreign import ccall unsafe "Language/Lean/Internal/Exception.chs.h lean_exception_del"
lean_exception_del'_ :: ((ExceptionPtr) -> (IO ()))
foreign import ccall unsafe "Language/Lean/Internal/Exception.chs.h lean_exception_get_message"
lean_exception_get_message'_ :: ((ExceptionPtr) -> (IO (Ptr CChar)))
foreign import ccall unsafe "Language/Lean/Internal/Exception.chs.h lean_exception_get_kind"
lean_exception_get_kind'_ :: ((ExceptionPtr) -> (IO CInt))