Teo Camarasu pushed to branch wip/abstract-q at Glasgow Haskell Compiler / GHC

Commits:

4 changed files:

Changes:

  • compiler/GHC/Data/IOEnv.hs
    ... ... @@ -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

  • compiler/GHC/Tc/Gen/Splice.hs
    ... ... @@ -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) = unliftIOEnv $ \runInIO -> liftIO $ act runInIO metaHandlersTcM
    
    1143 1144
     
    
    1144 1145
     runRemoteModFinalizers :: ThModFinalizers -> TcM ()
    
    1145 1146
     runRemoteModFinalizers (ThModFinalizers finRefs) = do
    
    ... ... @@ -1466,68 +1467,12 @@ 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 :: Bool -> [Char] -> TcM ()
    
    1471
    +report True msg  = seqList msg $ addErr        $ TcRnTHError $ ReportCustomQuasiError True  msg
    
    1472
    +report False msg = seqList msg $ addDiagnostic $ TcRnTHError $ ReportCustomQuasiError False msg
    
    1473
    +
    
    1474
    +addTopDecls :: [TH.Dec] -> TcM ()
    
    1475
    +addTopDecls thds = do
    
    1531 1476
           exts <- fmap extensionFlags getDynFlags
    
    1532 1477
           l <- getSrcSpanM
    
    1533 1478
           th_origin <- getThSpliceOrigin
    
    ... ... @@ -1555,52 +1500,13 @@ instance TH.Quasi TcM where
    1555 1500
           bindName :: RdrName -> TcM ()
    
    1556 1501
           bindName (Exact n)
    
    1557 1502
             = do { th_topnames_var <- fmap tcg_th_topnames getGblEnv
    
    1558
    -             ; updTcRef th_topnames_var (\ns -> extendNameSet ns n)
    
    1559
    -             }
    
    1503
    +            ; updTcRef th_topnames_var (\ns -> extendNameSet ns n)
    
    1504
    +            }
    
    1560 1505
     
    
    1561 1506
           bindName name = addErr $ TcRnTHError $ THNameError $ NonExactName name
    
    1562 1507
     
    
    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
    
    1508
    +putDoc :: TH.DocLoc -> String -> TcM ()
    
    1509
    +putDoc doc_loc s = do
    
    1604 1510
         th_doc_var <- tcg_th_docs <$> getGblEnv
    
    1605 1511
         resolved_doc_loc <- resolve_loc doc_loc
    
    1606 1512
         is_local <- checkLocalName resolved_doc_loc
    
    ... ... @@ -1622,15 +1528,129 @@ instance TH.Quasi TcM where
    1622 1528
           checkLocalName (InstDoc n) = nameIsLocalOrFrom <$> getModule <*> pure n
    
    1623 1529
           checkLocalName ModuleDoc = pure True
    
    1624 1530
     
    
    1625
    -
    
    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
    
    1531
    +getDoc :: TH.DocLoc -> TcM (Maybe String)
    
    1532
    +getDoc (TH.DeclDoc n) = lookupThName n >>= lookupDeclDoc
    
    1533
    +getDoc (TH.InstDoc t) = lookupThInstName t >>= lookupDeclDoc
    
    1534
    +getDoc (TH.ArgDoc n i) = lookupThName n >>= lookupArgDoc i
    
    1535
    +getDoc TH.ModuleDoc = do
    
    1630 1536
         df <- getDynFlags
    
    1631 1537
         docs <- getGblEnv >>= extractDocs df
    
    1632 1538
         return (renderHsDocString . hsDocString <$> (docs_mod_hdr =<< docs))
    
    1633 1539
     
    
    1540
    +getQ :: forall a. Typeable a => TcM (Maybe a)
    
    1541
    +getQ = do
    
    1542
    +    th_state_var <- fmap tcg_th_state getGblEnv
    
    1543
    +    th_state <- readTcRef th_state_var
    
    1544
    +    -- See #10596 for why we use a scoped type variable here.
    
    1545
    +    return (Map.lookup (typeRep (Proxy :: Proxy a)) th_state >>= fromDynamic)
    
    1546
    +
    
    1547
    +location :: TcM TH.Loc
    
    1548
    +location = do { m <- getModule
    
    1549
    +              ; l <- getSrcSpanM
    
    1550
    +              ; r <- case l of
    
    1551
    +                      UnhelpfulSpan _ -> pprPanic "qLocation: Unhelpful location"
    
    1552
    +                                                  (ppr l)
    
    1553
    +                      RealSrcSpan s _ -> return s
    
    1554
    +              ; return (TH.Loc { TH.loc_filename = unpackFS (srcSpanFile r)
    
    1555
    +                                , TH.loc_module   = moduleNameString (moduleName m)
    
    1556
    +                                , TH.loc_package  = unitString (moduleUnit m)
    
    1557
    +                                , TH.loc_start = (srcSpanStartLine r, srcSpanStartCol r)
    
    1558
    +                                , TH.loc_end = (srcSpanEndLine   r, srcSpanEndCol   r) }) }
    
    1559
    +
    
    1560
    +metaHandlersTcM :: TH.MetaHandlers TcM
    
    1561
    +metaHandlersTcM = TH.MetaHandlers {
    
    1562
    +    mNewName = \s -> do { u <- newUnique
    
    1563
    +                    ; let i = toInteger (getKey u)
    
    1564
    +                    ; return (TH.mkNameU s i) }
    
    1565
    +
    
    1566
    +    -- 'msg' is forced to ensure exceptions don't escape,
    
    1567
    +    -- see Note [Exceptions in TH]
    
    1568
    +    , mReport = report
    
    1569
    +
    
    1570
    +    , mLocation = location
    
    1571
    +
    
    1572
    +    , mLookupName       = lookupName
    
    1573
    +    , mReify            = reify
    
    1574
    +    , mReifyFixity      = \nm -> lookupThName nm >>= reifyFixity
    
    1575
    +    , mReifyType        = reifyTypeOfThing
    
    1576
    +    , mReifyInstances   = reifyInstances
    
    1577
    +    , mReifyRoles       = reifyRoles
    
    1578
    +    , mReifyAnnotations = reifyAnnotations
    
    1579
    +    , mReifyModule      = reifyModule
    
    1580
    +    , mReifyConStrictness = \nm -> do { nm' <- lookupThName nm
    
    1581
    +                                      ; dc  <- tcLookupDataCon nm'
    
    1582
    +                                      ; let bangs = dataConImplBangs dc
    
    1583
    +                                      ; return (map reifyDecidedStrictness bangs) }
    
    1584
    +
    
    1585
    +          -- For qRecover, discard error messages if
    
    1586
    +          -- the recovery action is chosen.  Otherwise
    
    1587
    +          -- we'll only fail higher up.
    
    1588
    +          -- NB: extremely subtle!!! TODO: write up note
    
    1589
    +          -- tryTcDiscardingErrs manipulates the reader env so we need to be careful we don't sneak in the outside env
    
    1590
    +    , mRecover = \recover main -> tryTcDiscardingErrs (runQuasi recover) (runQuasi main)
    
    1591
    +
    
    1592
    +    , mGetPackageRoot = do
    
    1593
    +        dflags <- getDynFlags
    
    1594
    +        return $ fromMaybe "." (workingDirectory dflags)
    
    1595
    +
    
    1596
    +    , mAddDependentFile = \fp -> do
    
    1597
    +        ref <- fmap tcg_dependent_files getGblEnv
    
    1598
    +        dep_files <- readTcRef ref
    
    1599
    +        writeTcRef ref (fp:dep_files)
    
    1600
    +
    
    1601
    +    , mAddDependentDirectory = \dp -> do
    
    1602
    +        ref <- fmap tcg_dependent_dirs getGblEnv
    
    1603
    +        dep_dirs <- readTcRef ref
    
    1604
    +        writeTcRef ref (dp:dep_dirs)
    
    1605
    +
    
    1606
    +    , mAddTempFile = \suffix -> do
    
    1607
    +        dflags <- getDynFlags
    
    1608
    +        logger <- getLogger
    
    1609
    +        tmpfs  <- hsc_tmpfs <$> getTopEnv
    
    1610
    +        liftIO $ newTempName logger tmpfs (tmpDir dflags) TFL_GhcSession suffix
    
    1611
    +
    
    1612
    +    , mAddTopDecls = addTopDecls
    
    1613
    +
    
    1614
    +    , mAddForeignFilePath = \lang fp -> do
    
    1615
    +        var <- fmap tcg_th_foreign_files getGblEnv
    
    1616
    +        updTcRef var ((lang, fp) :)
    
    1617
    +
    
    1618
    +    , mAddModFinalizer = \fin -> do
    
    1619
    +        r <- liftIO $ mkRemoteRef fin
    
    1620
    +        fref <- liftIO $ mkForeignRef r (freeRemoteRef r)
    
    1621
    +        addModFinalizerRef fref
    
    1622
    +
    
    1623
    +    , mAddCorePlugin = \plugin -> do
    
    1624
    +        hsc_env <- getTopEnv
    
    1625
    +        let fc        = hsc_FC hsc_env
    
    1626
    +        let home_unit = hsc_home_unit hsc_env
    
    1627
    +        let dflags    = hsc_dflags hsc_env
    
    1628
    +        let fopts     = initFinderOpts dflags
    
    1629
    +        r <- liftIO $ findHomeModule fc fopts home_unit (mkModuleName plugin)
    
    1630
    +        let err = TcRnTHError $ AddInvalidCorePlugin plugin
    
    1631
    +        case r of
    
    1632
    +          Found {} -> addErr err
    
    1633
    +          FoundMultiple {} -> addErr err
    
    1634
    +          _ -> return ()
    
    1635
    +        th_coreplugins_var <- tcg_th_coreplugins <$> getGblEnv
    
    1636
    +        updTcRef th_coreplugins_var (plugin:)
    
    1637
    +
    
    1638
    +    , mGetQ = getQ
    
    1639
    +
    
    1640
    +    , mPutQ = \x -> do
    
    1641
    +        th_state_var <- fmap tcg_th_state getGblEnv
    
    1642
    +        updTcRef th_state_var (\m -> Map.insert (typeOf x) (toDyn x) m)
    
    1643
    +
    
    1644
    +    , mIsExtEnabled = xoptM
    
    1645
    +
    
    1646
    +    , mExtsEnabled =
    
    1647
    +        EnumSet.toList . extensionFlags . hsc_dflags <$> getTopEnv
    
    1648
    +
    
    1649
    +    , mPutDoc = putDoc
    
    1650
    +
    
    1651
    +    , mGetDoc = getDoc
    
    1652
    +  }
    
    1653
    +
    
    1634 1654
     -- | Looks up documentation for a declaration in first the current module,
    
    1635 1655
     -- otherwise tries to find it in another module via 'hscGetModuleInterface'.
    
    1636 1656
     lookupDeclDoc :: Name -> TcM (Maybe String)
    
    ... ... @@ -1795,7 +1815,7 @@ runTH ty fhv = do
    1795 1815
           -- Remote GHCi, see Note [Remote Template Haskell] in
    
    1796 1816
           -- libraries/ghci/GHCi/TH.hs.
    
    1797 1817
           rstate <- getTHState inst
    
    1798
    -      loc <- TH.qLocation
    
    1818
    +      loc <- location
    
    1799 1819
           -- run a remote TH request
    
    1800 1820
           r <- liftIO $
    
    1801 1821
             withForeignRef rstate $ \state_hv ->
    
    ... ... @@ -1911,32 +1931,32 @@ wrapTHResult tcm = do
    1911 1931
     
    
    1912 1932
     handleTHMessage :: THMessage a -> TcM a
    
    1913 1933
     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
    
    1934
    +  NewName a -> wrapTHResult $ runQuasi $ TH.newName a
    
    1935
    +  Report b str -> wrapTHResult $ runQuasi $ TH.report b str
    
    1936
    +  LookupName b str -> wrapTHResult $ runQuasi $ TH.lookupName b str
    
    1937
    +  Reify n -> wrapTHResult $ runQuasi $ TH.reify n
    
    1938
    +  ReifyFixity n -> wrapTHResult $ runQuasi $ TH.reifyFixity n
    
    1939
    +  ReifyType n -> wrapTHResult $ runQuasi $ TH.reifyType n
    
    1940
    +  ReifyInstances n ts -> wrapTHResult $ runQuasi $ TH.reifyInstances n ts
    
    1941
    +  ReifyRoles n -> wrapTHResult $ runQuasi $ TH.reifyRoles n
    
    1922 1942
       ReifyAnnotations lookup tyrep ->
    
    1923 1943
         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
    
    1944
    +  ReifyModule m -> wrapTHResult $ runQuasi $ TH.reifyModule m
    
    1945
    +  ReifyConStrictness nm -> wrapTHResult $ runQuasi $ TH.reifyConStrictness nm
    
    1946
    +  GetPackageRoot -> wrapTHResult $ runQuasi $ TH.getPackageRoot
    
    1947
    +  AddDependentFile f -> wrapTHResult $ runQuasi $ TH.addDependentFile f
    
    1948
    +  AddDependentDirectory d -> wrapTHResult $ runQuasi $ TH.addDependentDirectory d
    
    1949
    +  AddTempFile s -> wrapTHResult $ runQuasi $ TH.addTempFile s
    
    1930 1950
       AddModFinalizer r -> do
    
    1931 1951
         interp <- hscInterp <$> getTopEnv
    
    1932 1952
         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
    
    1953
    +  AddCorePlugin str -> wrapTHResult $ runQuasi $ TH.addCorePlugin str
    
    1954
    +  AddTopDecls decs -> wrapTHResult $ runQuasi $ TH.addTopDecls decs
    
    1955
    +  AddForeignFilePath lang str -> wrapTHResult $ runQuasi $ TH.addForeignFilePath lang str
    
    1956
    +  IsExtEnabled ext -> wrapTHResult $ runQuasi $ TH.isExtEnabled ext
    
    1957
    +  ExtsEnabled -> wrapTHResult $ runQuasi $ TH.extsEnabled
    
    1958
    +  PutDoc l s -> wrapTHResult $ runQuasi $ TH.putDoc l s
    
    1959
    +  GetDoc l -> wrapTHResult $ runQuasi $ TH.getDoc l
    
    1940 1960
       FailIfErrs -> wrapTHResult failIfErrsM
    
    1941 1961
       _ -> panic ("handleTHMessage: unexpected message " ++ show msg)
    
    1942 1962
     
    

  • libraries/ghc-internal/src/GHC/Internal/TH/Monad.hs
    ... ... @@ -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 id metaHandlersIO
    
    152 154
       qNewName = newNameIO
    
    153 155
     
    
    154 156
       qReport True  msg = hPutStrLn stderr ("Template Haskell error: " ++ msg)
    
    ... ... @@ -180,9 +182,124 @@ instance Quasi IO where
    180 182
       qGetDoc _             = badIO "getDoc"
    
    181 183
       qAddDependentDirectory _ = badIO "AddDependentDirectory"
    
    182 184
     
    
    185
    +metaHandlersIO :: MetaHandlers IO
    
    186
    +metaHandlersIO  = MetaHandlers {
    
    187
    +   mNewName = newNameIO
    
    188
    +  , mReport = \b msg ->
    
    189
    +     if b then
    
    190
    +       hPutStrLn stderr ("Template Haskell error: " ++ msg)
    
    191
    +     else
    
    192
    +       hPutStrLn stderr ("Template Haskell error: " ++ msg) -- TODO: should this be different from above?
    
    193
    +  , mLookupName           = \ _ _ -> badIO "lookupName"
    
    194
    +  , mReify                = \_ -> badIO "reify"
    
    195
    +  , mReifyFixity          = \_ -> badIO "reifyFixity"
    
    196
    +  , mReifyType            = \_ -> badIO "reifyFixity"
    
    197
    +  , mReifyInstances       = \_ _ -> badIO "reifyInstances"
    
    198
    +  , mReifyRoles           = \_ -> badIO "reifyRoles"
    
    199
    +  , mReifyAnnotations     = \_ -> badIO "reifyAnnotations"
    
    200
    +  , mReifyModule          = \_ -> badIO "reifyModule"
    
    201
    +  , mReifyConStrictness   = \_ -> badIO "reifyConStrictness"
    
    202
    +  , mLocation             = badIO "currentLocation"
    
    203
    +  , mRecover              = \_ _ -> badIO "recover" -- Maybe we could fix this?
    
    204
    +  , mGetPackageRoot       = badIO "getProjectRoot"
    
    205
    +  , mAddDependentFile     = \_ -> badIO "addDependentFile"
    
    206
    +  , mAddTempFile          = \_ -> badIO "addTempFile"
    
    207
    +  , mAddTopDecls          = \_ -> badIO "addTopDecls"
    
    208
    +  , mAddForeignFilePath   = \_ _ -> badIO "addForeignFilePath"
    
    209
    +  , mAddModFinalizer      = \_ -> badIO "addModFinalizer"
    
    210
    +  , mAddCorePlugin        = \_ -> badIO "addCorePlugin"
    
    211
    +  , mGetQ                 = badIO "getQ"
    
    212
    +  , mPutQ                 = \_ -> badIO "putQ"
    
    213
    +  , mIsExtEnabled         = \_ -> badIO "isExtEnabled"
    
    214
    +  , mExtsEnabled          = badIO "extsEnabled"
    
    215
    +  , mPutDoc               = \_ _ -> badIO "putDoc"
    
    216
    +  , mGetDoc               = \_ -> badIO "getDoc"
    
    217
    +  , mAddDependentDirectory = \_ -> badIO "AddDependentDirectory"
    
    218
    +  }
    
    219
    +
    
    183 220
     instance Quote IO where
    
    184 221
       newName = newNameIO
    
    185 222
     
    
    223
    +data MetaHandlers m = MetaHandlers {
    
    224
    +    -- | Fresh names. See 'newName'.
    
    225
    +    mNewName :: String -> m Name
    
    226
    +
    
    227
    +    ------- Error reporting and recovery -------
    
    228
    +    -- | Report an error (True) or warning (False)
    
    229
    +    -- ...but carry on; use 'fail' to stop. See 'report'.
    
    230
    +    , mReport  :: Bool -> String -> m ()
    
    231
    +
    
    232
    +    -- | See 'recover'.
    
    233
    +    , mRecover :: forall a. Q a -- ^ the error handler
    
    234
    +            -> Q a -- ^ action which may fail
    
    235
    +            -> m a -- ^ Recover from the monadic 'fail'
    
    236
    +
    
    237
    +    ------- Inspect the type-checker's environment -------
    
    238
    +    -- | True <=> type namespace, False <=> value namespace. See 'lookupName'.
    
    239
    +    , mLookupName :: Bool -> String -> m (Maybe Name)
    
    240
    +    -- | See 'reify'.
    
    241
    +    , mReify          :: Name -> m Info
    
    242
    +    -- | See 'reifyFixity'.
    
    243
    +    , mReifyFixity    :: Name -> m (Maybe Fixity)
    
    244
    +    -- | See 'reifyType'.
    
    245
    +    , mReifyType      :: Name -> m Type
    
    246
    +    -- | Is (n tys) an instance? Returns list of matching instance Decs (with
    
    247
    +    -- empty sub-Decs) Works for classes and type functions. See 'reifyInstances'.
    
    248
    +    , mReifyInstances :: Name -> [Type] -> m [Dec]
    
    249
    +    -- | See 'reifyRoles'.
    
    250
    +    , mReifyRoles         :: Name -> m [Role]
    
    251
    +    -- | See 'reifyAnnotations'.
    
    252
    +    , mReifyAnnotations   :: forall a. Data a => AnnLookup -> m [a]
    
    253
    +    -- | See 'reifyModule'.
    
    254
    +    , mReifyModule        :: Module -> m ModuleInfo
    
    255
    +    -- | See 'reifyConStrictness'.
    
    256
    +    , mReifyConStrictness :: Name -> m [DecidedStrictness]
    
    257
    +
    
    258
    +    -- | See 'location'.
    
    259
    +    , mLocation :: m Loc
    
    260
    +
    
    261
    +    -- | See 'getPackageRoot'.
    
    262
    +    , mGetPackageRoot :: m FilePath
    
    263
    +
    
    264
    +    -- | See 'addDependentFile'.
    
    265
    +    , mAddDependentFile :: FilePath -> m ()
    
    266
    +
    
    267
    +    -- | See 'addDependentDirectory'.
    
    268
    +    , mAddDependentDirectory :: FilePath -> m ()
    
    269
    +
    
    270
    +    -- | See 'addTempFile'.
    
    271
    +    , mAddTempFile :: String -> m FilePath
    
    272
    +
    
    273
    +    -- | See 'addTopDecls'.
    
    274
    +    , mAddTopDecls :: [Dec] -> m ()
    
    275
    +
    
    276
    +    -- | See 'addForeignFilePath'.
    
    277
    +    , mAddForeignFilePath :: ForeignSrcLang -> String -> m ()
    
    278
    +
    
    279
    +    -- | See 'addModFinalizer'.
    
    280
    +    , mAddModFinalizer :: Q () -> m ()
    
    281
    +
    
    282
    +    -- | See 'addCorePlugin'.
    
    283
    +    , mAddCorePlugin :: String -> m ()
    
    284
    +
    
    285
    +    -- | See 'getQ'.
    
    286
    +    , mGetQ :: forall a. Typeable a => m (Maybe a)
    
    287
    +
    
    288
    +    -- | See 'putQ'.
    
    289
    +    , mPutQ :: forall a. Typeable a => a -> m ()
    
    290
    +
    
    291
    +    -- | See 'isExtEnabled'.
    
    292
    +    , mIsExtEnabled :: Extension -> m Bool
    
    293
    +    -- | See 'extsEnabled'.
    
    294
    +    , mExtsEnabled :: m [Extension]
    
    295
    +
    
    296
    +    -- | See 'putDoc'.
    
    297
    +    , mPutDoc :: DocLoc -> String -> m ()
    
    298
    +    -- | See 'getDoc'.
    
    299
    +    , mGetDoc :: DocLoc -> m (Maybe String)
    
    300
    +  }
    
    301
    +
    
    302
    +
    
    186 303
     newNameIO :: String -> IO Name
    
    187 304
     newNameIO s = do { n <- atomicModifyIORef' counter (\x -> (x + 1, x))
    
    188 305
                      ; pure (mkNameU s n) }
    
    ... ... @@ -213,7 +330,7 @@ counter = unsafePerformIO (newIORef 0)
    213 330
     -- inversion](https://en.wikipedia.org/wiki/Dependency_inversion_principle),
    
    214 331
     -- providing an abstract interface for the user which is later concretely
    
    215 332
     -- fufilled by an concrete 'Quasi' instance, internal to GHC.
    
    216
    -newtype Q a = Q { unQ :: forall m. Quasi m => m a }
    
    333
    +newtype Q a = Q { unQ :: forall m. (forall x. m x -> IO x) -> MetaHandlers m -> IO a }
    
    217 334
     
    
    218 335
     -- | \"Runs\" the 'Q' monad. Normal users of Template Haskell
    
    219 336
     -- should not need this function, as the splice brackets @$( ... )@
    
    ... ... @@ -227,22 +344,22 @@ newtype Q a = Q { unQ :: forall m. Quasi m => m a }
    227 344
     -- simply fail at runtime. Indeed, the only operations guaranteed to succeed
    
    228 345
     -- are 'newName', 'runIO', 'reportError' and 'reportWarning'.
    
    229 346
     runQ :: Quasi m => Q a -> m a
    
    230
    -runQ (Q m) = m
    
    347
    +runQ = qRunQ
    
    231 348
     
    
    232 349
     instance Monad Q where
    
    233
    -  Q m >>= k  = Q (m >>= \x -> unQ (k x))
    
    350
    +  Q m >>= k  = Q $ \r h -> (m r h >>= \x -> unQ (k x) r h)
    
    234 351
       (>>) = (*>)
    
    235 352
     
    
    236 353
     instance MonadFail Q where
    
    237
    -  fail s     = report True s >> Q (fail "Q monad failure")
    
    354
    +  fail s     = report True s >> Q (\_ _ -> fail "Q monad failure")
    
    238 355
     
    
    239 356
     instance Functor Q where
    
    240
    -  fmap f (Q x) = Q (fmap f x)
    
    357
    +  fmap f (Q x) = Q $ \r h -> fmap f (x r h)
    
    241 358
     
    
    242 359
     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)
    
    360
    +  pure x = Q $ \_ _ -> pure x
    
    361
    +  Q f <*> Q x = Q $ \r h -> (f r h <*> x r h)
    
    362
    +  Q m *> Q n = Q $ \r h -> (m r h *> n r h)
    
    246 363
     
    
    247 364
     -- | @since 2.17.0.0
    
    248 365
     instance Semigroup a => Semigroup (Q a) where
    
    ... ... @@ -311,8 +428,17 @@ class Monad m => Quote m where
    311 428
       -}
    
    312 429
       newName :: String -> m Name
    
    313 430
     
    
    431
    +runHandler :: (forall m. MetaHandlers m -> m a) -> Q a
    
    432
    +runHandler op = Q $ \r h -> r (op h)
    
    433
    +
    
    434
    +runHandler1 :: (forall m. MetaHandlers m -> a -> m b) -> a -> Q b
    
    435
    +runHandler1 op = \x -> Q $ \r h -> r (op h x)
    
    436
    +
    
    437
    +runHandler2 :: (forall m. MetaHandlers m -> a -> b -> m c) -> a -> b -> Q c
    
    438
    +runHandler2 op = \x y -> Q $ \r h -> r (op h x y)
    
    439
    +
    
    314 440
     instance Quote Q where
    
    315
    -  newName s = Q (qNewName s)
    
    441
    +  newName = runHandler1 mNewName
    
    316 442
     
    
    317 443
     -----------------------------------------------------
    
    318 444
     --
    
    ... ... @@ -510,7 +636,7 @@ joinCode = flip bindCode id
    510 636
     -- | Report an error (True) or warning (False),
    
    511 637
     -- but carry on; use 'fail' to stop.
    
    512 638
     report  :: Bool -> String -> Q ()
    
    513
    -report b s = Q (qReport b s)
    
    639
    +report b s = runHandler2 mReport b s
    
    514 640
     {-# DEPRECATED report "Use reportError or reportWarning instead" #-} -- deprecated in 7.6
    
    515 641
     
    
    516 642
     -- | Report an error to the user, but allow the current splice's computation to carry on. To abort the computation, use 'fail'.
    
    ... ... @@ -525,20 +651,20 @@ reportWarning = report False
    525 651
     recover :: Q a -- ^ handler to invoke on failure
    
    526 652
             -> Q a -- ^ computation to run
    
    527 653
             -> Q a
    
    528
    -recover (Q r) (Q m) = Q (qRecover r m)
    
    654
    +recover rec main = Q $ \r h -> r $ mRecover h rec main
    
    529 655
     
    
    530 656
     -- We don't export lookupName; the Bool isn't a great API
    
    531 657
     -- Instead we export lookupTypeName, lookupValueName
    
    532 658
     lookupName :: Bool -> String -> Q (Maybe Name)
    
    533
    -lookupName ns s = Q (qLookupName ns s)
    
    659
    +lookupName ns s = runHandler2 mLookupName ns s
    
    534 660
     
    
    535 661
     -- | 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 662
     lookupTypeName :: String -> Q (Maybe Name)
    
    537
    -lookupTypeName  s = Q (qLookupName True s)
    
    663
    +lookupTypeName  s = runHandler2 mLookupName True s
    
    538 664
     
    
    539 665
     -- | 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 666
     lookupValueName :: String -> Q (Maybe Name)
    
    541
    -lookupValueName s = Q (qLookupName False s)
    
    667
    +lookupValueName s = runHandler2 mLookupName False s
    
    542 668
     
    
    543 669
     {-
    
    544 670
     Note [Name lookup]
    
    ... ... @@ -613,7 +739,7 @@ To ensure we get information about @D@-the-value, use 'lookupValueName':
    613 739
     and to get information about @D@-the-type, use 'lookupTypeName'.
    
    614 740
     -}
    
    615 741
     reify :: Name -> Q Info
    
    616
    -reify v = Q (qReify v)
    
    742
    +reify v = runHandler1 mReify v
    
    617 743
     
    
    618 744
     {- | @reifyFixity nm@ attempts to find a fixity declaration for @nm@. For
    
    619 745
     example, if the function @foo@ has the fixity declaration @infixr 7 foo@, then
    
    ... ... @@ -622,7 +748,7 @@ example, if the function @foo@ has the fixity declaration @infixr 7 foo@, then
    622 748
     'Nothing', so you may assume @bar@ has 'defaultFixity'.
    
    623 749
     -}
    
    624 750
     reifyFixity :: Name -> Q (Maybe Fixity)
    
    625
    -reifyFixity nm = Q (qReifyFixity nm)
    
    751
    +reifyFixity nm = runHandler1 mReifyFixity nm
    
    626 752
     
    
    627 753
     {- | @reifyType nm@ attempts to find the type or kind of @nm@. For example,
    
    628 754
     @reifyType 'not@   returns @Bool -> Bool@, and
    
    ... ... @@ -630,7 +756,7 @@ reifyFixity nm = Q (qReifyFixity nm)
    630 756
     This works even if there's no explicit signature and the type or kind is inferred.
    
    631 757
     -}
    
    632 758
     reifyType :: Name -> Q Type
    
    633
    -reifyType nm = Q (qReifyType nm)
    
    759
    +reifyType nm = runHandler1 mReifyType nm
    
    634 760
     
    
    635 761
     {- | Template Haskell is capable of reifying information about types and
    
    636 762
     terms defined in previous declaration groups. Top-level declaration splices break up
    
    ... ... @@ -722,7 +848,7 @@ has some discussion around this.
    722 848
     
    
    723 849
     -}
    
    724 850
     reifyInstances :: Name -> [Type] -> Q [InstanceDec]
    
    725
    -reifyInstances cls tys = Q (qReifyInstances cls tys)
    
    851
    +reifyInstances cls tys = runHandler2 mReifyInstances cls tys
    
    726 852
     
    
    727 853
     {- | @reifyRoles nm@ returns the list of roles associated with the parameters
    
    728 854
     (both visible and invisible) of
    
    ... ... @@ -741,20 +867,20 @@ and @reifyRoles Proxy@, we will get @['NominalR', 'PhantomR']@. The 'NominalR' i
    741 867
     the role of the invisible @k@ parameter. Kind parameters are always nominal.
    
    742 868
     -}
    
    743 869
     reifyRoles :: Name -> Q [Role]
    
    744
    -reifyRoles nm = Q (qReifyRoles nm)
    
    870
    +reifyRoles nm = runHandler1 mReifyRoles nm
    
    745 871
     
    
    746 872
     -- | @reifyAnnotations target@ returns the list of annotations
    
    747 873
     -- associated with @target@.  Only the annotations that are
    
    748 874
     -- appropriately typed is returned.  So if you have @Int@ and @String@
    
    749 875
     -- annotations for the same target, you have to call this function twice.
    
    750 876
     reifyAnnotations :: Data a => AnnLookup -> Q [a]
    
    751
    -reifyAnnotations an = Q (qReifyAnnotations an)
    
    877
    +reifyAnnotations an = runHandler1 mReifyAnnotations an
    
    752 878
     
    
    753 879
     -- | @reifyModule mod@ looks up information about module @mod@.  To
    
    754 880
     -- look up the current module, call this function with the return
    
    755 881
     -- value of 'Language.Haskell.TH.Lib.thisModule'.
    
    756 882
     reifyModule :: Module -> Q ModuleInfo
    
    757
    -reifyModule m = Q (qReifyModule m)
    
    883
    +reifyModule m = runHandler1 mReifyModule m
    
    758 884
     
    
    759 885
     -- | @reifyConStrictness nm@ looks up the strictness information for the fields
    
    760 886
     -- of the constructor with the name @nm@. Note that the strictness information
    
    ... ... @@ -769,7 +895,7 @@ reifyModule m = Q (qReifyModule m)
    769 895
     -- circumstances, but it would return @['DecidedStrict', DecidedStrict]@ if the
    
    770 896
     -- @-XStrictData@ language extension was enabled.
    
    771 897
     reifyConStrictness :: Name -> Q [DecidedStrictness]
    
    772
    -reifyConStrictness n = Q (qReifyConStrictness n)
    
    898
    +reifyConStrictness n = runHandler1 mReifyConStrictness n
    
    773 899
     
    
    774 900
     -- | Is the list of instances returned by 'reifyInstances' nonempty?
    
    775 901
     --
    
    ... ... @@ -782,7 +908,7 @@ isInstance nm tys = do { decs <- reifyInstances nm tys
    782 908
     
    
    783 909
     -- | The location at which this computation is spliced.
    
    784 910
     location :: Q Loc
    
    785
    -location = Q qLocation
    
    911
    +location = runHandler mLocation
    
    786 912
     
    
    787 913
     -- |The 'runIO' function lets you run an I\/O computation in the 'Q' monad.
    
    788 914
     -- Take care: you are guaranteed the ordering of calls to 'runIO' within
    
    ... ... @@ -792,7 +918,7 @@ location = Q qLocation
    792 918
     -- necessarily flushed when the compiler finishes running, so you should
    
    793 919
     -- flush them yourself.
    
    794 920
     runIO :: IO a -> Q a
    
    795
    -runIO m = Q (qRunIO m)
    
    921
    +runIO m = Q $ \_ _ -> m
    
    796 922
     
    
    797 923
     -- | Get the package root for the current package which is being compiled.
    
    798 924
     -- This can be set explicitly with the -package-root flag but is normally
    
    ... ... @@ -804,7 +930,7 @@ runIO m = Q (qRunIO m)
    804 930
     -- change directory when compiling files but instead set the -package-root flag
    
    805 931
     -- appropriately.
    
    806 932
     getPackageRoot :: Q FilePath
    
    807
    -getPackageRoot = Q qGetPackageRoot
    
    933
    +getPackageRoot = runHandler mGetPackageRoot
    
    808 934
     
    
    809 935
     -- | Record external directories that runIO is using (dependent upon).
    
    810 936
     -- The compiler can then recognize that it should re-compile the Haskell file
    
    ... ... @@ -823,7 +949,7 @@ getPackageRoot = Q qGetPackageRoot
    823 949
     --   * The state of the directory is read at the interface generation time,
    
    824 950
     --     not at the time of the function call.
    
    825 951
     addDependentDirectory :: FilePath -> Q ()
    
    826
    -addDependentDirectory dp = Q (qAddDependentDirectory dp)
    
    952
    +addDependentDirectory dp = runHandler1 mAddDependentDirectory dp
    
    827 953
     
    
    828 954
     -- | Record external files that runIO is using (dependent upon).
    
    829 955
     -- The compiler can then recognize that it should re-compile the Haskell file
    
    ... ... @@ -837,17 +963,17 @@ addDependentDirectory dp = Q (qAddDependentDirectory dp)
    837 963
     --
    
    838 964
     --   * The dependency is based on file content, not a modification time
    
    839 965
     addDependentFile :: FilePath -> Q ()
    
    840
    -addDependentFile fp = Q (qAddDependentFile fp)
    
    966
    +addDependentFile fp = runHandler1 mAddDependentFile fp
    
    841 967
     
    
    842 968
     -- | Obtain a temporary file path with the given suffix. The compiler will
    
    843 969
     -- delete this file after compilation.
    
    844 970
     addTempFile :: String -> Q FilePath
    
    845
    -addTempFile suffix = Q (qAddTempFile suffix)
    
    971
    +addTempFile suffix = runHandler1 mAddTempFile suffix
    
    846 972
     
    
    847 973
     -- | Add additional top-level declarations. The added declarations will be type
    
    848 974
     -- checked along with the current declaration group.
    
    849 975
     addTopDecls :: [Dec] -> Q ()
    
    850
    -addTopDecls ds = Q (qAddTopDecls ds)
    
    976
    +addTopDecls ds = runHandler1 mAddTopDecls ds
    
    851 977
     
    
    852 978
     -- | Same as 'addForeignSource', but expects to receive a path pointing to the
    
    853 979
     -- foreign file instead of a 'String' of its contents. Consider using this in
    
    ... ... @@ -856,7 +982,7 @@ addTopDecls ds = Q (qAddTopDecls ds)
    856 982
     -- This is a good alternative to 'addForeignSource' when you are trying to
    
    857 983
     -- directly link in an object file.
    
    858 984
     addForeignFilePath :: ForeignSrcLang -> FilePath -> Q ()
    
    859
    -addForeignFilePath lang fp = Q (qAddForeignFilePath lang fp)
    
    985
    +addForeignFilePath lang fp = runHandler2 mAddForeignFilePath lang fp
    
    860 986
     
    
    861 987
     -- | Add a finalizer that will run in the Q monad after the current module has
    
    862 988
     -- been type checked. This only makes sense when run within a top-level splice.
    
    ... ... @@ -865,7 +991,7 @@ addForeignFilePath lang fp = Q (qAddForeignFilePath lang fp)
    865 991
     -- 'reify' is able to find the local definitions when executed inside the
    
    866 992
     -- finalizer.
    
    867 993
     addModFinalizer :: Q () -> Q ()
    
    868
    -addModFinalizer act = Q (qAddModFinalizer (unQ act))
    
    994
    +addModFinalizer act = runHandler1 mAddModFinalizer act
    
    869 995
     
    
    870 996
     -- | Adds a core plugin to the compilation pipeline.
    
    871 997
     --
    
    ... ... @@ -875,7 +1001,7 @@ addModFinalizer act = Q (qAddModFinalizer (unQ act))
    875 1001
     -- to tell the compiler that we needed to compile first a plugin module in the
    
    876 1002
     -- current package.
    
    877 1003
     addCorePlugin :: String -> Q ()
    
    878
    -addCorePlugin plugin = Q (qAddCorePlugin plugin)
    
    1004
    +addCorePlugin plugin = runHandler1 mAddCorePlugin plugin
    
    879 1005
     
    
    880 1006
     -- | Get state from the 'Q' monad. The state maintained by 'Q' is isomorphic to
    
    881 1007
     -- a type-indexed finite map. That is,
    
    ... ... @@ -889,20 +1015,20 @@ addCorePlugin plugin = Q (qAddCorePlugin plugin)
    889 1015
     -- Note that the state is local to the Haskell module in which the Template
    
    890 1016
     -- Haskell expression is executed.
    
    891 1017
     getQ :: Typeable a => Q (Maybe a)
    
    892
    -getQ = Q qGetQ
    
    1018
    +getQ = runHandler mGetQ
    
    893 1019
     
    
    894 1020
     -- | Replace the state in the 'Q' monad. Note that the state is local to the
    
    895 1021
     -- Haskell module in which the Template Haskell expression is executed.
    
    896 1022
     putQ :: Typeable a => a -> Q ()
    
    897
    -putQ x = Q (qPutQ x)
    
    1023
    +putQ x = runHandler1 mPutQ x
    
    898 1024
     
    
    899 1025
     -- | Determine whether the given language extension is enabled in the 'Q' monad.
    
    900 1026
     isExtEnabled :: Extension -> Q Bool
    
    901
    -isExtEnabled ext = Q (qIsExtEnabled ext)
    
    1027
    +isExtEnabled ext = runHandler1 mIsExtEnabled ext
    
    902 1028
     
    
    903 1029
     -- | List all enabled language extensions.
    
    904 1030
     extsEnabled :: Q [Extension]
    
    905
    -extsEnabled = Q qExtsEnabled
    
    1031
    +extsEnabled = runHandler mExtsEnabled
    
    906 1032
     
    
    907 1033
     -- | Add Haddock documentation to the specified location. This will overwrite
    
    908 1034
     -- any documentation at the location if it already exists. This will reify the
    
    ... ... @@ -921,19 +1047,20 @@ extsEnabled = Q qExtsEnabled
    921 1047
     -- Adding documentation to anything outside of the current module will cause an
    
    922 1048
     -- error.
    
    923 1049
     putDoc :: DocLoc -> String -> Q ()
    
    924
    -putDoc t s = Q (qPutDoc t s)
    
    1050
    +putDoc t s = runHandler2 mPutDoc t s
    
    925 1051
     
    
    926 1052
     -- | Retrieves the Haddock documentation at the specified location, if one
    
    927 1053
     -- exists.
    
    928 1054
     -- It can be used to read documentation on things defined outside of the current
    
    929 1055
     -- module, provided that those modules were compiled with the @-haddock@ flag.
    
    930 1056
     getDoc :: DocLoc -> Q (Maybe String)
    
    931
    -getDoc n = Q (qGetDoc n)
    
    1057
    +getDoc n = runHandler1 mGetDoc n
    
    932 1058
     
    
    933 1059
     instance MonadIO Q where
    
    934 1060
       liftIO = runIO
    
    935 1061
     
    
    936 1062
     instance Quasi Q where
    
    1063
    +  qRunQ               = id
    
    937 1064
       qNewName            = newName
    
    938 1065
       qReport             = report
    
    939 1066
       qRecover            = recover
    

  • libraries/ghci/GHCi/TH.hs
    ... ... @@ -163,56 +163,67 @@ ghcCmd m = GHCiQ $ \s -> do
    163 163
     instance MonadIO GHCiQ where
    
    164 164
       liftIO m = GHCiQ $ \s -> fmap (,s) m
    
    165 165
     
    
    166
    -instance TH.Quasi GHCiQ where
    
    167
    -  qNewName str = ghcCmd (NewName str)
    
    168
    -  qReport isError msg = ghcCmd (Report isError msg)
    
    169
    -
    
    170
    -  -- See Note [TH recover with -fexternal-interpreter] in GHC.Tc.Gen.Splice
    
    171
    -  qRecover (GHCiQ h) a = GHCiQ $ \s -> mask $ \unmask -> do
    
    172
    -    remoteTHCall (qsPipe s) StartRecover
    
    173
    -    e <- try $ unmask $ runGHCiQ (a <* ghcCmd FailIfErrs) s
    
    174
    -    remoteTHCall (qsPipe s) (EndRecover (isLeft e))
    
    175
    -    case e of
    
    176
    -      Left GHCiQException{} -> h s
    
    177
    -      Right r -> return r
    
    178
    -  qLookupName isType occ = ghcCmd (LookupName isType occ)
    
    179
    -  qReify name = ghcCmd (Reify name)
    
    180
    -  qReifyFixity name = ghcCmd (ReifyFixity name)
    
    181
    -  qReifyType name = ghcCmd (ReifyType name)
    
    182
    -  qReifyInstances name tys = ghcCmd (ReifyInstances name tys)
    
    183
    -  qReifyRoles name = ghcCmd (ReifyRoles name)
    
    184
    -
    
    185 166
       -- To reify annotations, we send GHC the AnnLookup and also the
    
    186 167
       -- TypeRep of the thing we're looking for, to avoid needing to
    
    187 168
       -- serialize irrelevant annotations.
    
    188
    -  qReifyAnnotations :: forall a . Data a => TH.AnnLookup -> GHCiQ [a]
    
    189
    -  qReifyAnnotations lookup =
    
    169
    +reifyAnnotations :: forall a . Data a => TH.AnnLookup -> GHCiQ [a]
    
    170
    +reifyAnnotations lookup =
    
    190 171
         map (deserializeWithData . B.unpack) <$>
    
    191 172
           ghcCmd (ReifyAnnotations lookup typerep)
    
    192 173
         where typerep = typeOf (undefined :: a)
    
    193 174
     
    
    194
    -  qReifyModule m = ghcCmd (ReifyModule m)
    
    195
    -  qReifyConStrictness name = ghcCmd (ReifyConStrictness name)
    
    196
    -  qLocation = fromMaybe noLoc . qsLocation <$> getState
    
    197
    -  qGetPackageRoot        = ghcCmd GetPackageRoot
    
    198
    -  qAddDependentFile file = ghcCmd (AddDependentFile file)
    
    199
    -  qAddDependentDirectory dir = ghcCmd (AddDependentDirectory dir)
    
    200
    -  qAddTempFile suffix = ghcCmd (AddTempFile suffix)
    
    201
    -  qAddTopDecls decls = ghcCmd (AddTopDecls decls)
    
    202
    -  qAddForeignFilePath lang fp = ghcCmd (AddForeignFilePath lang fp)
    
    203
    -  qAddModFinalizer fin = GHCiQ (\s -> mkRemoteRef fin >>= return . (, s)) >>=
    
    175
    +-- TODO: !!!
    
    176
    +-- This is wrong because it will discard any updates to the state.
    
    177
    +-- What I should do instead is refactor GHCiQ first (!) to use an IORef for state, and then save/restore that.
    
    178
    +runQinGHCiQ :: TH.Q a -> GHCiQ a
    
    179
    +runQinGHCiQ (TH.Q m) = GHCiQ $ \s -> (,s) <$> m (runInIO s) metaHandlersGHCiQ
    
    180
    +  where
    
    181
    +    runInIO :: QState -> GHCiQ a -> IO a
    
    182
    +    runInIO s (GHCiQ m) = fst <$> m s
    
    183
    +
    
    184
    +metaHandlersGHCiQ = TH.MetaHandlers {
    
    185
    +    mNewName = \str -> ghcCmd (NewName str)
    
    186
    +  , mReport = \isError msg -> ghcCmd (Report isError msg)
    
    187
    +
    
    188
    +  -- See Note [TH recover with -fexternal-interpreter] in GHC.Tc.Gen.Splice
    
    189
    +  , mRecover = \h a -> GHCiQ $ \s -> mask $ \unmask -> do
    
    190
    +      remoteTHCall (qsPipe s) StartRecover
    
    191
    +      e <- try $ unmask $ runGHCiQ (runQinGHCiQ a <* ghcCmd FailIfErrs) s -- TODO: simplify
    
    192
    +      remoteTHCall (qsPipe s) (EndRecover (isLeft e))
    
    193
    +      case e of
    
    194
    +        Left GHCiQException{} -> runGHCiQ (runQinGHCiQ h) s -- TODO: simplify
    
    195
    +        Right r -> return r
    
    196
    +  , mLookupName = \isType occ -> ghcCmd (LookupName isType occ)
    
    197
    +  , mReify = \name -> ghcCmd (Reify name)
    
    198
    +  , mReifyFixity = \name -> ghcCmd (ReifyFixity name)
    
    199
    +  , mReifyType = \name -> ghcCmd (ReifyType name)
    
    200
    +  , mReifyInstances = \name tys -> ghcCmd (ReifyInstances name tys)
    
    201
    +  , mReifyRoles = \name -> ghcCmd (ReifyRoles name)
    
    202
    +
    
    203
    +  , mReifyAnnotations = reifyAnnotations
    
    204
    +  , mReifyModule = \m -> ghcCmd (ReifyModule m)
    
    205
    +  , mReifyConStrictness = \name -> ghcCmd (ReifyConStrictness name)
    
    206
    +  , mLocation = fromMaybe noLoc . qsLocation <$> getState
    
    207
    +  , mGetPackageRoot = ghcCmd GetPackageRoot
    
    208
    +  , mAddDependentFile = \file -> ghcCmd (AddDependentFile file)
    
    209
    +  , mAddDependentDirectory = \dir -> ghcCmd (AddDependentDirectory dir)
    
    210
    +  , mAddTempFile = \suffix -> ghcCmd (AddTempFile suffix)
    
    211
    +  , mAddTopDecls = \decls -> ghcCmd (AddTopDecls decls)
    
    212
    +  , mAddForeignFilePath = \lang fp -> ghcCmd (AddForeignFilePath lang fp)
    
    213
    +  , mAddModFinalizer = \fin -> GHCiQ (\s -> mkRemoteRef fin >>= return . (, s)) >>=
    
    204 214
                              ghcCmd . AddModFinalizer
    
    205
    -  qAddCorePlugin str = ghcCmd (AddCorePlugin str)
    
    206
    -  qGetQ = GHCiQ $ \s ->
    
    215
    +  , mAddCorePlugin = \str -> ghcCmd (AddCorePlugin str)
    
    216
    +  , mGetQ = GHCiQ $ \s ->
    
    207 217
         let lookup :: forall a. Typeable a => Map TypeRep Dynamic -> Maybe a
    
    208 218
             lookup m = fromDynamic =<< M.lookup (typeOf (undefined::a)) m
    
    209 219
         in return (lookup (qsMap s), s)
    
    210
    -  qPutQ k = GHCiQ $ \s ->
    
    220
    +  , mPutQ = \k -> GHCiQ $ \s ->
    
    211 221
         return ((), s { qsMap = M.insert (typeOf k) (toDyn k) (qsMap s) })
    
    212
    -  qIsExtEnabled x = ghcCmd (IsExtEnabled x)
    
    213
    -  qExtsEnabled = ghcCmd ExtsEnabled
    
    214
    -  qPutDoc l s = ghcCmd (PutDoc l s)
    
    215
    -  qGetDoc l = ghcCmd (GetDoc l)
    
    222
    +  , mIsExtEnabled = \x -> ghcCmd (IsExtEnabled x)
    
    223
    +  , mExtsEnabled = ghcCmd ExtsEnabled
    
    224
    +  , mPutDoc = \l s -> ghcCmd (PutDoc l s)
    
    225
    +  , mGetDoc = \l -> ghcCmd (GetDoc l)
    
    226
    +}
    
    216 227
     
    
    217 228
     -- | The implementation of the 'StartTH' message: create
    
    218 229
     -- a new IORef QState, and return a RemoteRef to it.
    
    ... ... @@ -231,7 +242,7 @@ runModFinalizerRefs pipe rstate qrefs = do
    231 242
       qs <- mapM localRef qrefs
    
    232 243
       qstateref <- localRef rstate
    
    233 244
       qstate <- readIORef qstateref
    
    234
    -  _ <- runGHCiQ (TH.runQ $ sequence_ qs) qstate { qsPipe = pipe }
    
    245
    +  _ <- runGHCiQ (runQinGHCiQ $ sequence_ qs) qstate { qsPipe = pipe }
    
    235 246
       return ()
    
    236 247
     
    
    237 248
     -- | The implementation of the 'RunTH' message
    
    ... ... @@ -269,6 +280,6 @@ runTHQ pipe rstate mb_loc ghciq = do
    269 280
       qstateref <- localRef rstate
    
    270 281
       qstate <- readIORef qstateref
    
    271 282
       let st = qstate { qsLocation = mb_loc, qsPipe = pipe }
    
    272
    -  (r,new_state) <- runGHCiQ (TH.runQ ghciq) st
    
    283
    +  (r,new_state) <- runGHCiQ (runQinGHCiQ ghciq) st
    
    273 284
       writeIORef qstateref new_state
    
    274 285
       return $! LB.toStrict (runPut (put r))