Teo Camarasu pushed to branch wip/abstract-q at Glasgow Haskell Compiler / GHC
Commits:
-
67f9f5be
by Teo Camarasu at 2026-03-12T23:06:39+00:00
3 changed files:
- compiler/GHC/Data/IOEnv.hs
- compiler/GHC/Tc/Gen/Splice.hs
- libraries/ghc-internal/src/GHC/Internal/TH/Monad.hs
Changes:
| ... | ... | @@ -29,7 +29,7 @@ module GHC.Data.IOEnv ( |
| 29 | 29 | |
| 30 | 30 | -- I/O operations
|
| 31 | 31 | IORef, newMutVar, readMutVar, writeMutVar, updMutVar,
|
| 32 | - atomicUpdMutVar, atomicUpdMutVar'
|
|
| 32 | + atomicUpdMutVar, atomicUpdMutVar', unliftIOEnv
|
|
| 33 | 33 | ) where
|
| 34 | 34 | |
| 35 | 35 | import GHC.Prelude
|
| ... | ... | @@ -258,3 +258,10 @@ 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 | +unliftIOEnv :: forall env b. ((forall a. IOEnv env a -> IO a) -> IO b) -> IOEnv env b
|
|
| 263 | +unliftIOEnv k = IOEnv $ \env ->
|
|
| 264 | + let
|
|
| 265 | + unlift :: forall a. IOEnv env a -> IO a
|
|
| 266 | + unlift (IOEnv m) = m env
|
|
| 267 | + in k unlift |
| ... | ... | @@ -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)
|
| ... | ... | @@ -1139,7 +1140,7 @@ convertAnnotationWrapper fhv = do |
| 1139 | 1140 | -}
|
| 1140 | 1141 | |
| 1141 | 1142 | runQuasi :: TH.Q a -> TcM a
|
| 1142 | -runQuasi act = TH.runQ act
|
|
| 1143 | +runQuasi (TH.Q act) = runMetaHandlersInTcM metaHandlersTcM >>= liftIO . act
|
|
| 1143 | 1144 | |
| 1144 | 1145 | runRemoteModFinalizers :: ThModFinalizers -> TcM ()
|
| 1145 | 1146 | runRemoteModFinalizers (ThModFinalizers finRefs) = do
|
| ... | ... | @@ -1466,68 +1467,11 @@ 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) }
|
|
| 1473 | - |
|
| 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 | - UnhelpfulSpan _ -> pprPanic "qLocation: Unhelpful location"
|
|
| 1484 | - (ppr l)
|
|
| 1485 | - RealSrcSpan s _ -> return s
|
|
| 1486 | - ; return (TH.Loc { TH.loc_filename = unpackFS (srcSpanFile r)
|
|
| 1487 | - , TH.loc_module = moduleNameString (moduleName m)
|
|
| 1488 | - , TH.loc_package = unitString (moduleUnit m)
|
|
| 1489 | - , TH.loc_start = (srcSpanStartLine r, srcSpanStartCol r)
|
|
| 1490 | - , TH.loc_end = (srcSpanEndLine r, srcSpanEndCol r) }) }
|
|
| 1491 | - |
|
| 1492 | - qLookupName = lookupName
|
|
| 1493 | - qReify = reify
|
|
| 1494 | - qReifyFixity nm = lookupThName nm >>= reifyFixity
|
|
| 1495 | - qReifyType = reifyTypeOfThing
|
|
| 1496 | - qReifyInstances = reifyInstances
|
|
| 1497 | - qReifyRoles = reifyRoles
|
|
| 1498 | - qReifyAnnotations = reifyAnnotations
|
|
| 1499 | - qReifyModule = reifyModule
|
|
| 1500 | - qReifyConStrictness nm = do { nm' <- lookupThName nm
|
|
| 1501 | - ; dc <- tcLookupDataCon nm'
|
|
| 1502 | - ; let bangs = dataConImplBangs dc
|
|
| 1503 | - ; return (map reifyDecidedStrictness bangs) }
|
|
| 1504 | - |
|
| 1505 | - -- For qRecover, discard error messages if
|
|
| 1506 | - -- the recovery action is chosen. Otherwise
|
|
| 1507 | - -- we'll only fail higher up.
|
|
| 1508 | - qRecover recover main = tryTcDiscardingErrs recover main
|
|
| 1509 | - |
|
| 1510 | - qGetPackageRoot = do
|
|
| 1511 | - dflags <- getDynFlags
|
|
| 1512 | - return $ fromMaybe "." (workingDirectory dflags)
|
|
| 1513 | - |
|
| 1514 | - qAddDependentFile fp = do
|
|
| 1515 | - ref <- fmap tcg_dependent_files getGblEnv
|
|
| 1516 | - dep_files <- readTcRef ref
|
|
| 1517 | - writeTcRef ref (fp:dep_files)
|
|
| 1518 | - |
|
| 1519 | - qAddDependentDirectory dp = do
|
|
| 1520 | - ref <- fmap tcg_dependent_dirs getGblEnv
|
|
| 1521 | - dep_dirs <- readTcRef ref
|
|
| 1522 | - writeTcRef ref (dp:dep_dirs)
|
|
| 1523 | - |
|
| 1524 | - qAddTempFile suffix = do
|
|
| 1525 | - dflags <- getDynFlags
|
|
| 1526 | - logger <- getLogger
|
|
| 1527 | - tmpfs <- hsc_tmpfs <$> getTopEnv
|
|
| 1528 | - liftIO $ newTempName logger tmpfs (tmpDir dflags) TFL_GhcSession suffix
|
|
| 1529 | - |
|
| 1530 | - qAddTopDecls thds = do
|
|
| 1470 | +report True msg = seqList msg $ addErr $ TcRnTHError $ ReportCustomQuasiError True msg
|
|
| 1471 | +report False msg = seqList msg $ addDiagnostic $ TcRnTHError $ ReportCustomQuasiError False msg
|
|
| 1472 | + |
|
| 1473 | +addTopDecls :: [TH.Dec] -> TcM ()
|
|
| 1474 | +addTopDecls thds = do
|
|
| 1531 | 1475 | exts <- fmap extensionFlags getDynFlags
|
| 1532 | 1476 | l <- getSrcSpanM
|
| 1533 | 1477 | th_origin <- getThSpliceOrigin
|
| ... | ... | @@ -1555,52 +1499,12 @@ instance TH.Quasi TcM where |
| 1555 | 1499 | bindName :: RdrName -> TcM ()
|
| 1556 | 1500 | bindName (Exact n)
|
| 1557 | 1501 | = do { th_topnames_var <- fmap tcg_th_topnames getGblEnv
|
| 1558 | - ; updTcRef th_topnames_var (\ns -> extendNameSet ns n)
|
|
| 1559 | - }
|
|
| 1502 | + ; updTcRef th_topnames_var (\ns -> extendNameSet ns n)
|
|
| 1503 | + }
|
|
| 1560 | 1504 | |
| 1561 | 1505 | bindName name = addErr $ TcRnTHError $ THNameError $ NonExactName name
|
| 1562 | 1506 | |
| 1563 | - qAddForeignFilePath lang fp = do
|
|
| 1564 | - var <- fmap tcg_th_foreign_files getGblEnv
|
|
| 1565 | - updTcRef var ((lang, fp) :)
|
|
| 1566 | - |
|
| 1567 | - qAddModFinalizer fin = do
|
|
| 1568 | - r <- liftIO $ mkRemoteRef fin
|
|
| 1569 | - fref <- liftIO $ mkForeignRef r (freeRemoteRef r)
|
|
| 1570 | - addModFinalizerRef fref
|
|
| 1571 | - |
|
| 1572 | - qAddCorePlugin plugin = do
|
|
| 1573 | - hsc_env <- getTopEnv
|
|
| 1574 | - let fc = hsc_FC hsc_env
|
|
| 1575 | - let home_unit = hsc_home_unit hsc_env
|
|
| 1576 | - let dflags = hsc_dflags hsc_env
|
|
| 1577 | - let fopts = initFinderOpts dflags
|
|
| 1578 | - r <- liftIO $ findHomeModule fc fopts home_unit (mkModuleName plugin)
|
|
| 1579 | - let err = TcRnTHError $ AddInvalidCorePlugin plugin
|
|
| 1580 | - case r of
|
|
| 1581 | - Found {} -> addErr err
|
|
| 1582 | - FoundMultiple {} -> addErr err
|
|
| 1583 | - _ -> return ()
|
|
| 1584 | - th_coreplugins_var <- tcg_th_coreplugins <$> getGblEnv
|
|
| 1585 | - updTcRef th_coreplugins_var (plugin:)
|
|
| 1586 | - |
|
| 1587 | - qGetQ :: forall a. Typeable a => TcM (Maybe a)
|
|
| 1588 | - qGetQ = do
|
|
| 1589 | - th_state_var <- fmap tcg_th_state getGblEnv
|
|
| 1590 | - th_state <- readTcRef th_state_var
|
|
| 1591 | - -- See #10596 for why we use a scoped type variable here.
|
|
| 1592 | - return (Map.lookup (typeRep (Proxy :: Proxy a)) th_state >>= fromDynamic)
|
|
| 1593 | - |
|
| 1594 | - qPutQ x = do
|
|
| 1595 | - th_state_var <- fmap tcg_th_state getGblEnv
|
|
| 1596 | - updTcRef th_state_var (\m -> Map.insert (typeOf x) (toDyn x) m)
|
|
| 1597 | - |
|
| 1598 | - qIsExtEnabled = xoptM
|
|
| 1599 | - |
|
| 1600 | - qExtsEnabled =
|
|
| 1601 | - EnumSet.toList . extensionFlags . hsc_dflags <$> getTopEnv
|
|
| 1602 | - |
|
| 1603 | - qPutDoc doc_loc s = do
|
|
| 1507 | +putDoc doc_loc s = do
|
|
| 1604 | 1508 | th_doc_var <- tcg_th_docs <$> getGblEnv
|
| 1605 | 1509 | resolved_doc_loc <- resolve_loc doc_loc
|
| 1606 | 1510 | is_local <- checkLocalName resolved_doc_loc
|
| ... | ... | @@ -1623,14 +1527,184 @@ instance TH.Quasi TcM where |
| 1623 | 1527 | checkLocalName ModuleDoc = pure True
|
| 1624 | 1528 | |
| 1625 | 1529 | |
| 1626 | - qGetDoc (TH.DeclDoc n) = lookupThName n >>= lookupDeclDoc
|
|
| 1627 | - qGetDoc (TH.InstDoc t) = lookupThInstName t >>= lookupDeclDoc
|
|
| 1628 | - qGetDoc (TH.ArgDoc n i) = lookupThName n >>= lookupArgDoc i
|
|
| 1629 | - qGetDoc TH.ModuleDoc = do
|
|
| 1530 | +getDoc (TH.DeclDoc n) = lookupThName n >>= lookupDeclDoc
|
|
| 1531 | +getDoc (TH.InstDoc t) = lookupThInstName t >>= lookupDeclDoc
|
|
| 1532 | +getDoc (TH.ArgDoc n i) = lookupThName n >>= lookupArgDoc i
|
|
| 1533 | +getDoc TH.ModuleDoc = do
|
|
| 1630 | 1534 | df <- getDynFlags
|
| 1631 | 1535 | docs <- getGblEnv >>= extractDocs df
|
| 1632 | 1536 | return (renderHsDocString . hsDocString <$> (docs_mod_hdr =<< docs))
|
| 1633 | 1537 | |
| 1538 | +getQ :: forall a. Typeable a => TcM (Maybe a)
|
|
| 1539 | +getQ = do
|
|
| 1540 | + th_state_var <- fmap tcg_th_state getGblEnv
|
|
| 1541 | + th_state <- readTcRef th_state_var
|
|
| 1542 | + -- See #10596 for why we use a scoped type variable here.
|
|
| 1543 | + return (Map.lookup (typeRep (Proxy :: Proxy a)) th_state >>= fromDynamic)
|
|
| 1544 | + |
|
| 1545 | +location :: TcM TH.Loc
|
|
| 1546 | +location = do { m <- getModule
|
|
| 1547 | + ; l <- getSrcSpanM
|
|
| 1548 | + ; r <- case l of
|
|
| 1549 | + UnhelpfulSpan _ -> pprPanic "qLocation: Unhelpful location"
|
|
| 1550 | + (ppr l)
|
|
| 1551 | + RealSrcSpan s _ -> return s
|
|
| 1552 | + ; return (TH.Loc { TH.loc_filename = unpackFS (srcSpanFile r)
|
|
| 1553 | + , TH.loc_module = moduleNameString (moduleName m)
|
|
| 1554 | + , TH.loc_package = unitString (moduleUnit m)
|
|
| 1555 | + , TH.loc_start = (srcSpanStartLine r, srcSpanStartCol r)
|
|
| 1556 | + , TH.loc_end = (srcSpanEndLine r, srcSpanEndCol r) }) }
|
|
| 1557 | + |
|
| 1558 | +runMetaHandlersInTcM :: TH.MetaHandlers TcM -> TcM (TH.MetaHandlers IO)
|
|
| 1559 | +runMetaHandlersInTcM mh = unliftIOEnv $ \unliftTcM -> do
|
|
| 1560 | + let
|
|
| 1561 | + unliftTcM2 :: (a -> b -> TcM c) -> a -> b -> IO c
|
|
| 1562 | + unliftTcM2 m x y = unliftTcM (m x y)
|
|
| 1563 | + pure $ TH.MetaHandlers {
|
|
| 1564 | + mNewName = unliftTcM . mNewName mh
|
|
| 1565 | + |
|
| 1566 | + -- 'msg' is forced to ensure exceptions don't escape,
|
|
| 1567 | + -- see Note [Exceptions in TH]
|
|
| 1568 | + , mReport = unliftTcM2 $ mReport mh
|
|
| 1569 | + |
|
| 1570 | + , mLocation = unliftTcM $ mLocation mh
|
|
| 1571 | + |
|
| 1572 | + , mLookupName = unliftTcM2 $ mLookupName mh
|
|
| 1573 | + , mReify = unliftTcM . mReify mh
|
|
| 1574 | + , mReifyFixity = unliftTcM . mReifyFixity mh
|
|
| 1575 | + , mReifyType = unliftTcM . mReifyType mh
|
|
| 1576 | + , mReifyInstances = unliftTcM2 $ mReifyInstances mh
|
|
| 1577 | + , mReifyRoles = unliftTcM . mReifyRoles mh
|
|
| 1578 | + , mReifyAnnotations = unliftTcM . mReifyAnnotations mh
|
|
| 1579 | + , mReifyModule = unliftTcM . mReifyModule mh
|
|
| 1580 | + , mReifyConStrictness = unliftTcM . mReifyConStrictness mh
|
|
| 1581 | + |
|
| 1582 | + -- For qRecover, discard error messages if
|
|
| 1583 | + -- the recovery action is chosen. Otherwise
|
|
| 1584 | + -- we'll only fail higher up.
|
|
| 1585 | + , mRecover = \recover main -> unliftTcM $ mRecover mh (liftIO recover) (liftIO main)
|
|
| 1586 | + |
|
| 1587 | + , mGetPackageRoot = unliftTcM $ mGetPackageRoot mh
|
|
| 1588 | + |
|
| 1589 | + , mAddDependentFile = unliftTcM . mAddDependentFile mh
|
|
| 1590 | + |
|
| 1591 | + , mAddDependentDirectory = unliftTcM . mAddDependentDirectory mh
|
|
| 1592 | + |
|
| 1593 | + , mAddTempFile = unliftTcM . mAddTempFile mh
|
|
| 1594 | + |
|
| 1595 | + , mAddTopDecls = unliftTcM . mAddTopDecls mh
|
|
| 1596 | + |
|
| 1597 | + , mAddForeignFilePath = unliftTcM2 $ mAddForeignFilePath mh
|
|
| 1598 | + |
|
| 1599 | + , mAddModFinalizer = unliftTcM . mAddModFinalizer mh
|
|
| 1600 | + |
|
| 1601 | + , mAddCorePlugin = unliftTcM . mAddCorePlugin mh
|
|
| 1602 | + |
|
| 1603 | + , mGetQ = unliftTcM $ mGetQ mh
|
|
| 1604 | + |
|
| 1605 | + , mPutQ = unliftTcM . mPutQ mh
|
|
| 1606 | + |
|
| 1607 | + , mIsExtEnabled = unliftTcM . mIsExtEnabled mh
|
|
| 1608 | + |
|
| 1609 | + , mExtsEnabled = unliftTcM $ mExtsEnabled mh
|
|
| 1610 | + |
|
| 1611 | + , mPutDoc = unliftTcM2 $ mPutDoc mh
|
|
| 1612 | + |
|
| 1613 | + , mGetDoc = unliftTcM . mGetDoc mh
|
|
| 1614 | + }
|
|
| 1615 | + |
|
| 1616 | +metaHandlersTcM :: TH.MetaHandlers TcM
|
|
| 1617 | +metaHandlersTcM = TH.MetaHandlers {
|
|
| 1618 | + mNewName = \s -> do { u <- newUnique
|
|
| 1619 | + ; let i = toInteger (getKey u)
|
|
| 1620 | + ; return (TH.mkNameU s i) }
|
|
| 1621 | + |
|
| 1622 | + -- 'msg' is forced to ensure exceptions don't escape,
|
|
| 1623 | + -- see Note [Exceptions in TH]
|
|
| 1624 | + , mReport = report
|
|
| 1625 | + |
|
| 1626 | + , mLocation = location
|
|
| 1627 | + |
|
| 1628 | + , mLookupName = lookupName
|
|
| 1629 | + , mReify = reify
|
|
| 1630 | + , mReifyFixity = \nm -> lookupThName nm >>= reifyFixity
|
|
| 1631 | + , mReifyType = reifyTypeOfThing
|
|
| 1632 | + , mReifyInstances = reifyInstances
|
|
| 1633 | + , mReifyRoles = reifyRoles
|
|
| 1634 | + , mReifyAnnotations = reifyAnnotations
|
|
| 1635 | + , mReifyModule = reifyModule
|
|
| 1636 | + , mReifyConStrictness = \nm -> do { nm' <- lookupThName nm
|
|
| 1637 | + ; dc <- tcLookupDataCon nm'
|
|
| 1638 | + ; let bangs = dataConImplBangs dc
|
|
| 1639 | + ; return (map reifyDecidedStrictness bangs) }
|
|
| 1640 | + |
|
| 1641 | + -- For qRecover, discard error messages if
|
|
| 1642 | + -- the recovery action is chosen. Otherwise
|
|
| 1643 | + -- we'll only fail higher up.
|
|
| 1644 | + , mRecover = \recover main -> tryTcDiscardingErrs recover main
|
|
| 1645 | + |
|
| 1646 | + , mGetPackageRoot = do
|
|
| 1647 | + dflags <- getDynFlags
|
|
| 1648 | + return $ fromMaybe "." (workingDirectory dflags)
|
|
| 1649 | + |
|
| 1650 | + , mAddDependentFile = \fp -> do
|
|
| 1651 | + ref <- fmap tcg_dependent_files getGblEnv
|
|
| 1652 | + dep_files <- readTcRef ref
|
|
| 1653 | + writeTcRef ref (fp:dep_files)
|
|
| 1654 | + |
|
| 1655 | + , mAddDependentDirectory = \dp -> do
|
|
| 1656 | + ref <- fmap tcg_dependent_dirs getGblEnv
|
|
| 1657 | + dep_dirs <- readTcRef ref
|
|
| 1658 | + writeTcRef ref (dp:dep_dirs)
|
|
| 1659 | + |
|
| 1660 | + , mAddTempFile = \suffix -> do
|
|
| 1661 | + dflags <- getDynFlags
|
|
| 1662 | + logger <- getLogger
|
|
| 1663 | + tmpfs <- hsc_tmpfs <$> getTopEnv
|
|
| 1664 | + liftIO $ newTempName logger tmpfs (tmpDir dflags) TFL_GhcSession suffix
|
|
| 1665 | + |
|
| 1666 | + , mAddTopDecls = addTopDecls
|
|
| 1667 | + |
|
| 1668 | + , mAddForeignFilePath = \lang fp -> do
|
|
| 1669 | + var <- fmap tcg_th_foreign_files getGblEnv
|
|
| 1670 | + updTcRef var ((lang, fp) :)
|
|
| 1671 | + |
|
| 1672 | + , mAddModFinalizer = \fin -> do
|
|
| 1673 | + r <- liftIO $ mkRemoteRef fin
|
|
| 1674 | + fref <- liftIO $ mkForeignRef r (freeRemoteRef r)
|
|
| 1675 | + addModFinalizerRef fref
|
|
| 1676 | + |
|
| 1677 | + , mAddCorePlugin = \plugin -> do
|
|
| 1678 | + hsc_env <- getTopEnv
|
|
| 1679 | + let fc = hsc_FC hsc_env
|
|
| 1680 | + let home_unit = hsc_home_unit hsc_env
|
|
| 1681 | + let dflags = hsc_dflags hsc_env
|
|
| 1682 | + let fopts = initFinderOpts dflags
|
|
| 1683 | + r <- liftIO $ findHomeModule fc fopts home_unit (mkModuleName plugin)
|
|
| 1684 | + let err = TcRnTHError $ AddInvalidCorePlugin plugin
|
|
| 1685 | + case r of
|
|
| 1686 | + Found {} -> addErr err
|
|
| 1687 | + FoundMultiple {} -> addErr err
|
|
| 1688 | + _ -> return ()
|
|
| 1689 | + th_coreplugins_var <- tcg_th_coreplugins <$> getGblEnv
|
|
| 1690 | + updTcRef th_coreplugins_var (plugin:)
|
|
| 1691 | + |
|
| 1692 | + , mGetQ = getQ
|
|
| 1693 | + |
|
| 1694 | + , mPutQ = \x -> do
|
|
| 1695 | + th_state_var <- fmap tcg_th_state getGblEnv
|
|
| 1696 | + updTcRef th_state_var (\m -> Map.insert (typeOf x) (toDyn x) m)
|
|
| 1697 | + |
|
| 1698 | + , mIsExtEnabled = xoptM
|
|
| 1699 | + |
|
| 1700 | + , mExtsEnabled =
|
|
| 1701 | + EnumSet.toList . extensionFlags . hsc_dflags <$> getTopEnv
|
|
| 1702 | + |
|
| 1703 | + , mPutDoc = putDoc
|
|
| 1704 | + |
|
| 1705 | + , mGetDoc = getDoc
|
|
| 1706 | + }
|
|
| 1707 | + |
|
| 1634 | 1708 | -- | Looks up documentation for a declaration in first the current module,
|
| 1635 | 1709 | -- otherwise tries to find it in another module via 'hscGetModuleInterface'.
|
| 1636 | 1710 | lookupDeclDoc :: Name -> TcM (Maybe String)
|
| ... | ... | @@ -1795,7 +1869,7 @@ runTH ty fhv = do |
| 1795 | 1869 | -- Remote GHCi, see Note [Remote Template Haskell] in
|
| 1796 | 1870 | -- libraries/ghci/GHCi/TH.hs.
|
| 1797 | 1871 | rstate <- getTHState inst
|
| 1798 | - loc <- TH.qLocation
|
|
| 1872 | + loc <- location
|
|
| 1799 | 1873 | -- run a remote TH request
|
| 1800 | 1874 | r <- liftIO $
|
| 1801 | 1875 | withForeignRef rstate $ \state_hv ->
|
| ... | ... | @@ -1911,32 +1985,33 @@ wrapTHResult tcm = do |
| 1911 | 1985 | |
| 1912 | 1986 | handleTHMessage :: THMessage a -> TcM a
|
| 1913 | 1987 | handleTHMessage msg = case msg of
|
| 1914 | - NewName a -> wrapTHResult $ TH.qNewName a
|
|
| 1915 | - Report b str -> wrapTHResult $ TH.qReport b str
|
|
| 1916 | - LookupName b str -> wrapTHResult $ TH.qLookupName b str
|
|
| 1917 | - Reify n -> wrapTHResult $ TH.qReify n
|
|
| 1918 | - ReifyFixity n -> wrapTHResult $ TH.qReifyFixity n
|
|
| 1919 | - ReifyType n -> wrapTHResult $ TH.qReifyType n
|
|
| 1920 | - ReifyInstances n ts -> wrapTHResult $ TH.qReifyInstances n ts
|
|
| 1921 | - ReifyRoles n -> wrapTHResult $ TH.qReifyRoles n
|
|
| 1922 | - ReifyAnnotations lookup tyrep ->
|
|
| 1923 | - wrapTHResult $ (map B.pack <$> getAnnotationsByTypeRep lookup tyrep)
|
|
| 1924 | - ReifyModule m -> wrapTHResult $ TH.qReifyModule m
|
|
| 1925 | - ReifyConStrictness nm -> wrapTHResult $ TH.qReifyConStrictness nm
|
|
| 1926 | - GetPackageRoot -> wrapTHResult $ TH.qGetPackageRoot
|
|
| 1927 | - AddDependentFile f -> wrapTHResult $ TH.qAddDependentFile f
|
|
| 1928 | - AddDependentDirectory d -> wrapTHResult $ TH.qAddDependentDirectory d
|
|
| 1929 | - AddTempFile s -> wrapTHResult $ TH.qAddTempFile s
|
|
| 1930 | - AddModFinalizer r -> do
|
|
| 1931 | - interp <- hscInterp <$> getTopEnv
|
|
| 1932 | - wrapTHResult $ liftIO (mkFinalizedHValue interp r) >>= addModFinalizerRef
|
|
| 1933 | - AddCorePlugin str -> wrapTHResult $ TH.qAddCorePlugin str
|
|
| 1934 | - AddTopDecls decs -> wrapTHResult $ TH.qAddTopDecls decs
|
|
| 1935 | - AddForeignFilePath lang str -> wrapTHResult $ TH.qAddForeignFilePath lang str
|
|
| 1936 | - IsExtEnabled ext -> wrapTHResult $ TH.qIsExtEnabled ext
|
|
| 1937 | - ExtsEnabled -> wrapTHResult $ TH.qExtsEnabled
|
|
| 1938 | - PutDoc l s -> wrapTHResult $ TH.qPutDoc l s
|
|
| 1939 | - GetDoc l -> wrapTHResult $ TH.qGetDoc l
|
|
| 1988 | + -- TODO
|
|
| 1989 | + -- NewName a -> wrapTHResult $ TH.qNewName a
|
|
| 1990 | + -- Report b str -> wrapTHResult $ TH.qReport b str
|
|
| 1991 | + -- LookupName b str -> wrapTHResult $ TH.qLookupName b str
|
|
| 1992 | + -- Reify n -> wrapTHResult $ TH.qReify n
|
|
| 1993 | + -- ReifyFixity n -> wrapTHResult $ TH.qReifyFixity n
|
|
| 1994 | + -- ReifyType n -> wrapTHResult $ TH.qReifyType n
|
|
| 1995 | + -- ReifyInstances n ts -> wrapTHResult $ TH.qReifyInstances n ts
|
|
| 1996 | + -- ReifyRoles n -> wrapTHResult $ TH.qReifyRoles n
|
|
| 1997 | + -- ReifyAnnotations lookup tyrep ->
|
|
| 1998 | + -- wrapTHResult $ (map B.pack <$> getAnnotationsByTypeRep lookup tyrep)
|
|
| 1999 | + -- ReifyModule m -> wrapTHResult $ TH.qReifyModule m
|
|
| 2000 | + -- ReifyConStrictness nm -> wrapTHResult $ TH.qReifyConStrictness nm
|
|
| 2001 | + -- GetPackageRoot -> wrapTHResult $ TH.qGetPackageRoot
|
|
| 2002 | + -- AddDependentFile f -> wrapTHResult $ TH.qAddDependentFile f
|
|
| 2003 | + -- AddDependentDirectory d -> wrapTHResult $ TH.qAddDependentDirectory d
|
|
| 2004 | + -- AddTempFile s -> wrapTHResult $ TH.qAddTempFile s
|
|
| 2005 | + -- AddModFinalizer r -> do
|
|
| 2006 | + -- interp <- hscInterp <$> getTopEnv
|
|
| 2007 | + -- wrapTHResult $ liftIO (mkFinalizedHValue interp r) >>= addModFinalizerRef
|
|
| 2008 | + -- AddCorePlugin str -> wrapTHResult $ TH.qAddCorePlugin str
|
|
| 2009 | + -- AddTopDecls decs -> wrapTHResult $ TH.qAddTopDecls decs
|
|
| 2010 | + -- AddForeignFilePath lang str -> wrapTHResult $ TH.qAddForeignFilePath lang str
|
|
| 2011 | + -- IsExtEnabled ext -> wrapTHResult $ TH.qIsExtEnabled ext
|
|
| 2012 | + -- ExtsEnabled -> wrapTHResult $ TH.qExtsEnabled
|
|
| 2013 | + -- PutDoc l s -> wrapTHResult $ TH.qPutDoc l s
|
|
| 2014 | + -- GetDoc l -> wrapTHResult $ TH.qGetDoc l
|
|
| 1940 | 2015 | FailIfErrs -> wrapTHResult failIfErrsM
|
| 1941 | 2016 | _ -> panic ("handleTHMessage: unexpected message " ++ show msg)
|
| 1942 | 2017 |
| ... | ... | @@ -59,6 +59,7 @@ import GHC.Internal.TH.Syntax |
| 59 | 59 | -----------------------------------------------------
|
| 60 | 60 | |
| 61 | 61 | class (MonadIO m, MonadFail m) => Quasi m where
|
| 62 | + qRunQ :: Q a -> m a
|
|
| 62 | 63 | -- | Fresh names. See 'newName'.
|
| 63 | 64 | qNewName :: String -> m Name
|
| 64 | 65 | |
| ... | ... | @@ -149,6 +150,7 @@ class (MonadIO m, MonadFail m) => Quasi m where |
| 149 | 150 | -- type environment, so reification isn't going to
|
| 150 | 151 | -- work.
|
| 151 | 152 | instance Quasi IO where
|
| 153 | + qRunQ (Q m) = m (MetaHandlers {}) -- TODO: create a metahandlers instance which matches the quasi instance, ie, mostly badIO
|
|
| 152 | 154 | qNewName = newNameIO
|
| 153 | 155 | |
| 154 | 156 | qReport True msg = hPutStrLn stderr ("Template Haskell error: " ++ msg)
|
| ... | ... | @@ -183,6 +185,86 @@ instance Quasi IO where |
| 183 | 185 | instance Quote IO where
|
| 184 | 186 | newName = newNameIO
|
| 185 | 187 | |
| 188 | +data MetaHandlers m = MetaHandlers {
|
|
| 189 | + -- | Fresh names. See 'newName'.
|
|
| 190 | + mNewName :: String -> m Name
|
|
| 191 | + |
|
| 192 | + ------- Error reporting and recovery -------
|
|
| 193 | + -- | Report an error (True) or warning (False)
|
|
| 194 | + -- ...but carry on; use 'fail' to stop. See 'report'.
|
|
| 195 | + , mReport :: Bool -> String -> m ()
|
|
| 196 | + |
|
| 197 | + -- | See 'recover'.
|
|
| 198 | + , mRecover :: forall a. m a -- ^ the error handler
|
|
| 199 | + -> m a -- ^ action which may fail
|
|
| 200 | + -> m a -- ^ Recover from the monadic 'fail'
|
|
| 201 | + |
|
| 202 | + ------- Inspect the type-checker's environment -------
|
|
| 203 | + -- | True <=> type namespace, False <=> value namespace. See 'lookupName'.
|
|
| 204 | + , mLookupName :: Bool -> String -> m (Maybe Name)
|
|
| 205 | + -- | See 'reify'.
|
|
| 206 | + , mReify :: Name -> m Info
|
|
| 207 | + -- | See 'reifyFixity'.
|
|
| 208 | + , mReifyFixity :: Name -> m (Maybe Fixity)
|
|
| 209 | + -- | See 'reifyType'.
|
|
| 210 | + , mReifyType :: Name -> m Type
|
|
| 211 | + -- | Is (n tys) an instance? Returns list of matching instance Decs (with
|
|
| 212 | + -- empty sub-Decs) Works for classes and type functions. See 'reifyInstances'.
|
|
| 213 | + , mReifyInstances :: Name -> [Type] -> m [Dec]
|
|
| 214 | + -- | See 'reifyRoles'.
|
|
| 215 | + , mReifyRoles :: Name -> m [Role]
|
|
| 216 | + -- | See 'reifyAnnotations'.
|
|
| 217 | + , mReifyAnnotations :: forall a. Data a => AnnLookup -> m [a]
|
|
| 218 | + -- | See 'reifyModule'.
|
|
| 219 | + , mReifyModule :: Module -> m ModuleInfo
|
|
| 220 | + -- | See 'reifyConStrictness'.
|
|
| 221 | + , mReifyConStrictness :: Name -> m [DecidedStrictness]
|
|
| 222 | + |
|
| 223 | + -- | See 'location'.
|
|
| 224 | + , mLocation :: m Loc
|
|
| 225 | + |
|
| 226 | + -- | See 'getPackageRoot'.
|
|
| 227 | + , mGetPackageRoot :: m FilePath
|
|
| 228 | + |
|
| 229 | + -- | See 'addDependentFile'.
|
|
| 230 | + , mAddDependentFile :: FilePath -> m ()
|
|
| 231 | + |
|
| 232 | + -- | See 'addDependentDirectory'.
|
|
| 233 | + , mAddDependentDirectory :: FilePath -> m ()
|
|
| 234 | + |
|
| 235 | + -- | See 'addTempFile'.
|
|
| 236 | + , mAddTempFile :: String -> m FilePath
|
|
| 237 | + |
|
| 238 | + -- | See 'addTopDecls'.
|
|
| 239 | + , mAddTopDecls :: [Dec] -> m ()
|
|
| 240 | + |
|
| 241 | + -- | See 'addForeignFilePath'.
|
|
| 242 | + , mAddForeignFilePath :: ForeignSrcLang -> String -> m ()
|
|
| 243 | + |
|
| 244 | + -- | See 'addModFinalizer'.
|
|
| 245 | + , mAddModFinalizer :: Q () -> m ()
|
|
| 246 | + |
|
| 247 | + -- | See 'addCorePlugin'.
|
|
| 248 | + , mAddCorePlugin :: String -> m ()
|
|
| 249 | + |
|
| 250 | + -- | See 'getQ'.
|
|
| 251 | + , mGetQ :: forall a. Typeable a => m (Maybe a)
|
|
| 252 | + |
|
| 253 | + -- | See 'putQ'.
|
|
| 254 | + , mPutQ :: forall a. Typeable a => a -> m ()
|
|
| 255 | + |
|
| 256 | + -- | See 'isExtEnabled'.
|
|
| 257 | + , mIsExtEnabled :: Extension -> m Bool
|
|
| 258 | + -- | See 'extsEnabled'.
|
|
| 259 | + , mExtsEnabled :: m [Extension]
|
|
| 260 | + |
|
| 261 | + -- | See 'putDoc'.
|
|
| 262 | + , mPutDoc :: DocLoc -> String -> m ()
|
|
| 263 | + -- | See 'getDoc'.
|
|
| 264 | + , mGetDoc :: DocLoc -> m (Maybe String)
|
|
| 265 | + }
|
|
| 266 | + |
|
| 267 | + |
|
| 186 | 268 | newNameIO :: String -> IO Name
|
| 187 | 269 | newNameIO s = do { n <- atomicModifyIORef' counter (\x -> (x + 1, x))
|
| 188 | 270 | ; pure (mkNameU s n) }
|
| ... | ... | @@ -213,7 +295,7 @@ counter = unsafePerformIO (newIORef 0) |
| 213 | 295 | -- inversion](https://en.wikipedia.org/wiki/Dependency_inversion_principle),
|
| 214 | 296 | -- providing an abstract interface for the user which is later concretely
|
| 215 | 297 | -- fufilled by an concrete 'Quasi' instance, internal to GHC.
|
| 216 | -newtype Q a = Q { unQ :: forall m. Quasi m => m a }
|
|
| 298 | +newtype Q a = Q { unQ :: MetaHandlers IO -> IO a }
|
|
| 217 | 299 | |
| 218 | 300 | -- | \"Runs\" the 'Q' monad. Normal users of Template Haskell
|
| 219 | 301 | -- should not need this function, as the splice brackets @$( ... )@
|
| ... | ... | @@ -227,22 +309,22 @@ newtype Q a = Q { unQ :: forall m. Quasi m => m a } |
| 227 | 309 | -- simply fail at runtime. Indeed, the only operations guaranteed to succeed
|
| 228 | 310 | -- are 'newName', 'runIO', 'reportError' and 'reportWarning'.
|
| 229 | 311 | runQ :: Quasi m => Q a -> m a
|
| 230 | -runQ (Q m) = m
|
|
| 312 | +runQ = qRunQ
|
|
| 231 | 313 | |
| 232 | 314 | instance Monad Q where
|
| 233 | - Q m >>= k = Q (m >>= \x -> unQ (k x))
|
|
| 315 | + Q m >>= k = Q $ \h -> (m h >>= \x -> unQ (k x) h)
|
|
| 234 | 316 | (>>) = (*>)
|
| 235 | 317 | |
| 236 | 318 | instance MonadFail Q where
|
| 237 | - fail s = report True s >> Q (fail "Q monad failure")
|
|
| 319 | + fail s = report True s >> Q (\h -> fail "Q monad failure")
|
|
| 238 | 320 | |
| 239 | 321 | instance Functor Q where
|
| 240 | - fmap f (Q x) = Q (fmap f x)
|
|
| 322 | + fmap f (Q x) = Q $ \h -> fmap f (x h)
|
|
| 241 | 323 | |
| 242 | 324 | instance Applicative Q where
|
| 243 | - pure x = Q (pure x)
|
|
| 244 | - Q f <*> Q x = Q (f <*> x)
|
|
| 245 | - Q m *> Q n = Q (m *> n)
|
|
| 325 | + pure x = Q $ \h -> (pure x)
|
|
| 326 | + Q f <*> Q x = Q $ \h -> (f h <*> x h)
|
|
| 327 | + Q m *> Q n = Q $ \h ->(m h *> n h)
|
|
| 246 | 328 | |
| 247 | 329 | -- | @since 2.17.0.0
|
| 248 | 330 | instance Semigroup a => Semigroup (Q a) where
|
| ... | ... | @@ -312,7 +394,7 @@ class Monad m => Quote m where |
| 312 | 394 | newName :: String -> m Name
|
| 313 | 395 | |
| 314 | 396 | instance Quote Q where
|
| 315 | - newName s = Q (qNewName s)
|
|
| 397 | + newName s = Q $ \h -> mNewName h s
|
|
| 316 | 398 | |
| 317 | 399 | -----------------------------------------------------
|
| 318 | 400 | --
|
| ... | ... | @@ -510,7 +592,7 @@ joinCode = flip bindCode id |
| 510 | 592 | -- | Report an error (True) or warning (False),
|
| 511 | 593 | -- but carry on; use 'fail' to stop.
|
| 512 | 594 | report :: Bool -> String -> Q ()
|
| 513 | -report b s = Q (qReport b s)
|
|
| 595 | +report b s = Q $ \h -> mReport h b s
|
|
| 514 | 596 | {-# DEPRECATED report "Use reportError or reportWarning instead" #-} -- deprecated in 7.6
|
| 515 | 597 | |
| 516 | 598 | -- | Report an error to the user, but allow the current splice's computation to carry on. To abort the computation, use 'fail'.
|
| ... | ... | @@ -525,20 +607,20 @@ reportWarning = report False |
| 525 | 607 | recover :: Q a -- ^ handler to invoke on failure
|
| 526 | 608 | -> Q a -- ^ computation to run
|
| 527 | 609 | -> Q a
|
| 528 | -recover (Q r) (Q m) = Q (qRecover r m)
|
|
| 610 | +recover (Q r) (Q m) = Q $ \h -> mRecover h (r h) (m h)
|
|
| 529 | 611 | |
| 530 | 612 | -- We don't export lookupName; the Bool isn't a great API
|
| 531 | 613 | -- Instead we export lookupTypeName, lookupValueName
|
| 532 | 614 | lookupName :: Bool -> String -> Q (Maybe Name)
|
| 533 | -lookupName ns s = Q (qLookupName ns s)
|
|
| 615 | +lookupName ns s = Q $ \h -> (mLookupName h ns s)
|
|
| 534 | 616 | |
| 535 | 617 | -- | Look up the given name in the (type namespace of the) current splice's scope. See "Language.Haskell.TH.Syntax#namelookup" for more details.
|
| 536 | 618 | lookupTypeName :: String -> Q (Maybe Name)
|
| 537 | -lookupTypeName s = Q (qLookupName True s)
|
|
| 619 | +lookupTypeName s = Q $ \h -> (mLookupName h True s)
|
|
| 538 | 620 | |
| 539 | 621 | -- | Look up the given name in the (value namespace of the) current splice's scope. See "Language.Haskell.TH.Syntax#namelookup" for more details.
|
| 540 | 622 | lookupValueName :: String -> Q (Maybe Name)
|
| 541 | -lookupValueName s = Q (qLookupName False s)
|
|
| 623 | +lookupValueName s = Q $ \h -> (mLookupName h False s)
|
|
| 542 | 624 | |
| 543 | 625 | {-
|
| 544 | 626 | Note [Name lookup]
|
| ... | ... | @@ -613,7 +695,7 @@ To ensure we get information about @D@-the-value, use 'lookupValueName': |
| 613 | 695 | and to get information about @D@-the-type, use 'lookupTypeName'.
|
| 614 | 696 | -}
|
| 615 | 697 | reify :: Name -> Q Info
|
| 616 | -reify v = Q (qReify v)
|
|
| 698 | +reify v = Q $ \h -> (mReify h v)
|
|
| 617 | 699 | |
| 618 | 700 | {- | @reifyFixity nm@ attempts to find a fixity declaration for @nm@. For
|
| 619 | 701 | example, if the function @foo@ has the fixity declaration @infixr 7 foo@, then
|
| ... | ... | @@ -622,7 +704,7 @@ example, if the function @foo@ has the fixity declaration @infixr 7 foo@, then |
| 622 | 704 | 'Nothing', so you may assume @bar@ has 'defaultFixity'.
|
| 623 | 705 | -}
|
| 624 | 706 | reifyFixity :: Name -> Q (Maybe Fixity)
|
| 625 | -reifyFixity nm = Q (qReifyFixity nm)
|
|
| 707 | +reifyFixity nm = Q $ \h ->(mReifyFixity h nm)
|
|
| 626 | 708 | |
| 627 | 709 | {- | @reifyType nm@ attempts to find the type or kind of @nm@. For example,
|
| 628 | 710 | @reifyType 'not@ returns @Bool -> Bool@, and
|
| ... | ... | @@ -630,7 +712,7 @@ reifyFixity nm = Q (qReifyFixity nm) |
| 630 | 712 | This works even if there's no explicit signature and the type or kind is inferred.
|
| 631 | 713 | -}
|
| 632 | 714 | reifyType :: Name -> Q Type
|
| 633 | -reifyType nm = Q (qReifyType nm)
|
|
| 715 | +reifyType nm = Q $ \h ->(mReifyType h nm)
|
|
| 634 | 716 | |
| 635 | 717 | {- | Template Haskell is capable of reifying information about types and
|
| 636 | 718 | terms defined in previous declaration groups. Top-level declaration splices break up
|
| ... | ... | @@ -722,7 +804,7 @@ has some discussion around this. |
| 722 | 804 | |
| 723 | 805 | -}
|
| 724 | 806 | reifyInstances :: Name -> [Type] -> Q [InstanceDec]
|
| 725 | -reifyInstances cls tys = Q (qReifyInstances cls tys)
|
|
| 807 | +reifyInstances cls tys = Q $ \h ->(mReifyInstances h cls tys)
|
|
| 726 | 808 | |
| 727 | 809 | {- | @reifyRoles nm@ returns the list of roles associated with the parameters
|
| 728 | 810 | (both visible and invisible) of
|
| ... | ... | @@ -741,20 +823,20 @@ and @reifyRoles Proxy@, we will get @['NominalR', 'PhantomR']@. The 'NominalR' i |
| 741 | 823 | the role of the invisible @k@ parameter. Kind parameters are always nominal.
|
| 742 | 824 | -}
|
| 743 | 825 | reifyRoles :: Name -> Q [Role]
|
| 744 | -reifyRoles nm = Q (qReifyRoles nm)
|
|
| 826 | +reifyRoles nm = Q $ \h -> (mReifyRoles h nm)
|
|
| 745 | 827 | |
| 746 | 828 | -- | @reifyAnnotations target@ returns the list of annotations
|
| 747 | 829 | -- associated with @target@. Only the annotations that are
|
| 748 | 830 | -- appropriately typed is returned. So if you have @Int@ and @String@
|
| 749 | 831 | -- annotations for the same target, you have to call this function twice.
|
| 750 | 832 | reifyAnnotations :: Data a => AnnLookup -> Q [a]
|
| 751 | -reifyAnnotations an = Q (qReifyAnnotations an)
|
|
| 833 | +reifyAnnotations an = Q $ \h -> (mReifyAnnotations h an)
|
|
| 752 | 834 | |
| 753 | 835 | -- | @reifyModule mod@ looks up information about module @mod@. To
|
| 754 | 836 | -- look up the current module, call this function with the return
|
| 755 | 837 | -- value of 'Language.Haskell.TH.Lib.thisModule'.
|
| 756 | 838 | reifyModule :: Module -> Q ModuleInfo
|
| 757 | -reifyModule m = Q (qReifyModule m)
|
|
| 839 | +reifyModule m = Q $ \h -> (mReifyModule h m)
|
|
| 758 | 840 | |
| 759 | 841 | -- | @reifyConStrictness nm@ looks up the strictness information for the fields
|
| 760 | 842 | -- of the constructor with the name @nm@. Note that the strictness information
|
| ... | ... | @@ -769,7 +851,7 @@ reifyModule m = Q (qReifyModule m) |
| 769 | 851 | -- circumstances, but it would return @['DecidedStrict', DecidedStrict]@ if the
|
| 770 | 852 | -- @-XStrictData@ language extension was enabled.
|
| 771 | 853 | reifyConStrictness :: Name -> Q [DecidedStrictness]
|
| 772 | -reifyConStrictness n = Q (qReifyConStrictness n)
|
|
| 854 | +reifyConStrictness n = Q $ \h ->(mReifyConStrictness h n)
|
|
| 773 | 855 | |
| 774 | 856 | -- | Is the list of instances returned by 'reifyInstances' nonempty?
|
| 775 | 857 | --
|
| ... | ... | @@ -782,7 +864,7 @@ isInstance nm tys = do { decs <- reifyInstances nm tys |
| 782 | 864 | |
| 783 | 865 | -- | The location at which this computation is spliced.
|
| 784 | 866 | location :: Q Loc
|
| 785 | -location = Q qLocation
|
|
| 867 | +location = Q mLocation
|
|
| 786 | 868 | |
| 787 | 869 | -- |The 'runIO' function lets you run an I\/O computation in the 'Q' monad.
|
| 788 | 870 | -- Take care: you are guaranteed the ordering of calls to 'runIO' within
|
| ... | ... | @@ -792,7 +874,7 @@ location = Q qLocation |
| 792 | 874 | -- necessarily flushed when the compiler finishes running, so you should
|
| 793 | 875 | -- flush them yourself.
|
| 794 | 876 | runIO :: IO a -> Q a
|
| 795 | -runIO m = Q (qRunIO m)
|
|
| 877 | +runIO m = Q $ \h -> m
|
|
| 796 | 878 | |
| 797 | 879 | -- | Get the package root for the current package which is being compiled.
|
| 798 | 880 | -- This can be set explicitly with the -package-root flag but is normally
|
| ... | ... | @@ -804,7 +886,7 @@ runIO m = Q (qRunIO m) |
| 804 | 886 | -- change directory when compiling files but instead set the -package-root flag
|
| 805 | 887 | -- appropriately.
|
| 806 | 888 | getPackageRoot :: Q FilePath
|
| 807 | -getPackageRoot = Q qGetPackageRoot
|
|
| 889 | +getPackageRoot = Q mGetPackageRoot
|
|
| 808 | 890 | |
| 809 | 891 | -- | Record external directories that runIO is using (dependent upon).
|
| 810 | 892 | -- The compiler can then recognize that it should re-compile the Haskell file
|
| ... | ... | @@ -823,7 +905,7 @@ getPackageRoot = Q qGetPackageRoot |
| 823 | 905 | -- * The state of the directory is read at the interface generation time,
|
| 824 | 906 | -- not at the time of the function call.
|
| 825 | 907 | addDependentDirectory :: FilePath -> Q ()
|
| 826 | -addDependentDirectory dp = Q (qAddDependentDirectory dp)
|
|
| 908 | +addDependentDirectory dp = Q $ \h -> (mAddDependentDirectory h dp)
|
|
| 827 | 909 | |
| 828 | 910 | -- | Record external files that runIO is using (dependent upon).
|
| 829 | 911 | -- The compiler can then recognize that it should re-compile the Haskell file
|
| ... | ... | @@ -837,17 +919,17 @@ addDependentDirectory dp = Q (qAddDependentDirectory dp) |
| 837 | 919 | --
|
| 838 | 920 | -- * The dependency is based on file content, not a modification time
|
| 839 | 921 | addDependentFile :: FilePath -> Q ()
|
| 840 | -addDependentFile fp = Q (qAddDependentFile fp)
|
|
| 922 | +addDependentFile fp = Q $ \h -> (mAddDependentFile h fp)
|
|
| 841 | 923 | |
| 842 | 924 | -- | Obtain a temporary file path with the given suffix. The compiler will
|
| 843 | 925 | -- delete this file after compilation.
|
| 844 | 926 | addTempFile :: String -> Q FilePath
|
| 845 | -addTempFile suffix = Q (qAddTempFile suffix)
|
|
| 927 | +addTempFile suffix = Q $ \h -> (mAddTempFile h suffix)
|
|
| 846 | 928 | |
| 847 | 929 | -- | Add additional top-level declarations. The added declarations will be type
|
| 848 | 930 | -- checked along with the current declaration group.
|
| 849 | 931 | addTopDecls :: [Dec] -> Q ()
|
| 850 | -addTopDecls ds = Q (qAddTopDecls ds)
|
|
| 932 | +addTopDecls ds = Q $ \h ->(mAddTopDecls h ds)
|
|
| 851 | 933 | |
| 852 | 934 | -- | Same as 'addForeignSource', but expects to receive a path pointing to the
|
| 853 | 935 | -- foreign file instead of a 'String' of its contents. Consider using this in
|
| ... | ... | @@ -856,7 +938,7 @@ addTopDecls ds = Q (qAddTopDecls ds) |
| 856 | 938 | -- This is a good alternative to 'addForeignSource' when you are trying to
|
| 857 | 939 | -- directly link in an object file.
|
| 858 | 940 | addForeignFilePath :: ForeignSrcLang -> FilePath -> Q ()
|
| 859 | -addForeignFilePath lang fp = Q (qAddForeignFilePath lang fp)
|
|
| 941 | +addForeignFilePath lang fp = Q $ \h ->(mAddForeignFilePath h lang fp)
|
|
| 860 | 942 | |
| 861 | 943 | -- | Add a finalizer that will run in the Q monad after the current module has
|
| 862 | 944 | -- been type checked. This only makes sense when run within a top-level splice.
|
| ... | ... | @@ -865,7 +947,7 @@ addForeignFilePath lang fp = Q (qAddForeignFilePath lang fp) |
| 865 | 947 | -- 'reify' is able to find the local definitions when executed inside the
|
| 866 | 948 | -- finalizer.
|
| 867 | 949 | addModFinalizer :: Q () -> Q ()
|
| 868 | -addModFinalizer act = Q (qAddModFinalizer (unQ act))
|
|
| 950 | +addModFinalizer act = Q $ \h -> mAddModFinalizer h act
|
|
| 869 | 951 | |
| 870 | 952 | -- | Adds a core plugin to the compilation pipeline.
|
| 871 | 953 | --
|
| ... | ... | @@ -875,7 +957,7 @@ addModFinalizer act = Q (qAddModFinalizer (unQ act)) |
| 875 | 957 | -- to tell the compiler that we needed to compile first a plugin module in the
|
| 876 | 958 | -- current package.
|
| 877 | 959 | addCorePlugin :: String -> Q ()
|
| 878 | -addCorePlugin plugin = Q (qAddCorePlugin plugin)
|
|
| 960 | +addCorePlugin plugin = Q $ \h -> mAddCorePlugin h plugin
|
|
| 879 | 961 | |
| 880 | 962 | -- | Get state from the 'Q' monad. The state maintained by 'Q' is isomorphic to
|
| 881 | 963 | -- a type-indexed finite map. That is,
|
| ... | ... | @@ -889,20 +971,20 @@ addCorePlugin plugin = Q (qAddCorePlugin plugin) |
| 889 | 971 | -- Note that the state is local to the Haskell module in which the Template
|
| 890 | 972 | -- Haskell expression is executed.
|
| 891 | 973 | getQ :: Typeable a => Q (Maybe a)
|
| 892 | -getQ = Q qGetQ
|
|
| 974 | +getQ = Q mGetQ
|
|
| 893 | 975 | |
| 894 | 976 | -- | Replace the state in the 'Q' monad. Note that the state is local to the
|
| 895 | 977 | -- Haskell module in which the Template Haskell expression is executed.
|
| 896 | 978 | putQ :: Typeable a => a -> Q ()
|
| 897 | -putQ x = Q (qPutQ x)
|
|
| 979 | +putQ x = Q $ \h -> mPutQ h x
|
|
| 898 | 980 | |
| 899 | 981 | -- | Determine whether the given language extension is enabled in the 'Q' monad.
|
| 900 | 982 | isExtEnabled :: Extension -> Q Bool
|
| 901 | -isExtEnabled ext = Q (qIsExtEnabled ext)
|
|
| 983 | +isExtEnabled ext = Q $ \h -> mIsExtEnabled h ext
|
|
| 902 | 984 | |
| 903 | 985 | -- | List all enabled language extensions.
|
| 904 | 986 | extsEnabled :: Q [Extension]
|
| 905 | -extsEnabled = Q qExtsEnabled
|
|
| 987 | +extsEnabled = Q $ mExtsEnabled
|
|
| 906 | 988 | |
| 907 | 989 | -- | Add Haddock documentation to the specified location. This will overwrite
|
| 908 | 990 | -- any documentation at the location if it already exists. This will reify the
|
| ... | ... | @@ -921,19 +1003,20 @@ extsEnabled = Q qExtsEnabled |
| 921 | 1003 | -- Adding documentation to anything outside of the current module will cause an
|
| 922 | 1004 | -- error.
|
| 923 | 1005 | putDoc :: DocLoc -> String -> Q ()
|
| 924 | -putDoc t s = Q (qPutDoc t s)
|
|
| 1006 | +putDoc t s = Q $ \h -> mPutDoc h t s
|
|
| 925 | 1007 | |
| 926 | 1008 | -- | Retrieves the Haddock documentation at the specified location, if one
|
| 927 | 1009 | -- exists.
|
| 928 | 1010 | -- It can be used to read documentation on things defined outside of the current
|
| 929 | 1011 | -- module, provided that those modules were compiled with the @-haddock@ flag.
|
| 930 | 1012 | getDoc :: DocLoc -> Q (Maybe String)
|
| 931 | -getDoc n = Q (qGetDoc n)
|
|
| 1013 | +getDoc n = Q $ \h ->mGetDoc h n
|
|
| 932 | 1014 | |
| 933 | 1015 | instance MonadIO Q where
|
| 934 | 1016 | liftIO = runIO
|
| 935 | 1017 | |
| 936 | 1018 | instance Quasi Q where
|
| 1019 | + qRunQ = id
|
|
| 937 | 1020 | qNewName = newName
|
| 938 | 1021 | qReport = report
|
| 939 | 1022 | qRecover = recover
|