{-# LANGUAGE CPP #-}

-- | @unsafe@ variants of the "Language.C.Inline" quasi-quoters, to call the C code
-- unsafely in the sense of
-- <https://www.haskell.org/onlinereport/haskell2010/haskellch8.html#x15-1590008.4.3>.
-- In GHC, unsafe foreign calls are faster than safe foreign calls, but the user
-- must guarantee the control flow will never enter Haskell code (via a callback
-- or otherwise) before the call is done.
--
-- This module is intended to be imported qualified:
--
-- @
-- import qualified "Language.C.Inline.Unsafe" as CU
-- @

module Language.C.Inline.Unsafe
  ( exp
  , pure
  , block
  ) where

#if __GLASGOW_HASKELL__ < 710
import           Prelude hiding (exp)
#else
import           Prelude hiding (exp, pure)
#endif

import qualified Language.Haskell.TH.Quote as TH
import qualified Language.Haskell.TH.Syntax as TH

import           Language.C.Inline.Context
import           Language.C.Inline.Internal

-- | C expressions.
exp :: TH.QuasiQuoter
exp :: QuasiQuoter
exp = Purity
-> (Loc
    -> TypeQ
    -> Type CIdentifier
    -> [(CIdentifier, Type CIdentifier)]
    -> String
    -> ExpQ)
-> QuasiQuoter
genericQuote Purity
IO ((Loc
  -> TypeQ
  -> Type CIdentifier
  -> [(CIdentifier, Type CIdentifier)]
  -> String
  -> ExpQ)
 -> QuasiQuoter)
-> (Loc
    -> TypeQ
    -> Type CIdentifier
    -> [(CIdentifier, Type CIdentifier)]
    -> String
    -> ExpQ)
-> QuasiQuoter
forall a b. (a -> b) -> a -> b
$ Safety
-> Loc
-> TypeQ
-> Type CIdentifier
-> [(CIdentifier, Type CIdentifier)]
-> String
-> ExpQ
inlineExp Safety
TH.Unsafe

-- | Variant of 'exp', for use with expressions known to have no side effects.
--
-- __BEWARE__: Use this function with caution, only when you know what you are
-- doing. If an expression does in fact have side-effects, then indiscriminate
-- use of 'pure' may endanger referential transparency, and in principle even
-- type safety. Also note that the function may run more than once and that it
-- may run in parallel with itself, given that
-- 'System.IO.Unsafe.unsafeDupablePerformIO' is used to call the provided C
-- code [to ensure good performance using the threaded
-- runtime](https://github.com/fpco/inline-c/issues/115).  Please refer to the
-- documentation for 'System.IO.Unsafe.unsafeDupablePerformIO' for more
-- details.
pure :: TH.QuasiQuoter
pure :: QuasiQuoter
pure = Purity
-> (Loc
    -> TypeQ
    -> Type CIdentifier
    -> [(CIdentifier, Type CIdentifier)]
    -> String
    -> ExpQ)
-> QuasiQuoter
genericQuote Purity
Pure ((Loc
  -> TypeQ
  -> Type CIdentifier
  -> [(CIdentifier, Type CIdentifier)]
  -> String
  -> ExpQ)
 -> QuasiQuoter)
-> (Loc
    -> TypeQ
    -> Type CIdentifier
    -> [(CIdentifier, Type CIdentifier)]
    -> String
    -> ExpQ)
-> QuasiQuoter
forall a b. (a -> b) -> a -> b
$ Safety
-> Loc
-> TypeQ
-> Type CIdentifier
-> [(CIdentifier, Type CIdentifier)]
-> String
-> ExpQ
inlineExp Safety
TH.Unsafe

-- | C code blocks (i.e. statements).
block :: TH.QuasiQuoter
block :: QuasiQuoter
block = Purity
-> (Loc
    -> TypeQ
    -> Type CIdentifier
    -> [(CIdentifier, Type CIdentifier)]
    -> String
    -> ExpQ)
-> QuasiQuoter
genericQuote Purity
IO ((Loc
  -> TypeQ
  -> Type CIdentifier
  -> [(CIdentifier, Type CIdentifier)]
  -> String
  -> ExpQ)
 -> QuasiQuoter)
-> (Loc
    -> TypeQ
    -> Type CIdentifier
    -> [(CIdentifier, Type CIdentifier)]
    -> String
    -> ExpQ)
-> QuasiQuoter
forall a b. (a -> b) -> a -> b
$ Safety
-> Bool
-> Maybe String
-> Loc
-> TypeQ
-> Type CIdentifier
-> [(CIdentifier, Type CIdentifier)]
-> String
-> ExpQ
inlineItems Safety
TH.Unsafe Bool
False Maybe String
forall a. Maybe a
Nothing