summaryrefslogtreecommitdiff
path: root/compiler/GHC/Hs
diff options
context:
space:
mode:
authorromes <rodrigo.m.mesquita@gmail.com>2022-03-19 17:42:46 +0000
committerMarge Bot <ben+marge-bot@smart-cactus.org>2022-06-01 07:44:44 -0400
commit7975202ba9010c581918413808ee06fbab9ac85f (patch)
treeffebdbd9d9fcef2300b1a6d3950bb5dd3f8435c4 /compiler/GHC/Hs
parent392ce3fca5d33688add52309a05914efa163e6f6 (diff)
downloadhaskell-7975202ba9010c581918413808ee06fbab9ac85f.tar.gz
TTG: Rework and improve splices
This commit redefines the structure of Splices in the AST. We get rid of `HsSplice` which used to represent typed and untyped splices, quasi quotes, and the result of splicing either an expression, a type or a pattern. Instead we have `HsUntypedSplice` which models an untyped splice or a quasi quoter, which works in practice just like untyped splices. The `HsExpr` constructor `HsSpliceE` which used to be constructed with an `HsSplice` is split into `HsTypedSplice` and `HsUntypedSplice`. The former is directly constructed with an `HsExpr` and the latter now takes an `HsUntypedSplice`. Both `HsType` and `Pat` constructors `HsSpliceTy` and `SplicePat` now take an `HsUntypedSplice` instead of a `HsSplice` (remember only /untyped splices/ can be spliced as types or patterns). The result of splicing an expression, type, or pattern is now comfortably stored in the extension fields `XSpliceTy`, `XSplicePat`, `XUntypedSplice` as, respectively, `HsUntypedSpliceResult (HsType GhcRn)`, `HsUntypedSpliceResult (Pat GhcRn)`, and `HsUntypedSpliceResult (HsExpr GhcRn)` Overall the TTG extension points are now better used to make invalid states unrepresentable and model the progression between stages better. See Note [Lifecycle of an untyped splice, and PendingRnSplice] and Note [Lifecycle of an typed splice, and PendingTcSplice] for more details. Updates haddock submodule Fixes #21263 ------------------------- Metric Decrease: hard_hole_fits -------------------------
Diffstat (limited to 'compiler/GHC/Hs')
-rw-r--r--compiler/GHC/Hs/Decls.hs7
-rw-r--r--compiler/GHC/Hs/Expr.hs281
-rw-r--r--compiler/GHC/Hs/Expr.hs-boot25
-rw-r--r--compiler/GHC/Hs/Instances.hs19
-rw-r--r--compiler/GHC/Hs/Pat.hs11
-rw-r--r--compiler/GHC/Hs/Syn/Type.hs9
-rw-r--r--compiler/GHC/Hs/Type.hs13
-rw-r--r--compiler/GHC/Hs/Utils.hs29
8 files changed, 155 insertions, 239 deletions
diff --git a/compiler/GHC/Hs/Decls.hs b/compiler/GHC/Hs/Decls.hs
index c83a05256a..d2b1b6a117 100644
--- a/compiler/GHC/Hs/Decls.hs
+++ b/compiler/GHC/Hs/Decls.hs
@@ -69,7 +69,7 @@ module GHC.Hs.Decls (
-- ** @default@ declarations
DefaultDecl(..), LDefaultDecl,
-- ** Template haskell declaration splice
- SpliceExplicitFlag(..),
+ SpliceDecoration(..),
SpliceDecl(..), LSpliceDecl,
-- ** Foreign function interface declarations
ForeignDecl(..), LForeignDecl, ForeignImport(..), ForeignExport(..),
@@ -104,7 +104,7 @@ import GHC.Prelude
import Language.Haskell.Syntax.Decls
-import {-# SOURCE #-} GHC.Hs.Expr ( pprExpr, pprSpliceDecl )
+import {-# SOURCE #-} GHC.Hs.Expr ( pprExpr, pprUntypedSplice )
-- Because Expr imports Decls via HsBracket
import GHC.Hs.Binds
@@ -313,7 +313,8 @@ type instance XXSpliceDecl (GhcPass _) = DataConCantHappen
instance OutputableBndrId p
=> Outputable (SpliceDecl (GhcPass p)) where
- ppr (SpliceDecl _ (L _ e) f) = pprSpliceDecl e f
+ ppr (SpliceDecl _ (L _ e) DollarSplice) = pprUntypedSplice True Nothing e
+ ppr (SpliceDecl _ (L _ e) BareSplice) = pprUntypedSplice False Nothing e
{-
************************************************************************
diff --git a/compiler/GHC/Hs/Expr.hs b/compiler/GHC/Hs/Expr.hs
index 274b5dfcb3..d664456654 100644
--- a/compiler/GHC/Hs/Expr.hs
+++ b/compiler/GHC/Hs/Expr.hs
@@ -33,7 +33,7 @@ import Language.Haskell.Syntax.Expr
-- friends:
import GHC.Prelude
-import GHC.Hs.Decls
+import GHC.Hs.Decls() -- import instances
import GHC.Hs.Pat
import GHC.Hs.Lit
import Language.Haskell.Syntax.Extension
@@ -44,7 +44,6 @@ import GHC.Parser.Annotation
-- others:
import GHC.Tc.Types.Evidence
-import GHC.Core.DataCon (FieldLabelString)
import GHC.Types.Name
import GHC.Types.Name.Set
import GHC.Types.Basic
@@ -64,6 +63,9 @@ import GHC.Builtin.Types (mkTupleStr)
import GHC.Tc.Utils.TcType (TcType, TcTyVar)
import {-# SOURCE #-} GHC.Tc.Types (TcLclEnv)
+import GHCi.RemoteTypes ( ForeignRef )
+import qualified Language.Haskell.TH as TH (Q)
+
-- libraries:
import Data.Data hiding (Fixity(..))
import qualified Data.Data as Data (Fixity(..))
@@ -171,80 +173,14 @@ deriving instance (Data (hs_syn GhcTc), Typeable hs_syn) => Data (HsWrap hs_syn)
-- ---------------------------------------------------------------------
-{-
-Note [The life cycle of a TH quotation]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-When desugaring a bracket (aka quotation), we want to produce Core
-code that, when run, will produce the TH syntax tree for the quotation.
-To that end, we want to desugar /renamed/ but not /typechecked/ code;
-the latter is cluttered with the typechecker's elaboration that should
-not appear in the TH syntax tree. So in (HsExpr GhcTc) tree, we must
-have a (HsExpr GhcRn) for the quotation itself.
-
-As such, when typechecking both typed and untyped brackets,
-we keep a /renamed/ bracket in the extension field.
-
-The HsBracketTc, the GhcTc ext field for both brackets, contains:
- - The renamed quote :: HsQuote GhcRn -- for the desugarer
- - [PendingTcSplice]
- - The type of the quote
- - Maybe QuoteWrapper
-
-Note that (HsBracketTc) stores the untyped (HsQuote GhcRn) for both typed and
-untyped brackets. They are treated uniformly by the desugarer, and we can
-easily construct untyped brackets from typed ones (with ExpBr).
-
-Typed quotes
-~~~~~~~~~~~~
-Here is the life cycle of a /typed/ quote [|| e ||], whose datacon is
- HsTypedBracket (XTypedBracket p) (LHsExpr p)
-
- In pass p (XTypedBracket p) (LHsExpr p)
- -------------------------------------------
- GhcPs Annotations only LHsExpr GhcPs
- GhcRn Annotations only LHsExpr GhcRn
- GhcTc HsBracketTc LHsExpr GhcTc: unused!
-
-Note that in the GhcTc tree, the second field (HsExpr GhcTc)
-is entirely unused; the desugarer uses the (HsExpr GhcRn) from the
-first field.
-
-Untyped quotes
-~~~~~~~~~~~~~~
-Here is the life cycle of an /untyped/ quote, whose datacon is
- HsUntypedBracket (XUntypedBracket p) (HsQuote p)
-
-Here HsQuote is a sum-type of expressions [| e |], patterns [| p |],
-types [| t |] etc.
-
- In pass p (XUntypedBracket p) (HsQuote p)
- -------------------------------------------------------
- GhcPs Annotations only HsQuote GhcPs
- GhcRn Annotations, [PendingRnSplice] HsQuote GhcRn
- GhcTc HsBracketTc HsQuote GhcTc: unused!
-
-The difficulty is: the typechecker does not typecheck the body of an
-untyped quote, so how do we make a (HsQuote GhcTc) to put in the
-second field?
-
-Answer: we use the extension constructor of HsQuote, XQuote, and make
-all the other constructors into DataConCantHappen. That is, the only
-non-bottom value of type (HsQuote GhcTc) is (XQuote noExtField). Hence
-the instances
- type instance XExpBr GhcTc = DataConCantHappen
- ...etc...
-
-See the related Note [How brackets and nested splices are handled] in GHC.Tc.Gen.Splice
--}
-
data HsBracketTc = HsBracketTc
- { brack_renamed_quote :: (HsQuote GhcRn) -- See Note [The life cycle of a TH quotation]
- , brack_ty :: Type
- , brack_quote_wrapper :: (Maybe QuoteWrapper) -- The wrapper to apply type and dictionary argument to the quote.
- , brack_pending_splices :: [PendingTcSplice] -- Output of the type checker is the *original*
- -- renamed expression, plus
- -- _typechecked_ splices to be
- -- pasted back in by the desugarer
+ { hsb_quote :: HsQuote GhcRn -- See Note [The life cycle of a TH quotation]
+ , hsb_ty :: Type
+ , hsb_wrap :: Maybe QuoteWrapper -- The wrapper to apply type and dictionary argument to the quote.
+ , hsb_splices :: [PendingTcSplice] -- Output of the type checker is the *original*
+ -- renamed expression, plus
+ -- _typechecked_ splices to be
+ -- pasted back in by the desugarer
}
type instance XTypedBracket GhcPs = EpAnn [AddEpAnn]
@@ -407,7 +343,6 @@ type instance XArithSeq GhcPs = EpAnn [AddEpAnn]
type instance XArithSeq GhcRn = NoExtField
type instance XArithSeq GhcTc = PostTcExpr
-type instance XSpliceE (GhcPass _) = EpAnnCO
type instance XProc (GhcPass _) = EpAnn [AddEpAnn]
type instance XStatic GhcPs = EpAnn [AddEpAnn]
@@ -701,7 +636,17 @@ ppr_expr (ExprWithTySig _ expr sig)
ppr_expr (ArithSeq _ _ info) = brackets (ppr info)
-ppr_expr (HsSpliceE _ s) = pprSplice s
+ppr_expr (HsTypedSplice ext e) =
+ case ghcPass @p of
+ GhcPs -> pprTypedSplice Nothing e
+ GhcRn -> pprTypedSplice (Just ext) e
+ GhcTc -> pprTypedSplice Nothing e
+ppr_expr (HsUntypedSplice ext s) =
+ case ghcPass @p of
+ GhcPs -> pprUntypedSplice True Nothing s
+ GhcRn | HsUntypedSpliceNested n <- ext -> pprUntypedSplice True (Just n) s
+ GhcRn | HsUntypedSpliceTop _ e <- ext -> ppr e
+ GhcTc -> dataConCantHappen ext
ppr_expr (HsTypedBracket b e)
= case ghcPass @p of
@@ -855,7 +800,8 @@ hsExprNeedsParens prec = go
go (ExprWithTySig{}) = prec >= sigPrec
go (ArithSeq{}) = False
go (HsPragE{}) = prec >= appPrec
- go (HsSpliceE{}) = False
+ go (HsTypedSplice{}) = False
+ go (HsUntypedSplice{}) = False
go (HsTypedBracket{}) = False
go (HsUntypedBracket{}) = False
go (HsProc{}) = prec > topPrec
@@ -1693,15 +1639,46 @@ pprQuals quals = interpp'SP quals
************************************************************************
-}
-newtype HsSplicedT = HsSplicedT DelayedSplice deriving (Data)
+-- | Finalizers produced by a splice with
+-- 'Language.Haskell.TH.Syntax.addModFinalizer'
+--
+-- See Note [Delaying modFinalizers in untyped splices] in GHC.Rename.Splice. For how
+-- this is used.
+--
+newtype ThModFinalizers = ThModFinalizers [ForeignRef (TH.Q ())]
+
+-- A Data instance which ignores the argument of 'ThModFinalizers'.
+instance Data ThModFinalizers where
+ gunfold _ z _ = z $ ThModFinalizers []
+ toConstr a = mkConstr (dataTypeOf a) "ThModFinalizers" [] Data.Prefix
+ dataTypeOf a = mkDataType "HsExpr.ThModFinalizers" [toConstr a]
+
+-- See Note [Delaying modFinalizers in untyped splices] in GHC.Rename.Splice.
+-- This is the result of splicing a splice. It is produced by
+-- the renamer and consumed by the typechecker. It lives only between the two.
+data HsUntypedSpliceResult thing -- 'thing' can be HsExpr or HsType
+ = HsUntypedSpliceTop
+ { utsplice_result_finalizers :: ThModFinalizers -- ^ TH finalizers produced by the splice.
+ , utsplice_result :: thing -- ^ The result of splicing; See Note [Lifecycle of a splice]
+ }
+ | HsUntypedSpliceNested SplicePointName -- A unique name to identify this splice point
+
+type instance XTypedSplice GhcPs = (EpAnnCO, EpAnn [AddEpAnn])
+type instance XTypedSplice GhcRn = SplicePointName
+type instance XTypedSplice GhcTc = DelayedSplice
-type instance XTypedSplice (GhcPass _) = EpAnn [AddEpAnn]
-type instance XUntypedSplice (GhcPass _) = EpAnn [AddEpAnn]
-type instance XQuasiQuote (GhcPass _) = NoExtField
-type instance XSpliced (GhcPass _) = NoExtField
-type instance XXSplice GhcPs = DataConCantHappen
-type instance XXSplice GhcRn = DataConCantHappen
-type instance XXSplice GhcTc = HsSplicedT
+type instance XUntypedSplice GhcPs = EpAnnCO
+type instance XUntypedSplice GhcRn = HsUntypedSpliceResult (HsExpr GhcRn)
+type instance XUntypedSplice GhcTc = DataConCantHappen
+
+-- HsUntypedSplice
+type instance XUntypedSpliceExpr GhcPs = EpAnn [AddEpAnn]
+type instance XUntypedSpliceExpr GhcRn = EpAnn [AddEpAnn]
+type instance XUntypedSpliceExpr GhcTc = DataConCantHappen
+
+type instance XQuasiQuote p = NoExtField
+
+type instance XXUntypedSplice p = DataConCantHappen
-- See Note [Running typed splices in the zonker]
-- These are the arguments that are passed to `GHC.Tc.Gen.Splice.runTopSplice`
@@ -1736,116 +1713,38 @@ data PendingRnSplice
data PendingTcSplice
= PendingTcSplice SplicePointName (LHsExpr GhcTc)
-{-
-Note [Pending Splices]
-~~~~~~~~~~~~~~~~~~~~~~
-When we rename an untyped bracket, we name and lift out all the nested
-splices, so that when the typechecker hits the bracket, it can
-typecheck those nested splices without having to walk over the untyped
-bracket code. So for example
- [| f $(g x) |]
-looks like
-
- HsUntypedBracket _ (HsApp (HsVar "f") (HsSpliceE _ (HsUntypedSplice sn (g x)))
-
-which the renamer rewrites to
-
- HsUntypedBracket
- [PendingRnSplice UntypedExpSplice sn (g x)]
- (HsApp (HsVar f) (HsSpliceE _ (HsUntypedSplice sn (g x)))
-
-* The 'sn' is the Name of the splice point, the SplicePointName
-
-* The PendingRnExpSplice gives the splice that splice-point name maps to;
- and the typechecker can now conveniently find these sub-expressions
-
-* Note that a nested splice, such as the `$(g x)` now appears twice:
- - In the PendingRnSplice: this is the version that will later be typechecked
- - In the HsSpliceE in the body of the bracket. This copy is used only for pretty printing.
-
-There are four varieties of pending splices generated by the renamer,
-distinguished by their UntypedSpliceFlavour
-
- * Pending expression splices (UntypedExpSplice), e.g.,
- [|$(f x) + 2|]
-
- UntypedExpSplice is also used for
- * quasi-quotes, where the pending expression expands to
- $(quoter "...blah...")
- (see GHC.Rename.Splice.makePending, HsQuasiQuote case)
-
- * cross-stage lifting, where the pending expression expands to
- $(lift x)
- (see GHC.Rename.Splice.checkCrossStageLifting)
-
- * Pending pattern splices (UntypedPatSplice), e.g.,
- [| \$(f x) -> x |]
-
- * Pending type splices (UntypedTypeSplice), e.g.,
- [| f :: $(g x) |]
-
- * Pending declaration (UntypedDeclSplice), e.g.,
- [| let $(f x) in ... |]
-
-There is a fifth variety of pending splice, which is generated by the type
-checker:
-
- * Pending *typed* expression splices, (PendingTcSplice), e.g.,
- [||1 + $$(f 2)||]
--}
-
-instance OutputableBndrId p
- => Outputable (HsSplicedThing (GhcPass p)) where
- ppr (HsSplicedExpr e) = ppr_expr e
- ppr (HsSplicedTy t) = ppr t
- ppr (HsSplicedPat p) = ppr p
-
-instance (OutputableBndrId p) => Outputable (HsSplice (GhcPass p)) where
- ppr s = pprSplice s
pprPendingSplice :: (OutputableBndrId p)
=> SplicePointName -> LHsExpr (GhcPass p) -> SDoc
pprPendingSplice n e = angleBrackets (ppr n <> comma <+> ppr (stripParensLHsExpr e))
-pprSpliceDecl :: (OutputableBndrId p)
- => HsSplice (GhcPass p) -> SpliceExplicitFlag -> SDoc
-pprSpliceDecl e@HsQuasiQuote{} _ = pprSplice e
-pprSpliceDecl e ExplicitSplice = text "$" <> ppr_splice_decl e
-pprSpliceDecl e ImplicitSplice = ppr_splice_decl e
-
-ppr_splice_decl :: (OutputableBndrId p)
- => HsSplice (GhcPass p) -> SDoc
-ppr_splice_decl (HsUntypedSplice _ _ n e) = ppr_splice empty n e empty
-ppr_splice_decl e = pprSplice e
-
-pprSplice :: forall p. (OutputableBndrId p) => HsSplice (GhcPass p) -> SDoc
-pprSplice (HsTypedSplice _ DollarSplice n e)
- = ppr_splice (text "$$") n e empty
-pprSplice (HsTypedSplice _ BareSplice _ _ )
- = panic "Bare typed splice" -- impossible
-pprSplice (HsUntypedSplice _ DollarSplice n e)
- = ppr_splice (text "$") n e empty
-pprSplice (HsUntypedSplice _ BareSplice n e)
- = ppr_splice empty n e empty
-pprSplice (HsQuasiQuote _ n q _ s) = ppr_quasi n q s
-pprSplice (HsSpliced _ _ thing) = ppr thing
-pprSplice (XSplice x) = case ghcPass @p of
-#if __GLASGOW_HASKELL__ < 811
- GhcPs -> dataConCantHappen x
- GhcRn -> dataConCantHappen x
-#endif
- GhcTc -> case x of
- HsSplicedT _ -> text "Unevaluated typed splice"
+pprTypedSplice :: (OutputableBndrId p) => Maybe SplicePointName -> LHsExpr (GhcPass p) -> SDoc
+pprTypedSplice n e = ppr_splice (text "$$") n e
-ppr_quasi :: OutputableBndr p => p -> p -> FastString -> SDoc
-ppr_quasi n quoter quote = whenPprDebug (brackets (ppr n)) <>
- char '[' <> ppr quoter <> vbar <>
+pprUntypedSplice :: forall p. (OutputableBndrId p)
+ => Bool -- Whether to preceed the splice with "$"
+ -> Maybe SplicePointName -- Used for pretty printing when exists
+ -> HsUntypedSplice (GhcPass p)
+ -> SDoc
+pprUntypedSplice True n (HsUntypedSpliceExpr _ e) = ppr_splice (text "$") n e
+pprUntypedSplice False n (HsUntypedSpliceExpr _ e) = ppr_splice empty n e
+pprUntypedSplice _ _ (HsQuasiQuote _ q s) = ppr_quasi q (unLoc s)
+
+ppr_quasi :: OutputableBndr p => p -> FastString -> SDoc
+ppr_quasi quoter quote = char '[' <> ppr quoter <> vbar <>
ppr quote <> text "|]"
ppr_splice :: (OutputableBndrId p)
- => SDoc -> (IdP (GhcPass p)) -> LHsExpr (GhcPass p) -> SDoc -> SDoc
-ppr_splice herald n e trail
- = herald <> whenPprDebug (brackets (ppr n)) <> ppr e <> trail
+ => SDoc
+ -> Maybe SplicePointName
+ -> LHsExpr (GhcPass p)
+ -> SDoc
+ppr_splice herald mn e
+ = herald
+ <> (case mn of
+ Nothing -> empty
+ Just splice_name -> whenPprDebug (brackets (ppr splice_name)))
+ <> ppr e
type instance XExpBr GhcPs = NoExtField
@@ -2059,14 +1958,16 @@ type instance Anno (GRHS (GhcPass p) (LocatedA (HsCmd (GhcPass p)))) = SrcAnn N
type instance Anno (StmtLR (GhcPass pl) (GhcPass pr) (LocatedA (HsExpr (GhcPass pr)))) = SrcSpanAnnA
type instance Anno (StmtLR (GhcPass pl) (GhcPass pr) (LocatedA (HsCmd (GhcPass pr)))) = SrcSpanAnnA
-type instance Anno (HsSplice (GhcPass p)) = SrcSpanAnnA
+type instance Anno (HsUntypedSplice (GhcPass p)) = SrcSpanAnnA
type instance Anno [LocatedA (StmtLR (GhcPass pl) (GhcPass pr) (LocatedA (HsExpr (GhcPass pr))))] = SrcSpanAnnL
type instance Anno [LocatedA (StmtLR (GhcPass pl) (GhcPass pr) (LocatedA (HsCmd (GhcPass pr))))] = SrcSpanAnnL
type instance Anno (FieldLabelStrings (GhcPass p)) = SrcAnn NoEpAnns
-type instance Anno (FieldLabelString) = SrcAnn NoEpAnns
-type instance Anno (DotFieldOcc (GhcPass p)) = SrcAnn NoEpAnns
+type instance Anno FastString = SrcAnn NoEpAnns
+ -- NB: type FieldLabelString = FastString
+
+type instance Anno (DotFieldOcc (GhcPass p)) = SrcAnn NoEpAnns
instance (Anno a ~ SrcSpanAnn' (EpAnn an))
=> WrapXRec (GhcPass p) a where
diff --git a/compiler/GHC/Hs/Expr.hs-boot b/compiler/GHC/Hs/Expr.hs-boot
index 204af54681..6f1744096d 100644
--- a/compiler/GHC/Hs/Expr.hs-boot
+++ b/compiler/GHC/Hs/Expr.hs-boot
@@ -1,3 +1,5 @@
+{-# LANGUAGE RoleAnnotations #-}
+{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-} -- Wrinkle in Note [Trees That Grow]
@@ -10,15 +12,19 @@ module GHC.Hs.Expr where
import GHC.Utils.Outputable ( SDoc, Outputable )
import Language.Haskell.Syntax.Pat ( LPat )
import {-# SOURCE #-} GHC.Hs.Pat () -- for Outputable
-import GHC.Types.Basic ( SpliceExplicitFlag(..))
import Language.Haskell.Syntax.Expr
( HsExpr, LHsExpr
, HsCmd
, MatchGroup
, GRHSs
- , HsSplice
+ , HsUntypedSplice
)
import GHC.Hs.Extension ( OutputableBndrId, GhcPass )
+import GHC.Types.Name ( Name )
+import Data.Bool ( Bool )
+import Data.Maybe ( Maybe )
+
+type SplicePointName = Name
instance (OutputableBndrId p) => Outputable (HsExpr (GhcPass p))
instance (OutputableBndrId p) => Outputable (HsCmd (GhcPass p))
@@ -27,10 +33,8 @@ pprLExpr :: (OutputableBndrId p) => LHsExpr (GhcPass p) -> SDoc
pprExpr :: (OutputableBndrId p) => HsExpr (GhcPass p) -> SDoc
-pprSplice :: (OutputableBndrId p) => HsSplice (GhcPass p) -> SDoc
-
-pprSpliceDecl :: (OutputableBndrId p)
- => HsSplice (GhcPass p) -> SpliceExplicitFlag -> SDoc
+pprTypedSplice :: (OutputableBndrId p) => Maybe SplicePointName -> LHsExpr (GhcPass p) -> SDoc
+pprUntypedSplice :: (OutputableBndrId p) => Bool -> Maybe SplicePointName -> HsUntypedSplice (GhcPass p) -> SDoc
pprPatBind :: forall bndr p . (OutputableBndrId bndr,
OutputableBndrId p)
@@ -38,3 +42,12 @@ pprPatBind :: forall bndr p . (OutputableBndrId bndr,
pprFunBind :: (OutputableBndrId idR)
=> MatchGroup (GhcPass idR) (LHsExpr (GhcPass idR)) -> SDoc
+
+data ThModFinalizers
+type role HsUntypedSpliceResult representational
+data HsUntypedSpliceResult thing
+ = HsUntypedSpliceTop
+ { utsplice_result_finalizers :: ThModFinalizers
+ , utsplice_result :: thing
+ }
+ | HsUntypedSpliceNested SplicePointName
diff --git a/compiler/GHC/Hs/Instances.hs b/compiler/GHC/Hs/Instances.hs
index 1904de63d4..3f4c0b16bd 100644
--- a/compiler/GHC/Hs/Instances.hs
+++ b/compiler/GHC/Hs/Instances.hs
@@ -373,15 +373,16 @@ deriving instance Data (HsMatchContext GhcPs)
deriving instance Data (HsMatchContext GhcRn)
deriving instance Data (HsMatchContext GhcTc)
--- deriving instance (DataIdLR p p) => Data (HsSplice p)
-deriving instance Data (HsSplice GhcPs)
-deriving instance Data (HsSplice GhcRn)
-deriving instance Data (HsSplice GhcTc)
-
--- deriving instance (DataIdLR p p) => Data (HsSplicedThing p)
-deriving instance Data (HsSplicedThing GhcPs)
-deriving instance Data (HsSplicedThing GhcRn)
-deriving instance Data (HsSplicedThing GhcTc)
+-- deriving instance (DataIdLR p p) => Data (HsUntypedSplice p)
+deriving instance Data (HsUntypedSplice GhcPs)
+deriving instance Data (HsUntypedSplice GhcRn)
+deriving instance Data (HsUntypedSplice GhcTc)
+
+deriving instance Data (HsUntypedSpliceResult (HsExpr GhcRn))
+
+deriving instance Data (HsUntypedSpliceResult (Pat GhcRn))
+
+deriving instance Data (HsUntypedSpliceResult (HsType GhcRn))
-- deriving instance (DataIdLR p p) => Data (HsQuote p)
deriving instance Data (HsQuote GhcPs)
diff --git a/compiler/GHC/Hs/Pat.hs b/compiler/GHC/Hs/Pat.hs
index 9ca56e3290..f3e4fbe9c4 100644
--- a/compiler/GHC/Hs/Pat.hs
+++ b/compiler/GHC/Hs/Pat.hs
@@ -53,7 +53,7 @@ import GHC.Prelude
import Language.Haskell.Syntax.Pat
import Language.Haskell.Syntax.Expr ( HsExpr )
-import {-# SOURCE #-} GHC.Hs.Expr (pprLExpr, pprSplice)
+import {-# SOURCE #-} GHC.Hs.Expr (pprLExpr, pprUntypedSplice, HsUntypedSpliceResult(..))
-- friends:
import GHC.Hs.Binds
@@ -137,7 +137,7 @@ type instance XViewPat GhcTc = Type
-- (= the argument type of the view function), for hsPatType.
type instance XSplicePat GhcPs = NoExtField
-type instance XSplicePat GhcRn = NoExtField
+type instance XSplicePat GhcRn = HsUntypedSpliceResult (Pat GhcRn) -- See Note [Lifecycle of a splice] in GHC.Hs.Expr
type instance XSplicePat GhcTc = DataConCantHappen
type instance XLitPat (GhcPass _) = NoExtField
@@ -319,7 +319,12 @@ pprPat (NPlusKPat _ n k _ _ _) = hcat [ppr_n, char '+', ppr k]
GhcPs -> ppr n
GhcRn -> ppr n
GhcTc -> ppr n
-pprPat (SplicePat _ splice) = pprSplice splice
+pprPat (SplicePat ext splice) =
+ case ghcPass @p of
+ GhcPs -> pprUntypedSplice True Nothing splice
+ GhcRn | HsUntypedSpliceNested n <- ext -> pprUntypedSplice True (Just n) splice
+ GhcRn | HsUntypedSpliceTop _ p <- ext -> ppr p
+ GhcTc -> dataConCantHappen ext
pprPat (SigPat _ pat ty) = ppr pat <+> dcolon <+> ppr ty
pprPat (ListPat _ pats) = brackets (interpp'SP pats)
pprPat (TuplePat _ pats bx)
diff --git a/compiler/GHC/Hs/Syn/Type.hs b/compiler/GHC/Hs/Syn/Type.hs
index 30009ef400..63b568df4a 100644
--- a/compiler/GHC/Hs/Syn/Type.hs
+++ b/compiler/GHC/Hs/Syn/Type.hs
@@ -125,13 +125,14 @@ hsExprType (ArithSeq _ mb_overloaded_op asi) = case mb_overloaded_op of
Nothing -> asi_ty
where
asi_ty = arithSeqInfoType asi
-hsExprType (HsTypedBracket (HsBracketTc _ ty _wrap _pending) _) = ty
-hsExprType (HsUntypedBracket (HsBracketTc _ ty _wrap _pending) _) = ty
-hsExprType e@(HsSpliceE{}) = pprPanic "hsExprType: Unexpected HsSpliceE"
- (ppr e)
+hsExprType (HsTypedBracket (HsBracketTc { hsb_ty = ty }) _) = ty
+hsExprType (HsUntypedBracket (HsBracketTc { hsb_ty = ty }) _) = ty
+hsExprType e@(HsTypedSplice{}) = pprPanic "hsExprType: Unexpected HsTypedSplice"
+ (ppr e)
-- Typed splices should have been eliminated during zonking, but we
-- can't use `dataConCantHappen` since they are still present before
-- than in the typechecked AST.
+hsExprType (HsUntypedSplice ext _) = dataConCantHappen ext
hsExprType (HsProc _ _ lcmd_top) = lhsCmdTopType lcmd_top
hsExprType (HsStatic (_, ty) _s) = ty
hsExprType (HsPragE _ _ e) = lhsExprType e
diff --git a/compiler/GHC/Hs/Type.hs b/compiler/GHC/Hs/Type.hs
index 5cb4200ecd..fe9aad3475 100644
--- a/compiler/GHC/Hs/Type.hs
+++ b/compiler/GHC/Hs/Type.hs
@@ -91,7 +91,7 @@ import GHC.Prelude
import Language.Haskell.Syntax.Type
-import {-# SOURCE #-} GHC.Hs.Expr ( pprSplice )
+import {-# SOURCE #-} GHC.Hs.Expr ( pprUntypedSplice, HsUntypedSpliceResult(..) )
import Language.Haskell.Syntax.Extension
import GHC.Hs.Extension
@@ -303,7 +303,7 @@ type instance XKindSig (GhcPass _) = EpAnn [AddEpAnn]
type instance XAppKindTy (GhcPass _) = SrcSpan -- Where the `@` lives
type instance XSpliceTy GhcPs = NoExtField
-type instance XSpliceTy GhcRn = NoExtField
+type instance XSpliceTy GhcRn = HsUntypedSpliceResult (HsType GhcRn)
type instance XSpliceTy GhcTc = Kind
type instance XDocTy (GhcPass _) = EpAnn [AddEpAnn]
@@ -1008,7 +1008,7 @@ ppr_mono_lty :: OutputableBndrId p
=> LHsType (GhcPass p) -> SDoc
ppr_mono_lty ty = ppr_mono_ty (unLoc ty)
-ppr_mono_ty :: (OutputableBndrId p) => HsType (GhcPass p) -> SDoc
+ppr_mono_ty :: forall p. (OutputableBndrId p) => HsType (GhcPass p) -> SDoc
ppr_mono_ty (HsForAllTy { hst_tele = tele, hst_body = ty })
= sep [pprHsForAll tele Nothing, ppr_mono_lty ty]
@@ -1036,7 +1036,12 @@ ppr_mono_ty (HsKindSig _ ty kind)
= ppr_mono_lty ty <+> dcolon <+> ppr kind
ppr_mono_ty (HsListTy _ ty) = brackets (ppr_mono_lty ty)
ppr_mono_ty (HsIParamTy _ n ty) = (ppr n <+> dcolon <+> ppr_mono_lty ty)
-ppr_mono_ty (HsSpliceTy _ s) = pprSplice s
+ppr_mono_ty (HsSpliceTy ext s) =
+ case ghcPass @p of
+ GhcPs -> pprUntypedSplice True Nothing s
+ GhcRn | HsUntypedSpliceNested n <- ext -> pprUntypedSplice True (Just n) s
+ GhcRn | HsUntypedSpliceTop _ t <- ext -> ppr t
+ GhcTc -> pprUntypedSplice True Nothing s
ppr_mono_ty (HsExplicitListTy _ prom tys)
| isPromoted prom = quote $ brackets (maybeAddSpace tys $ interpp'SP tys)
| otherwise = brackets (interpp'SP tys)
diff --git a/compiler/GHC/Hs/Utils.hs b/compiler/GHC/Hs/Utils.hs
index 9d4e733375..4dd0aab928 100644
--- a/compiler/GHC/Hs/Utils.hs
+++ b/compiler/GHC/Hs/Utils.hs
@@ -89,10 +89,6 @@ module GHC.Hs.Utils(
unitRecStmtTc,
mkLetStmt,
- -- * Template Haskell
- mkUntypedSplice, mkTypedSplice,
- mkHsQuasiQuote,
-
-- * Collecting binders
isUnliftedHsBind, isBangedHsBind,
@@ -451,19 +447,6 @@ mkLetStmt anns binds = LetStmt anns binds
mkHsOpApp :: LHsExpr GhcPs -> IdP GhcPs -> LHsExpr GhcPs -> HsExpr GhcPs
mkHsOpApp e1 op e2 = OpApp noAnn e1 (noLocA (HsVar noExtField (noLocA op))) e2
-unqualSplice :: RdrName
-unqualSplice = mkRdrUnqual (mkVarOccFS (fsLit "splice"))
-
-mkUntypedSplice :: EpAnn [AddEpAnn] -> SpliceDecoration -> LHsExpr GhcPs -> HsSplice GhcPs
-mkUntypedSplice ann hasParen e = HsUntypedSplice ann hasParen unqualSplice e
-
-mkTypedSplice :: EpAnn [AddEpAnn] -> SpliceDecoration -> LHsExpr GhcPs -> HsSplice GhcPs
-mkTypedSplice ann hasParen e = HsTypedSplice ann hasParen unqualSplice e
-
-mkHsQuasiQuote :: RdrName -> SrcSpan -> FastString -> HsSplice GhcPs
-mkHsQuasiQuote quoter span quote
- = HsQuasiQuote noExtField unqualSplice quoter span quote
-
mkHsString :: String -> HsLit (GhcPass p)
mkHsString s = HsString NoSourceText (mkFastString s)
@@ -1216,9 +1199,7 @@ collect_pat flag pat bndrs = case pat of
NPlusKPat _ n _ _ _ _ -> unXRec @p n : bndrs
SigPat _ pat _ -> collect_lpat flag pat bndrs
XPat ext -> collectXXPat @p flag ext bndrs
- SplicePat _ (HsSpliced _ _ (HsSplicedPat pat))
- -> collect_pat flag pat bndrs
- SplicePat _ _ -> bndrs
+ SplicePat ext _ -> collectXSplicePat @p flag ext bndrs
-- See Note [Dictionary binders in ConPatOut]
ConPat {pat_args=ps} -> case flag of
CollNoDictBinders -> foldr (collect_lpat flag) bndrs (hsConPatArgs ps)
@@ -1244,6 +1225,7 @@ add_ev_bndr (EvBind { eb_lhs = b }) bs | isId b = b:bs
class UnXRec p => CollectPass p where
collectXXPat :: CollectFlag p -> XXPat p -> [IdP p] -> [IdP p]
collectXXHsBindsLR :: forall pR. XXHsBindsLR p pR -> [IdP p] -> [IdP p]
+ collectXSplicePat :: CollectFlag p -> XSplicePat p -> [IdP p] -> [IdP p]
instance IsPass p => CollectPass (GhcPass p) where
collectXXPat flag ext =
@@ -1265,6 +1247,13 @@ instance IsPass p => CollectPass (GhcPass p) where
-- binding (hence see AbsBinds) is in zonking in GHC.Tc.Utils.Zonk
+ collectXSplicePat flag ext =
+ case ghcPass @p of
+ GhcPs -> id
+ GhcRn | (HsUntypedSpliceTop _ pat) <- ext -> collect_pat flag pat
+ GhcRn | (HsUntypedSpliceNested _) <- ext -> id
+ GhcTc -> dataConCantHappen ext
+
{-
Note [Dictionary binders in ConPatOut]