Teo Camarasu pushed to branch wip/teo/move-out-bits-of-th-from-ghc-internal at Glasgow Haskell Compiler / GHC
Commits:
-
0d36a167
by Teo Camarasu at 2025-08-13T12:10:34+01:00
-
47533cb1
by Teo Camarasu at 2025-08-13T12:10:34+01:00
9 changed files:
- libraries/ghc-internal/src/GHC/Internal/TH/Lib.hs
- libraries/ghc-internal/src/GHC/Internal/TH/Lift.hs
- libraries/ghc-internal/src/GHC/Internal/TH/Syntax.hs
- libraries/template-haskell/Language/Haskell/TH/Lib.hs
- libraries/template-haskell/Language/Haskell/TH/Quote.hs
- libraries/template-haskell/Language/Haskell/TH/Syntax.hs
- testsuite/tests/interface-stability/template-haskell-exports.stdout
- testsuite/tests/quasiquotation/T4491/test.T
- testsuite/tests/th/Makefile
Changes:
| ... | ... | @@ -555,20 +555,6 @@ pragInlD name inline rm phases |
| 555 | 555 | pragOpaqueD :: Quote m => Name -> m Dec
|
| 556 | 556 | pragOpaqueD name = pure $ PragmaD $ OpaqueP name
|
| 557 | 557 | |
| 558 | -{-# DEPRECATED pragSpecD "Please use 'pragSpecED' instead. 'pragSpecD' will be removed in GHC 9.18." #-}
|
|
| 559 | -pragSpecD :: Quote m => Name -> m Type -> Phases -> m Dec
|
|
| 560 | -pragSpecD n ty phases
|
|
| 561 | - = do
|
|
| 562 | - ty1 <- ty
|
|
| 563 | - pure $ PragmaD $ SpecialiseP n ty1 Nothing phases
|
|
| 564 | - |
|
| 565 | -{-# DEPRECATED pragSpecInlD "Please use 'pragSpecInlED' instead. 'pragSpecInlD' will be removed in GHC 9.18." #-}
|
|
| 566 | -pragSpecInlD :: Quote m => Name -> m Type -> Inline -> Phases -> m Dec
|
|
| 567 | -pragSpecInlD n ty inline phases
|
|
| 568 | - = do
|
|
| 569 | - ty1 <- ty
|
|
| 570 | - pure $ PragmaD $ SpecialiseP n ty1 (Just inline) phases
|
|
| 571 | - |
|
| 572 | 558 | pragSpecED :: Quote m
|
| 573 | 559 | => Maybe [m (TyVarBndr ())] -> [m RuleBndr]
|
| 574 | 560 | -> m Exp
|
| ... | ... | @@ -868,22 +854,6 @@ implicitParamT n t |
| 868 | 854 | t' <- t
|
| 869 | 855 | pure $ ImplicitParamT n t'
|
| 870 | 856 | |
| 871 | -{-# DEPRECATED classP "As of template-haskell-2.10, constraint predicates (Pred) are just types (Type), in keeping with ConstraintKinds. Please use 'conT' and 'appT'." #-}
|
|
| 872 | -classP :: Quote m => Name -> [m Type] -> m Pred
|
|
| 873 | -classP cla tys
|
|
| 874 | - = do
|
|
| 875 | - tysl <- sequenceA tys
|
|
| 876 | - pure (foldl AppT (ConT cla) tysl)
|
|
| 877 | - |
|
| 878 | -{-# DEPRECATED equalP "As of template-haskell-2.10, constraint predicates (Pred) are just types (Type), in keeping with ConstraintKinds. Please see 'equalityT'." #-}
|
|
| 879 | -equalP :: Quote m => m Type -> m Type -> m Pred
|
|
| 880 | -equalP tleft tright
|
|
| 881 | - = do
|
|
| 882 | - tleft1 <- tleft
|
|
| 883 | - tright1 <- tright
|
|
| 884 | - eqT <- equalityT
|
|
| 885 | - pure (foldl AppT eqT [tleft1, tright1])
|
|
| 886 | - |
|
| 887 | 857 | promotedT :: Quote m => Name -> m Type
|
| 888 | 858 | promotedT = pure . PromotedT
|
| 889 | 859 | |
| ... | ... | @@ -906,20 +876,6 @@ noSourceStrictness = pure NoSourceStrictness |
| 906 | 876 | sourceLazy = pure SourceLazy
|
| 907 | 877 | sourceStrict = pure SourceStrict
|
| 908 | 878 | |
| 909 | -{-# DEPRECATED isStrict
|
|
| 910 | - ["Use 'bang'. See https://gitlab.haskell.org/ghc/ghc/wikis/migration/8.0. ",
|
|
| 911 | - "Example usage: 'bang noSourceUnpackedness sourceStrict'"] #-}
|
|
| 912 | -{-# DEPRECATED notStrict
|
|
| 913 | - ["Use 'bang'. See https://gitlab.haskell.org/ghc/ghc/wikis/migration/8.0. ",
|
|
| 914 | - "Example usage: 'bang noSourceUnpackedness noSourceStrictness'"] #-}
|
|
| 915 | -{-# DEPRECATED unpacked
|
|
| 916 | - ["Use 'bang'. See https://gitlab.haskell.org/ghc/ghc/wikis/migration/8.0. ",
|
|
| 917 | - "Example usage: 'bang sourceUnpack sourceStrict'"] #-}
|
|
| 918 | -isStrict, notStrict, unpacked :: Quote m => m Strict
|
|
| 919 | -isStrict = bang noSourceUnpackedness sourceStrict
|
|
| 920 | -notStrict = bang noSourceUnpackedness noSourceStrictness
|
|
| 921 | -unpacked = bang sourceUnpack sourceStrict
|
|
| 922 | - |
|
| 923 | 879 | bang :: Quote m => m SourceUnpackedness -> m SourceStrictness -> m Bang
|
| 924 | 880 | bang u s = do u' <- u
|
| 925 | 881 | s' <- s
|
| ... | ... | @@ -931,16 +887,6 @@ bangType = liftA2 (,) |
| 931 | 887 | varBangType :: Quote m => Name -> m BangType -> m VarBangType
|
| 932 | 888 | varBangType v bt = (\(b, t) -> (v, b, t)) <$> bt
|
| 933 | 889 | |
| 934 | -{-# DEPRECATED strictType
|
|
| 935 | - "As of @template-haskell-2.11.0.0@, 'StrictType' has been replaced by 'BangType'. Please use 'bangType' instead." #-}
|
|
| 936 | -strictType :: Quote m => m Strict -> m Type -> m StrictType
|
|
| 937 | -strictType = bangType
|
|
| 938 | - |
|
| 939 | -{-# DEPRECATED varStrictType
|
|
| 940 | - "As of @template-haskell-2.11.0.0@, 'VarStrictType' has been replaced by 'VarBangType'. Please use 'varBangType' instead." #-}
|
|
| 941 | -varStrictType :: Quote m => Name -> m StrictType -> m VarStrictType
|
|
| 942 | -varStrictType = varBangType
|
|
| 943 | - |
|
| 944 | 890 | -- * Type Literals
|
| 945 | 891 | |
| 946 | 892 | -- MonadFail here complicates things (a lot) because it would mean we would
|
| ... | ... | @@ -24,40 +24,22 @@ |
| 24 | 24 | |
| 25 | 25 | module GHC.Internal.TH.Lift
|
| 26 | 26 | ( Lift(..)
|
| 27 | - -- * Generic Lift implementations
|
|
| 28 | - , dataToQa
|
|
| 29 | - , dataToCodeQ
|
|
| 30 | - , dataToExpQ
|
|
| 31 | - , liftDataTyped
|
|
| 32 | - , liftData
|
|
| 33 | - , dataToPatQ
|
|
| 34 | 27 | -- * Wired-in names
|
| 35 | 28 | , liftString
|
| 36 | - , trueName
|
|
| 37 | - , falseName
|
|
| 38 | - , nothingName
|
|
| 39 | - , justName
|
|
| 40 | - , leftName
|
|
| 41 | - , rightName
|
|
| 42 | - , nonemptyName
|
|
| 43 | 29 | )
|
| 44 | 30 | where
|
| 45 | 31 | |
| 46 | 32 | import GHC.Internal.TH.Syntax
|
| 47 | 33 | import qualified GHC.Internal.TH.Lib as Lib (litE) -- See wrinkle (W4) of Note [Tracking dependencies on primitives]
|
| 48 | -import GHC.Internal.Lexeme ( startsVarSym, startsVarId )
|
|
| 49 | 34 | |
| 50 | 35 | import GHC.Internal.Data.Either
|
| 51 | -import GHC.Internal.Type.Reflection
|
|
| 52 | 36 | import GHC.Internal.Data.Bool
|
| 53 | 37 | import GHC.Internal.Base hiding (NonEmpty(..), Type, Module, inline)
|
| 54 | -import GHC.Internal.Data.Foldable
|
|
| 55 | 38 | import GHC.Internal.Data.NonEmpty (NonEmpty(..))
|
| 56 | 39 | import GHC.Internal.Integer
|
| 57 | 40 | import GHC.Internal.Real
|
| 58 | 41 | import GHC.Internal.Word
|
| 59 | 42 | import GHC.Internal.Int
|
| 60 | -import GHC.Internal.Data.Data hiding (Fixity)
|
|
| 61 | 43 | import GHC.Internal.Natural
|
| 62 | 44 | import GHC.Internal.ForeignPtr
|
| 63 | 45 | |
| ... | ... | @@ -294,20 +276,6 @@ deriving instance (Lift a, Lift b, Lift c, Lift d, Lift e, Lift f) |
| 294 | 276 | deriving instance (Lift a, Lift b, Lift c, Lift d, Lift e, Lift f, Lift g)
|
| 295 | 277 | => Lift (# a | b | c | d | e | f | g #)
|
| 296 | 278 | |
| 297 | -trueName, falseName :: Name
|
|
| 298 | -trueName = 'True
|
|
| 299 | -falseName = 'False
|
|
| 300 | - |
|
| 301 | -nothingName, justName :: Name
|
|
| 302 | -nothingName = 'Nothing
|
|
| 303 | -justName = 'Just
|
|
| 304 | - |
|
| 305 | -leftName, rightName :: Name
|
|
| 306 | -leftName = 'Left
|
|
| 307 | -rightName = 'Right
|
|
| 308 | - |
|
| 309 | -nonemptyName :: Name
|
|
| 310 | -nonemptyName = '(:|)
|
|
| 311 | 279 | |
| 312 | 280 | -----------------------------------------------------
|
| 313 | 281 | --
|
| ... | ... | @@ -443,157 +411,3 @@ deriving instance Lift Info |
| 443 | 411 | deriving instance Lift AnnLookup
|
| 444 | 412 | -- | @since template-haskell-2.22.1.0
|
| 445 | 413 | deriving instance Lift Extension |
| 446 | - |
|
| 447 | ------------------------------------------------------
|
|
| 448 | ---
|
|
| 449 | --- Generic Lift implementations
|
|
| 450 | ---
|
|
| 451 | ------------------------------------------------------
|
|
| 452 | - |
|
| 453 | --- | 'dataToQa' is an internal utility function for constructing generic
|
|
| 454 | --- conversion functions from types with 'Data' instances to various
|
|
| 455 | --- quasi-quoting representations. See the source of 'dataToExpQ' and
|
|
| 456 | --- 'dataToPatQ' for two example usages: @mkCon@, @mkLit@
|
|
| 457 | --- and @appQ@ are overloadable to account for different syntax for
|
|
| 458 | --- expressions and patterns; @antiQ@ allows you to override type-specific
|
|
| 459 | --- cases, a common usage is just @const Nothing@, which results in
|
|
| 460 | --- no overloading.
|
|
| 461 | -dataToQa :: forall m a k q. (Quote m, Data a)
|
|
| 462 | - => (Name -> k)
|
|
| 463 | - -> (Lit -> m q)
|
|
| 464 | - -> (k -> [m q] -> m q)
|
|
| 465 | - -> (forall b . Data b => b -> Maybe (m q))
|
|
| 466 | - -> a
|
|
| 467 | - -> m q
|
|
| 468 | -dataToQa mkCon mkLit appCon antiQ t =
|
|
| 469 | - case antiQ t of
|
|
| 470 | - Nothing ->
|
|
| 471 | - case constrRep constr of
|
|
| 472 | - AlgConstr _ ->
|
|
| 473 | - appCon (mkCon funOrConName) conArgs
|
|
| 474 | - where
|
|
| 475 | - funOrConName :: Name
|
|
| 476 | - funOrConName =
|
|
| 477 | - case showConstr constr of
|
|
| 478 | - "(:)" -> Name (mkOccName ":")
|
|
| 479 | - (NameG DataName
|
|
| 480 | - (mkPkgName "ghc-internal")
|
|
| 481 | - (mkModName "GHC.Internal.Types"))
|
|
| 482 | - con@"[]" -> Name (mkOccName con)
|
|
| 483 | - (NameG DataName
|
|
| 484 | - (mkPkgName "ghc-internal")
|
|
| 485 | - (mkModName "GHC.Internal.Types"))
|
|
| 486 | - con@('(':_) -> Name (mkOccName con)
|
|
| 487 | - (NameG DataName
|
|
| 488 | - (mkPkgName "ghc-internal")
|
|
| 489 | - (mkModName "GHC.Internal.Tuple"))
|
|
| 490 | - |
|
| 491 | - -- Tricky case: see Note [Data for non-algebraic types]
|
|
| 492 | - fun@(x:_) | startsVarSym x || startsVarId x
|
|
| 493 | - -> mkNameG_v tyconPkg tyconMod fun
|
|
| 494 | - con -> mkNameG_d tyconPkg tyconMod con
|
|
| 495 | - |
|
| 496 | - where
|
|
| 497 | - tycon :: TyCon
|
|
| 498 | - tycon = (typeRepTyCon . typeOf) t
|
|
| 499 | - |
|
| 500 | - tyconPkg, tyconMod :: String
|
|
| 501 | - tyconPkg = tyConPackage tycon
|
|
| 502 | - tyconMod = tyConModule tycon
|
|
| 503 | - |
|
| 504 | - conArgs :: [m q]
|
|
| 505 | - conArgs = gmapQ (dataToQa mkCon mkLit appCon antiQ) t
|
|
| 506 | - IntConstr n ->
|
|
| 507 | - mkLit $ IntegerL n
|
|
| 508 | - FloatConstr n ->
|
|
| 509 | - mkLit $ RationalL n
|
|
| 510 | - CharConstr c ->
|
|
| 511 | - mkLit $ CharL c
|
|
| 512 | - where
|
|
| 513 | - constr :: Constr
|
|
| 514 | - constr = toConstr t
|
|
| 515 | - |
|
| 516 | - Just y -> y
|
|
| 517 | - |
|
| 518 | - |
|
| 519 | -{- Note [Data for non-algebraic types]
|
|
| 520 | -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 521 | -Class Data was originally intended for algebraic data types. But
|
|
| 522 | -it is possible to use it for abstract types too. For example, in
|
|
| 523 | -package `text` we find
|
|
| 524 | - |
|
| 525 | - instance Data Text where
|
|
| 526 | - ...
|
|
| 527 | - toConstr _ = packConstr
|
|
| 528 | - |
|
| 529 | - packConstr :: Constr
|
|
| 530 | - packConstr = mkConstr textDataType "pack" [] Prefix
|
|
| 531 | - |
|
| 532 | -Here `packConstr` isn't a real data constructor, it's an ordinary
|
|
| 533 | -function. Two complications
|
|
| 534 | - |
|
| 535 | -* In such a case, we must take care to build the Name using
|
|
| 536 | - mkNameG_v (for values), not mkNameG_d (for data constructors).
|
|
| 537 | - See #10796.
|
|
| 538 | - |
|
| 539 | -* The pseudo-constructor is named only by its string, here "pack".
|
|
| 540 | - But 'dataToQa' needs the TyCon of its defining module, and has
|
|
| 541 | - to assume it's defined in the same module as the TyCon itself.
|
|
| 542 | - But nothing enforces that; #12596 shows what goes wrong if
|
|
| 543 | - "pack" is defined in a different module than the data type "Text".
|
|
| 544 | - -}
|
|
| 545 | - |
|
| 546 | --- | A typed variant of 'dataToExpQ'.
|
|
| 547 | -dataToCodeQ :: (Quote m, Data a)
|
|
| 548 | - => (forall b . Data b => b -> Maybe (Code m b))
|
|
| 549 | - -> a -> Code m a
|
|
| 550 | -dataToCodeQ f = unsafeCodeCoerce . dataToExpQ (fmap unTypeCode . f)
|
|
| 551 | - |
|
| 552 | --- | 'dataToExpQ' converts a value to a 'Exp' representation of the
|
|
| 553 | --- same value, in the SYB style. It is generalized to take a function
|
|
| 554 | --- override type-specific cases; see 'liftData' for a more commonly
|
|
| 555 | --- used variant.
|
|
| 556 | -dataToExpQ :: (Quote m, Data a)
|
|
| 557 | - => (forall b . Data b => b -> Maybe (m Exp))
|
|
| 558 | - -> a
|
|
| 559 | - -> m Exp
|
|
| 560 | -dataToExpQ = dataToQa varOrConE litE (foldl appE)
|
|
| 561 | - where
|
|
| 562 | - -- Make sure that VarE is used if the Constr value relies on a
|
|
| 563 | - -- function underneath the surface (instead of a constructor).
|
|
| 564 | - -- See #10796.
|
|
| 565 | - varOrConE s =
|
|
| 566 | - case nameSpace s of
|
|
| 567 | - Just VarName -> return (VarE s)
|
|
| 568 | - Just (FldName {}) -> return (VarE s)
|
|
| 569 | - Just DataName -> return (ConE s)
|
|
| 570 | - _ -> error $ "Can't construct an expression from name "
|
|
| 571 | - ++ showName s
|
|
| 572 | - appE x y = do { a <- x; b <- y; return (AppE a b)}
|
|
| 573 | - litE c = return (LitE c)
|
|
| 574 | - |
|
| 575 | --- | A typed variant of 'liftData'.
|
|
| 576 | -liftDataTyped :: (Quote m, Data a) => a -> Code m a
|
|
| 577 | -liftDataTyped = dataToCodeQ (const Nothing)
|
|
| 578 | - |
|
| 579 | --- | 'liftData' is a variant of 'lift' in the 'Lift' type class which
|
|
| 580 | --- works for any type with a 'Data' instance.
|
|
| 581 | -liftData :: (Quote m, Data a) => a -> m Exp
|
|
| 582 | -liftData = dataToExpQ (const Nothing)
|
|
| 583 | - |
|
| 584 | --- | 'dataToPatQ' converts a value to a 'Pat' representation of the same
|
|
| 585 | --- value, in the SYB style. It takes a function to handle type-specific cases,
|
|
| 586 | --- alternatively, pass @const Nothing@ to get default behavior.
|
|
| 587 | -dataToPatQ :: (Quote m, Data a)
|
|
| 588 | - => (forall b . Data b => b -> Maybe (m Pat))
|
|
| 589 | - -> a
|
|
| 590 | - -> m Pat
|
|
| 591 | -dataToPatQ = dataToQa id litP conP
|
|
| 592 | - where litP l = return (LitP l)
|
|
| 593 | - conP n ps =
|
|
| 594 | - case nameSpace n of
|
|
| 595 | - Just DataName -> do
|
|
| 596 | - ps' <- sequence ps
|
|
| 597 | - return (ConP n [] ps')
|
|
| 598 | - _ -> error $ "Can't construct a pattern from name "
|
|
| 599 | - ++ showName n |
| ... | ... | @@ -22,9 +22,6 @@ module GHC.Internal.TH.Syntax |
| 22 | 22 | -- * Language extensions
|
| 23 | 23 | , module GHC.Internal.LanguageExtensions
|
| 24 | 24 | , ForeignSrcLang(..)
|
| 25 | - -- * Notes
|
|
| 26 | - -- ** Unresolved Infix
|
|
| 27 | - -- $infix
|
|
| 28 | 25 | ) where
|
| 29 | 26 | |
| 30 | 27 | #ifdef BOOTSTRAP_TH
|
| ... | ... | @@ -847,12 +844,6 @@ addTempFile suffix = Q (qAddTempFile suffix) |
| 847 | 844 | addTopDecls :: [Dec] -> Q ()
|
| 848 | 845 | addTopDecls ds = Q (qAddTopDecls ds)
|
| 849 | 846 | |
| 850 | --- |
|
|
| 851 | -addForeignFile :: ForeignSrcLang -> String -> Q ()
|
|
| 852 | -addForeignFile = addForeignSource
|
|
| 853 | -{-# DEPRECATED addForeignFile
|
|
| 854 | - "Use 'Language.Haskell.TH.Syntax.addForeignSource' instead"
|
|
| 855 | - #-} -- deprecated in 8.6
|
|
| 856 | 847 | |
| 857 | 848 | -- | Emit a foreign file which will be compiled and linked to the object for
|
| 858 | 849 | -- the current module. Currently only languages that can be compiled with
|
| ... | ... | @@ -1614,73 +1605,6 @@ maxPrecedence = (9::Int) |
| 1614 | 1605 | defaultFixity :: Fixity
|
| 1615 | 1606 | defaultFixity = Fixity maxPrecedence InfixL
|
| 1616 | 1607 | |
| 1617 | - |
|
| 1618 | -{-
|
|
| 1619 | -Note [Unresolved infix]
|
|
| 1620 | -~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 1621 | --}
|
|
| 1622 | -{- $infix #infix#
|
|
| 1623 | - |
|
| 1624 | -When implementing antiquotation for quasiquoters, one often wants
|
|
| 1625 | -to parse strings into expressions:
|
|
| 1626 | - |
|
| 1627 | -> parse :: String -> Maybe Exp
|
|
| 1628 | - |
|
| 1629 | -But how should we parse @a + b * c@? If we don't know the fixities of
|
|
| 1630 | -@+@ and @*@, we don't know whether to parse it as @a + (b * c)@ or @(a
|
|
| 1631 | -+ b) * c@.
|
|
| 1632 | - |
|
| 1633 | -In cases like this, use 'UInfixE', 'UInfixP', 'UInfixT', or 'PromotedUInfixT',
|
|
| 1634 | -which stand for \"unresolved infix expression / pattern / type / promoted
|
|
| 1635 | -constructor\", respectively. When the compiler is given a splice containing a
|
|
| 1636 | -tree of @UInfixE@ applications such as
|
|
| 1637 | - |
|
| 1638 | -> UInfixE
|
|
| 1639 | -> (UInfixE e1 op1 e2)
|
|
| 1640 | -> op2
|
|
| 1641 | -> (UInfixE e3 op3 e4)
|
|
| 1642 | - |
|
| 1643 | -it will look up and the fixities of the relevant operators and
|
|
| 1644 | -reassociate the tree as necessary.
|
|
| 1645 | - |
|
| 1646 | - * trees will not be reassociated across 'ParensE', 'ParensP', or 'ParensT',
|
|
| 1647 | - which are of use for parsing expressions like
|
|
| 1648 | - |
|
| 1649 | - > (a + b * c) + d * e
|
|
| 1650 | - |
|
| 1651 | - * 'InfixE', 'InfixP', 'InfixT', and 'PromotedInfixT' expressions are never
|
|
| 1652 | - reassociated.
|
|
| 1653 | - |
|
| 1654 | - * The 'UInfixE' constructor doesn't support sections. Sections
|
|
| 1655 | - such as @(a *)@ have no ambiguity, so 'InfixE' suffices. For longer
|
|
| 1656 | - sections such as @(a + b * c -)@, use an 'InfixE' constructor for the
|
|
| 1657 | - outer-most section, and use 'UInfixE' constructors for all
|
|
| 1658 | - other operators:
|
|
| 1659 | - |
|
| 1660 | - > InfixE
|
|
| 1661 | - > Just (UInfixE ...a + b * c...)
|
|
| 1662 | - > op
|
|
| 1663 | - > Nothing
|
|
| 1664 | - |
|
| 1665 | - Sections such as @(a + b +)@ and @((a + b) +)@ should be rendered
|
|
| 1666 | - into 'Exp's differently:
|
|
| 1667 | - |
|
| 1668 | - > (+ a + b) ---> InfixE Nothing + (Just $ UInfixE a + b)
|
|
| 1669 | - > -- will result in a fixity error if (+) is left-infix
|
|
| 1670 | - > (+ (a + b)) ---> InfixE Nothing + (Just $ ParensE $ UInfixE a + b)
|
|
| 1671 | - > -- no fixity errors
|
|
| 1672 | - |
|
| 1673 | - * Quoted expressions such as
|
|
| 1674 | - |
|
| 1675 | - > [| a * b + c |] :: Q Exp
|
|
| 1676 | - > [p| a : b : c |] :: Q Pat
|
|
| 1677 | - > [t| T + T |] :: Q Type
|
|
| 1678 | - |
|
| 1679 | - will never contain 'UInfixE', 'UInfixP', 'UInfixT', 'PromotedUInfixT',
|
|
| 1680 | - 'InfixT', 'PromotedInfixT, 'ParensE', 'ParensP', or 'ParensT' constructors.
|
|
| 1681 | - |
|
| 1682 | --}
|
|
| 1683 | - |
|
| 1684 | 1608 | -----------------------------------------------------
|
| 1685 | 1609 | --
|
| 1686 | 1610 | -- The main syntax data types
|
| ... | ... | @@ -395,3 +395,66 @@ mdoE = Internal.mdoE Nothing |
| 395 | 395 | |
| 396 | 396 | conP :: Quote m => Name -> [m Pat] -> m Pat
|
| 397 | 397 | conP n xs = Internal.conP n [] xs
|
| 398 | + |
|
| 399 | + |
|
| 400 | +--------------------------------------------------------------------------------
|
|
| 401 | +-- * Constraint predicates (deprecated)
|
|
| 402 | + |
|
| 403 | +{-# DEPRECATED classP "As of template-haskell-2.10, constraint predicates (Pred) are just types (Type), in keeping with ConstraintKinds. Please use 'conT' and 'appT'." #-}
|
|
| 404 | +classP :: Quote m => Name -> [m Type] -> m Pred
|
|
| 405 | +classP cla tys
|
|
| 406 | + = do
|
|
| 407 | + tysl <- sequenceA tys
|
|
| 408 | + pure (foldl AppT (ConT cla) tysl)
|
|
| 409 | + |
|
| 410 | +{-# DEPRECATED equalP "As of template-haskell-2.10, constraint predicates (Pred) are just types (Type), in keeping with ConstraintKinds. Please see 'equalityT'." #-}
|
|
| 411 | +equalP :: Quote m => m Type -> m Type -> m Pred
|
|
| 412 | +equalP tleft tright
|
|
| 413 | + = do
|
|
| 414 | + tleft1 <- tleft
|
|
| 415 | + tright1 <- tright
|
|
| 416 | + eqT <- equalityT
|
|
| 417 | + pure (foldl AppT eqT [tleft1, tright1])
|
|
| 418 | + |
|
| 419 | +--------------------------------------------------------------------------------
|
|
| 420 | +-- * Strictness queries (deprecated)
|
|
| 421 | +{-# DEPRECATED isStrict
|
|
| 422 | + ["Use 'bang'. See https://gitlab.haskell.org/ghc/ghc/wikis/migration/8.0. ",
|
|
| 423 | + "Example usage: 'bang noSourceUnpackedness sourceStrict'"] #-}
|
|
| 424 | +{-# DEPRECATED notStrict
|
|
| 425 | + ["Use 'bang'. See https://gitlab.haskell.org/ghc/ghc/wikis/migration/8.0. ",
|
|
| 426 | + "Example usage: 'bang noSourceUnpackedness noSourceStrictness'"] #-}
|
|
| 427 | +{-# DEPRECATED unpacked
|
|
| 428 | + ["Use 'bang'. See https://gitlab.haskell.org/ghc/ghc/wikis/migration/8.0. ",
|
|
| 429 | + "Example usage: 'bang sourceUnpack sourceStrict'"] #-}
|
|
| 430 | +isStrict, notStrict, unpacked :: Quote m => m Strict
|
|
| 431 | +isStrict = bang noSourceUnpackedness sourceStrict
|
|
| 432 | +notStrict = bang noSourceUnpackedness noSourceStrictness
|
|
| 433 | +unpacked = bang sourceUnpack sourceStrict
|
|
| 434 | + |
|
| 435 | +{-# DEPRECATED strictType
|
|
| 436 | + "As of @template-haskell-2.11.0.0@, 'StrictType' has been replaced by 'BangType'. Please use 'bangType' instead." #-}
|
|
| 437 | +strictType :: Quote m => m Strict -> m Type -> m StrictType
|
|
| 438 | +strictType = bangType
|
|
| 439 | + |
|
| 440 | +{-# DEPRECATED varStrictType
|
|
| 441 | + "As of @template-haskell-2.11.0.0@, 'VarStrictType' has been replaced by 'VarBangType'. Please use 'varBangType' instead." #-}
|
|
| 442 | +varStrictType :: Quote m => Name -> m StrictType -> m VarStrictType
|
|
| 443 | +varStrictType = varBangType
|
|
| 444 | + |
|
| 445 | +--------------------------------------------------------------------------------
|
|
| 446 | +-- * Specialisation pragmas (deprecated)
|
|
| 447 | + |
|
| 448 | +{-# DEPRECATED pragSpecD "Please use 'pragSpecED' instead. 'pragSpecD' will be removed in GHC 9.18." #-}
|
|
| 449 | +pragSpecD :: Quote m => Name -> m Type -> Phases -> m Dec
|
|
| 450 | +pragSpecD n ty phases
|
|
| 451 | + = do
|
|
| 452 | + ty1 <- ty
|
|
| 453 | + pure $ PragmaD $ SpecialiseP n ty1 Nothing phases
|
|
| 454 | + |
|
| 455 | +{-# DEPRECATED pragSpecInlD "Please use 'pragSpecInlED' instead. 'pragSpecInlD' will be removed in GHC 9.18." #-}
|
|
| 456 | +pragSpecInlD :: Quote m => Name -> m Type -> Inline -> Phases -> m Dec
|
|
| 457 | +pragSpecInlD n ty inline phases
|
|
| 458 | + = do
|
|
| 459 | + ty1 <- ty
|
|
| 460 | + pure $ PragmaD $ SpecialiseP n ty1 (Just inline) phases |
| ... | ... | @@ -19,12 +19,12 @@ module Language.Haskell.TH.Quote |
| 19 | 19 | , namedDefaultQuasiQuoter
|
| 20 | 20 | , defaultQuasiQuoter
|
| 21 | 21 | -- * For backwards compatibility
|
| 22 | - ,dataToQa, dataToExpQ, dataToPatQ
|
|
| 22 | + , dataToQa, dataToExpQ, dataToPatQ
|
|
| 23 | 23 | ) where
|
| 24 | 24 | |
| 25 | 25 | import GHC.Boot.TH.Syntax
|
| 26 | 26 | import GHC.Boot.TH.Quote
|
| 27 | -import GHC.Boot.TH.Lift
|
|
| 27 | +import Language.Haskell.TH.Syntax (dataToQa, dataToExpQ, dataToPatQ)
|
|
| 28 | 28 | |
| 29 | 29 | |
| 30 | 30 | -- | 'quoteFile' takes a 'QuasiQuoter' and lifts it into one that read
|
| 1 | 1 | {-# LANGUAGE MagicHash #-}
|
| 2 | +{-# LANGUAGE RankNTypes #-}
|
|
| 3 | +{-# LANGUAGE ScopedTypeVariables #-}
|
|
| 2 | 4 | {-# LANGUAGE TemplateHaskellQuotes #-}
|
| 3 | -{-# LANGUAGE Safe #-}
|
|
| 5 | +{-# LANGUAGE Trustworthy #-}
|
|
| 4 | 6 | {-# LANGUAGE UnboxedTuples #-}
|
| 5 | 7 | |
| 6 | 8 | module Language.Haskell.TH.Syntax (
|
| ... | ... | @@ -190,19 +192,267 @@ module Language.Haskell.TH.Syntax ( |
| 190 | 192 | nothingName,
|
| 191 | 193 | rightName,
|
| 192 | 194 | trueName,
|
| 195 | + -- * Notes
|
|
| 196 | + -- ** Unresolved Infix
|
|
| 197 | + -- $infix
|
|
| 193 | 198 | )
|
| 194 | 199 | where
|
| 195 | 200 | |
| 196 | 201 | import GHC.Boot.TH.Lift
|
| 197 | 202 | import GHC.Boot.TH.Syntax
|
| 198 | 203 | import System.FilePath
|
| 204 | +import Data.Data hiding (Fixity(..))
|
|
| 205 | +import Data.List.NonEmpty (NonEmpty(..))
|
|
| 206 | +import GHC.Lexeme ( startsVarSym, startsVarId )
|
|
| 199 | 207 | |
| 200 | 208 | -- This module completely re-exports 'GHC.Boot.TH.Syntax',
|
| 201 | 209 | -- and exports additionally functions that depend on filepath.
|
| 202 | 210 | |
| 211 | +-- |
|
|
| 212 | +addForeignFile :: ForeignSrcLang -> String -> Q ()
|
|
| 213 | +addForeignFile = addForeignSource
|
|
| 214 | +{-# DEPRECATED addForeignFile
|
|
| 215 | + "Use 'Language.Haskell.TH.Syntax.addForeignSource' instead"
|
|
| 216 | + #-} -- deprecated in 8.6
|
|
| 217 | + |
|
| 203 | 218 | -- | The input is a filepath, which if relative is offset by the package root.
|
| 204 | 219 | makeRelativeToProject :: FilePath -> Q FilePath
|
| 205 | 220 | makeRelativeToProject fp | isRelative fp = do
|
| 206 | 221 | root <- getPackageRoot
|
| 207 | 222 | return (root </> fp)
|
| 208 | 223 | makeRelativeToProject fp = return fp
|
| 224 | + |
|
| 225 | +trueName, falseName :: Name
|
|
| 226 | +trueName = 'True
|
|
| 227 | +falseName = 'False
|
|
| 228 | + |
|
| 229 | +nothingName, justName :: Name
|
|
| 230 | +nothingName = 'Nothing
|
|
| 231 | +justName = 'Just
|
|
| 232 | + |
|
| 233 | +leftName, rightName :: Name
|
|
| 234 | +leftName = 'Left
|
|
| 235 | +rightName = 'Right
|
|
| 236 | + |
|
| 237 | +nonemptyName :: Name
|
|
| 238 | +nonemptyName = '(:|)
|
|
| 239 | + |
|
| 240 | +-----------------------------------------------------
|
|
| 241 | +--
|
|
| 242 | +-- Generic Lift implementations
|
|
| 243 | +--
|
|
| 244 | +-----------------------------------------------------
|
|
| 245 | + |
|
| 246 | +-- | 'dataToQa' is an internal utility function for constructing generic
|
|
| 247 | +-- conversion functions from types with 'Data' instances to various
|
|
| 248 | +-- quasi-quoting representations. See the source of 'dataToExpQ' and
|
|
| 249 | +-- 'dataToPatQ' for two example usages: @mkCon@, @mkLit@
|
|
| 250 | +-- and @appQ@ are overloadable to account for different syntax for
|
|
| 251 | +-- expressions and patterns; @antiQ@ allows you to override type-specific
|
|
| 252 | +-- cases, a common usage is just @const Nothing@, which results in
|
|
| 253 | +-- no overloading.
|
|
| 254 | +dataToQa :: forall m a k q. (Quote m, Data a)
|
|
| 255 | + => (Name -> k)
|
|
| 256 | + -> (Lit -> m q)
|
|
| 257 | + -> (k -> [m q] -> m q)
|
|
| 258 | + -> (forall b . Data b => b -> Maybe (m q))
|
|
| 259 | + -> a
|
|
| 260 | + -> m q
|
|
| 261 | +dataToQa mkCon mkLit appCon antiQ t =
|
|
| 262 | + case antiQ t of
|
|
| 263 | + Nothing ->
|
|
| 264 | + case constrRep constr of
|
|
| 265 | + AlgConstr _ ->
|
|
| 266 | + appCon (mkCon funOrConName) conArgs
|
|
| 267 | + where
|
|
| 268 | + funOrConName :: Name
|
|
| 269 | + funOrConName =
|
|
| 270 | + case showConstr constr of
|
|
| 271 | + "(:)" -> Name (mkOccName ":")
|
|
| 272 | + (NameG DataName
|
|
| 273 | + (mkPkgName "ghc-internal")
|
|
| 274 | + (mkModName "GHC.Internal.Types"))
|
|
| 275 | + con@"[]" -> Name (mkOccName con)
|
|
| 276 | + (NameG DataName
|
|
| 277 | + (mkPkgName "ghc-internal")
|
|
| 278 | + (mkModName "GHC.Internal.Types"))
|
|
| 279 | + con@('(':_) -> Name (mkOccName con)
|
|
| 280 | + (NameG DataName
|
|
| 281 | + (mkPkgName "ghc-internal")
|
|
| 282 | + (mkModName "GHC.Internal.Tuple"))
|
|
| 283 | + |
|
| 284 | + -- Tricky case: see Note [Data for non-algebraic types]
|
|
| 285 | + fun@(x:_) | startsVarSym x || startsVarId x
|
|
| 286 | + -> mkNameG_v tyconPkg tyconMod fun
|
|
| 287 | + con -> mkNameG_d tyconPkg tyconMod con
|
|
| 288 | + |
|
| 289 | + where
|
|
| 290 | + tycon :: TyCon
|
|
| 291 | + tycon = (typeRepTyCon . typeOf) t
|
|
| 292 | + |
|
| 293 | + tyconPkg, tyconMod :: String
|
|
| 294 | + tyconPkg = tyConPackage tycon
|
|
| 295 | + tyconMod = tyConModule tycon
|
|
| 296 | + |
|
| 297 | + conArgs :: [m q]
|
|
| 298 | + conArgs = gmapQ (dataToQa mkCon mkLit appCon antiQ) t
|
|
| 299 | + IntConstr n ->
|
|
| 300 | + mkLit $ IntegerL n
|
|
| 301 | + FloatConstr n ->
|
|
| 302 | + mkLit $ RationalL n
|
|
| 303 | + CharConstr c ->
|
|
| 304 | + mkLit $ CharL c
|
|
| 305 | + where
|
|
| 306 | + constr :: Constr
|
|
| 307 | + constr = toConstr t
|
|
| 308 | + |
|
| 309 | + Just y -> y
|
|
| 310 | + |
|
| 311 | + |
|
| 312 | +{- Note [Data for non-algebraic types]
|
|
| 313 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 314 | +Class Data was originally intended for algebraic data types. But
|
|
| 315 | +it is possible to use it for abstract types too. For example, in
|
|
| 316 | +package `text` we find
|
|
| 317 | + |
|
| 318 | + instance Data Text where
|
|
| 319 | + ...
|
|
| 320 | + toConstr _ = packConstr
|
|
| 321 | + |
|
| 322 | + packConstr :: Constr
|
|
| 323 | + packConstr = mkConstr textDataType "pack" [] Prefix
|
|
| 324 | + |
|
| 325 | +Here `packConstr` isn't a real data constructor, it's an ordinary
|
|
| 326 | +function. Two complications
|
|
| 327 | + |
|
| 328 | +* In such a case, we must take care to build the Name using
|
|
| 329 | + mkNameG_v (for values), not mkNameG_d (for data constructors).
|
|
| 330 | + See #10796.
|
|
| 331 | + |
|
| 332 | +* The pseudo-constructor is named only by its string, here "pack".
|
|
| 333 | + But 'dataToQa' needs the TyCon of its defining module, and has
|
|
| 334 | + to assume it's defined in the same module as the TyCon itself.
|
|
| 335 | + But nothing enforces that; #12596 shows what goes wrong if
|
|
| 336 | + "pack" is defined in a different module than the data type "Text".
|
|
| 337 | + -}
|
|
| 338 | + |
|
| 339 | +-- | A typed variant of 'dataToExpQ'.
|
|
| 340 | +dataToCodeQ :: (Quote m, Data a)
|
|
| 341 | + => (forall b . Data b => b -> Maybe (Code m b))
|
|
| 342 | + -> a -> Code m a
|
|
| 343 | +dataToCodeQ f = unsafeCodeCoerce . dataToExpQ (fmap unTypeCode . f)
|
|
| 344 | + |
|
| 345 | +-- | 'dataToExpQ' converts a value to a 'Exp' representation of the
|
|
| 346 | +-- same value, in the SYB style. It is generalized to take a function
|
|
| 347 | +-- override type-specific cases; see 'liftData' for a more commonly
|
|
| 348 | +-- used variant.
|
|
| 349 | +dataToExpQ :: (Quote m, Data a)
|
|
| 350 | + => (forall b . Data b => b -> Maybe (m Exp))
|
|
| 351 | + -> a
|
|
| 352 | + -> m Exp
|
|
| 353 | +dataToExpQ = dataToQa varOrConE litE (foldl appE)
|
|
| 354 | + where
|
|
| 355 | + -- Make sure that VarE is used if the Constr value relies on a
|
|
| 356 | + -- function underneath the surface (instead of a constructor).
|
|
| 357 | + -- See #10796.
|
|
| 358 | + varOrConE s =
|
|
| 359 | + case nameSpace s of
|
|
| 360 | + Just VarName -> return (VarE s)
|
|
| 361 | + Just (FldName {}) -> return (VarE s)
|
|
| 362 | + Just DataName -> return (ConE s)
|
|
| 363 | + _ -> error $ "Can't construct an expression from name "
|
|
| 364 | + ++ showName s
|
|
| 365 | + appE x y = do { a <- x; b <- y; return (AppE a b)}
|
|
| 366 | + litE c = return (LitE c)
|
|
| 367 | + |
|
| 368 | +-- | A typed variant of 'liftData'.
|
|
| 369 | +liftDataTyped :: (Quote m, Data a) => a -> Code m a
|
|
| 370 | +liftDataTyped = dataToCodeQ (const Nothing)
|
|
| 371 | + |
|
| 372 | +-- | 'liftData' is a variant of 'lift' in the 'Lift' type class which
|
|
| 373 | +-- works for any type with a 'Data' instance.
|
|
| 374 | +liftData :: (Quote m, Data a) => a -> m Exp
|
|
| 375 | +liftData = dataToExpQ (const Nothing)
|
|
| 376 | + |
|
| 377 | +-- | 'dataToPatQ' converts a value to a 'Pat' representation of the same
|
|
| 378 | +-- value, in the SYB style. It takes a function to handle type-specific cases,
|
|
| 379 | +-- alternatively, pass @const Nothing@ to get default behavior.
|
|
| 380 | +dataToPatQ :: (Quote m, Data a)
|
|
| 381 | + => (forall b . Data b => b -> Maybe (m Pat))
|
|
| 382 | + -> a
|
|
| 383 | + -> m Pat
|
|
| 384 | +dataToPatQ = dataToQa id litP conP
|
|
| 385 | + where litP l = return (LitP l)
|
|
| 386 | + conP n ps =
|
|
| 387 | + case nameSpace n of
|
|
| 388 | + Just DataName -> do
|
|
| 389 | + ps' <- sequence ps
|
|
| 390 | + return (ConP n [] ps')
|
|
| 391 | + _ -> error $ "Can't construct a pattern from name "
|
|
| 392 | + ++ showName n
|
|
| 393 | + |
|
| 394 | +{-
|
|
| 395 | +Note [Unresolved infix]
|
|
| 396 | +~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 397 | +-}
|
|
| 398 | +{- $infix #infix#
|
|
| 399 | + |
|
| 400 | +When implementing antiquotation for quasiquoters, one often wants
|
|
| 401 | +to parse strings into expressions:
|
|
| 402 | + |
|
| 403 | +> parse :: String -> Maybe Exp
|
|
| 404 | + |
|
| 405 | +But how should we parse @a + b * c@? If we don't know the fixities of
|
|
| 406 | +@+@ and @*@, we don't know whether to parse it as @a + (b * c)@ or @(a
|
|
| 407 | ++ b) * c@.
|
|
| 408 | + |
|
| 409 | +In cases like this, use 'UInfixE', 'UInfixP', 'UInfixT', or 'PromotedUInfixT',
|
|
| 410 | +which stand for \"unresolved infix expression / pattern / type / promoted
|
|
| 411 | +constructor\", respectively. When the compiler is given a splice containing a
|
|
| 412 | +tree of @UInfixE@ applications such as
|
|
| 413 | + |
|
| 414 | +> UInfixE
|
|
| 415 | +> (UInfixE e1 op1 e2)
|
|
| 416 | +> op2
|
|
| 417 | +> (UInfixE e3 op3 e4)
|
|
| 418 | + |
|
| 419 | +it will look up and the fixities of the relevant operators and
|
|
| 420 | +reassociate the tree as necessary.
|
|
| 421 | + |
|
| 422 | + * trees will not be reassociated across 'ParensE', 'ParensP', or 'ParensT',
|
|
| 423 | + which are of use for parsing expressions like
|
|
| 424 | + |
|
| 425 | + > (a + b * c) + d * e
|
|
| 426 | + |
|
| 427 | + * 'InfixE', 'InfixP', 'InfixT', and 'PromotedInfixT' expressions are never
|
|
| 428 | + reassociated.
|
|
| 429 | + |
|
| 430 | + * The 'UInfixE' constructor doesn't support sections. Sections
|
|
| 431 | + such as @(a *)@ have no ambiguity, so 'InfixE' suffices. For longer
|
|
| 432 | + sections such as @(a + b * c -)@, use an 'InfixE' constructor for the
|
|
| 433 | + outer-most section, and use 'UInfixE' constructors for all
|
|
| 434 | + other operators:
|
|
| 435 | + |
|
| 436 | + > InfixE
|
|
| 437 | + > Just (UInfixE ...a + b * c...)
|
|
| 438 | + > op
|
|
| 439 | + > Nothing
|
|
| 440 | + |
|
| 441 | + Sections such as @(a + b +)@ and @((a + b) +)@ should be rendered
|
|
| 442 | + into 'Exp's differently:
|
|
| 443 | + |
|
| 444 | + > (+ a + b) ---> InfixE Nothing + (Just $ UInfixE a + b)
|
|
| 445 | + > -- will result in a fixity error if (+) is left-infix
|
|
| 446 | + > (+ (a + b)) ---> InfixE Nothing + (Just $ ParensE $ UInfixE a + b)
|
|
| 447 | + > -- no fixity errors
|
|
| 448 | + |
|
| 449 | + * Quoted expressions such as
|
|
| 450 | + |
|
| 451 | + > [| a * b + c |] :: Q Exp
|
|
| 452 | + > [p| a : b : c |] :: Q Pat
|
|
| 453 | + > [t| T + T |] :: Q Type
|
|
| 454 | + |
|
| 455 | + will never contain 'UInfixE', 'UInfixP', 'UInfixT', 'PromotedUInfixT',
|
|
| 456 | + 'InfixT', 'PromotedInfixT, 'ParensE', 'ParensP', or 'ParensT' constructors.
|
|
| 457 | + |
|
| 458 | +-} |
| ... | ... | @@ -1375,7 +1375,7 @@ module Language.Haskell.TH.Quote where |
| 1375 | 1375 | quoteFile :: QuasiQuoter -> QuasiQuoter
|
| 1376 | 1376 | |
| 1377 | 1377 | module Language.Haskell.TH.Syntax where
|
| 1378 | - -- Safety: Safe
|
|
| 1378 | + -- Safety: Trustworthy
|
|
| 1379 | 1379 | type AnnLookup :: *
|
| 1380 | 1380 | data AnnLookup = AnnLookupModule Module | AnnLookupName Name
|
| 1381 | 1381 | type AnnTarget :: *
|
| ... | ... | @@ -7,4 +7,4 @@ test('T4491', |
| 7 | 7 | # the TH way
|
| 8 | 8 | only_ways([config.ghc_th_way]),
|
| 9 | 9 | ],
|
| 10 | - compile_and_run, ['']) |
|
| 10 | + compile_and_run, ['-package template-haskell']) |
| ... | ... | @@ -9,8 +9,8 @@ T2386: |
| 9 | 9 | '$(TEST_HC)' $(TEST_HC_OPTS) $(ghcThWayFlags) -v0 -c T2386.hs
|
| 10 | 10 | |
| 11 | 11 | T7445:
|
| 12 | - '$(TEST_HC)' $(TEST_HC_OPTS) $(ghcThWayFlags) -v0 -c T7445a.hs
|
|
| 13 | - '$(TEST_HC)' $(TEST_HC_OPTS) $(ghcThWayFlags) -v0 -c T7445.hs
|
|
| 12 | + '$(TEST_HC)' $(TEST_HC_OPTS) $(ghcThWayFlags) -package template-haskell -v0 -c T7445a.hs
|
|
| 13 | + '$(TEST_HC)' $(TEST_HC_OPTS) $(ghcThWayFlags) -package template-haskell -v0 -c T7445.hs
|
|
| 14 | 14 | |
| 15 | 15 | HC_OPTS = -XTemplateHaskell -package template-haskell
|
| 16 | 16 |