more the exception handling in a single place

This commit is contained in:
krangelov
2021-08-31 10:04:33 +02:00
parent 0bf7522291
commit 5f5b0caba5
2 changed files with 44 additions and 56 deletions

View File

@@ -47,14 +47,13 @@ module PGF2 (-- * PGF
PGFError(..) PGFError(..)
) where ) where
import Control.Exception(Exception,throwIO,mask_,bracket) import Control.Exception(mask_,bracket)
import System.IO.Unsafe(unsafePerformIO) import System.IO.Unsafe(unsafePerformIO)
import PGF2.Expr import PGF2.Expr
import PGF2.FFI import PGF2.FFI
import Foreign import Foreign
import Foreign.C import Foreign.C
import Data.Typeable
import qualified Data.Map as Map import qualified Data.Map as Map
import Data.IORef import Data.IORef
@@ -67,20 +66,10 @@ type ConcName = String -- ^ Name of concrete syntax
readPGF :: FilePath -> IO PGF readPGF :: FilePath -> IO PGF
readPGF fpath = readPGF fpath =
withCString fpath $ \c_fpath -> withCString fpath $ \c_fpath ->
allocaBytes (#size PgfExn) $ \c_exn ->
mask_ $ do mask_ $ do
c_pgf <- pgf_read_pgf c_fpath c_exn c_pgf <- withPgfExn fpath (pgf_read_pgf c_fpath)
ex_type <- (#peek PgfExn, type) c_exn :: IO (#type PgfExnType) fptr <- newForeignPtr pgf_free_fptr c_pgf
if ex_type == (#const PGF_EXN_NONE) return (PGF fptr Map.empty)
then do fptr <- newForeignPtr pgf_free_fptr c_pgf
return (PGF fptr Map.empty)
else if ex_type == (#const PGF_EXN_SYSTEM_ERROR)
then do errno <- (#peek PgfExn, code) c_exn
ioError (errnoToIOError "readPGF" (Errno errno) Nothing (Just fpath))
else do c_msg <- (#peek PgfExn, msg) c_exn
msg <- peekCString c_msg
free c_msg
throwIO (PGFError msg)
-- | Reads a PGF file and stores the unpacked data in an NGF file -- | Reads a PGF file and stores the unpacked data in an NGF file
-- ready to be shared with other process, or used for quick startup. -- ready to be shared with other process, or used for quick startup.
@@ -90,20 +79,10 @@ bootNGF :: FilePath -> FilePath -> IO PGF
bootNGF pgf_path ngf_path = bootNGF pgf_path ngf_path =
withCString pgf_path $ \c_pgf_path -> withCString pgf_path $ \c_pgf_path ->
withCString ngf_path $ \c_ngf_path -> withCString ngf_path $ \c_ngf_path ->
allocaBytes (#size PgfExn) $ \c_exn ->
mask_ $ do mask_ $ do
c_pgf <- pgf_boot_ngf c_pgf_path c_ngf_path c_exn c_pgf <- withPgfExn pgf_path (pgf_boot_ngf c_pgf_path c_ngf_path)
ex_type <- (#peek PgfExn, type) c_exn :: IO (#type PgfExnType) fptr <- newForeignPtr pgf_free_fptr c_pgf
if ex_type == (#const PGF_EXN_NONE) return (PGF fptr Map.empty)
then do fptr <- newForeignPtr pgf_free_fptr c_pgf
return (PGF fptr Map.empty)
else if ex_type == (#const PGF_EXN_SYSTEM_ERROR)
then do errno <- (#peek PgfExn, code) c_exn
ioError (errnoToIOError "bootNGF" (Errno errno) Nothing (Just pgf_path))
else do c_msg <- (#peek PgfExn, msg) c_exn
msg <- peekCString c_msg
free c_msg
throwIO (PGFError msg)
-- | Tries to read the grammar from an already booted NGF file. -- | Tries to read the grammar from an already booted NGF file.
-- If the file does not exist then a new one is created, and the -- If the file does not exist then a new one is created, and the
@@ -112,20 +91,10 @@ bootNGF pgf_path ngf_path =
readNGF :: FilePath -> IO PGF readNGF :: FilePath -> IO PGF
readNGF fpath = readNGF fpath =
withCString fpath $ \c_fpath -> withCString fpath $ \c_fpath ->
allocaBytes (#size PgfExn) $ \c_exn ->
mask_ $ do mask_ $ do
c_pgf <- pgf_read_ngf c_fpath c_exn c_pgf <- withPgfExn fpath (pgf_read_ngf c_fpath)
ex_type <- (#peek PgfExn, type) c_exn :: IO (#type PgfExnType) fptr <- newForeignPtr pgf_free_fptr c_pgf
if ex_type == (#const PGF_EXN_NONE) return (PGF fptr Map.empty)
then do fptr <- newForeignPtr pgf_free_fptr c_pgf
return (PGF fptr Map.empty)
else if ex_type == (#const PGF_EXN_SYSTEM_ERROR)
then do errno <- (#peek PgfExn, code) c_exn
ioError (errnoToIOError "readPGF" (Errno errno) Nothing (Just fpath))
else do c_msg <- (#peek PgfExn, msg) c_exn
msg <- peekCString c_msg
free c_msg
throwIO (PGFError msg)
-- | The abstract language name is the name of the top-level -- | The abstract language name is the name of the top-level
-- abstract module -- abstract module
@@ -187,11 +156,10 @@ categories p =
unsafePerformIO $ do unsafePerformIO $ do
ref <- newIORef [] ref <- newIORef []
(allocaBytes (#size PgfItor) $ \itor -> (allocaBytes (#size PgfItor) $ \itor ->
allocaBytes (#size PgfExn) $ \c_exn ->
bracket (wrapItorCallback (getCategories ref)) freeHaskellFunPtr $ \fptr -> bracket (wrapItorCallback (getCategories ref)) freeHaskellFunPtr $ \fptr ->
withForeignPtr (a_pgf p) $ \p_pgf -> do withForeignPtr (a_pgf p) $ \p_pgf -> do
(#poke PgfItor, fn) itor fptr (#poke PgfItor, fn) itor fptr
pgf_iter_categories p_pgf itor c_exn withPgfExn "" (pgf_iter_categories p_pgf itor)
cs <- readIORef ref cs <- readIORef ref
return (reverse cs)) return (reverse cs))
where where
@@ -244,11 +212,10 @@ functions p =
unsafePerformIO $ do unsafePerformIO $ do
ref <- newIORef [] ref <- newIORef []
(allocaBytes (#size PgfItor) $ \itor -> (allocaBytes (#size PgfItor) $ \itor ->
allocaBytes (#size PgfExn) $ \c_exn ->
bracket (wrapItorCallback (getFunctions ref)) freeHaskellFunPtr $ \fptr -> bracket (wrapItorCallback (getFunctions ref)) freeHaskellFunPtr $ \fptr ->
withForeignPtr (a_pgf p) $ \p_pgf -> do withForeignPtr (a_pgf p) $ \p_pgf -> do
(#poke PgfItor, fn) itor fptr (#poke PgfItor, fn) itor fptr
pgf_iter_functions p_pgf itor c_exn withPgfExn "" (pgf_iter_functions p_pgf itor)
fs <- readIORef ref fs <- readIORef ref
return (reverse fs)) return (reverse fs))
where where
@@ -265,11 +232,10 @@ functionsByCat p cat =
ref <- newIORef [] ref <- newIORef []
(withText cat $ \c_cat -> (withText cat $ \c_cat ->
allocaBytes (#size PgfItor) $ \itor -> allocaBytes (#size PgfItor) $ \itor ->
allocaBytes (#size PgfExn) $ \c_exn ->
bracket (wrapItorCallback (getFunctions ref)) freeHaskellFunPtr $ \fptr -> bracket (wrapItorCallback (getFunctions ref)) freeHaskellFunPtr $ \fptr ->
withForeignPtr (a_pgf p) $ \p_pgf -> do withForeignPtr (a_pgf p) $ \p_pgf -> do
(#poke PgfItor, fn) itor fptr (#poke PgfItor, fn) itor fptr
pgf_iter_functions_by_cat p_pgf c_cat itor c_exn withPgfExn "" (pgf_iter_functions_by_cat p_pgf c_cat itor)
fs <- readIORef ref fs <- readIORef ref
return (reverse fs)) return (reverse fs))
where where
@@ -348,11 +314,3 @@ readType str =
freeStablePtr c_ty freeStablePtr c_ty
return (Just ty) return (Just ty)
-----------------------------------------------------------------------
-- Exceptions
newtype PGFError = PGFError String
deriving (Show, Typeable)
instance Exception PGFError

View File

@@ -6,11 +6,12 @@ import GHC.Exts
import GHC.Prim import GHC.Prim
import GHC.Integer.Logarithms import GHC.Integer.Logarithms
import Data.Word import Data.Word
import Data.Typeable
import Foreign import Foreign
import Foreign.C import Foreign.C
import Foreign.Ptr import Foreign.Ptr
import qualified Data.Map as Map import qualified Data.Map as Map
import Control.Exception(bracket,mask_) import Control.Exception(Exception,bracket,mask_,throwIO)
import System.IO.Unsafe(unsafePerformIO) import System.IO.Unsafe(unsafePerformIO)
import PGF2.Expr import PGF2.Expr
@@ -100,6 +101,9 @@ foreign import ccall "pgf/expr.h pgf_function_is_constructor"
foreign import ccall "pgf/expr.h pgf_function_is_constructor" foreign import ccall "pgf/expr.h pgf_function_is_constructor"
pgf_function_prob :: Ptr PgfPGF -> Ptr PgfText -> IO (#type prob_t) pgf_function_prob :: Ptr PgfPGF -> Ptr PgfText -> IO (#type prob_t)
-----------------------------------------------------------------------
-- Texts
peekText :: Ptr PgfText -> IO String peekText :: Ptr PgfText -> IO String
peekText ptr = peekText ptr =
alloca $ \pptr -> do alloca $ \pptr -> do
@@ -167,6 +171,32 @@ utf8Length s = count 0 s
where where
ucs = fromEnum x ucs = fromEnum x
-----------------------------------------------------------------------
-- Exceptions
newtype PGFError = PGFError String
deriving (Show, Typeable)
instance Exception PGFError
withPgfExn fpath f =
allocaBytes (#size PgfExn) $ \c_exn -> do
res <- f c_exn
ex_type <- (#peek PgfExn, type) c_exn :: IO (#type PgfExnType)
case ex_type of
(#const PGF_EXN_NONE) -> return res
(#const PGF_EXN_SYSTEM_ERROR) -> do
errno <- (#peek PgfExn, code) c_exn
ioError (errnoToIOError "readPGF" (Errno errno) Nothing (Just fpath))
(#const PGF_EXN_PGF_ERROR) -> do
c_msg <- (#peek PgfExn, msg) c_exn
msg <- peekCString c_msg
free c_msg
throwIO (PGFError msg)
_ -> throwIO (PGFError "An unidentified error occurred")
-----------------------------------------------------------------------
-- Marshalling
type CBindType = (#type PgfBindType) type CBindType = (#type PgfBindType)