<commit_before>{-# LANGUAGE UnboxedTuples #-}

-----------------------------------------------------------------------------
-- |
-- Module      :  Language.Haskell.Syntax
-- Copyright   :  (c) The University of Glasgow 2003
-- License     :  BSD-style (see the file libraries/base/LICENSE)
--
-- Maintainer  :  <EMAIL>
-- Stability   :  experimental
-- Portability :  portable
--
-- Abstract syntax definitions for Template Haskell.
--
-----------------------------------------------------------------------------

module Language.Haskell.TH.Syntax where

import GHC.Exts
import Data.Data (Data(..), Typeable, mkConstr, mkDataType, constrIndex)
import qualified Data.Data as Data
import Control.Applicative( Applicative(..) )
import Data.IORef
import System.IO.Unsafe	( unsafePerformIO )
import Control.Monad (liftM)
import System.IO	( hPutStrLn, stderr )
import Data.Char        ( isAlpha )
import Data.Word        ( Word8 )

-----------------------------------------------------
--
--		The Quasi class
--
-----------------------------------------------------

class (Monad m, Applicative m) => Quasi m where
  qNewName :: String -> m Name
	-- ^ Fresh names

	-- Error reporting and recovery
  qReport  :: Bool -> String -> m ()	-- ^ Report an error (True) or warning (False)
					-- ...but carry on; use 'fail' to stop
  qRecover :: m a -- ^ the error handler
           -> m a -- ^ action which may fail
           -> m a		-- ^ Recover from the monadic 'fail'

	-- Inspect the type-checker's environment
  qLookupName :: Bool -> String -> m (Maybe Name)
       -- True <=> type namespace, False <=> value namespace
  qReify          :: Name -> m Info
  qReifyInstances :: Name -> [Type] -> m [Dec]
       -- Is (n tys) an instance?
       -- Returns list of matching instance Decs
       --    (with empty sub-Decs)
       -- Works for classes and type functions
  qReifyRoles     :: Name -> m [Role]

  qLocation :: m Loc

  qRunIO :: IO a -> m a
  -- ^ Input/output (dangerous)

  qAddDependentFile :: FilePath -> m ()

  qAddTopDecls :: [Dec] -> m ()

-----------------------------------------------------
--	The IO instance of Quasi
--
--  This instance is used only when running a Q
--  computation in the IO monad, usually just to
--  print the result.  There is no interesting
--  type environment, so reification isn't going to
--  work.
--
-----------------------------------------------------

instance Quasi IO where
  qNewName s = do { n <- readIORef counter
                 ; writeIORef counter (n+1)
                 ; return (mkNameU s n) }

  qReport True  msg = hPutStrLn stderr ("Template Haskell error: " ++ msg)
  qReport False msg = hPutStrLn stderr ("Template Haskell error: " ++ msg)

  qLookupName _ _     = badIO "lookupName"
  qReify _            = badIO "reify"
  qReifyInstances _ _ = badIO "classInstances"
  qReifyRoles _       = badIO "reifyRoles"
  qLocation    	      = badIO "currentLocation"
  qRecover _ _ 	      = badIO "recover" -- Maybe we could fix this?
  qAddDependentFile _ = badIO "addDependentFile"
  qAddTopDecls _      = badIO "addTopDecls"

  qRunIO m = m

badIO :: String -> IO a
badIO op = do	{ qReport True ("Can't do `" ++ op ++ "' in the IO monad")
		; fail "Template Haskell failure" }

-- Global variable to generate unique symbols
counter :: IORef Int
{-# NOINLINE counter #-}
counter = unsafePerformIO (newIORef 0)


-----------------------------------------------------
--
--		The Q monad
--
-----------------------------------------------------

newtype Q a = Q { unQ :: forall m. Quasi m => m a }

-- \"Runs\" the 'Q' monad. Normal users of Template Haskell
-- should not need this function, as the splice brackets @$( ... )@
-- are the usual way of running a 'Q' computation.
--
-- This function is primarily used in GHC internals, and for debugging
-- splices by running them in 'IO'.
--
-- Note that many functions in 'Q', such as 'reify' and other compiler
-- queries, are not supported when running 'Q' in 'IO'; these operations
-- simply fail at runtime. Indeed, the only operations guaranteed to succeed
-- are 'newName', 'runIO', 'reportError' and 'reportWarning'.
runQ :: Quasi m => Q a -> m a
runQ (Q m) = m

instance Monad Q where
  return x   = Q (return x)
  Q m >>= k  = Q (m >>= \x -> unQ (k x))
  Q m >> Q n = Q (m >> n)
  fail s     = report True s >> Q (fail "Q monad failure")

instance Functor Q where
  fmap f (Q x) = Q (fmap f x)

instance Applicative Q where
  pure x = Q (pure x)
  Q f <*> Q x = Q (f <*> x)

-----------------------------------------------------
--
--		The TExp type
--
-----------------------------------------------------

newtype TExp a = TExp { unType :: Q Exp }

----------------------------------------------------
-- Packaged versions for the programmer, hiding the Quasi-ness<commit_msg>Make a TExp a wrap a TH.Exp instead of a TH.ExpQ.<commit_after>{-# LANGUAGE UnboxedTuples #-}

-----------------------------------------------------------------------------
-- |
-- Module      :  Language.Haskell.Syntax
-- Copyright   :  (c) The University of Glasgow 2003
-- License     :  BSD-style (see the file libraries/base/LICENSE)
--
-- Maintainer  :  <EMAIL>
-- Stability   :  experimental
-- Portability :  portable
--
-- Abstract syntax definitions for Template Haskell.
--
-----------------------------------------------------------------------------

module Language.Haskell.TH.Syntax where

import GHC.Exts
import Data.Data (Data(..), Typeable, mkConstr, mkDataType, constrIndex)
import qualified Data.Data as Data
import Control.Applicative( Applicative(..) )
import Data.IORef
import System.IO.Unsafe	( unsafePerformIO )
import Control.Monad (liftM)
import System.IO	( hPutStrLn, stderr )
import Data.Char        ( isAlpha )
import Data.Word        ( Word8 )

-----------------------------------------------------
--
--		The Quasi class
--
-----------------------------------------------------

class (Monad m, Applicative m) => Quasi m where
  qNewName :: String -> m Name
	-- ^ Fresh names

	-- Error reporting and recovery
  qReport  :: Bool -> String -> m ()	-- ^ Report an error (True) or warning (False)
					-- ...but carry on; use 'fail' to stop
  qRecover :: m a -- ^ the error handler
           -> m a -- ^ action which may fail
           -> m a		-- ^ Recover from the monadic 'fail'

	-- Inspect the type-checker's environment
  qLookupName :: Bool -> String -> m (Maybe Name)
       -- True <=> type namespace, False <=> value namespace
  qReify          :: Name -> m Info
  qReifyInstances :: Name -> [Type] -> m [Dec]
       -- Is (n tys) an instance?
       -- Returns list of matching instance Decs
       --    (with empty sub-Decs)
       -- Works for classes and type functions
  qReifyRoles     :: Name -> m [Role]

  qLocation :: m Loc

  qRunIO :: IO a -> m a
  -- ^ Input/output (dangerous)

  qAddDependentFile :: FilePath -> m ()

  qAddTopDecls :: [Dec] -> m ()

-----------------------------------------------------
--	The IO instance of Quasi
--
--  This instance is used only when running a Q
--  computation in the IO monad, usually just to
--  print the result.  There is no interesting
--  type environment, so reification isn't going to
--  work.
--
-----------------------------------------------------

instance Quasi IO where
  qNewName s = do { n <- readIORef counter
                 ; writeIORef counter (n+1)
                 ; return (mkNameU s n) }

  qReport True  msg = hPutStrLn stderr ("Template Haskell error: " ++ msg)
  qReport False msg = hPutStrLn stderr ("Template Haskell error: " ++ msg)

  qLookupName _ _     = badIO "lookupName"
  qReify _            = badIO "reify"
  qReifyInstances _ _ = badIO "classInstances"
  qReifyRoles _       = badIO "reifyRoles"
  qLocation    	      = badIO "currentLocation"
  qRecover _ _ 	      = badIO "recover" -- Maybe we could fix this?
  qAddDependentFile _ = badIO "addDependentFile"
  qAddTopDecls _      = badIO "addTopDecls"

  qRunIO m = m

badIO :: String -> IO a
badIO op = do	{ qReport True ("Can't do `" ++ op ++ "' in the IO monad")
		; fail "Template Haskell failure" }

-- Global variable to generate unique symbols
counter :: IORef Int
{-# NOINLINE counter #-}
counter = unsafePerformIO (newIORef 0)


-----------------------------------------------------
--
--		The Q monad
--
-----------------------------------------------------

newtype Q a = Q { unQ :: forall m. Quasi m => m a }

-- \"Runs\" the 'Q' monad. Normal users of Template Haskell
-- should not need this function, as the splice brackets @$( ... )@
-- are the usual way of running a 'Q' computation.
--
-- This function is primarily used in GHC internals, and for debugging
-- splices by running them in 'IO'.
--
-- Note that many functions in 'Q', such as 'reify' and other compiler
-- queries, are not supported when running 'Q' in 'IO'; these operations
-- simply fail at runtime. Indeed, the only operations guaranteed to succeed
-- are 'newName', 'runIO', 'reportError' and 'reportWarning'.
runQ :: Quasi m => Q a -> m a
runQ (Q m) = m

instance Monad Q where
  return x   = Q (return x)
  Q m >>= k  = Q (m >>= \x -> unQ (k x))
  Q m >> Q n = Q (m >> n)
  fail s     = report True s >> Q (fail "Q monad failure")

instance Functor Q where
  fmap f (Q x) = Q (fmap f x)

instance Applicative Q where
  pure x = Q (pure x)
  Q f <*> Q x = Q (f <*> x)

-----------------------------------------------------
--
--		The TExp type
--
-----------------------------------------------------

newtype TExp a = TExp { unType :: Exp }

unTypeQ :: Q (TExp a) -> Q Exp
unTypeQ m = do { TExp e <- m
               ; return e }

unsafeTExpCoerce :: Q Exp -> Q (TExp a)
unsafeTExpCoerce m = do { e <- m
                        ; return (TExp e) }

----------------------------------------------------
-- Packaged versions for the programmer, hiding the Quasi-ness
{'fraction_non_alphanumeric': 0.23255105150868638, 'fraction_numerical': 0.001422330590267195, 'mean_word_length': 1.6208732694355699, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 75, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3223881', 'n_tokens_mistral': 2939, 'n_tokens_neox': 2825, 'n_words': 1076}