Teo Camarasu pushed to branch wip/abstract-q at Glasgow Haskell Compiler / GHC
Commits:
-
8bb87c2c
by Teo Camarasu at 2026-06-25T18:09:17+01:00
9 changed files:
- + changelog.d/AbstractQ
- compiler/GHC/Data/IOEnv.hs
- compiler/GHC/Tc/Gen/Splice.hs
- compiler/GHC/Tc/Gen/Splice.hs-boot
- libraries/ghc-internal/src/GHC/Internal/TH/Lib.hs
- libraries/ghc-internal/src/GHC/Internal/TH/Monad.hs
- libraries/ghci/GHCi/TH.hs
- libraries/template-haskell/Language/Haskell/TH/Syntax.hs
- testsuite/tests/interface-stability/template-haskell-exports.stdout
Changes:
| 1 | +section: template-haskell
|
|
| 2 | +synopsis: Hide the implementation of Q
|
|
| 3 | +description: The constructor of Q is now hidden.
|
|
| 4 | + This is done to improve the stability of ``template-haskell``.
|
|
| 5 | + To minimize breakage, we have added a new ``qRunQ`` operation to ``Quasi``.
|
|
| 6 | + The ``Quasi TcM`` instance is no longer exposed from the ``ghc`` API.
|
|
| 7 | + See the `GHC proposal <https://github.com/ghc-proposals/ghc-proposals/pull/700>`_ for more details.
|
|
| 8 | +mrs: !15696
|
|
| 9 | +issues: #27341 |
| ... | ... | @@ -22,7 +22,7 @@ module GHC.Data.IOEnv ( |
| 22 | 22 | IOEnvFailure(..),
|
| 23 | 23 | |
| 24 | 24 | -- Getting at the environment
|
| 25 | - getEnv, setEnv, updEnv, updEnvIO,
|
|
| 25 | + getEnv, setEnv, updEnv, updEnvIO, withRunInIO,
|
|
| 26 | 26 | |
| 27 | 27 | runIOEnv, unsafeInterleaveM, uninterruptibleMaskM_,
|
| 28 | 28 | tryM, tryAllM, tryMostM, fixM,
|
| ... | ... | @@ -258,3 +258,12 @@ updEnv upd (IOEnv m) = IOEnv (\ env -> m (upd env)) |
| 258 | 258 | updEnvIO :: (env -> IO env') -> IOEnv env' a -> IOEnv env a
|
| 259 | 259 | {-# INLINE updEnvIO #-}
|
| 260 | 260 | updEnvIO upd (IOEnv m) = IOEnv (\ env -> m =<< upd env)
|
| 261 | + |
|
| 262 | +-- | 'withRunInIO' specialised to `IOEnv`.
|
|
| 263 | +-- See https://hackage.haskell.org/package/unliftio-core/docs/Control-Monad-IO-Unlift.html#v:withRunInIO for an explanation.
|
|
| 264 | +withRunInIO:: forall env b. ((forall a. IOEnv env a -> IO a) -> IO b) -> IOEnv env b
|
|
| 265 | +withRunInIO k = IOEnv $ \env ->
|
|
| 266 | + let
|
|
| 267 | + unlift :: forall a. IOEnv env a -> IO a
|
|
| 268 | + unlift (IOEnv m) = m env
|
|
| 269 | + in k unlift |
| ... | ... | @@ -25,7 +25,7 @@ module GHC.Tc.Gen.Splice( |
| 25 | 25 | tcTypedSplice, tcTypedBracket, tcUntypedBracket,
|
| 26 | 26 | runAnnotation, getUntypedSpliceBody,
|
| 27 | 27 | |
| 28 | - runMetaE, runMetaP, runMetaT, runMetaD, runQuasi,
|
|
| 28 | + runMetaE, runMetaP, runMetaT, runMetaD, runQinTcM,
|
|
| 29 | 29 | tcTopSpliceExpr, lookupThName_maybe,
|
| 30 | 30 | defaultRunMeta, runMeta', runRemoteModFinalizers,
|
| 31 | 31 | finishTH, runTopSplice
|
| ... | ... | @@ -138,6 +138,7 @@ import qualified GHC.LanguageExtensions as LangExt |
| 138 | 138 | -- THSyntax gives access to internal functions and data types
|
| 139 | 139 | import qualified GHC.Boot.TH.Syntax as TH
|
| 140 | 140 | import qualified GHC.Boot.TH.Monad as TH
|
| 141 | +import GHC.Boot.TH.Monad (MetaHandlers(..))
|
|
| 141 | 142 | import qualified GHC.Boot.TH.Ppr as TH
|
| 142 | 143 | |
| 143 | 144 | #if defined(HAVE_INTERNAL_INTERPRETER)
|
| ... | ... | @@ -1138,8 +1139,8 @@ convertAnnotationWrapper fhv = do |
| 1138 | 1139 | ************************************************************************
|
| 1139 | 1140 | -}
|
| 1140 | 1141 | |
| 1141 | -runQuasi :: TH.Q a -> TcM a
|
|
| 1142 | -runQuasi act = TH.runQ act
|
|
| 1142 | +runQinTcM :: TH.Q a -> TcM a
|
|
| 1143 | +runQinTcM (TH.Q act) = withRunInIO $ \runInIO -> act (metaHandlersTcM runInIO)
|
|
| 1143 | 1144 | |
| 1144 | 1145 | runRemoteModFinalizers :: ThModFinalizers -> TcM ()
|
| 1145 | 1146 | runRemoteModFinalizers (ThModFinalizers finRefs) = do
|
| ... | ... | @@ -1152,7 +1153,7 @@ runRemoteModFinalizers (ThModFinalizers finRefs) = do |
| 1152 | 1153 | #if defined(HAVE_INTERNAL_INTERPRETER)
|
| 1153 | 1154 | InternalInterp -> do
|
| 1154 | 1155 | qs <- liftIO (withForeignRefs finRefs $ mapM localRef)
|
| 1155 | - runQuasi $ sequence_ qs
|
|
| 1156 | + runQinTcM $ sequence_ qs
|
|
| 1156 | 1157 | #endif
|
| 1157 | 1158 | |
| 1158 | 1159 | ExternalInterp ext -> withExtInterp ext $ \inst -> do
|
| ... | ... | @@ -1466,70 +1467,14 @@ when showing an error message. |
| 1466 | 1467 | To call runQ in the Tc monad, we need to make TcM an instance of Quasi:
|
| 1467 | 1468 | -}
|
| 1468 | 1469 | |
| 1469 | -instance TH.Quasi TcM where
|
|
| 1470 | - qNewName s = do { u <- newUnique
|
|
| 1471 | - ; let i = toInteger (getKey u)
|
|
| 1472 | - ; return (TH.mkNameU s i) }
|
|
| 1470 | +-- 'msg' is forced to ensure exceptions don't escape,
|
|
| 1471 | +-- see Note [Exceptions in TH]
|
|
| 1472 | +report :: Bool -> [Char] -> TcM ()
|
|
| 1473 | +report True msg = seqList msg $ addErr $ TcRnTHError $ ReportCustomQuasiError True msg
|
|
| 1474 | +report False msg = seqList msg $ addDiagnostic $ TcRnTHError $ ReportCustomQuasiError False msg
|
|
| 1473 | 1475 | |
| 1474 | - -- 'msg' is forced to ensure exceptions don't escape,
|
|
| 1475 | - -- see Note [Exceptions in TH]
|
|
| 1476 | - qReport True msg = seqList msg $ addErr $ TcRnTHError $ ReportCustomQuasiError True msg
|
|
| 1477 | - qReport False msg = seqList msg $ addDiagnostic $ TcRnTHError $ ReportCustomQuasiError False msg
|
|
| 1478 | - |
|
| 1479 | - qLocation :: TcM TH.Loc
|
|
| 1480 | - qLocation = do { m <- getModule
|
|
| 1481 | - ; l <- getSrcSpanM
|
|
| 1482 | - ; r <- case l of
|
|
| 1483 | - RealSrcSpan s _ -> return s
|
|
| 1484 | - GeneratedSrcSpan{} -> pprPanic "qLocation: generatedSrcSpan"
|
|
| 1485 | - (pprGeneratedSrcSpanDetails)
|
|
| 1486 | - UnhelpfulSpan _ -> pprPanic "qLocation: Unhelpful location"
|
|
| 1487 | - (ppr l)
|
|
| 1488 | - ; return (TH.Loc { TH.loc_filename = unpackFS (srcSpanFile r)
|
|
| 1489 | - , TH.loc_module = moduleNameString (moduleName m)
|
|
| 1490 | - , TH.loc_package = unitString (moduleUnit m)
|
|
| 1491 | - , TH.loc_start = (srcSpanStartLine r, srcSpanStartCol r)
|
|
| 1492 | - , TH.loc_end = (srcSpanEndLine r, srcSpanEndCol r) }) }
|
|
| 1493 | - |
|
| 1494 | - qLookupName = lookupName
|
|
| 1495 | - qReify = reify
|
|
| 1496 | - qReifyFixity nm = lookupThName nm >>= reifyFixity
|
|
| 1497 | - qReifyType = reifyTypeOfThing
|
|
| 1498 | - qReifyInstances = reifyInstances
|
|
| 1499 | - qReifyRoles = reifyRoles
|
|
| 1500 | - qReifyAnnotations = reifyAnnotations
|
|
| 1501 | - qReifyModule = reifyModule
|
|
| 1502 | - qReifyConStrictness nm = do { nm' <- lookupThName nm
|
|
| 1503 | - ; dc <- tcLookupDataCon nm'
|
|
| 1504 | - ; let bangs = dataConImplBangs dc
|
|
| 1505 | - ; return (map reifyDecidedStrictness bangs) }
|
|
| 1506 | - |
|
| 1507 | - -- For qRecover, discard error messages if
|
|
| 1508 | - -- the recovery action is chosen. Otherwise
|
|
| 1509 | - -- we'll only fail higher up.
|
|
| 1510 | - qRecover recover main = tryTcDiscardingErrs recover main
|
|
| 1511 | - |
|
| 1512 | - qGetPackageRoot = do
|
|
| 1513 | - dflags <- getDynFlags
|
|
| 1514 | - return $ fromMaybe "." (workingDirectory dflags)
|
|
| 1515 | - |
|
| 1516 | - qAddDependentFile fp = do
|
|
| 1517 | - ref <- fmap tcg_dependent_files getGblEnv
|
|
| 1518 | - dep_files <- readTcRef ref
|
|
| 1519 | - writeTcRef ref (fp:dep_files)
|
|
| 1520 | - |
|
| 1521 | - qAddDependentDirectory dp = do
|
|
| 1522 | - ref <- fmap tcg_dependent_dirs getGblEnv
|
|
| 1523 | - dep_dirs <- readTcRef ref
|
|
| 1524 | - writeTcRef ref (dp:dep_dirs)
|
|
| 1525 | - |
|
| 1526 | - qAddTempFile suffix = do
|
|
| 1527 | - dflags <- getDynFlags
|
|
| 1528 | - logger <- getLogger
|
|
| 1529 | - tmpfs <- hsc_tmpfs <$> getTopEnv
|
|
| 1530 | - liftIO $ newTempName logger tmpfs (tmpDir dflags) TFL_GhcSession suffix
|
|
| 1531 | - |
|
| 1532 | - qAddTopDecls thds = do
|
|
| 1476 | +addTopDecls :: [TH.Dec] -> TcM ()
|
|
| 1477 | +addTopDecls thds = do
|
|
| 1533 | 1478 | exts <- fmap extensionFlags getDynFlags
|
| 1534 | 1479 | l <- getSrcSpanM
|
| 1535 | 1480 | th_origin <- getThSpliceOrigin
|
| ... | ... | @@ -1557,52 +1502,13 @@ instance TH.Quasi TcM where |
| 1557 | 1502 | bindName :: RdrName -> TcM ()
|
| 1558 | 1503 | bindName (Exact n)
|
| 1559 | 1504 | = do { th_topnames_var <- fmap tcg_th_topnames getGblEnv
|
| 1560 | - ; updTcRef th_topnames_var (\ns -> extendNameSet ns n)
|
|
| 1561 | - }
|
|
| 1505 | + ; updTcRef th_topnames_var (\ns -> extendNameSet ns n)
|
|
| 1506 | + }
|
|
| 1562 | 1507 | |
| 1563 | 1508 | bindName name = addErr $ TcRnTHError $ THNameError $ NonExactName name
|
| 1564 | 1509 | |
| 1565 | - qAddForeignFilePath lang fp = do
|
|
| 1566 | - var <- fmap tcg_th_foreign_files getGblEnv
|
|
| 1567 | - updTcRef var ((lang, fp) :)
|
|
| 1568 | - |
|
| 1569 | - qAddModFinalizer fin = do
|
|
| 1570 | - r <- liftIO $ mkRemoteRef fin
|
|
| 1571 | - fref <- liftIO $ mkForeignRef r (freeRemoteRef r)
|
|
| 1572 | - addModFinalizerRef fref
|
|
| 1573 | - |
|
| 1574 | - qAddCorePlugin plugin = do
|
|
| 1575 | - hsc_env <- getTopEnv
|
|
| 1576 | - let fc = hsc_FC hsc_env
|
|
| 1577 | - let home_unit = hsc_home_unit hsc_env
|
|
| 1578 | - let dflags = hsc_dflags hsc_env
|
|
| 1579 | - let fopts = initFinderOpts dflags
|
|
| 1580 | - r <- liftIO $ findHomeModule fc fopts home_unit (mkModuleName plugin)
|
|
| 1581 | - let err = TcRnTHError $ AddInvalidCorePlugin plugin
|
|
| 1582 | - case r of
|
|
| 1583 | - Found {} -> addErr err
|
|
| 1584 | - FoundMultiple {} -> addErr err
|
|
| 1585 | - _ -> return ()
|
|
| 1586 | - th_coreplugins_var <- tcg_th_coreplugins <$> getGblEnv
|
|
| 1587 | - updTcRef th_coreplugins_var (plugin:)
|
|
| 1588 | - |
|
| 1589 | - qGetQ :: forall a. Typeable a => TcM (Maybe a)
|
|
| 1590 | - qGetQ = do
|
|
| 1591 | - th_state_var <- fmap tcg_th_state getGblEnv
|
|
| 1592 | - th_state <- readTcRef th_state_var
|
|
| 1593 | - -- See #10596 for why we use a scoped type variable here.
|
|
| 1594 | - return (Map.lookup (typeRep (Proxy :: Proxy a)) th_state >>= fromDynamic)
|
|
| 1595 | - |
|
| 1596 | - qPutQ x = do
|
|
| 1597 | - th_state_var <- fmap tcg_th_state getGblEnv
|
|
| 1598 | - updTcRef th_state_var (\m -> Map.insert (typeOf x) (toDyn x) m)
|
|
| 1599 | - |
|
| 1600 | - qIsExtEnabled = xoptM
|
|
| 1601 | - |
|
| 1602 | - qExtsEnabled =
|
|
| 1603 | - EnumSet.toList . extensionFlags . hsc_dflags <$> getTopEnv
|
|
| 1604 | - |
|
| 1605 | - qPutDoc doc_loc s = do
|
|
| 1510 | +putDoc :: TH.DocLoc -> String -> TcM ()
|
|
| 1511 | +putDoc doc_loc s = do
|
|
| 1606 | 1512 | th_doc_var <- tcg_th_docs <$> getGblEnv
|
| 1607 | 1513 | resolved_doc_loc <- resolve_loc doc_loc
|
| 1608 | 1514 | is_local <- checkLocalName resolved_doc_loc
|
| ... | ... | @@ -1624,15 +1530,131 @@ instance TH.Quasi TcM where |
| 1624 | 1530 | checkLocalName (InstDoc n) = nameIsLocalOrFrom <$> getModule <*> pure n
|
| 1625 | 1531 | checkLocalName ModuleDoc = pure True
|
| 1626 | 1532 | |
| 1627 | - |
|
| 1628 | - qGetDoc (TH.DeclDoc n) = lookupThName n >>= lookupDeclDoc
|
|
| 1629 | - qGetDoc (TH.InstDoc t) = lookupThInstName t >>= lookupDeclDoc
|
|
| 1630 | - qGetDoc (TH.ArgDoc n i) = lookupThName n >>= lookupArgDoc i
|
|
| 1631 | - qGetDoc TH.ModuleDoc = do
|
|
| 1533 | +getDoc :: TH.DocLoc -> TcM (Maybe String)
|
|
| 1534 | +getDoc (TH.DeclDoc n) = lookupThName n >>= lookupDeclDoc
|
|
| 1535 | +getDoc (TH.InstDoc t) = lookupThInstName t >>= lookupDeclDoc
|
|
| 1536 | +getDoc (TH.ArgDoc n i) = lookupThName n >>= lookupArgDoc i
|
|
| 1537 | +getDoc TH.ModuleDoc = do
|
|
| 1632 | 1538 | df <- getDynFlags
|
| 1633 | 1539 | docs <- getGblEnv >>= extractDocs df
|
| 1634 | 1540 | return (renderHsDocString . hsDocString <$> (docs_mod_hdr =<< docs))
|
| 1635 | 1541 | |
| 1542 | +getQ :: forall a. Typeable a => TcM (Maybe a)
|
|
| 1543 | +getQ = do
|
|
| 1544 | + th_state_var <- fmap tcg_th_state getGblEnv
|
|
| 1545 | + th_state <- readTcRef th_state_var
|
|
| 1546 | + -- See #10596 for why we use a scoped type variable here.
|
|
| 1547 | + return (Map.lookup (typeRep (Proxy :: Proxy a)) th_state >>= fromDynamic)
|
|
| 1548 | + |
|
| 1549 | +location :: TcM TH.Loc
|
|
| 1550 | +location = do { m <- getModule
|
|
| 1551 | + ; l <- getSrcSpanM
|
|
| 1552 | + ; r <- case l of
|
|
| 1553 | + RealSrcSpan s _ -> return s
|
|
| 1554 | + GeneratedSrcSpan{} -> pprPanic "qLocation: generatedSrcSpan"
|
|
| 1555 | + (pprGeneratedSrcSpanDetails)
|
|
| 1556 | + UnhelpfulSpan _ -> pprPanic "qLocation: Unhelpful location"
|
|
| 1557 | + (ppr l)
|
|
| 1558 | + ; return (TH.Loc { TH.loc_filename = unpackFS (srcSpanFile r)
|
|
| 1559 | + , TH.loc_module = moduleNameString (moduleName m)
|
|
| 1560 | + , TH.loc_package = unitString (moduleUnit m)
|
|
| 1561 | + , TH.loc_start = (srcSpanStartLine r, srcSpanStartCol r)
|
|
| 1562 | + , TH.loc_end = (srcSpanEndLine r, srcSpanEndCol r) }) }
|
|
| 1563 | + |
|
| 1564 | +metaHandlersTcM :: (forall x. TcM x -> IO x) -> TH.MetaHandlers
|
|
| 1565 | +metaHandlersTcM runInIO = TH.MetaHandlers {
|
|
| 1566 | + mLiftIO = id
|
|
| 1567 | + -- We are careful to use the TcM instance not the one for IO, since that would lead to a different error.
|
|
| 1568 | + , mFail = \s -> runInIO $ fail @TcM s
|
|
| 1569 | + , mNewName = \s -> runInIO $ do { u <- newUnique
|
|
| 1570 | + ; let i = toInteger (getKey u)
|
|
| 1571 | + ; return (TH.mkNameU s i) }
|
|
| 1572 | + |
|
| 1573 | + , mReport = fmap runInIO . report
|
|
| 1574 | + |
|
| 1575 | + , mLocation = runInIO location
|
|
| 1576 | + |
|
| 1577 | + , mLookupName = fmap runInIO . lookupName
|
|
| 1578 | + , mReify = runInIO . reify
|
|
| 1579 | + , mReifyFixity = \nm -> runInIO $ lookupThName nm >>= reifyFixity
|
|
| 1580 | + , mReifyType = runInIO . reifyTypeOfThing
|
|
| 1581 | + , mReifyInstances = fmap runInIO . reifyInstances
|
|
| 1582 | + , mReifyRoles = runInIO . reifyRoles
|
|
| 1583 | + , mReifyAnnotations = runInIO . reifyAnnotations
|
|
| 1584 | + , mReifyModule = runInIO . reifyModule
|
|
| 1585 | + , mReifyConStrictness = \nm -> runInIO $ do
|
|
| 1586 | + { nm' <- lookupThName nm
|
|
| 1587 | + ; dc <- tcLookupDataCon nm'
|
|
| 1588 | + ; let bangs = dataConImplBangs dc
|
|
| 1589 | + ; return (map reifyDecidedStrictness bangs) }
|
|
| 1590 | + |
|
| 1591 | + -- For qRecover, discard error messages if
|
|
| 1592 | + -- the recovery action is chosen. Otherwise
|
|
| 1593 | + -- we'll only fail higher up.
|
|
| 1594 | + , mRecover = \recover main -> runInIO $ tryTcDiscardingErrs (runQinTcM recover) (runQinTcM main)
|
|
| 1595 | + |
|
| 1596 | + , mGetPackageRoot = runInIO $ do
|
|
| 1597 | + dflags <- getDynFlags
|
|
| 1598 | + return $ fromMaybe "." (workingDirectory dflags)
|
|
| 1599 | + |
|
| 1600 | + , mAddDependentFile = \fp -> runInIO $ do
|
|
| 1601 | + ref <- fmap tcg_dependent_files getGblEnv
|
|
| 1602 | + dep_files <- readTcRef ref
|
|
| 1603 | + writeTcRef ref (fp:dep_files)
|
|
| 1604 | + |
|
| 1605 | + , mAddDependentDirectory = \dp -> runInIO $ do
|
|
| 1606 | + ref <- fmap tcg_dependent_dirs getGblEnv
|
|
| 1607 | + dep_dirs <- readTcRef ref
|
|
| 1608 | + writeTcRef ref (dp:dep_dirs)
|
|
| 1609 | + |
|
| 1610 | + , mAddTempFile = \suffix -> runInIO $ do
|
|
| 1611 | + dflags <- getDynFlags
|
|
| 1612 | + logger <- getLogger
|
|
| 1613 | + tmpfs <- hsc_tmpfs <$> getTopEnv
|
|
| 1614 | + liftIO $ newTempName logger tmpfs (tmpDir dflags) TFL_GhcSession suffix
|
|
| 1615 | + |
|
| 1616 | + , mAddTopDecls = runInIO . addTopDecls
|
|
| 1617 | + |
|
| 1618 | + , mAddForeignFilePath = \lang fp -> runInIO $ do
|
|
| 1619 | + var <- fmap tcg_th_foreign_files getGblEnv
|
|
| 1620 | + updTcRef var ((lang, fp) :)
|
|
| 1621 | + |
|
| 1622 | + , mAddModFinalizer = \fin -> runInIO $ do
|
|
| 1623 | + r <- liftIO $ mkRemoteRef fin
|
|
| 1624 | + fref <- liftIO $ mkForeignRef r (freeRemoteRef r)
|
|
| 1625 | + addModFinalizerRef fref
|
|
| 1626 | + |
|
| 1627 | + , mAddCorePlugin = \plugin -> runInIO $ do
|
|
| 1628 | + hsc_env <- getTopEnv
|
|
| 1629 | + let fc = hsc_FC hsc_env
|
|
| 1630 | + let home_unit = hsc_home_unit hsc_env
|
|
| 1631 | + let dflags = hsc_dflags hsc_env
|
|
| 1632 | + let fopts = initFinderOpts dflags
|
|
| 1633 | + r <- liftIO $ findHomeModule fc fopts home_unit (mkModuleName plugin)
|
|
| 1634 | + let err = TcRnTHError $ AddInvalidCorePlugin plugin
|
|
| 1635 | + case r of
|
|
| 1636 | + Found {} -> addErr err
|
|
| 1637 | + FoundMultiple {} -> addErr err
|
|
| 1638 | + _ -> return ()
|
|
| 1639 | + th_coreplugins_var <- tcg_th_coreplugins <$> getGblEnv
|
|
| 1640 | + updTcRef th_coreplugins_var (plugin:)
|
|
| 1641 | + |
|
| 1642 | + , mGetQ = runInIO getQ
|
|
| 1643 | + |
|
| 1644 | + , mPutQ = \x -> runInIO $ do
|
|
| 1645 | + th_state_var <- fmap tcg_th_state getGblEnv
|
|
| 1646 | + updTcRef th_state_var (\m -> Map.insert (typeOf x) (toDyn x) m)
|
|
| 1647 | + |
|
| 1648 | + , mIsExtEnabled = runInIO . xoptM
|
|
| 1649 | + |
|
| 1650 | + , mExtsEnabled = runInIO $
|
|
| 1651 | + EnumSet.toList . extensionFlags . hsc_dflags <$> getTopEnv
|
|
| 1652 | + |
|
| 1653 | + , mPutDoc = fmap runInIO . putDoc
|
|
| 1654 | + |
|
| 1655 | + , mGetDoc = runInIO . getDoc
|
|
| 1656 | + }
|
|
| 1657 | + |
|
| 1636 | 1658 | -- | Looks up documentation for a declaration in first the current module,
|
| 1637 | 1659 | -- otherwise tries to find it in another module via 'hscGetModuleInterface'.
|
| 1638 | 1660 | lookupDeclDoc :: Name -> TcM (Maybe String)
|
| ... | ... | @@ -1788,7 +1810,7 @@ runTH ty fhv = do |
| 1788 | 1810 | InternalInterp -> do
|
| 1789 | 1811 | -- Run it in the local TcM
|
| 1790 | 1812 | hv <- liftIO $ wormhole interp fhv
|
| 1791 | - r <- runQuasi (unsafeCoerce hv :: TH.Q a)
|
|
| 1813 | + r <- runQinTcM (unsafeCoerce hv :: TH.Q a)
|
|
| 1792 | 1814 | return r
|
| 1793 | 1815 | #endif
|
| 1794 | 1816 | |
| ... | ... | @@ -1797,7 +1819,7 @@ runTH ty fhv = do |
| 1797 | 1819 | -- Remote GHCi, see Note [Remote Template Haskell] in
|
| 1798 | 1820 | -- libraries/ghci/GHCi/TH.hs.
|
| 1799 | 1821 | rstate <- getTHState inst
|
| 1800 | - loc <- TH.qLocation
|
|
| 1822 | + loc <- location
|
|
| 1801 | 1823 | -- run a remote TH request
|
| 1802 | 1824 | r <- liftIO $
|
| 1803 | 1825 | withForeignRef rstate $ \state_hv ->
|
| ... | ... | @@ -1913,32 +1935,32 @@ wrapTHResult tcm = do |
| 1913 | 1935 | |
| 1914 | 1936 | handleTHMessage :: THMessage a -> TcM a
|
| 1915 | 1937 | handleTHMessage msg = case msg of
|
| 1916 | - NewName a -> wrapTHResult $ TH.qNewName a
|
|
| 1917 | - Report b str -> wrapTHResult $ TH.qReport b str
|
|
| 1918 | - LookupName b str -> wrapTHResult $ TH.qLookupName b str
|
|
| 1919 | - Reify n -> wrapTHResult $ TH.qReify n
|
|
| 1920 | - ReifyFixity n -> wrapTHResult $ TH.qReifyFixity n
|
|
| 1921 | - ReifyType n -> wrapTHResult $ TH.qReifyType n
|
|
| 1922 | - ReifyInstances n ts -> wrapTHResult $ TH.qReifyInstances n ts
|
|
| 1923 | - ReifyRoles n -> wrapTHResult $ TH.qReifyRoles n
|
|
| 1938 | + NewName a -> wrapTHResult $ runQinTcM $ TH.newName a
|
|
| 1939 | + Report b str -> wrapTHResult $ runQinTcM $ TH.report b str
|
|
| 1940 | + LookupName b str -> wrapTHResult $ runQinTcM $ TH.lookupName b str
|
|
| 1941 | + Reify n -> wrapTHResult $ runQinTcM $ TH.reify n
|
|
| 1942 | + ReifyFixity n -> wrapTHResult $ runQinTcM $ TH.reifyFixity n
|
|
| 1943 | + ReifyType n -> wrapTHResult $ runQinTcM $ TH.reifyType n
|
|
| 1944 | + ReifyInstances n ts -> wrapTHResult $ runQinTcM $ TH.reifyInstances n ts
|
|
| 1945 | + ReifyRoles n -> wrapTHResult $ runQinTcM $ TH.reifyRoles n
|
|
| 1924 | 1946 | ReifyAnnotations lookup tyrep ->
|
| 1925 | 1947 | wrapTHResult $ (map B.pack <$> getAnnotationsByTypeRep lookup tyrep)
|
| 1926 | - ReifyModule m -> wrapTHResult $ TH.qReifyModule m
|
|
| 1927 | - ReifyConStrictness nm -> wrapTHResult $ TH.qReifyConStrictness nm
|
|
| 1928 | - GetPackageRoot -> wrapTHResult $ TH.qGetPackageRoot
|
|
| 1929 | - AddDependentFile f -> wrapTHResult $ TH.qAddDependentFile f
|
|
| 1930 | - AddDependentDirectory d -> wrapTHResult $ TH.qAddDependentDirectory d
|
|
| 1931 | - AddTempFile s -> wrapTHResult $ TH.qAddTempFile s
|
|
| 1948 | + ReifyModule m -> wrapTHResult $ runQinTcM $ TH.reifyModule m
|
|
| 1949 | + ReifyConStrictness nm -> wrapTHResult $ runQinTcM $ TH.reifyConStrictness nm
|
|
| 1950 | + GetPackageRoot -> wrapTHResult $ runQinTcM $ TH.getPackageRoot
|
|
| 1951 | + AddDependentFile f -> wrapTHResult $ runQinTcM $ TH.addDependentFile f
|
|
| 1952 | + AddDependentDirectory d -> wrapTHResult $ runQinTcM $ TH.addDependentDirectory d
|
|
| 1953 | + AddTempFile s -> wrapTHResult $ runQinTcM $ TH.addTempFile s
|
|
| 1932 | 1954 | AddModFinalizer r -> do
|
| 1933 | 1955 | interp <- hscInterp <$> getTopEnv
|
| 1934 | 1956 | wrapTHResult $ liftIO (mkFinalizedHValue interp r) >>= addModFinalizerRef
|
| 1935 | - AddCorePlugin str -> wrapTHResult $ TH.qAddCorePlugin str
|
|
| 1936 | - AddTopDecls decs -> wrapTHResult $ TH.qAddTopDecls decs
|
|
| 1937 | - AddForeignFilePath lang str -> wrapTHResult $ TH.qAddForeignFilePath lang str
|
|
| 1938 | - IsExtEnabled ext -> wrapTHResult $ TH.qIsExtEnabled ext
|
|
| 1939 | - ExtsEnabled -> wrapTHResult $ TH.qExtsEnabled
|
|
| 1940 | - PutDoc l s -> wrapTHResult $ TH.qPutDoc l s
|
|
| 1941 | - GetDoc l -> wrapTHResult $ TH.qGetDoc l
|
|
| 1957 | + AddCorePlugin str -> wrapTHResult $ runQinTcM $ TH.addCorePlugin str
|
|
| 1958 | + AddTopDecls decs -> wrapTHResult $ runQinTcM $ TH.addTopDecls decs
|
|
| 1959 | + AddForeignFilePath lang str -> wrapTHResult $ runQinTcM $ TH.addForeignFilePath lang str
|
|
| 1960 | + IsExtEnabled ext -> wrapTHResult $ runQinTcM $ TH.isExtEnabled ext
|
|
| 1961 | + ExtsEnabled -> wrapTHResult $ runQinTcM $ TH.extsEnabled
|
|
| 1962 | + PutDoc l s -> wrapTHResult $ runQinTcM $ TH.putDoc l s
|
|
| 1963 | + GetDoc l -> wrapTHResult $ runQinTcM $ TH.getDoc l
|
|
| 1942 | 1964 | FailIfErrs -> wrapTHResult failIfErrsM
|
| 1943 | 1965 | _ -> panic ("handleTHMessage: unexpected message " ++ show msg)
|
| 1944 | 1966 |
| ... | ... | @@ -42,6 +42,6 @@ runMetaT :: LHsExpr GhcTc -> TcM (LHsType GhcPs) |
| 42 | 42 | runMetaD :: LHsExpr GhcTc -> TcM [LHsDecl GhcPs]
|
| 43 | 43 | |
| 44 | 44 | lookupThName_maybe :: TH.Name -> TcM (Maybe Name)
|
| 45 | -runQuasi :: TH.Q a -> TcM a
|
|
| 45 | +runQinTcM :: TH.Q a -> TcM a
|
|
| 46 | 46 | runRemoteModFinalizers :: ThModFinalizers -> TcM ()
|
| 47 | 47 | finishTH :: TcM () |
| ... | ... | @@ -1079,7 +1079,7 @@ withDecDoc :: String -> Q Dec -> Q Dec |
| 1079 | 1079 | withDecDoc doc dec = do
|
| 1080 | 1080 | dec' <- dec
|
| 1081 | 1081 | case doc_loc dec' of
|
| 1082 | - Just loc -> qAddModFinalizer $ qPutDoc loc doc
|
|
| 1082 | + Just loc -> addModFinalizer $ putDoc loc doc
|
|
| 1083 | 1083 | Nothing -> pure ()
|
| 1084 | 1084 | pure dec'
|
| 1085 | 1085 | where
|
| ... | ... | @@ -1128,7 +1128,7 @@ funD_doc :: Name -> [Q Clause] |
| 1128 | 1128 | -> [Maybe String] -- ^ Documentation to attach to arguments
|
| 1129 | 1129 | -> Q Dec
|
| 1130 | 1130 | funD_doc nm cs mfun_doc arg_docs = do
|
| 1131 | - qAddModFinalizer $ sequence_
|
|
| 1131 | + addModFinalizer $ sequence_
|
|
| 1132 | 1132 | [putDoc (ArgDoc nm i) s | (i, Just s) <- zip [0..] arg_docs]
|
| 1133 | 1133 | let dec = funD nm cs
|
| 1134 | 1134 | case mfun_doc of
|
| ... | ... | @@ -1145,7 +1145,7 @@ dataD_doc :: Q Cxt -> Name -> [Q (TyVarBndr BndrVis)] -> Maybe (Q Kind) |
| 1145 | 1145 | -- ^ Documentation to attach to the data declaration
|
| 1146 | 1146 | -> Q Dec
|
| 1147 | 1147 | dataD_doc ctxt tc tvs ksig cons_with_docs derivs mdoc = do
|
| 1148 | - qAddModFinalizer $ mapM_ docCons cons_with_docs
|
|
| 1148 | + addModFinalizer $ mapM_ docCons cons_with_docs
|
|
| 1149 | 1149 | let dec = dataD ctxt tc tvs ksig (map (\(con, _, _) -> con) cons_with_docs) derivs
|
| 1150 | 1150 | maybe dec (flip withDecDoc dec) mdoc
|
| 1151 | 1151 | |
| ... | ... | @@ -1159,7 +1159,7 @@ newtypeD_doc :: Q Cxt -> Name -> [Q (TyVarBndr BndrVis)] -> Maybe (Q Kind) |
| 1159 | 1159 | -- ^ Documentation to attach to the newtype declaration
|
| 1160 | 1160 | -> Q Dec
|
| 1161 | 1161 | newtypeD_doc ctxt tc tvs ksig con_with_docs@(con, _, _) derivs mdoc = do
|
| 1162 | - qAddModFinalizer $ docCons con_with_docs
|
|
| 1162 | + addModFinalizer $ docCons con_with_docs
|
|
| 1163 | 1163 | let dec = newtypeD ctxt tc tvs ksig con derivs
|
| 1164 | 1164 | maybe dec (flip withDecDoc dec) mdoc
|
| 1165 | 1165 | |
| ... | ... | @@ -1172,7 +1172,7 @@ typeDataD_doc :: Name -> [Q (TyVarBndr BndrVis)] -> Maybe (Q Kind) |
| 1172 | 1172 | -- ^ Documentation to attach to the data declaration
|
| 1173 | 1173 | -> Q Dec
|
| 1174 | 1174 | typeDataD_doc tc tvs ksig cons_with_docs mdoc = do
|
| 1175 | - qAddModFinalizer $ mapM_ docCons cons_with_docs
|
|
| 1175 | + addModFinalizer $ mapM_ docCons cons_with_docs
|
|
| 1176 | 1176 | let dec = typeDataD tc tvs ksig (map (\(con, _, _) -> con) cons_with_docs)
|
| 1177 | 1177 | maybe dec (flip withDecDoc dec) mdoc
|
| 1178 | 1178 | |
| ... | ... | @@ -1186,7 +1186,7 @@ dataInstD_doc :: Q Cxt -> (Maybe [Q (TyVarBndr ())]) -> Q Type -> Maybe (Q Kind) |
| 1186 | 1186 | -- ^ Documentation to attach to the instance declaration
|
| 1187 | 1187 | -> Q Dec
|
| 1188 | 1188 | dataInstD_doc ctxt mb_bndrs ty ksig cons_with_docs derivs mdoc = do
|
| 1189 | - qAddModFinalizer $ mapM_ docCons cons_with_docs
|
|
| 1189 | + addModFinalizer $ mapM_ docCons cons_with_docs
|
|
| 1190 | 1190 | let dec = dataInstD ctxt mb_bndrs ty ksig (map (\(con, _, _) -> con) cons_with_docs)
|
| 1191 | 1191 | derivs
|
| 1192 | 1192 | maybe dec (flip withDecDoc dec) mdoc
|
| ... | ... | @@ -1202,7 +1202,7 @@ newtypeInstD_doc :: Q Cxt -> (Maybe [Q (TyVarBndr ())]) -> Q Type |
| 1202 | 1202 | -- ^ Documentation to attach to the instance declaration
|
| 1203 | 1203 | -> Q Dec
|
| 1204 | 1204 | newtypeInstD_doc ctxt mb_bndrs ty ksig con_with_docs@(con, _, _) derivs mdoc = do
|
| 1205 | - qAddModFinalizer $ docCons con_with_docs
|
|
| 1205 | + addModFinalizer $ docCons con_with_docs
|
|
| 1206 | 1206 | let dec = newtypeInstD ctxt mb_bndrs ty ksig con derivs
|
| 1207 | 1207 | maybe dec (flip withDecDoc dec) mdoc
|
| 1208 | 1208 | |
| ... | ... | @@ -1212,7 +1212,7 @@ patSynD_doc :: Name -> Q PatSynArgs -> Q PatSynDir -> Q Pat |
| 1212 | 1212 | -> [Maybe String] -- ^ Documentation to attach to the pattern arguments
|
| 1213 | 1213 | -> Q Dec
|
| 1214 | 1214 | patSynD_doc name args dir pat mdoc arg_docs = do
|
| 1215 | - qAddModFinalizer $ sequence_
|
|
| 1215 | + addModFinalizer $ sequence_
|
|
| 1216 | 1216 | [putDoc (ArgDoc name i) s | (i, Just s) <- zip [0..] arg_docs]
|
| 1217 | 1217 | let dec = patSynD name args dir pat
|
| 1218 | 1218 | maybe dec (flip withDecDoc dec) mdoc
|
| ... | ... | @@ -29,13 +29,13 @@ import Data.Data hiding (Fixity(..)) |
| 29 | 29 | import Data.IORef
|
| 30 | 30 | import System.IO.Unsafe (unsafePerformIO)
|
| 31 | 31 | import Control.Monad.IO.Class (MonadIO (..))
|
| 32 | -import System.IO (FilePath, hPutStrLn, stderr)
|
|
| 32 | +import System.IO (hPutStrLn, stderr)
|
|
| 33 | 33 | import qualified Data.Kind as Kind (Type)
|
| 34 | 34 | import GHC.Types (TYPE, RuntimeRep(..))
|
| 35 | 35 | #else
|
| 36 | 36 | import GHC.Internal.Base (
|
| 37 | 37 | Applicative(..), Functor(..), Monad(..), Monoid(..), Semigroup(..), String,
|
| 38 | - flip, id, (.), (++),
|
|
| 38 | + flip, id, (.), (++), ($),
|
|
| 39 | 39 | )
|
| 40 | 40 | import GHC.Internal.Classes (not)
|
| 41 | 41 | import GHC.Internal.Data.Data hiding (Fixity(..))
|
| ... | ... | @@ -59,145 +59,150 @@ import GHC.Internal.ForeignSrcLang |
| 59 | 59 | import GHC.Internal.LanguageExtensions
|
| 60 | 60 | import GHC.Internal.TH.Syntax
|
| 61 | 61 | |
| 62 | ------------------------------------------------------
|
|
| 63 | ---
|
|
| 64 | --- The Quasi class
|
|
| 65 | ---
|
|
| 66 | ------------------------------------------------------
|
|
| 67 | - |
|
| 68 | -class (MonadIO m, MonadFail m) => Quasi m where
|
|
| 69 | - -- | Fresh names. See 'newName'.
|
|
| 70 | - qNewName :: String -> m Name
|
|
| 71 | - |
|
| 72 | - ------- Error reporting and recovery -------
|
|
| 73 | - -- | Report an error (True) or warning (False)
|
|
| 74 | - -- ...but carry on; use 'fail' to stop. See 'report'.
|
|
| 75 | - qReport :: Bool -> String -> m ()
|
|
| 76 | - |
|
| 77 | - -- | See 'recover'.
|
|
| 78 | - qRecover :: m a -- ^ the error handler
|
|
| 79 | - -> m a -- ^ action which may fail
|
|
| 80 | - -> m a -- ^ Recover from the monadic 'fail'
|
|
| 81 | - |
|
| 82 | - ------- Inspect the type-checker's environment -------
|
|
| 83 | - -- | True <=> type namespace, False <=> value namespace. See 'lookupName'.
|
|
| 84 | - qLookupName :: Bool -> String -> m (Maybe Name)
|
|
| 85 | - -- | See 'reify'.
|
|
| 86 | - qReify :: Name -> m Info
|
|
| 87 | - -- | See 'reifyFixity'.
|
|
| 88 | - qReifyFixity :: Name -> m (Maybe Fixity)
|
|
| 89 | - -- | See 'reifyType'.
|
|
| 90 | - qReifyType :: Name -> m Type
|
|
| 91 | - -- | Is (n tys) an instance? Returns list of matching instance Decs (with
|
|
| 92 | - -- empty sub-Decs) Works for classes and type functions. See 'reifyInstances'.
|
|
| 93 | - qReifyInstances :: Name -> [Type] -> m [Dec]
|
|
| 94 | - -- | See 'reifyRoles'.
|
|
| 95 | - qReifyRoles :: Name -> m [Role]
|
|
| 96 | - -- | See 'reifyAnnotations'.
|
|
| 97 | - qReifyAnnotations :: Data a => AnnLookup -> m [a]
|
|
| 98 | - -- | See 'reifyModule'.
|
|
| 99 | - qReifyModule :: Module -> m ModuleInfo
|
|
| 100 | - -- | See 'reifyConStrictness'.
|
|
| 101 | - qReifyConStrictness :: Name -> m [DecidedStrictness]
|
|
| 102 | - |
|
| 103 | - -- | See 'location'.
|
|
| 104 | - qLocation :: m Loc
|
|
| 105 | - |
|
| 106 | - -- | Input/output (dangerous). See 'runIO'.
|
|
| 107 | - qRunIO :: IO a -> m a
|
|
| 108 | - qRunIO = liftIO
|
|
| 109 | - -- | See 'getPackageRoot'.
|
|
| 110 | - qGetPackageRoot :: m FilePath
|
|
| 111 | - |
|
| 112 | - -- | See 'addDependentFile'.
|
|
| 113 | - qAddDependentFile :: FilePath -> m ()
|
|
| 114 | - |
|
| 115 | - -- | See 'addDependentDirectory'.
|
|
| 116 | - qAddDependentDirectory :: FilePath -> m ()
|
|
| 117 | - |
|
| 118 | - -- | See 'addTempFile'.
|
|
| 119 | - qAddTempFile :: String -> m FilePath
|
|
| 120 | - |
|
| 121 | - -- | See 'addTopDecls'.
|
|
| 122 | - qAddTopDecls :: [Dec] -> m ()
|
|
| 123 | - |
|
| 124 | - -- | See 'addForeignFilePath'.
|
|
| 125 | - qAddForeignFilePath :: ForeignSrcLang -> String -> m ()
|
|
| 126 | - |
|
| 127 | - -- | See 'addModFinalizer'.
|
|
| 128 | - qAddModFinalizer :: Q () -> m ()
|
|
| 129 | - |
|
| 130 | - -- | See 'addCorePlugin'.
|
|
| 131 | - qAddCorePlugin :: String -> m ()
|
|
| 132 | - |
|
| 133 | - -- | See 'getQ'.
|
|
| 134 | - qGetQ :: Typeable a => m (Maybe a)
|
|
| 135 | - |
|
| 136 | - -- | See 'putQ'.
|
|
| 137 | - qPutQ :: Typeable a => a -> m ()
|
|
| 138 | - |
|
| 139 | - -- | See 'isExtEnabled'.
|
|
| 140 | - qIsExtEnabled :: Extension -> m Bool
|
|
| 141 | - -- | See 'extsEnabled'.
|
|
| 142 | - qExtsEnabled :: m [Extension]
|
|
| 143 | - |
|
| 144 | - -- | See 'putDoc'.
|
|
| 145 | - qPutDoc :: DocLoc -> String -> m ()
|
|
| 146 | - -- | See 'getDoc'.
|
|
| 147 | - qGetDoc :: DocLoc -> m (Maybe String)
|
|
| 62 | +-- | 'MetaHandlers' defines the interface between GHC and TH splices.
|
|
| 63 | +-- This is an internal interface between two parts of the compiler,
|
|
| 64 | +-- and should never be directly exposed to users.
|
|
| 65 | +--
|
|
| 66 | +-- It mirrors the 'Quasi' typeclass, which is part of the public facing interface of TH.
|
|
| 67 | +-- With time the two interfaces may drift apart.
|
|
| 68 | +--
|
|
| 69 | +-- This type is defined in `ghc-internal` rather than `lib:ghc` to avoid
|
|
| 70 | +-- `template-haskell` having to depend on GHC, ie, it implements dependency inversion.
|
|
| 71 | +--
|
|
| 72 | +-- For more information about the historical design of this interface,
|
|
| 73 | +-- see: https://github.com/ghc-proposals/ghc-proposals/pull/700
|
|
| 74 | +data MetaHandlers = MetaHandlers {
|
|
| 75 | + -- | We have an explicit handler for liftIO to allow users to forbid lifting into 'IO'
|
|
| 76 | + mLiftIO :: forall a. IO a -> IO a
|
|
| 77 | + , mFail :: forall a. String -> IO a
|
|
| 78 | + -- | Fresh names. See 'newName'.
|
|
| 79 | + , mNewName :: String -> IO Name
|
|
| 80 | + |
|
| 81 | + ------- Error reporting and recovery -------
|
|
| 82 | + -- | Report an error (True) or warning (False)
|
|
| 83 | + -- ...but carry on; use 'fail' to stop. See 'report'.
|
|
| 84 | + , mReport :: Bool -> String -> IO ()
|
|
| 85 | + |
|
| 86 | + -- | See 'recover'.
|
|
| 87 | + , mRecover :: forall a. Q a -- ^ the error handler
|
|
| 88 | + -> Q a -- ^ action which may fail
|
|
| 89 | + -> IO a -- ^ Recover from the monadic 'fail'
|
|
| 90 | + |
|
| 91 | + ------- Inspect the type-checker's environment -------
|
|
| 92 | + -- | True <=> type namespace, False <=> value namespace. See 'lookupName'.
|
|
| 93 | + , mLookupName :: Bool -> String -> IO (Maybe Name)
|
|
| 94 | + -- | See 'reify'.
|
|
| 95 | + , mReify :: Name -> IO Info
|
|
| 96 | + -- | See 'reifyFixity'.
|
|
| 97 | + , mReifyFixity :: Name -> IO (Maybe Fixity)
|
|
| 98 | + -- | See 'reifyType'.
|
|
| 99 | + , mReifyType :: Name -> IO Type
|
|
| 100 | + -- | Is (n tys) an instance? Returns list of matching instance Decs (with
|
|
| 101 | + -- empty sub-Decs) Works for classes and type functions. See 'reifyInstances'.
|
|
| 102 | + , mReifyInstances :: Name -> [Type] -> IO [Dec]
|
|
| 103 | + -- | See 'reifyRoles'.
|
|
| 104 | + , mReifyRoles :: Name -> IO [Role]
|
|
| 105 | + -- | See 'reifyAnnotations'.
|
|
| 106 | + , mReifyAnnotations :: forall a. Data a => AnnLookup -> IO [a]
|
|
| 107 | + -- | See 'reifyModule'.
|
|
| 108 | + , mReifyModule :: Module -> IO ModuleInfo
|
|
| 109 | + -- | See 'reifyConStrictness'.
|
|
| 110 | + , mReifyConStrictness :: Name -> IO [DecidedStrictness]
|
|
| 111 | + |
|
| 112 | + -- | See 'location'.
|
|
| 113 | + , mLocation :: IO Loc
|
|
| 114 | + |
|
| 115 | + -- | See 'getPackageRoot'.
|
|
| 116 | + , mGetPackageRoot :: IO FilePath
|
|
| 117 | + |
|
| 118 | + -- | See 'addDependentFile'.
|
|
| 119 | + , mAddDependentFile :: FilePath -> IO ()
|
|
| 120 | + |
|
| 121 | + -- | See 'addDependentDirectory'.
|
|
| 122 | + , mAddDependentDirectory :: FilePath -> IO ()
|
|
| 123 | + |
|
| 124 | + -- | See 'addTempFile'.
|
|
| 125 | + , mAddTempFile :: String -> IO FilePath
|
|
| 126 | + |
|
| 127 | + -- | See 'addTopDecls'.
|
|
| 128 | + , mAddTopDecls :: [Dec] -> IO ()
|
|
| 129 | + |
|
| 130 | + -- | See 'addForeignFilePath'.
|
|
| 131 | + , mAddForeignFilePath :: ForeignSrcLang -> String -> IO ()
|
|
| 132 | + |
|
| 133 | + -- | See 'addModFinalizer'.
|
|
| 134 | + , mAddModFinalizer :: Q () -> IO ()
|
|
| 135 | + |
|
| 136 | + -- | See 'addCorePlugin'.
|
|
| 137 | + , mAddCorePlugin :: String -> IO ()
|
|
| 138 | + |
|
| 139 | + -- | See 'getQ'.
|
|
| 140 | + , mGetQ :: forall a. Typeable a => IO (Maybe a)
|
|
| 141 | + |
|
| 142 | + -- | See 'putQ'.
|
|
| 143 | + , mPutQ :: forall a. Typeable a => a -> IO ()
|
|
| 144 | + |
|
| 145 | + -- | See 'isExtEnabled'.
|
|
| 146 | + , mIsExtEnabled :: Extension -> IO Bool
|
|
| 147 | + -- | See 'extsEnabled'.
|
|
| 148 | + , mExtsEnabled :: IO [Extension]
|
|
| 149 | + |
|
| 150 | + -- | See 'putDoc'.
|
|
| 151 | + , mPutDoc :: DocLoc -> String -> IO ()
|
|
| 152 | + -- | See 'getDoc'.
|
|
| 153 | + , mGetDoc :: DocLoc -> IO (Maybe String)
|
|
| 154 | + }
|
|
| 148 | 155 | |
| 149 | ------------------------------------------------------
|
|
| 150 | --- The IO instance of Quasi
|
|
| 151 | ------------------------------------------------------
|
|
| 156 | +badIO :: String -> IO a
|
|
| 157 | +badIO op = do { hPutStrLn stderr ("Can't do `" ++ op ++ "' in the IO monad")
|
|
| 158 | + ; fail "Template Haskell failure" }
|
|
| 152 | 159 | |
| 153 | --- | This instance is used only when running a Q
|
|
| 154 | --- computation in the IO monad, usually just to
|
|
| 155 | --- print the result. There is no interesting
|
|
| 156 | --- type environment, so reification isn't going to
|
|
| 157 | --- work.
|
|
| 158 | -instance Quasi IO where
|
|
| 159 | - qNewName = newNameIO
|
|
| 160 | - |
|
| 161 | - qReport True msg = hPutStrLn stderr ("Template Haskell error: " ++ msg)
|
|
| 162 | - qReport False msg = hPutStrLn stderr ("Template Haskell error: " ++ msg)
|
|
| 163 | - |
|
| 164 | - qLookupName _ _ = badIO "lookupName"
|
|
| 165 | - qReify _ = badIO "reify"
|
|
| 166 | - qReifyFixity _ = badIO "reifyFixity"
|
|
| 167 | - qReifyType _ = badIO "reifyFixity"
|
|
| 168 | - qReifyInstances _ _ = badIO "reifyInstances"
|
|
| 169 | - qReifyRoles _ = badIO "reifyRoles"
|
|
| 170 | - qReifyAnnotations _ = badIO "reifyAnnotations"
|
|
| 171 | - qReifyModule _ = badIO "reifyModule"
|
|
| 172 | - qReifyConStrictness _ = badIO "reifyConStrictness"
|
|
| 173 | - qLocation = badIO "currentLocation"
|
|
| 174 | - qRecover _ _ = badIO "recover" -- Maybe we could fix this?
|
|
| 175 | - qGetPackageRoot = badIO "getProjectRoot"
|
|
| 176 | - qAddDependentFile _ = badIO "addDependentFile"
|
|
| 177 | - qAddTempFile _ = badIO "addTempFile"
|
|
| 178 | - qAddTopDecls _ = badIO "addTopDecls"
|
|
| 179 | - qAddForeignFilePath _ _ = badIO "addForeignFilePath"
|
|
| 180 | - qAddModFinalizer _ = badIO "addModFinalizer"
|
|
| 181 | - qAddCorePlugin _ = badIO "addCorePlugin"
|
|
| 182 | - qGetQ = badIO "getQ"
|
|
| 183 | - qPutQ _ = badIO "putQ"
|
|
| 184 | - qIsExtEnabled _ = badIO "isExtEnabled"
|
|
| 185 | - qExtsEnabled = badIO "extsEnabled"
|
|
| 186 | - qPutDoc _ _ = badIO "putDoc"
|
|
| 187 | - qGetDoc _ = badIO "getDoc"
|
|
| 188 | - qAddDependentDirectory _ = badIO "AddDependentDirectory"
|
|
| 160 | +metaHandlersIO :: MetaHandlers
|
|
| 161 | +metaHandlersIO = MetaHandlers {
|
|
| 162 | + mLiftIO = id
|
|
| 163 | + , mFail = fail
|
|
| 164 | + , mNewName = newNameIO
|
|
| 165 | + , mReport = \b msg ->
|
|
| 166 | + if b then
|
|
| 167 | + hPutStrLn stderr ("Template Haskell error: " ++ msg)
|
|
| 168 | + else
|
|
| 169 | + hPutStrLn stderr ("Template Haskell error: " ++ msg) -- TODO: should this be different from above?
|
|
| 170 | + , mLookupName = \ _ _ -> badIO "lookupName"
|
|
| 171 | + , mReify = \_ -> badIO "reify"
|
|
| 172 | + , mReifyFixity = \_ -> badIO "reifyFixity"
|
|
| 173 | + , mReifyType = \_ -> badIO "reifyFixity"
|
|
| 174 | + , mReifyInstances = \_ _ -> badIO "reifyInstances"
|
|
| 175 | + , mReifyRoles = \_ -> badIO "reifyRoles"
|
|
| 176 | + , mReifyAnnotations = \_ -> badIO "reifyAnnotations"
|
|
| 177 | + , mReifyModule = \_ -> badIO "reifyModule"
|
|
| 178 | + , mReifyConStrictness = \_ -> badIO "reifyConStrictness"
|
|
| 179 | + , mLocation = badIO "currentLocation"
|
|
| 180 | + , mRecover = \_ _ -> badIO "recover" -- Maybe we could fix this?
|
|
| 181 | + , mGetPackageRoot = badIO "getProjectRoot"
|
|
| 182 | + , mAddDependentFile = \_ -> badIO "addDependentFile"
|
|
| 183 | + , mAddTempFile = \_ -> badIO "addTempFile"
|
|
| 184 | + , mAddTopDecls = \_ -> badIO "addTopDecls"
|
|
| 185 | + , mAddForeignFilePath = \_ _ -> badIO "addForeignFilePath"
|
|
| 186 | + , mAddModFinalizer = \_ -> badIO "addModFinalizer"
|
|
| 187 | + , mAddCorePlugin = \_ -> badIO "addCorePlugin"
|
|
| 188 | + , mGetQ = badIO "getQ"
|
|
| 189 | + , mPutQ = \_ -> badIO "putQ"
|
|
| 190 | + , mIsExtEnabled = \_ -> badIO "isExtEnabled"
|
|
| 191 | + , mExtsEnabled = badIO "extsEnabled"
|
|
| 192 | + , mPutDoc = \_ _ -> badIO "putDoc"
|
|
| 193 | + , mGetDoc = \_ -> badIO "getDoc"
|
|
| 194 | + , mAddDependentDirectory = \_ -> badIO "AddDependentDirectory"
|
|
| 195 | + }
|
|
| 189 | 196 | |
| 190 | 197 | instance Quote IO where
|
| 191 | 198 | newName = newNameIO
|
| 192 | 199 | |
| 200 | + |
|
| 201 | + |
|
| 193 | 202 | newNameIO :: String -> IO Name
|
| 194 | 203 | newNameIO s = do { n <- atomicModifyIORef' counter (\x -> (x + 1, x))
|
| 195 | 204 | ; pure (mkNameU s n) }
|
| 196 | 205 | |
| 197 | -badIO :: String -> IO a
|
|
| 198 | -badIO op = do { qReport True ("Can't do `" ++ op ++ "' in the IO monad")
|
|
| 199 | - ; fail "Template Haskell failure" }
|
|
| 200 | - |
|
| 201 | 206 | -- Global variable to generate unique symbols
|
| 202 | 207 | counter :: IORef Uniq
|
| 203 | 208 | {-# NOINLINE counter #-}
|
| ... | ... | @@ -210,46 +215,24 @@ counter = unsafePerformIO (newIORef 0) |
| 210 | 215 | --
|
| 211 | 216 | -----------------------------------------------------
|
| 212 | 217 | |
| 213 | --- | In short, 'Q' provides the 'Quasi' operations in one neat monad for the
|
|
| 214 | --- user.
|
|
| 215 | ---
|
|
| 216 | --- The longer story, is that 'Q' wraps an arbitrary 'Quasi'-able monad.
|
|
| 217 | --- The perceptive reader notices that 'Quasi' has only two instances, 'Q'
|
|
| 218 | --- itself and 'IO', neither of which have concrete implementations.'Q' plays
|
|
| 219 | --- the trick of [dependency
|
|
| 220 | --- inversion](https://en.wikipedia.org/wiki/Dependency_inversion_principle),
|
|
| 221 | --- providing an abstract interface for the user which is later concretely
|
|
| 222 | --- fufilled by an concrete 'Quasi' instance, internal to GHC.
|
|
| 223 | -newtype Q a = Q { unQ :: forall m. Quasi m => m a }
|
|
| 224 | - |
|
| 225 | --- | \"Runs\" the 'Q' monad. Normal users of Template Haskell
|
|
| 226 | --- should not need this function, as the splice brackets @$( ... )@
|
|
| 227 | --- are the usual way of running a 'Q' computation.
|
|
| 228 | ---
|
|
| 229 | --- This function is primarily used in GHC internals, and for debugging
|
|
| 230 | --- splices by running them in 'IO'.
|
|
| 231 | ---
|
|
| 232 | --- Note that many functions in 'Q', such as 'reify' and other compiler
|
|
| 233 | --- queries, are not supported when running 'Q' in 'IO'; these operations
|
|
| 234 | --- simply fail at runtime. Indeed, the only operations guaranteed to succeed
|
|
| 235 | --- are 'newName', 'runIO', 'reportError' and 'reportWarning'.
|
|
| 236 | -runQ :: Quasi m => Q a -> m a
|
|
| 237 | -runQ (Q m) = m
|
|
| 218 | +-- | 'Q' is the base 'Monad' for TemplateHaskell splices,
|
|
| 219 | +-- similar to how 'IO' is the base 'Monad' for normal Haskell programs.
|
|
| 220 | +newtype Q a = Q { unQ :: MetaHandlers -> IO a }
|
|
| 238 | 221 | |
| 239 | 222 | instance Monad Q where
|
| 240 | - Q m >>= k = Q (m >>= \x -> unQ (k x))
|
|
| 223 | + Q m >>= k = Q $ \h -> (m h >>= \x -> unQ (k x) h)
|
|
| 241 | 224 | (>>) = (*>)
|
| 242 | 225 | |
| 243 | 226 | instance MonadFail Q where
|
| 244 | - fail s = report True s >> Q (fail "Q monad failure")
|
|
| 227 | + fail s = report True s >> Q (\h -> mFail h "Q monad failure")
|
|
| 245 | 228 | |
| 246 | 229 | instance Functor Q where
|
| 247 | - fmap f (Q x) = Q (fmap f x)
|
|
| 230 | + fmap f (Q x) = Q $ \h -> fmap f (x h)
|
|
| 248 | 231 | |
| 249 | 232 | instance Applicative Q where
|
| 250 | - pure x = Q (pure x)
|
|
| 251 | - Q f <*> Q x = Q (f <*> x)
|
|
| 252 | - Q m *> Q n = Q (m *> n)
|
|
| 233 | + pure x = Q $ \_ -> pure x
|
|
| 234 | + Q f <*> Q x = Q $ \h -> (f h <*> x h)
|
|
| 235 | + Q m *> Q n = Q $ \h -> (m h *> n h)
|
|
| 253 | 236 | |
| 254 | 237 | -- | @since 2.17.0.0
|
| 255 | 238 | instance Semigroup a => Semigroup (Q a) where
|
| ... | ... | @@ -319,7 +302,7 @@ class Monad m => Quote m where |
| 319 | 302 | newName :: String -> m Name
|
| 320 | 303 | |
| 321 | 304 | instance Quote Q where
|
| 322 | - newName s = Q (qNewName s)
|
|
| 305 | + newName s = Q $ \h -> mNewName h s
|
|
| 323 | 306 | |
| 324 | 307 | -----------------------------------------------------
|
| 325 | 308 | --
|
| ... | ... | @@ -517,35 +500,26 @@ joinCode = flip bindCode id |
| 517 | 500 | -- | Report an error (True) or warning (False),
|
| 518 | 501 | -- but carry on; use 'fail' to stop.
|
| 519 | 502 | report :: Bool -> String -> Q ()
|
| 520 | -report b s = Q (qReport b s)
|
|
| 521 | -{-# DEPRECATED report "Use reportError or reportWarning instead" #-} -- deprecated in 7.6
|
|
| 522 | - |
|
| 523 | --- | Report an error to the user, but allow the current splice's computation to carry on. To abort the computation, use 'fail'.
|
|
| 524 | -reportError :: String -> Q ()
|
|
| 525 | -reportError = report True
|
|
| 526 | - |
|
| 527 | --- | Report a warning to the user, and carry on.
|
|
| 528 | -reportWarning :: String -> Q ()
|
|
| 529 | -reportWarning = report False
|
|
| 503 | +report b s = Q $ \h -> mReport h b s
|
|
| 530 | 504 | |
| 531 | 505 | -- | Recover from errors raised by 'reportError' or 'fail'.
|
| 532 | 506 | recover :: Q a -- ^ handler to invoke on failure
|
| 533 | 507 | -> Q a -- ^ computation to run
|
| 534 | 508 | -> Q a
|
| 535 | -recover (Q r) (Q m) = Q (qRecover r m)
|
|
| 509 | +recover rec main = Q $ \h -> mRecover h rec main
|
|
| 536 | 510 | |
| 537 | 511 | -- We don't export lookupName; the Bool isn't a great API
|
| 538 | 512 | -- Instead we export lookupTypeName, lookupValueName
|
| 539 | 513 | lookupName :: Bool -> String -> Q (Maybe Name)
|
| 540 | -lookupName ns s = Q (qLookupName ns s)
|
|
| 514 | +lookupName ns s = Q $ \h -> mLookupName h ns s
|
|
| 541 | 515 | |
| 542 | 516 | -- | Look up the given name in the (type namespace of the) current splice's scope. See "Language.Haskell.TH.Syntax#namelookup" for more details.
|
| 543 | 517 | lookupTypeName :: String -> Q (Maybe Name)
|
| 544 | -lookupTypeName s = Q (qLookupName True s)
|
|
| 518 | +lookupTypeName s = Q $ \h -> mLookupName h True s
|
|
| 545 | 519 | |
| 546 | 520 | -- | Look up the given name in the (value namespace of the) current splice's scope. See "Language.Haskell.TH.Syntax#namelookup" for more details.
|
| 547 | 521 | lookupValueName :: String -> Q (Maybe Name)
|
| 548 | -lookupValueName s = Q (qLookupName False s)
|
|
| 522 | +lookupValueName s = Q $ \h -> mLookupName h False s
|
|
| 549 | 523 | |
| 550 | 524 | {-
|
| 551 | 525 | Note [Name lookup]
|
| ... | ... | @@ -620,7 +594,7 @@ To ensure we get information about @D@-the-value, use 'lookupValueName': |
| 620 | 594 | and to get information about @D@-the-type, use 'lookupTypeName'.
|
| 621 | 595 | -}
|
| 622 | 596 | reify :: Name -> Q Info
|
| 623 | -reify v = Q (qReify v)
|
|
| 597 | +reify v = Q $ \h -> mReify h v
|
|
| 624 | 598 | |
| 625 | 599 | {- | @reifyFixity nm@ attempts to find a fixity declaration for @nm@. For
|
| 626 | 600 | example, if the function @foo@ has the fixity declaration @infixr 7 foo@, then
|
| ... | ... | @@ -629,7 +603,7 @@ example, if the function @foo@ has the fixity declaration @infixr 7 foo@, then |
| 629 | 603 | 'Nothing', so you may assume @bar@ has 'defaultFixity'.
|
| 630 | 604 | -}
|
| 631 | 605 | reifyFixity :: Name -> Q (Maybe Fixity)
|
| 632 | -reifyFixity nm = Q (qReifyFixity nm)
|
|
| 606 | +reifyFixity nm = Q $ \h -> mReifyFixity h nm
|
|
| 633 | 607 | |
| 634 | 608 | {- | @reifyType nm@ attempts to find the type or kind of @nm@. For example,
|
| 635 | 609 | @reifyType 'not@ returns @Bool -> Bool@, and
|
| ... | ... | @@ -637,7 +611,7 @@ reifyFixity nm = Q (qReifyFixity nm) |
| 637 | 611 | This works even if there's no explicit signature and the type or kind is inferred.
|
| 638 | 612 | -}
|
| 639 | 613 | reifyType :: Name -> Q Type
|
| 640 | -reifyType nm = Q (qReifyType nm)
|
|
| 614 | +reifyType nm = Q $ \h -> mReifyType h nm
|
|
| 641 | 615 | |
| 642 | 616 | {- | Template Haskell is capable of reifying information about types and
|
| 643 | 617 | terms defined in previous declaration groups. Top-level declaration splices break up
|
| ... | ... | @@ -729,7 +703,7 @@ has some discussion around this. |
| 729 | 703 | |
| 730 | 704 | -}
|
| 731 | 705 | reifyInstances :: Name -> [Type] -> Q [InstanceDec]
|
| 732 | -reifyInstances cls tys = Q (qReifyInstances cls tys)
|
|
| 706 | +reifyInstances cls tys = Q $ \h -> mReifyInstances h cls tys
|
|
| 733 | 707 | |
| 734 | 708 | {- | @reifyRoles nm@ returns the list of roles associated with the parameters
|
| 735 | 709 | (both visible and invisible) of
|
| ... | ... | @@ -748,20 +722,20 @@ and @reifyRoles Proxy@, we will get @['NominalR', 'PhantomR']@. The 'NominalR' i |
| 748 | 722 | the role of the invisible @k@ parameter. Kind parameters are always nominal.
|
| 749 | 723 | -}
|
| 750 | 724 | reifyRoles :: Name -> Q [Role]
|
| 751 | -reifyRoles nm = Q (qReifyRoles nm)
|
|
| 725 | +reifyRoles nm = Q $ \h -> mReifyRoles h nm
|
|
| 752 | 726 | |
| 753 | 727 | -- | @reifyAnnotations target@ returns the list of annotations
|
| 754 | 728 | -- associated with @target@. Only the annotations that are
|
| 755 | 729 | -- appropriately typed is returned. So if you have @Int@ and @String@
|
| 756 | 730 | -- annotations for the same target, you have to call this function twice.
|
| 757 | 731 | reifyAnnotations :: Data a => AnnLookup -> Q [a]
|
| 758 | -reifyAnnotations an = Q (qReifyAnnotations an)
|
|
| 732 | +reifyAnnotations an = Q $ \h -> mReifyAnnotations h an
|
|
| 759 | 733 | |
| 760 | 734 | -- | @reifyModule mod@ looks up information about module @mod@. To
|
| 761 | 735 | -- look up the current module, call this function with the return
|
| 762 | 736 | -- value of 'Language.Haskell.TH.Lib.thisModule'.
|
| 763 | 737 | reifyModule :: Module -> Q ModuleInfo
|
| 764 | -reifyModule m = Q (qReifyModule m)
|
|
| 738 | +reifyModule m = Q $ \h -> mReifyModule h m
|
|
| 765 | 739 | |
| 766 | 740 | -- | @reifyConStrictness nm@ looks up the strictness information for the fields
|
| 767 | 741 | -- of the constructor with the name @nm@. Note that the strictness information
|
| ... | ... | @@ -776,7 +750,7 @@ reifyModule m = Q (qReifyModule m) |
| 776 | 750 | -- circumstances, but it would return @['DecidedStrict', DecidedStrict]@ if the
|
| 777 | 751 | -- @-XStrictData@ language extension was enabled.
|
| 778 | 752 | reifyConStrictness :: Name -> Q [DecidedStrictness]
|
| 779 | -reifyConStrictness n = Q (qReifyConStrictness n)
|
|
| 753 | +reifyConStrictness n = Q $ \h -> mReifyConStrictness h n
|
|
| 780 | 754 | |
| 781 | 755 | -- | Is the list of instances returned by 'reifyInstances' nonempty?
|
| 782 | 756 | --
|
| ... | ... | @@ -789,7 +763,7 @@ isInstance nm tys = do { decs <- reifyInstances nm tys |
| 789 | 763 | |
| 790 | 764 | -- | The location at which this computation is spliced.
|
| 791 | 765 | location :: Q Loc
|
| 792 | -location = Q qLocation
|
|
| 766 | +location = Q mLocation
|
|
| 793 | 767 | |
| 794 | 768 | -- |The 'runIO' function lets you run an I\/O computation in the 'Q' monad.
|
| 795 | 769 | -- Take care: you are guaranteed the ordering of calls to 'runIO' within
|
| ... | ... | @@ -799,7 +773,7 @@ location = Q qLocation |
| 799 | 773 | -- necessarily flushed when the compiler finishes running, so you should
|
| 800 | 774 | -- flush them yourself.
|
| 801 | 775 | runIO :: IO a -> Q a
|
| 802 | -runIO m = Q (qRunIO m)
|
|
| 776 | +runIO m = Q $ \h -> mLiftIO h m
|
|
| 803 | 777 | |
| 804 | 778 | -- | Get the package root for the current package which is being compiled.
|
| 805 | 779 | -- This can be set explicitly with the -package-root flag but is normally
|
| ... | ... | @@ -811,7 +785,7 @@ runIO m = Q (qRunIO m) |
| 811 | 785 | -- change directory when compiling files but instead set the -package-root flag
|
| 812 | 786 | -- appropriately.
|
| 813 | 787 | getPackageRoot :: Q FilePath
|
| 814 | -getPackageRoot = Q qGetPackageRoot
|
|
| 788 | +getPackageRoot = Q mGetPackageRoot
|
|
| 815 | 789 | |
| 816 | 790 | -- | Record external directories that runIO is using (dependent upon).
|
| 817 | 791 | -- The compiler can then recognize that it should re-compile the Haskell file
|
| ... | ... | @@ -830,7 +804,7 @@ getPackageRoot = Q qGetPackageRoot |
| 830 | 804 | -- * The state of the directory is read at the interface generation time,
|
| 831 | 805 | -- not at the time of the function call.
|
| 832 | 806 | addDependentDirectory :: FilePath -> Q ()
|
| 833 | -addDependentDirectory dp = Q (qAddDependentDirectory dp)
|
|
| 807 | +addDependentDirectory dp = Q $ \h -> mAddDependentDirectory h dp
|
|
| 834 | 808 | |
| 835 | 809 | -- | Record external files that runIO is using (dependent upon).
|
| 836 | 810 | -- The compiler can then recognize that it should re-compile the Haskell file
|
| ... | ... | @@ -844,17 +818,17 @@ addDependentDirectory dp = Q (qAddDependentDirectory dp) |
| 844 | 818 | --
|
| 845 | 819 | -- * The dependency is based on file content, not a modification time
|
| 846 | 820 | addDependentFile :: FilePath -> Q ()
|
| 847 | -addDependentFile fp = Q (qAddDependentFile fp)
|
|
| 821 | +addDependentFile fp = Q $ \h -> mAddDependentFile h fp
|
|
| 848 | 822 | |
| 849 | 823 | -- | Obtain a temporary file path with the given suffix. The compiler will
|
| 850 | 824 | -- delete this file after compilation.
|
| 851 | 825 | addTempFile :: String -> Q FilePath
|
| 852 | -addTempFile suffix = Q (qAddTempFile suffix)
|
|
| 826 | +addTempFile suffix = Q $ \h -> mAddTempFile h suffix
|
|
| 853 | 827 | |
| 854 | 828 | -- | Add additional top-level declarations. The added declarations will be type
|
| 855 | 829 | -- checked along with the current declaration group.
|
| 856 | 830 | addTopDecls :: [Dec] -> Q ()
|
| 857 | -addTopDecls ds = Q (qAddTopDecls ds)
|
|
| 831 | +addTopDecls ds = Q $ \h -> mAddTopDecls h ds
|
|
| 858 | 832 | |
| 859 | 833 | -- | Same as 'addForeignSource', but expects to receive a path pointing to the
|
| 860 | 834 | -- foreign file instead of a 'String' of its contents. Consider using this in
|
| ... | ... | @@ -863,7 +837,7 @@ addTopDecls ds = Q (qAddTopDecls ds) |
| 863 | 837 | -- This is a good alternative to 'addForeignSource' when you are trying to
|
| 864 | 838 | -- directly link in an object file.
|
| 865 | 839 | addForeignFilePath :: ForeignSrcLang -> FilePath -> Q ()
|
| 866 | -addForeignFilePath lang fp = Q (qAddForeignFilePath lang fp)
|
|
| 840 | +addForeignFilePath lang fp = Q $ \h -> mAddForeignFilePath h lang fp
|
|
| 867 | 841 | |
| 868 | 842 | -- | Add a finalizer that will run in the Q monad after the current module has
|
| 869 | 843 | -- been type checked. This only makes sense when run within a top-level splice.
|
| ... | ... | @@ -872,7 +846,7 @@ addForeignFilePath lang fp = Q (qAddForeignFilePath lang fp) |
| 872 | 846 | -- 'reify' is able to find the local definitions when executed inside the
|
| 873 | 847 | -- finalizer.
|
| 874 | 848 | addModFinalizer :: Q () -> Q ()
|
| 875 | -addModFinalizer act = Q (qAddModFinalizer (unQ act))
|
|
| 849 | +addModFinalizer act = Q $ \h -> mAddModFinalizer h act
|
|
| 876 | 850 | |
| 877 | 851 | -- | Adds a core plugin to the compilation pipeline.
|
| 878 | 852 | --
|
| ... | ... | @@ -882,7 +856,7 @@ addModFinalizer act = Q (qAddModFinalizer (unQ act)) |
| 882 | 856 | -- to tell the compiler that we needed to compile first a plugin module in the
|
| 883 | 857 | -- current package.
|
| 884 | 858 | addCorePlugin :: String -> Q ()
|
| 885 | -addCorePlugin plugin = Q (qAddCorePlugin plugin)
|
|
| 859 | +addCorePlugin plugin = Q $ \h -> mAddCorePlugin h plugin
|
|
| 886 | 860 | |
| 887 | 861 | -- | Get state from the 'Q' monad. The state maintained by 'Q' is isomorphic to
|
| 888 | 862 | -- a type-indexed finite map. That is,
|
| ... | ... | @@ -896,20 +870,20 @@ addCorePlugin plugin = Q (qAddCorePlugin plugin) |
| 896 | 870 | -- Note that the state is local to the Haskell module in which the Template
|
| 897 | 871 | -- Haskell expression is executed.
|
| 898 | 872 | getQ :: Typeable a => Q (Maybe a)
|
| 899 | -getQ = Q qGetQ
|
|
| 873 | +getQ = Q mGetQ
|
|
| 900 | 874 | |
| 901 | 875 | -- | Replace the state in the 'Q' monad. Note that the state is local to the
|
| 902 | 876 | -- Haskell module in which the Template Haskell expression is executed.
|
| 903 | 877 | putQ :: Typeable a => a -> Q ()
|
| 904 | -putQ x = Q (qPutQ x)
|
|
| 878 | +putQ x = Q $ \h -> mPutQ h x
|
|
| 905 | 879 | |
| 906 | 880 | -- | Determine whether the given language extension is enabled in the 'Q' monad.
|
| 907 | 881 | isExtEnabled :: Extension -> Q Bool
|
| 908 | -isExtEnabled ext = Q (qIsExtEnabled ext)
|
|
| 882 | +isExtEnabled ext = Q $ \h -> mIsExtEnabled h ext
|
|
| 909 | 883 | |
| 910 | 884 | -- | List all enabled language extensions.
|
| 911 | 885 | extsEnabled :: Q [Extension]
|
| 912 | -extsEnabled = Q qExtsEnabled
|
|
| 886 | +extsEnabled = Q mExtsEnabled
|
|
| 913 | 887 | |
| 914 | 888 | -- | Add Haddock documentation to the specified location. This will overwrite
|
| 915 | 889 | -- any documentation at the location if it already exists. This will reify the
|
| ... | ... | @@ -928,48 +902,18 @@ extsEnabled = Q qExtsEnabled |
| 928 | 902 | -- Adding documentation to anything outside of the current module will cause an
|
| 929 | 903 | -- error.
|
| 930 | 904 | putDoc :: DocLoc -> String -> Q ()
|
| 931 | -putDoc t s = Q (qPutDoc t s)
|
|
| 905 | +putDoc t s = Q $ \h -> mPutDoc h t s
|
|
| 932 | 906 | |
| 933 | 907 | -- | Retrieves the Haddock documentation at the specified location, if one
|
| 934 | 908 | -- exists.
|
| 935 | 909 | -- It can be used to read documentation on things defined outside of the current
|
| 936 | 910 | -- module, provided that those modules were compiled with the @-haddock@ flag.
|
| 937 | 911 | getDoc :: DocLoc -> Q (Maybe String)
|
| 938 | -getDoc n = Q (qGetDoc n)
|
|
| 912 | +getDoc n = Q $ \h -> mGetDoc h n
|
|
| 939 | 913 | |
| 940 | 914 | instance MonadIO Q where
|
| 941 | 915 | liftIO = runIO
|
| 942 | 916 | |
| 943 | -instance Quasi Q where
|
|
| 944 | - qNewName = newName
|
|
| 945 | - qReport = report
|
|
| 946 | - qRecover = recover
|
|
| 947 | - qReify = reify
|
|
| 948 | - qReifyFixity = reifyFixity
|
|
| 949 | - qReifyType = reifyType
|
|
| 950 | - qReifyInstances = reifyInstances
|
|
| 951 | - qReifyRoles = reifyRoles
|
|
| 952 | - qReifyAnnotations = reifyAnnotations
|
|
| 953 | - qReifyModule = reifyModule
|
|
| 954 | - qReifyConStrictness = reifyConStrictness
|
|
| 955 | - qLookupName = lookupName
|
|
| 956 | - qLocation = location
|
|
| 957 | - qGetPackageRoot = getPackageRoot
|
|
| 958 | - qAddDependentFile = addDependentFile
|
|
| 959 | - qAddDependentDirectory = addDependentDirectory
|
|
| 960 | - qAddTempFile = addTempFile
|
|
| 961 | - qAddTopDecls = addTopDecls
|
|
| 962 | - qAddForeignFilePath = addForeignFilePath
|
|
| 963 | - qAddModFinalizer = addModFinalizer
|
|
| 964 | - qAddCorePlugin = addCorePlugin
|
|
| 965 | - qGetQ = getQ
|
|
| 966 | - qPutQ = putQ
|
|
| 967 | - qIsExtEnabled = isExtEnabled
|
|
| 968 | - qExtsEnabled = extsEnabled
|
|
| 969 | - qPutDoc = putDoc
|
|
| 970 | - qGetDoc = getDoc
|
|
| 971 | - |
|
| 972 | - |
|
| 973 | 917 | ----------------------------------------------------
|
| 974 | 918 | -- The following operations are used solely in GHC.HsToCore.Quote when
|
| 975 | 919 | -- desugaring brackets. They are not necessary for the user, who can use
|
| 1 | 1 | {-# LANGUAGE ScopedTypeVariables, StandaloneDeriving, DeriveGeneric,
|
| 2 | - TupleSections, RecordWildCards, InstanceSigs, CPP #-}
|
|
| 2 | + TupleSections, RecordWildCards, InstanceSigs, CPP, RankNTypes #-}
|
|
| 3 | 3 | {-# OPTIONS_GHC -fno-warn-name-shadowing #-}
|
| 4 | 4 | |
| 5 | 5 | -- |
|
| ... | ... | @@ -164,58 +164,70 @@ ghcCmd m = GHCiQ $ \sRef -> do |
| 164 | 164 | instance MonadIO GHCiQ where
|
| 165 | 165 | liftIO m = GHCiQ $ \_ -> m
|
| 166 | 166 | |
| 167 | -instance TH.Quasi GHCiQ where
|
|
| 168 | - qNewName str = ghcCmd (NewName str)
|
|
| 169 | - qReport isError msg = ghcCmd (Report isError msg)
|
|
| 170 | - |
|
| 171 | - -- See Note [TH recover with -fexternal-interpreter] in GHC.Tc.Gen.Splice
|
|
| 172 | - qRecover (GHCiQ h) a = GHCiQ $ \sRef -> mask $ \unmask -> do
|
|
| 173 | - s <- readIORef sRef
|
|
| 174 | - remoteTHCall (qsPipe s) StartRecover
|
|
| 175 | - e <- try $ unmask $ runGHCiQ (a <* ghcCmd FailIfErrs) sRef
|
|
| 176 | - remoteTHCall (qsPipe s) (EndRecover (isLeft e))
|
|
| 177 | - case e of
|
|
| 178 | - Left GHCiQException{} -> h sRef
|
|
| 179 | - Right r -> return r
|
|
| 180 | - qLookupName isType occ = ghcCmd (LookupName isType occ)
|
|
| 181 | - qReify name = ghcCmd (Reify name)
|
|
| 182 | - qReifyFixity name = ghcCmd (ReifyFixity name)
|
|
| 183 | - qReifyType name = ghcCmd (ReifyType name)
|
|
| 184 | - qReifyInstances name tys = ghcCmd (ReifyInstances name tys)
|
|
| 185 | - qReifyRoles name = ghcCmd (ReifyRoles name)
|
|
| 186 | - |
|
| 187 | 167 | -- To reify annotations, we send GHC the AnnLookup and also the
|
| 188 | 168 | -- TypeRep of the thing we're looking for, to avoid needing to
|
| 189 | 169 | -- serialize irrelevant annotations.
|
| 190 | - qReifyAnnotations :: forall a . Data a => TH.AnnLookup -> GHCiQ [a]
|
|
| 191 | - qReifyAnnotations lookup =
|
|
| 170 | +reifyAnnotations :: forall a . Data a => TH.AnnLookup -> GHCiQ [a]
|
|
| 171 | +reifyAnnotations lookup =
|
|
| 192 | 172 | map (deserializeWithData . B.unpack) <$>
|
| 193 | 173 | ghcCmd (ReifyAnnotations lookup typerep)
|
| 194 | 174 | where typerep = typeOf (undefined :: a)
|
| 195 | 175 | |
| 196 | - qReifyModule m = ghcCmd (ReifyModule m)
|
|
| 197 | - qReifyConStrictness name = ghcCmd (ReifyConStrictness name)
|
|
| 198 | - qLocation = fromMaybe noLoc . qsLocation <$> getState
|
|
| 199 | - qGetPackageRoot = ghcCmd GetPackageRoot
|
|
| 200 | - qAddDependentFile file = ghcCmd (AddDependentFile file)
|
|
| 201 | - qAddDependentDirectory dir = ghcCmd (AddDependentDirectory dir)
|
|
| 202 | - qAddTempFile suffix = ghcCmd (AddTempFile suffix)
|
|
| 203 | - qAddTopDecls decls = ghcCmd (AddTopDecls decls)
|
|
| 204 | - qAddForeignFilePath lang fp = ghcCmd (AddForeignFilePath lang fp)
|
|
| 205 | - qAddModFinalizer fin = GHCiQ (\_ -> mkRemoteRef fin) >>=
|
|
| 176 | +runQinGHCiQ :: TH.Q a -> GHCiQ a
|
|
| 177 | +runQinGHCiQ (TH.Q m) = GHCiQ $ \sRef -> m (metaHandlersGHCiQ (runInIO sRef))
|
|
| 178 | + where
|
|
| 179 | + runInIO :: IORef QState -> GHCiQ a -> IO a
|
|
| 180 | + runInIO sRef (GHCiQ m) = m sRef
|
|
| 181 | + |
|
| 182 | +metaHandlersGHCiQ :: (forall x. GHCiQ x -> IO x) -> TH.MetaHandlers
|
|
| 183 | +metaHandlersGHCiQ runInIO = TH.MetaHandlers {
|
|
| 184 | + mLiftIO = id
|
|
| 185 | + , mFail = runInIO . fail
|
|
| 186 | + , mNewName = \str -> runInIO $ ghcCmd (NewName str)
|
|
| 187 | + , mReport = \isError msg -> runInIO $ ghcCmd (Report isError msg)
|
|
| 188 | + |
|
| 189 | + -- See Note [TH recover with -fexternal-interpreter] in GHC.Tc.Gen.Splice
|
|
| 190 | + , mRecover = \h a -> runInIO $ GHCiQ $ \sRef -> mask $ \unmask -> do
|
|
| 191 | + s <- readIORef sRef
|
|
| 192 | + remoteTHCall (qsPipe s) StartRecover
|
|
| 193 | + e <- try $ unmask $ runGHCiQ (runQinGHCiQ a <* ghcCmd FailIfErrs) sRef
|
|
| 194 | + remoteTHCall (qsPipe s) (EndRecover (isLeft e))
|
|
| 195 | + case e of
|
|
| 196 | + Left GHCiQException{} ->
|
|
| 197 | + runGHCiQ (runQinGHCiQ h) sRef
|
|
| 198 | + Right r -> return r
|
|
| 199 | + , mLookupName = \isType occ -> runInIO $ ghcCmd (LookupName isType occ)
|
|
| 200 | + , mReify = \name ->runInIO $ ghcCmd (Reify name)
|
|
| 201 | + , mReifyFixity = \name ->runInIO $ ghcCmd (ReifyFixity name)
|
|
| 202 | + , mReifyType = \name -> runInIO $ ghcCmd (ReifyType name)
|
|
| 203 | + , mReifyInstances = \name tys -> runInIO $ ghcCmd (ReifyInstances name tys)
|
|
| 204 | + , mReifyRoles = \name -> runInIO $ ghcCmd (ReifyRoles name)
|
|
| 205 | + |
|
| 206 | + , mReifyAnnotations = runInIO . reifyAnnotations
|
|
| 207 | + , mReifyModule = \m -> runInIO $ ghcCmd (ReifyModule m)
|
|
| 208 | + , mReifyConStrictness = \name -> runInIO $ ghcCmd (ReifyConStrictness name)
|
|
| 209 | + , mLocation = runInIO $ fromMaybe noLoc . qsLocation <$> getState
|
|
| 210 | + , mGetPackageRoot = runInIO $ ghcCmd GetPackageRoot
|
|
| 211 | + , mAddDependentFile = \file -> runInIO $ ghcCmd (AddDependentFile file)
|
|
| 212 | + , mAddDependentDirectory = \dir -> runInIO $ ghcCmd (AddDependentDirectory dir)
|
|
| 213 | + , mAddTempFile = \suffix -> runInIO $ ghcCmd (AddTempFile suffix)
|
|
| 214 | + , mAddTopDecls = \decls -> runInIO $ ghcCmd (AddTopDecls decls)
|
|
| 215 | + , mAddForeignFilePath = \lang fp -> runInIO $ ghcCmd (AddForeignFilePath lang fp)
|
|
| 216 | + , mAddModFinalizer = \fin -> runInIO $ GHCiQ (\_ -> mkRemoteRef fin) >>=
|
|
| 206 | 217 | ghcCmd . AddModFinalizer
|
| 207 | - qAddCorePlugin str = ghcCmd (AddCorePlugin str)
|
|
| 208 | - qGetQ = do
|
|
| 218 | + , mAddCorePlugin = \str -> runInIO $ ghcCmd (AddCorePlugin str)
|
|
| 219 | + , mGetQ = runInIO $ do
|
|
| 209 | 220 | s <- getState
|
| 210 | 221 | let lookup :: forall a. Typeable a => Map TypeRep Dynamic -> Maybe a
|
| 211 | 222 | lookup m = fromDynamic =<< M.lookup (typeOf (undefined::a)) m
|
| 212 | 223 | return $ lookup (qsMap s)
|
| 213 | - qPutQ k = GHCiQ $ \sRef ->
|
|
| 214 | - modifyIORef' sRef (\s -> s { qsMap = M.insert (typeOf k) (toDyn k) (qsMap s) })
|
|
| 215 | - qIsExtEnabled x = ghcCmd (IsExtEnabled x)
|
|
| 216 | - qExtsEnabled = ghcCmd ExtsEnabled
|
|
| 217 | - qPutDoc l s = ghcCmd (PutDoc l s)
|
|
| 218 | - qGetDoc l = ghcCmd (GetDoc l)
|
|
| 224 | + , mPutQ = \k -> runInIO $ GHCiQ $ \sRef ->
|
|
| 225 | + modifyIORef' sRef (\s -> s { qsMap = M.insert (typeOf k) (toDyn k) (qsMap s) })
|
|
| 226 | + , mIsExtEnabled = \x -> runInIO $ ghcCmd (IsExtEnabled x)
|
|
| 227 | + , mExtsEnabled = runInIO $ ghcCmd ExtsEnabled
|
|
| 228 | + , mPutDoc = \l s -> runInIO $ ghcCmd (PutDoc l s)
|
|
| 229 | + , mGetDoc = \l -> runInIO $ ghcCmd (GetDoc l)
|
|
| 230 | +}
|
|
| 219 | 231 | |
| 220 | 232 | -- | The implementation of the 'StartTH' message: create
|
| 221 | 233 | -- a new IORef QState, and return a RemoteRef to it.
|
| ... | ... | @@ -235,7 +247,7 @@ runModFinalizerRefs pipe rstate qrefs = do |
| 235 | 247 | qstateref <- localRef rstate
|
| 236 | 248 | qstate <- readIORef qstateref
|
| 237 | 249 | qstate' <- newIORef $ qstate { qsPipe = pipe }
|
| 238 | - _ <- runGHCiQ (TH.runQ $ sequence_ qs) qstate'
|
|
| 250 | + _ <- runGHCiQ (runQinGHCiQ $ sequence_ qs) qstate'
|
|
| 239 | 251 | return ()
|
| 240 | 252 | |
| 241 | 253 | -- | The implementation of the 'RunTH' message
|
| ... | ... | @@ -272,5 +284,5 @@ runTHQ |
| 272 | 284 | runTHQ pipe rstate mb_loc ghciq = do
|
| 273 | 285 | qstateref <- localRef rstate
|
| 274 | 286 | modifyIORef' qstateref (\qstate -> qstate { qsLocation = mb_loc, qsPipe = pipe })
|
| 275 | - r <- runGHCiQ (TH.runQ ghciq) qstateref
|
|
| 287 | + r <- runGHCiQ (runQinGHCiQ ghciq) qstateref
|
|
| 276 | 288 | return $! LB.toStrict (runPut (put r)) |
| ... | ... | @@ -5,13 +5,17 @@ |
| 5 | 5 | {-# LANGUAGE TemplateHaskellQuotes #-}
|
| 6 | 6 | {-# LANGUAGE Trustworthy #-}
|
| 7 | 7 | {-# LANGUAGE UnboxedTuples #-}
|
| 8 | +-- Don't warn for using 'report' from ghc-internal
|
|
| 9 | +{-# OPTIONS_GHC -Wno-warnings-deprecations #-}
|
|
| 8 | 10 | |
| 9 | 11 | module Language.Haskell.TH.Syntax (
|
| 10 | 12 | Quote (..),
|
| 11 | 13 | Exp (..),
|
| 12 | 14 | Match (..),
|
| 13 | 15 | Clause (..),
|
| 14 | - Q (..),
|
|
| 16 | + Q,
|
|
| 17 | + -- backwards compatibility
|
|
| 18 | + Language.Haskell.TH.Syntax.unQ,
|
|
| 15 | 19 | Pat (..),
|
| 16 | 20 | Stmt (..),
|
| 17 | 21 | Con (..),
|
| ... | ... | @@ -202,11 +206,14 @@ where |
| 202 | 206 | |
| 203 | 207 | import GHC.Boot.TH.Lift
|
| 204 | 208 | import GHC.Boot.TH.Syntax
|
| 205 | -import GHC.Boot.TH.Monad
|
|
| 209 | +import GHC.Boot.TH.Monad hiding (report)
|
|
| 210 | +import qualified GHC.Boot.TH.Monad as Internal
|
|
| 206 | 211 | import System.FilePath
|
| 207 | 212 | import Data.Data hiding (Fixity(..))
|
| 208 | 213 | import Data.List.NonEmpty (NonEmpty(..))
|
| 209 | 214 | import GHC.Lexeme ( startsVarSym, startsVarId )
|
| 215 | +import Control.Monad.IO.Class (MonadIO, liftIO)
|
|
| 216 | +import System.IO (hPutStrLn, stderr)
|
|
| 210 | 217 | |
| 211 | 218 | -- This module completely re-exports 'GHC.Boot.TH.Syntax',
|
| 212 | 219 | -- and exports additionally functions that depend on @filepath@ or @System.IO@.
|
| ... | ... | @@ -499,3 +506,172 @@ reassociate the tree as necessary. |
| 499 | 506 | -- Subsumed by the more general 'SpecialiseEP' constructor.
|
| 500 | 507 | pattern SpecialiseP :: Name -> Type -> (Maybe Inline) -> Phases -> Pragma
|
| 501 | 508 | pattern SpecialiseP nm ty inl phases = SpecialiseEP Nothing [] (SigE (VarE nm) ty) inl phases
|
| 509 | + |
|
| 510 | +unQ :: Q a -> (forall m. Quasi m => m a)
|
|
| 511 | +unQ m = runQ m
|
|
| 512 | + |
|
| 513 | +-----------------------------------------------------
|
|
| 514 | +--
|
|
| 515 | +-- The Quasi class
|
|
| 516 | +--
|
|
| 517 | +-----------------------------------------------------
|
|
| 518 | + |
|
| 519 | +-- | The 'Quasi' typeclass used to provide an exhaustive list of the effects exposed by the 'Q' monad.
|
|
| 520 | +-- This invariant no longer holds, and it is encouraged to use 'Q' or 'Quote' instead.
|
|
| 521 | +class (MonadIO m, MonadFail m) => Quasi m where
|
|
| 522 | + qRunQ :: Q a -> m a
|
|
| 523 | + -- | Fresh names. See 'newName'.
|
|
| 524 | + qNewName :: String -> m Name
|
|
| 525 | + qNewName = qRunQ . newName
|
|
| 526 | + |
|
| 527 | + ------- Error reporting and recovery -------
|
|
| 528 | + -- | Report an error (True) or warning (False)
|
|
| 529 | + -- ...but carry on; use 'fail' to stop. See 'report'.
|
|
| 530 | + qReport :: Bool -> String -> m ()
|
|
| 531 | + qReport b s = qRunQ $ report b s
|
|
| 532 | + |
|
| 533 | + -- | See 'recover'.
|
|
| 534 | + qRecover :: m a -- ^ the error handler
|
|
| 535 | + -> m a -- ^ action which may fail
|
|
| 536 | + -> m a -- ^ Recover from the monadic 'fail'
|
|
| 537 | + |
|
| 538 | + ------- Inspect the type-checker's environment -------
|
|
| 539 | + -- | True <=> type namespace, False <=> value namespace. See 'lookupName'.
|
|
| 540 | + qLookupName :: Bool -> String -> m (Maybe Name)
|
|
| 541 | + qLookupName ns s = qRunQ $ lookupName ns s
|
|
| 542 | + -- | See 'reify'.
|
|
| 543 | + qReify :: Name -> m Info
|
|
| 544 | + qReify v = qRunQ $ reify v
|
|
| 545 | + -- | See 'reifyFixity'.
|
|
| 546 | + qReifyFixity :: Name -> m (Maybe Fixity)
|
|
| 547 | + qReifyFixity v = qRunQ $ reifyFixity v
|
|
| 548 | + -- | See 'reifyType'.
|
|
| 549 | + qReifyType :: Name -> m Type
|
|
| 550 | + qReifyType v = qRunQ $ reifyType v
|
|
| 551 | + -- | Is (n tys) an instance? Returns list of matching instance Decs (with
|
|
| 552 | + -- empty sub-Decs) Works for classes and type functions. See 'reifyInstances'.
|
|
| 553 | + qReifyInstances :: Name -> [Type] -> m [Dec]
|
|
| 554 | + qReifyInstances cls tys = qRunQ $ reifyInstances cls tys
|
|
| 555 | + -- | See 'reifyRoles'.
|
|
| 556 | + qReifyRoles :: Name -> m [Role]
|
|
| 557 | + qReifyRoles nm = qRunQ $ reifyRoles nm
|
|
| 558 | + -- | See 'reifyAnnotations'.
|
|
| 559 | + qReifyAnnotations :: Data a => AnnLookup -> m [a]
|
|
| 560 | + qReifyAnnotations an = qRunQ $ reifyAnnotations an
|
|
| 561 | + -- | See 'reifyModule'.
|
|
| 562 | + qReifyModule :: Module -> m ModuleInfo
|
|
| 563 | + qReifyModule m = qRunQ $ reifyModule m
|
|
| 564 | + -- | See 'reifyConStrictness'.
|
|
| 565 | + qReifyConStrictness :: Name -> m [DecidedStrictness]
|
|
| 566 | + qReifyConStrictness nm = qRunQ $ reifyConStrictness nm
|
|
| 567 | + |
|
| 568 | + -- | See 'location'.
|
|
| 569 | + qLocation :: m Loc
|
|
| 570 | + qLocation = qRunQ location
|
|
| 571 | + |
|
| 572 | + -- | Input/output (dangerous). See 'runIO'.
|
|
| 573 | + qRunIO :: IO a -> m a
|
|
| 574 | + qRunIO = liftIO
|
|
| 575 | + -- | See 'getPackageRoot'.
|
|
| 576 | + qGetPackageRoot :: m FilePath
|
|
| 577 | + qGetPackageRoot = qRunQ getPackageRoot
|
|
| 578 | + |
|
| 579 | + -- | See 'addDependentFile'.
|
|
| 580 | + qAddDependentFile :: FilePath -> m ()
|
|
| 581 | + qAddDependentFile p = qRunQ $ addDependentFile p
|
|
| 582 | + |
|
| 583 | + -- | See 'addDependentDirectory'.
|
|
| 584 | + qAddDependentDirectory :: FilePath -> m ()
|
|
| 585 | + qAddDependentDirectory p = qRunQ $ addDependentDirectory p
|
|
| 586 | + |
|
| 587 | + -- | See 'addTempFile'.
|
|
| 588 | + qAddTempFile :: String -> m FilePath
|
|
| 589 | + qAddTempFile p = qRunQ $ addTempFile p
|
|
| 590 | + |
|
| 591 | + -- | See 'addTopDecls'.
|
|
| 592 | + qAddTopDecls :: [Dec] -> m ()
|
|
| 593 | + qAddTopDecls decls = qRunQ $ addTopDecls decls
|
|
| 594 | + |
|
| 595 | + -- | See 'addForeignFilePath'.
|
|
| 596 | + qAddForeignFilePath :: ForeignSrcLang -> String -> m ()
|
|
| 597 | + qAddForeignFilePath lang fp = qRunQ $ addForeignFilePath lang fp
|
|
| 598 | + |
|
| 599 | + -- | See 'addModFinalizer'.
|
|
| 600 | + qAddModFinalizer :: Q () -> m ()
|
|
| 601 | + qAddModFinalizer fin = qRunQ $ addModFinalizer fin
|
|
| 602 | + |
|
| 603 | + -- | See 'addCorePlugin'.
|
|
| 604 | + qAddCorePlugin :: String -> m ()
|
|
| 605 | + qAddCorePlugin nm = qRunQ $ addCorePlugin nm
|
|
| 606 | + |
|
| 607 | + -- | See 'getQ'.
|
|
| 608 | + qGetQ :: Typeable a => m (Maybe a)
|
|
| 609 | + qGetQ = qRunQ getQ
|
|
| 610 | + |
|
| 611 | + -- | See 'putQ'.
|
|
| 612 | + qPutQ :: Typeable a => a -> m ()
|
|
| 613 | + qPutQ x = qRunQ $ putQ x
|
|
| 614 | + |
|
| 615 | + -- | See 'isExtEnabled'.
|
|
| 616 | + qIsExtEnabled :: Extension -> m Bool
|
|
| 617 | + qIsExtEnabled ext = qRunQ $ isExtEnabled ext
|
|
| 618 | + -- | See 'extsEnabled'.
|
|
| 619 | + qExtsEnabled :: m [Extension]
|
|
| 620 | + qExtsEnabled = qRunQ extsEnabled
|
|
| 621 | + |
|
| 622 | + -- | See 'putDoc'.
|
|
| 623 | + qPutDoc :: DocLoc -> String -> m ()
|
|
| 624 | + qPutDoc l s = qRunQ $ putDoc l s
|
|
| 625 | + -- | See 'getDoc'.
|
|
| 626 | + qGetDoc :: DocLoc -> m (Maybe String)
|
|
| 627 | + qGetDoc l = qRunQ $ getDoc l
|
|
| 628 | + |
|
| 629 | +-- | \"Runs\" the 'Q' monad. Normal users of Template Haskell
|
|
| 630 | +-- should not need this function, as the splice brackets @$( ... )@
|
|
| 631 | +-- are the usual way of running a 'Q' computation.
|
|
| 632 | +--
|
|
| 633 | +-- This function is primarily used in GHC internals, and for debugging
|
|
| 634 | +-- splices by running them in 'IO'.
|
|
| 635 | +--
|
|
| 636 | +-- Note that many functions in 'Q', such as 'reify' and other compiler
|
|
| 637 | +-- queries, are not supported when running 'Q' in 'IO'; these operations
|
|
| 638 | +-- simply fail at runtime. Indeed, the only operations guaranteed to succeed
|
|
| 639 | +-- are 'newName', 'runIO', 'reportError' and 'reportWarning'.
|
|
| 640 | +runQ :: Quasi m => Q a -> m a
|
|
| 641 | +runQ = qRunQ
|
|
| 642 | + |
|
| 643 | +-----------------------------------------------------
|
|
| 644 | +-- The IO instance of Quasi
|
|
| 645 | +-----------------------------------------------------
|
|
| 646 | + |
|
| 647 | +-- | This instance is used only when running a Q
|
|
| 648 | +-- computation in the IO monad, usually just to
|
|
| 649 | +-- print the result. There is no interesting
|
|
| 650 | +-- type environment, so reification isn't going to
|
|
| 651 | +-- work. Please use 'Quote' instead, which is much safer.
|
|
| 652 | +instance Quasi IO where
|
|
| 653 | + qRunQ (Q m) = m metaHandlersIO
|
|
| 654 | + qNewName = newNameIO
|
|
| 655 | + |
|
| 656 | + qReport True msg = hPutStrLn stderr ("Template Haskell error: " ++ msg)
|
|
| 657 | + qReport False msg = hPutStrLn stderr ("Template Haskell error: " ++ msg)
|
|
| 658 | + qRecover _ _ = badIO "recover" -- Maybe we could fix this?
|
|
| 659 | + |
|
| 660 | +instance Quasi Q where
|
|
| 661 | + qRunQ = id
|
|
| 662 | + qRecover = recover
|
|
| 663 | + |
|
| 664 | + |
|
| 665 | +-- | Report an error (True) or warning (False),
|
|
| 666 | +-- but carry on; use 'fail' to stop.
|
|
| 667 | +report :: Bool -> String -> Q ()
|
|
| 668 | +report = Internal.report
|
|
| 669 | +{-# DEPRECATED report "Use reportError or reportWarning instead" #-} -- deprecated in 7.6
|
|
| 670 | + |
|
| 671 | +-- | Report an error to the user, but allow the current splice's computation to carry on. To abort the computation, use 'fail'.
|
|
| 672 | +reportError :: String -> Q ()
|
|
| 673 | +reportError = report True
|
|
| 674 | + |
|
| 675 | +-- | Report a warning to the user, and carry on.
|
|
| 676 | +reportWarning :: String -> Q ()
|
|
| 677 | +reportWarning = report False |
| ... | ... | @@ -354,7 +354,6 @@ module Language.Haskell.TH where |
| 354 | 354 | type Pred = Type
|
| 355 | 355 | type PredQ :: *
|
| 356 | 356 | type PredQ = Q Pred
|
| 357 | - type role Q nominal
|
|
| 358 | 357 | type Q :: * -> *
|
| 359 | 358 | newtype Q a = ...
|
| 360 | 359 | type Quote :: (* -> *) -> Constraint
|
| ... | ... | @@ -655,7 +654,7 @@ module Language.Haskell.TH where |
| 655 | 654 | roleAnnotD :: forall (m :: * -> *). Quote m => Name -> [GHC.Internal.TH.Lib.Role] -> m Dec
|
| 656 | 655 | ruleVar :: forall (m :: * -> *). Quote m => Name -> m RuleBndr
|
| 657 | 656 | runIO :: forall a. GHC.Internal.Types.IO a -> Q a
|
| 658 | - runQ :: forall (m :: * -> *) a. GHC.Internal.TH.Monad.Quasi m => Q a -> m a
|
|
| 657 | + runQ :: forall (m :: * -> *) a. Language.Haskell.TH.Syntax.Quasi m => Q a -> m a
|
|
| 659 | 658 | safe :: Safety
|
| 660 | 659 | sectionL :: forall (m :: * -> *). Quote m => m Exp -> m Exp -> m Exp
|
| 661 | 660 | sectionR :: forall (m :: * -> *). Quote m => m Exp -> m Exp -> m Exp
|
| ... | ... | @@ -1703,11 +1702,11 @@ module Language.Haskell.TH.Syntax where |
| 1703 | 1702 | data Pragma = InlineP Name Inline RuleMatch Phases | OpaqueP Name | SpecialiseEP (GHC.Internal.Maybe.Maybe [TyVarBndr ()]) [RuleBndr] Exp (GHC.Internal.Maybe.Maybe Inline) Phases | SpecialiseInstP Type | RuleP GHC.Internal.Base.String (GHC.Internal.Maybe.Maybe [TyVarBndr ()]) [RuleBndr] Exp Exp Phases | AnnP AnnTarget Exp | LineP GHC.Internal.Types.Int GHC.Internal.Base.String | CompleteP [Name] (GHC.Internal.Maybe.Maybe Name) | SCCP Name (GHC.Internal.Maybe.Maybe GHC.Internal.Base.String)
|
| 1704 | 1703 | type Pred :: *
|
| 1705 | 1704 | type Pred = Type
|
| 1706 | - type role Q nominal
|
|
| 1707 | 1705 | type Q :: * -> *
|
| 1708 | - newtype Q a = Q {unQ :: forall (m :: * -> *). Quasi m => m a}
|
|
| 1706 | + newtype Q a = ...
|
|
| 1709 | 1707 | type Quasi :: (* -> *) -> Constraint
|
| 1710 | 1708 | class (GHC.Internal.Control.Monad.IO.Class.MonadIO m, GHC.Internal.Control.Monad.Fail.MonadFail m) => Quasi m where
|
| 1709 | + qRunQ :: forall a. Q a -> m a
|
|
| 1711 | 1710 | qNewName :: GHC.Internal.Base.String -> m Name
|
| 1712 | 1711 | qReport :: GHC.Internal.Types.Bool -> GHC.Internal.Base.String -> m ()
|
| 1713 | 1712 | qRecover :: forall a. m a -> m a -> m a
|
| ... | ... | @@ -1730,13 +1729,13 @@ module Language.Haskell.TH.Syntax where |
| 1730 | 1729 | qAddForeignFilePath :: ForeignSrcLang -> GHC.Internal.Base.String -> m ()
|
| 1731 | 1730 | qAddModFinalizer :: Q () -> m ()
|
| 1732 | 1731 | qAddCorePlugin :: GHC.Internal.Base.String -> m ()
|
| 1733 | - qGetQ :: forall a. ghc-internal-9.1500.0:GHC.Internal.Data.Typeable.Internal.Typeable a => m (GHC.Internal.Maybe.Maybe a)
|
|
| 1734 | - qPutQ :: forall a. ghc-internal-9.1500.0:GHC.Internal.Data.Typeable.Internal.Typeable a => a -> m ()
|
|
| 1732 | + qGetQ :: forall a. ghc-internal-10.100.0:GHC.Internal.Data.Typeable.Internal.Typeable a => m (GHC.Internal.Maybe.Maybe a)
|
|
| 1733 | + qPutQ :: forall a. ghc-internal-10.100.0:GHC.Internal.Data.Typeable.Internal.Typeable a => a -> m ()
|
|
| 1735 | 1734 | qIsExtEnabled :: Extension -> m GHC.Internal.Types.Bool
|
| 1736 | 1735 | qExtsEnabled :: m [Extension]
|
| 1737 | 1736 | qPutDoc :: DocLoc -> GHC.Internal.Base.String -> m ()
|
| 1738 | 1737 | qGetDoc :: DocLoc -> m (GHC.Internal.Maybe.Maybe GHC.Internal.Base.String)
|
| 1739 | - {-# MINIMAL qNewName, qReport, qRecover, qLookupName, qReify, qReifyFixity, qReifyType, qReifyInstances, qReifyRoles, qReifyAnnotations, qReifyModule, qReifyConStrictness, qLocation, qGetPackageRoot, qAddDependentFile, qAddDependentDirectory, qAddTempFile, qAddTopDecls, qAddForeignFilePath, qAddModFinalizer, qAddCorePlugin, qGetQ, qPutQ, qIsExtEnabled, qExtsEnabled, qPutDoc, qGetDoc #-}
|
|
| 1738 | + {-# MINIMAL qRunQ, qRecover #-}
|
|
| 1740 | 1739 | type Quote :: (* -> *) -> Constraint
|
| 1741 | 1740 | class GHC.Internal.Base.Monad m => Quote m where
|
| 1742 | 1741 | newName :: GHC.Internal.Base.String -> m Name
|
| ... | ... | @@ -1814,7 +1813,7 @@ module Language.Haskell.TH.Syntax where |
| 1814 | 1813 | falseName :: Name
|
| 1815 | 1814 | getDoc :: DocLoc -> Q (GHC.Internal.Maybe.Maybe GHC.Internal.Base.String)
|
| 1816 | 1815 | getPackageRoot :: Q GHC.Internal.IO.FilePath
|
| 1817 | - getQ :: forall a. ghc-internal-9.1500.0:GHC.Internal.Data.Typeable.Internal.Typeable a => Q (GHC.Internal.Maybe.Maybe a)
|
|
| 1816 | + getQ :: forall a. ghc-internal-10.100.0:GHC.Internal.Data.Typeable.Internal.Typeable a => Q (GHC.Internal.Maybe.Maybe a)
|
|
| 1818 | 1817 | get_cons_names :: Con -> [Name]
|
| 1819 | 1818 | hoistCode :: forall (m :: * -> *) (n :: * -> *) (r :: GHC.Internal.Types.RuntimeRep) (a :: TYPE r). GHC.Internal.Base.Monad m => (forall x. m x -> n x) -> Code m a -> Code n a
|
| 1820 | 1819 | isExtEnabled :: Extension -> Q GHC.Internal.Types.Bool
|
| ... | ... | @@ -1861,7 +1860,7 @@ module Language.Haskell.TH.Syntax where |
| 1861 | 1860 | oneName :: Name
|
| 1862 | 1861 | pkgString :: PkgName -> GHC.Internal.Base.String
|
| 1863 | 1862 | putDoc :: DocLoc -> GHC.Internal.Base.String -> Q ()
|
| 1864 | - putQ :: forall a. ghc-internal-9.1500.0:GHC.Internal.Data.Typeable.Internal.Typeable a => a -> Q ()
|
|
| 1863 | + putQ :: forall a. ghc-internal-10.100.0:GHC.Internal.Data.Typeable.Internal.Typeable a => a -> Q ()
|
|
| 1865 | 1864 | recover :: forall a. Q a -> Q a -> Q a
|
| 1866 | 1865 | reify :: Name -> Q Info
|
| 1867 | 1866 | reifyAnnotations :: forall a. GHC.Internal.Data.Data.Data a => AnnLookup -> Q [a]
|
| ... | ... | @@ -1884,6 +1883,7 @@ module Language.Haskell.TH.Syntax where |
| 1884 | 1883 | trueName :: Name
|
| 1885 | 1884 | tupleDataName :: GHC.Internal.Types.Int -> Name
|
| 1886 | 1885 | tupleTypeName :: GHC.Internal.Types.Int -> Name
|
| 1886 | + unQ :: forall a. Q a -> forall (m :: * -> *). Quasi m => m a
|
|
| 1887 | 1887 | unTypeCode :: forall (r :: GHC.Internal.Types.RuntimeRep) (a :: TYPE r) (m :: * -> *). Quote m => Code m a -> m Exp
|
| 1888 | 1888 | unTypeQ :: forall (r :: GHC.Internal.Types.RuntimeRep) (a :: TYPE r) (m :: * -> *). Quote m => m (TExp a) -> m Exp
|
| 1889 | 1889 | unboxedSumDataName :: SumAlt -> SumArity -> Name
|
| ... | ... | @@ -2289,10 +2289,10 @@ instance forall a b c d e f g. (GHC.Internal.TH.Lift.Lift a, GHC.Internal.TH.Lif |
| 2289 | 2289 | instance GHC.Internal.TH.Lift.Lift (# #) -- Defined in ‘GHC.Internal.TH.Lift’
|
| 2290 | 2290 | instance GHC.Internal.TH.Lift.Lift GHC.Internal.Prim.Char# -- Defined in ‘GHC.Internal.TH.Lift’
|
| 2291 | 2291 | instance GHC.Internal.TH.Lift.Lift GHC.Internal.Prim.Word# -- Defined in ‘GHC.Internal.TH.Lift’
|
| 2292 | -instance GHC.Internal.TH.Monad.Quasi GHC.Internal.Types.IO -- Defined in ‘GHC.Internal.TH.Monad’
|
|
| 2293 | -instance GHC.Internal.TH.Monad.Quasi GHC.Internal.TH.Monad.Q -- Defined in ‘GHC.Internal.TH.Monad’
|
|
| 2294 | 2292 | instance GHC.Internal.TH.Monad.Quote GHC.Internal.Types.IO -- Defined in ‘GHC.Internal.TH.Monad’
|
| 2295 | 2293 | instance GHC.Internal.TH.Monad.Quote GHC.Internal.TH.Monad.Q -- Defined in ‘GHC.Internal.TH.Monad’
|
| 2296 | 2294 | instance [safe] Language.Haskell.TH.Lib.DefaultBndrFlag GHC.Internal.TH.Syntax.BndrVis -- Defined in ‘Language.Haskell.TH.Lib’
|
| 2297 | 2295 | instance [safe] Language.Haskell.TH.Lib.DefaultBndrFlag GHC.Internal.TH.Syntax.Specificity -- Defined in ‘Language.Haskell.TH.Lib’
|
| 2298 | 2296 | instance [safe] Language.Haskell.TH.Lib.DefaultBndrFlag () -- Defined in ‘Language.Haskell.TH.Lib’
|
| 2297 | +instance Language.Haskell.TH.Syntax.Quasi GHC.Internal.Types.IO -- Defined in ‘Language.Haskell.TH.Syntax’
|
|
| 2298 | +instance Language.Haskell.TH.Syntax.Quasi GHC.Internal.TH.Monad.Q -- Defined in ‘Language.Haskell.TH.Syntax’ |