module Data.LLVM.BitCode (
    -- * Bitcode Parsing
    parseBitCode,     parseBitCodeFromFile
  , parseBitCodeLazy, parseBitCodeLazyFromFile

    -- * Re-exported
  , Error(..), formatError
  ) where

import Data.LLVM.BitCode.Bitstream
    (Bitstream,parseBitCodeBitstream,parseBitCodeBitstreamLazy)
import Data.LLVM.BitCode.IR (parseModule)
import Data.LLVM.BitCode.Parse (runParse,badRefError,Error(..),formatError)
import Text.LLVM.AST (Module)

import Control.Monad ((<=<))
import qualified Control.Exception as X
import qualified Data.ByteString as S
import qualified Data.ByteString.Lazy as L

parseBitCode :: S.ByteString -> IO (Either Error Module)
parseBitCode :: ByteString -> IO (Either Error Module)
parseBitCode  = Either String Bitstream -> IO (Either Error Module)
parseBitstream (Either String Bitstream -> IO (Either Error Module))
-> (ByteString -> Either String Bitstream)
-> ByteString
-> IO (Either Error Module)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Either String Bitstream
parseBitCodeBitstream

parseBitCodeFromFile :: FilePath -> IO (Either Error Module)
parseBitCodeFromFile :: String -> IO (Either Error Module)
parseBitCodeFromFile  = ByteString -> IO (Either Error Module)
parseBitCode (ByteString -> IO (Either Error Module))
-> (String -> IO ByteString) -> String -> IO (Either Error Module)
forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< String -> IO ByteString
S.readFile

parseBitCodeLazy :: L.ByteString -> IO (Either Error Module)
parseBitCodeLazy :: ByteString -> IO (Either Error Module)
parseBitCodeLazy  = Either String Bitstream -> IO (Either Error Module)
parseBitstream (Either String Bitstream -> IO (Either Error Module))
-> (ByteString -> Either String Bitstream)
-> ByteString
-> IO (Either Error Module)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Either String Bitstream
parseBitCodeBitstreamLazy

parseBitCodeLazyFromFile :: FilePath -> IO (Either Error Module)
parseBitCodeLazyFromFile :: String -> IO (Either Error Module)
parseBitCodeLazyFromFile  = ByteString -> IO (Either Error Module)
parseBitCodeLazy (ByteString -> IO (Either Error Module))
-> (String -> IO ByteString) -> String -> IO (Either Error Module)
forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< String -> IO ByteString
L.readFile

parseBitstream :: Either String Bitstream -> IO (Either Error Module)
parseBitstream :: Either String Bitstream -> IO (Either Error Module)
parseBitstream Either String Bitstream
e = case Either String Bitstream
e of
  Left String
err   -> [String] -> String -> IO (Either Error Module)
forall {m :: * -> *} {b}.
Monad m =>
[String] -> String -> m (Either Error b)
mkError [String
"Bitstream"] String
err
  Right Bitstream
bits -> (BadForwardRef -> IO (Either Error Module))
-> IO (Either Error Module) -> IO (Either Error Module)
forall e a. Exception e => (e -> IO a) -> IO a -> IO a
X.handle (Either Error Module -> IO (Either Error Module)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Either Error Module -> IO (Either Error Module))
-> (BadForwardRef -> Either Error Module)
-> BadForwardRef
-> IO (Either Error Module)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Error -> Either Error Module
forall a b. a -> Either a b
Left (Error -> Either Error Module)
-> (BadForwardRef -> Error) -> BadForwardRef -> Either Error Module
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BadForwardRef -> Error
badRefError)
                         (Either Error Module -> IO (Either Error Module)
forall a. a -> IO a
X.evaluate (Parse Module -> Either Error Module
forall a. Parse a -> Either Error a
runParse (Bitstream -> Parse Module
parseModule Bitstream
bits)))
  where
  mkError :: [String] -> String -> m (Either Error b)
mkError [String]
cxt String
msg = Either Error b -> m (Either Error b)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Either Error b -> m (Either Error b))
-> Either Error b -> m (Either Error b)
forall a b. (a -> b) -> a -> b
$ Error -> Either Error b
forall a b. a -> Either a b
Left Error
    { errMessage :: String
errMessage = String
msg
    , errContext :: [String]
errContext = [String]
cxt
    }