diff options
author | romes <rodrigo.m.mesquita@gmail.com> | 2022-03-19 17:42:46 +0000 |
---|---|---|
committer | Marge Bot <ben+marge-bot@smart-cactus.org> | 2022-06-01 07:44:44 -0400 |
commit | 7975202ba9010c581918413808ee06fbab9ac85f (patch) | |
tree | ffebdbd9d9fcef2300b1a6d3950bb5dd3f8435c4 /compiler/GHC/Hs | |
parent | 392ce3fca5d33688add52309a05914efa163e6f6 (diff) | |
download | haskell-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.hs | 7 | ||||
-rw-r--r-- | compiler/GHC/Hs/Expr.hs | 281 | ||||
-rw-r--r-- | compiler/GHC/Hs/Expr.hs-boot | 25 | ||||
-rw-r--r-- | compiler/GHC/Hs/Instances.hs | 19 | ||||
-rw-r--r-- | compiler/GHC/Hs/Pat.hs | 11 | ||||
-rw-r--r-- | compiler/GHC/Hs/Syn/Type.hs | 9 | ||||
-rw-r--r-- | compiler/GHC/Hs/Type.hs | 13 | ||||
-rw-r--r-- | compiler/GHC/Hs/Utils.hs | 29 |
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] |