summaryrefslogtreecommitdiff
path: root/compiler/deSugar/DsMeta.hs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/deSugar/DsMeta.hs')
-rw-r--r--compiler/deSugar/DsMeta.hs129
1 files changed, 117 insertions, 12 deletions
diff --git a/compiler/deSugar/DsMeta.hs b/compiler/deSugar/DsMeta.hs
index b00717e53a..370e310204 100644
--- a/compiler/deSugar/DsMeta.hs
+++ b/compiler/deSugar/DsMeta.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE CPP #-}
+{-# LANGUAGE CPP, TypeFamilies #-}
-----------------------------------------------------------------------------
--
@@ -119,8 +119,9 @@ repTopDs group@(HsGroup { hs_valds = valds
, hs_ruleds = ruleds
, hs_vects = vects
, hs_docs = docs })
- = do { let { tv_bndrs = hsSigTvBinders valds
- ; bndrs = tv_bndrs ++ hsGroupBinders group
+ = do { let { bndrs = hsSigTvBinders valds
+ ++ hsGroupBinders group
+ ++ hsPatSynSelectors valds
; instds = tyclds >>= group_instds } ;
ss <- mkGenSyms bndrs ;
@@ -197,7 +198,6 @@ hsSigTvBinders binds
ValBindsIn _ sigs -> sigs
ValBindsOut _ sigs -> sigs
-
{- Notes
Note [Scoped type variables in bindings]
@@ -700,7 +700,7 @@ rep_sigs' sigs = do { sigs1 <- mapM rep_sig sigs ;
rep_sig :: LSig Name -> DsM [(SrcSpan, Core TH.DecQ)]
rep_sig (L loc (TypeSig nms ty)) = mapM (rep_wc_ty_sig sigDName loc ty) nms
-rep_sig (L _ (PatSynSig {})) = notHandled "Pattern type signatures" empty
+rep_sig (L loc (PatSynSig nm ty)) = (:[]) <$> rep_patsyn_ty_sig loc ty nm
rep_sig (L loc (ClassOpSig is_deflt nms ty))
| is_deflt = mapM (rep_ty_sig defaultSigDName loc ty) nms
| otherwise = mapM (rep_ty_sig sigDName loc ty) nms
@@ -708,7 +708,7 @@ rep_sig d@(L _ (IdSig {})) = pprPanic "rep_sig IdSig" (ppr d)
rep_sig (L _ (FixSig {})) = return [] -- fixity sigs at top level
rep_sig (L loc (InlineSig nm ispec)) = rep_inline nm ispec loc
rep_sig (L loc (SpecSig nm tys ispec))
- = concatMapM (\t -> rep_specialise nm t ispec loc) tys
+ = concatMapM (\t -> rep_specialise nm t ispec loc) tys
rep_sig (L loc (SpecInstSig _ ty)) = rep_specialiseInst ty loc
rep_sig (L _ (MinimalSig {})) = notHandled "MINIMAL pragmas" empty
@@ -720,6 +720,16 @@ rep_ty_sig mk_sig loc sig_ty nm
; sig <- repProto mk_sig nm1 ty1
; return (loc, sig) }
+rep_patsyn_ty_sig :: SrcSpan -> LHsSigType Name -> Located Name
+ -> DsM (SrcSpan, Core TH.DecQ)
+-- represents a pattern synonym type signature; see NOTE [Pattern
+-- synonym signatures and Template Haskell]
+rep_patsyn_ty_sig loc sig_ty nm
+ = do { nm1 <- lookupLOcc nm
+ ; ty1 <- repHsPatSynSigType sig_ty
+ ; sig <- repProto patSynSigDName nm1 ty1
+ ; return (loc, sig) }
+
rep_wc_ty_sig :: Name -> SrcSpan -> LHsSigWcType Name -> Located Name
-> DsM (SrcSpan, Core TH.DecQ)
-- We must special-case the top-level explicit for-all of a TypeSig
@@ -889,17 +899,32 @@ repHsSigType (HsIB { hsib_vars = vars
then return th_ty
else repTForall th_tvs th_ctxt th_ty }
+repHsPatSynSigType :: LHsSigType Name -> DsM (Core TH.TypeQ)
+repHsPatSynSigType (HsIB { hsib_vars = implicit_tvs
+ , hsib_body = body })
+ = addTyVarBinds (newTvs (impls ++ univs)) $ \th_univs ->
+ addTyVarBinds (newTvs exis) $ \th_exis ->
+ do { th_reqs <- repLContext reqs
+ ; th_provs <- repLContext provs
+ ; th_ty <- repLTy ty
+ ; repTForall th_univs th_reqs =<< (repTForall th_exis th_provs th_ty) }
+ where
+ impls = map (noLoc . UserTyVar . noLoc) implicit_tvs
+ newTvs tvs = HsQTvs
+ { hsq_implicit = []
+ , hsq_explicit = tvs
+ , hsq_dependent = emptyNameSet }
+ (univs, reqs, exis, provs, ty) = splitLHsPatSynTy body
+
repHsSigWcType :: LHsSigWcType Name -> DsM (Core TH.TypeQ)
repHsSigWcType ib_ty@(HsIB { hsib_body = sig1 })
= repHsSigType (ib_ty { hsib_body = hswc_body sig1 })
-- yield the representation of a list of types
---
repLTys :: [LHsType Name] -> DsM [Core TH.TypeQ]
repLTys tys = mapM repLTy tys
-- represent a type
---
repLTy :: LHsType Name -> DsM (Core TH.TypeQ)
repLTy (L _ ty) = repTy ty
@@ -1073,11 +1098,11 @@ repE :: HsExpr Name -> DsM (Core TH.ExpQ)
repE (HsVar (L _ x)) =
do { mb_val <- dsLookupMetaEnv x
; case mb_val of
- Nothing -> do { str <- globalVar x
- ; repVarOrCon x str }
+ Nothing -> do { str <- globalVar x
+ ; repVarOrCon x str }
Just (DsBound y) -> repVarOrCon x (coreVar y)
Just (DsSplice e) -> do { e' <- dsExpr e
- ; return (MkC e') } }
+ ; return (MkC e') } }
repE e@(HsIPVar _) = notHandled "Implicit parameters" (ppr e)
repE e@(HsOverLabel _) = notHandled "Overloaded labels" (ppr e)
@@ -1415,7 +1440,87 @@ rep_bind (L _ (VarBind { var_id = v, var_rhs = e}))
rep_bind (L _ (AbsBinds {})) = panic "rep_bind: AbsBinds"
rep_bind (L _ (AbsBindsSig {})) = panic "rep_bind: AbsBindsSig"
-rep_bind (L _ dec@(PatSynBind {})) = notHandled "pattern synonyms" (ppr dec)
+rep_bind (L loc (PatSynBind (PSB { psb_id = syn
+ , psb_fvs = _fvs
+ , psb_args = args
+ , psb_def = pat
+ , psb_dir = dir })))
+ = do { syn' <- lookupLBinder syn
+ ; dir' <- repPatSynDir dir
+ ; ss <- mkGenArgSyms args
+ ; patSynD' <- addBinds ss (
+ do { args' <- repPatSynArgs args
+ ; pat' <- repLP pat
+ ; repPatSynD syn' args' dir' pat' })
+ ; patSynD'' <- wrapGenArgSyms args ss patSynD'
+ ; return (loc, patSynD'') }
+ where
+ mkGenArgSyms :: HsPatSynDetails (Located Name) -> DsM [GenSymBind]
+ -- for Record Pattern Synonyms we want to conflate the selector
+ -- and the pattern-only names in order to provide a nicer TH
+ -- API. Whereas inside GHC, record pattern synonym selectors and
+ -- their pattern-only bound right hand sides have different names,
+ -- we want to treat them the same in TH. This is the reason why we
+ -- need an adjusted mkGenArgSyms in the `RecordPatSyn` case below.
+ mkGenArgSyms (PrefixPatSyn args) = mkGenSyms (map unLoc args)
+ mkGenArgSyms (InfixPatSyn arg1 arg2) = mkGenSyms [unLoc arg1, unLoc arg2]
+ mkGenArgSyms (RecordPatSyn fields)
+ = do { let pats = map (unLoc . recordPatSynPatVar) fields
+ sels = map (unLoc . recordPatSynSelectorId) fields
+ ; ss <- mkGenSyms sels
+ ; return $ replaceNames (zip sels pats) ss }
+
+ replaceNames selsPats genSyms
+ = [ (pat, id) | (sel, id) <- genSyms, (sel', pat) <- selsPats
+ , sel == sel' ]
+
+ wrapGenArgSyms :: HsPatSynDetails (Located Name)
+ -> [GenSymBind] -> Core TH.DecQ -> DsM (Core TH.DecQ)
+ wrapGenArgSyms (RecordPatSyn _) _ dec = return dec
+ wrapGenArgSyms _ ss dec = wrapGenSyms ss dec
+
+repPatSynD :: Core TH.Name
+ -> Core TH.PatSynArgsQ
+ -> Core TH.PatSynDirQ
+ -> Core TH.PatQ
+ -> DsM (Core TH.DecQ)
+repPatSynD (MkC syn) (MkC args) (MkC dir) (MkC pat)
+ = rep2 patSynDName [syn, args, dir, pat]
+
+repPatSynArgs :: HsPatSynDetails (Located Name) -> DsM (Core TH.PatSynArgsQ)
+repPatSynArgs (PrefixPatSyn args)
+ = do { args' <- repList nameTyConName lookupLOcc args
+ ; repPrefixPatSynArgs args' }
+repPatSynArgs (InfixPatSyn arg1 arg2)
+ = do { arg1' <- lookupLOcc arg1
+ ; arg2' <- lookupLOcc arg2
+ ; repInfixPatSynArgs arg1' arg2' }
+repPatSynArgs (RecordPatSyn fields)
+ = do { sels' <- repList nameTyConName lookupLOcc sels
+ ; repRecordPatSynArgs sels' }
+ where sels = map recordPatSynSelectorId fields
+
+repPrefixPatSynArgs :: Core [TH.Name] -> DsM (Core TH.PatSynArgsQ)
+repPrefixPatSynArgs (MkC nms) = rep2 prefixPatSynName [nms]
+
+repInfixPatSynArgs :: Core TH.Name -> Core TH.Name -> DsM (Core TH.PatSynArgsQ)
+repInfixPatSynArgs (MkC nm1) (MkC nm2) = rep2 infixPatSynName [nm1, nm2]
+
+repRecordPatSynArgs :: Core [TH.Name]
+ -> DsM (Core TH.PatSynArgsQ)
+repRecordPatSynArgs (MkC sels) = rep2 recordPatSynName [sels]
+
+repPatSynDir :: HsPatSynDir Name -> DsM (Core TH.PatSynDirQ)
+repPatSynDir Unidirectional = rep2 unidirPatSynName []
+repPatSynDir ImplicitBidirectional = rep2 implBidirPatSynName []
+repPatSynDir (ExplicitBidirectional (MG { mg_alts = L _ clauses }))
+ = do { clauses' <- mapM repClauseTup clauses
+ ; repExplBidirPatSynDir (nonEmptyCoreList clauses') }
+
+repExplBidirPatSynDir :: Core [TH.ClauseQ] -> DsM (Core TH.PatSynDirQ)
+repExplBidirPatSynDir (MkC cls) = rep2 explBidirPatSynName [cls]
+
+
-----------------------------------------------------------------------------
-- Since everything in a Bind is mutually recursive we need rename all
-- all the variables simultaneously. For example: