{-# LANGUAGE CPP #-} {-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE TupleSections #-} {-# LANGUAGE ViewPatterns #-} -- | Interface to the GHC API that closely mimicks Template Haskell -- -- See "Language.Haskell.TH.Lib". -- -- This module is intended to be CPP-free, with all CPP confined to -- "Data.Record.Plugin.GHC.Shim". The only exception to this is the redundant -- pattern matches that we need for the poor extension design in ghc 9.0; I've -- not yet found a nice way to shim this. module Data.Record.Internal.GHC.TemplateHaskellStyle ( -- * Names nameBase , mkExpVar , mkTyVar , mkTyCon , pattern ExpVar , pattern TyVar , pattern TyCon -- * Expressions , litE , stringE , pattern VarE , pattern ConE , recConE , pattern RecUpdE , appE , listE , lamE , lamE1 , caseE , appsE , appTypeE , tupE , sigE -- ** Without direct equivalent , intE -- * Types , parensT , litT , pattern VarT , pattern ConT , appT , listT -- ** Without direct equivalent , stringT , appsT , funT , tupT -- * Patterns , varP , conP , bangP , listP , wildP -- * Strictness , bangType -- * Class contexts , equalP -- * Constructors , pattern RecC , forallRecC -- * Type variable binders , kindedTV -- ** Without direct equivalent , tyVarBndrName -- * Top-level declarations , sigD , valD , pattern DataD , pattern DerivClause , instanceD , classD , tySynEqn -- * Pragmas , pattern TypeAnnotation , pattern PragAnnD -- * Re-exported types (intentionally without constructors) -- -- We intentionally: -- -- o Do not export constructors (unless otherwise indicated): the functions -- in this module are replacements for those constructors. -- o Only export the located versions of these types: we should try to -- minimize location loss when generating code, for better errors. , AnnDecl , DerivStrategy(..) -- Exported with constructors, is similar enough to TH , GhcPs , HsLit , HsTyLit , LConDecl , LDerivStrategy , LHsDecl , LHsDerivingClause , LHsExpr , LHsType , LHsTyVarBndr , LPat , LTyFamInstDecl , LRdrName ) where import Data.List (foldl') import Data.Record.Internal.GHC.Shim hiding (mkTyVar) import Data.List.NonEmpty (NonEmpty(..)) import qualified Data.List.NonEmpty as NE {------------------------------------------------------------------------------- Internal auxiliary: types of names -------------------------------------------------------------------------------} isTermVar, isTermCon, isTypeVar, isTypeCon :: LRdrName -> Bool isTermVar = checkNameType isVarOcc isTermCon = checkNameType isDataOcc isTypeVar = checkNameType isTvOcc isTypeCon = checkNameType isTcOcc checkNameType :: (OccName -> Bool) -> LRdrName -> Bool checkNameType f (L _ n) = f (rdrNameOcc n) {------------------------------------------------------------------------------- Names -------------------------------------------------------------------------------} -- | Equivalent of 'Language.Haskell.TH.Syntax.nameBase' nameBase :: LRdrName -> String nameBase = occNameString . rdrNameOcc . unLoc -- | Equivalent of 'Language.Haskell.TH.Syntax.mkName', for expression vars mkExpVar :: SrcSpan -> String -> LRdrName mkExpVar l = L l . mkRdrUnqual . mkVarOcc -- | Equivalent of 'Language.Haskell.TH.Syntax.mkName', for type vars mkTyVar :: SrcSpan -> String -> LRdrName mkTyVar l = L l . mkRdrUnqual . mkTyVarOcc -- | Equivalent of 'Language.Haskell.TH.Syntax.mkName', for type constructors mkTyCon :: SrcSpan -> String -> LRdrName mkTyCon l = L l . mkRdrUnqual . mkTcOcc -- | Inverse to 'mkExpVar' -- -- NOTE: Defined in terms of 'nameBase', so discards qualifiers. viewExpVar :: LRdrName -> Maybe String viewExpVar n | isTermVar n = Just (nameBase n) viewExpVar _otherwise = Nothing -- | Inverse to 'mkTyVar' -- -- NOTE: Defined in terms of 'nameBase', so discards qualifiers. viewTyVar :: LRdrName -> Maybe String viewTyVar n | isTypeVar n = Just (nameBase n) viewTyVar _otherwise = Nothing -- | Inverse to 'mkTyCon' viewTyCon :: LRdrName -> Maybe String viewTyCon n | isTypeCon n = Just (nameBase n) viewTyCon _otherwise = Nothing -- This patterns are not bidirectional: to construct a LRdrName, we need a -- location. We may want to change this somehow. Use a Located String? pattern ExpVar :: String -> LRdrName pattern ExpVar n <- (viewExpVar -> Just n) pattern TyVar :: String -> LRdrName pattern TyVar n <- (viewTyVar -> Just n) pattern TyCon :: String -> LRdrName pattern TyCon n <- (viewTyCon -> Just n) {------------------------------------------------------------------------------- Expressions -------------------------------------------------------------------------------} -- | Equivalent of 'Language.Haskell.TH.Lib.varE' varE :: HasCallStack => LRdrName -> LHsExpr GhcPs varE name | isTermVar name = inheritLoc name $ HsVar defExt (reLocA name) | otherwise = error "varE: incorrect name type" -- | Inverse to 'varE' viewVarE :: LHsExpr GhcPs -> Maybe LRdrName viewVarE (L _ (HsVar _ (reLoc -> name))) | isTermVar name = Just name viewVarE _ = Nothing pattern VarE :: HasCallStack => () => LRdrName -> LHsExpr GhcPs pattern VarE name <- (viewVarE -> Just name) where VarE = varE -- | Equivalent of 'Language.Haskell.TH.Lib.conE' conE :: HasCallStack => LRdrName -> LHsExpr GhcPs conE name | isTermCon name = inheritLoc name $ HsVar defExt (reLocA name) | otherwise = error "conE: incorrect name type" -- | Inverse to 'conE' viewConE :: LHsExpr GhcPs -> Maybe LRdrName viewConE (L _ (HsVar _ (reLoc -> name))) | isTermCon name = Just name viewConE _ = Nothing pattern ConE :: HasCallStack => () => LRdrName -> LHsExpr GhcPs pattern ConE name <- (viewConE -> Just name) where ConE = conE -- | Equivalent of 'Language.Haskell.TH.Lib.litE' litE :: HsLit GhcPs -> LHsExpr GhcPs litE = noLocA . HsLit defExt -- | Equivalent of 'Language.Haskell.TH.Lib.stringE' stringE :: String -> LHsExpr GhcPs stringE = litE . HsString NoSourceText . fsLit -- | Equivalent of 'Language.Haskell.TH.Lib.recConE' recConE :: LRdrName -> [(LRdrName, LHsExpr GhcPs)] -> LHsExpr GhcPs recConE = \recName -> mkRec recName . map (uncurry mkFld) where mkRec :: LRdrName -> [LHsRecField GhcPs (LHsExpr GhcPs)] -> LHsExpr GhcPs mkRec name fields = inheritLoc name $ RecordCon defExt (reLocA name) (HsRecFields fields Nothing) mkFld :: LRdrName -> LHsExpr GhcPs -> LHsRecField GhcPs (LHsExpr GhcPs) mkFld name val = inheritLoc name $ #if __GLASGOW_HASKELL__ >= 904 HsFieldBind defExt #elif __GLASGOW_HASKELL__ >= 902 HsRecField defExt #else HsRecField #endif (inheritLoc name (mkFieldOcc (reLocA name))) val False -- | Equivalent of 'Language.Haskell.TH.Lib.recUpdE' recUpdE :: LHsExpr GhcPs -> [(LRdrName, LHsExpr GhcPs)] -> LHsExpr GhcPs recUpdE = \recExpr -> updRec recExpr . map (uncurry updFld) where updRec :: LHsExpr GhcPs -> [LHsRecUpdField GhcPs] -> LHsExpr GhcPs updRec expr fields = inheritLoc expr $ RecordUpd defExt expr #if __GLASGOW_HASKELL__ >= 902 $ Left #endif fields updFld :: LRdrName -> LHsExpr GhcPs -> LHsRecUpdField GhcPs updFld name val = inheritLoc name $ #if __GLASGOW_HASKELL__ >= 904 HsFieldBind #else HsRecField #endif #if __GLASGOW_HASKELL__ >= 902 defExt #endif (inheritLoc name (mkAmbiguousFieldOcc (reLocA name))) val False viewRecUpdE :: LHsExpr GhcPs -> Maybe (LHsExpr GhcPs, [(LRdrName, LHsExpr GhcPs)]) viewRecUpdE (L _ (RecordUpd _ recExpr fields)) = (recExpr,) <$> simpleRecordUpdates fields viewRecUpdE _otherwise = Nothing pattern RecUpdE :: LHsExpr GhcPs -> [(LRdrName, LHsExpr GhcPs)] -> LHsExpr GhcPs pattern RecUpdE recExpr fields <- (viewRecUpdE -> Just (recExpr, fields)) where RecUpdE = recUpdE -- | Equivalent of 'Language.Haskell.TH.Lib.appE' appE :: LHsExpr GhcPs -> LHsExpr GhcPs -> LHsExpr GhcPs appE a b = mkHsApp a b -- | Equivalent of 'Language.Haskell.TH.Lib.listE' listE :: [LHsExpr GhcPs] -> LHsExpr GhcPs listE es = inheritLoc es $ ExplicitList defExt #if __GLASGOW_HASKELL__ < 902 Nothing #endif es -- | Equivalent of 'Language.Haskell.TH.Lib.lamE' lamE :: NonEmpty (LPat GhcPs) -> LHsExpr GhcPs -> LHsExpr GhcPs lamE pats body = inheritLoc body $ HsLam defExt $ MG defExt (inheritLoc body [inheritLoc body match]) Generated where match :: Match GhcPs (LHsExpr GhcPs) match = Match defExt LambdaExpr (NE.toList pats) (simpleGHRSs body) -- | Convenience wrapper around 'lamE' for a single argument lamE1 :: LPat GhcPs -> LHsExpr GhcPs -> LHsExpr GhcPs lamE1 p = lamE (p :| []) -- | Equivalent of 'Language.Haskell.TH.Lib.caseE' caseE :: LHsExpr GhcPs -> [(LPat GhcPs, LHsExpr GhcPs)] -> LHsExpr GhcPs caseE x alts = inheritLoc x $ HsCase defExt x (MG defExt (inheritLoc x (map mkAlt alts)) Generated) where mkAlt :: (LPat GhcPs, LHsExpr GhcPs) -> LMatch GhcPs (LHsExpr GhcPs) mkAlt (pat, body) = inheritLoc x $ Match defExt CaseAlt [pat] (simpleGHRSs body) -- | Equivalent of 'Language.Haskell.TH.Lib.appsE' appsE :: LHsExpr GhcPs -> [LHsExpr GhcPs] -> LHsExpr GhcPs appsE = foldl' appE -- | Equivalent of 'Language.Haskell.TH.Lib.appT' appTypeE :: LHsExpr GhcPs -> LHsType GhcPs -> LHsExpr GhcPs appTypeE expr typ = inheritLoc expr $ HsAppType #if __GLASGOW_HASKELL__ >= 902 (toSrcSpan expr) #else defExt #endif expr (HsWC defExt typ) -- | Equivalent of 'Language.Haskell.TH.Lib.tupE' tupE :: NonEmpty (LHsExpr GhcPs) -> LHsExpr GhcPs tupE xs = inheritLoc xs $ ExplicitTuple defExt [inheritLoc xs (Present defExt x) | x <- NE.toList xs] Boxed -- | Equivalent of 'Language.Haskell.TH.Lib.sigE' sigE :: LHsExpr GhcPs -> LHsType GhcPs -> LHsExpr GhcPs sigE expr ty = inheritLoc expr $ ExprWithTySig defExt expr (HsWC defExt (implicitBndrs ty)) {------------------------------------------------------------------------------- .. without direct equivalent -------------------------------------------------------------------------------} -- | By analogy with 'stringE' intE :: Integral a => a -> LHsExpr GhcPs intE = litE . HsInt defExt . mkIntegralLit {------------------------------------------------------------------------------- Types -------------------------------------------------------------------------------} -- | Equivalent of 'Language.Haskell.TH.Lib.parensT' parensT :: LHsType GhcPs -> LHsType GhcPs parensT = noLocA . HsParTy defExt -- | Equivalent of 'Language.Haskell.TH.Lib.litT' litT :: HsTyLit -> LHsType GhcPs litT = noLocA . HsTyLit defExt -- | Equivalent of 'Language.Haskell.TH.Lib.varT' varT :: HasCallStack => LRdrName -> LHsType GhcPs varT name | isTypeVar name = inheritLoc name (HsTyVar defExt NotPromoted (reLocA name)) | otherwise = error "varT: incorrect name type" -- | Inverse to 'varT' viewVarT :: LHsType GhcPs -> Maybe LRdrName viewVarT (L _ (HsTyVar _ _ (reLoc -> name))) | isTypeVar name = Just name viewVarT _otherwise = Nothing pattern VarT :: HasCallStack => () => LRdrName -> LHsType GhcPs pattern VarT name <- (viewVarT -> Just name) where VarT = varT -- | Equivalent of 'Language.Haskell.TH.Lib.conT' conT :: HasCallStack => LRdrName -> LHsType GhcPs conT name | isTypeCon name = inheritLoc name (HsTyVar defExt NotPromoted (reLocA name)) | otherwise = error "varT: incorrect name type" -- | Inverse to 'conT' viewConT :: LHsType GhcPs -> Maybe LRdrName viewConT (L _ (HsTyVar _ _ (reLoc -> name))) | isTypeCon name = Just name viewConT _otherwise = Nothing pattern ConT :: HasCallStack => () => LRdrName -> LHsType GhcPs pattern ConT name <- (viewConT -> Just name) where ConT = conT -- | Equivalent of 'Language.Haskell.TH.Lib.appT' appT :: LHsType GhcPs -> LHsType GhcPs -> LHsType GhcPs appT = mkHsAppTy -- | Equivalent of 'Language.Haskell.TH.Lib.listT' -- -- Signature by analogy with 'Language.Haskell.TH.Lib.listE'. listT :: [LHsType GhcPs] -> LHsType GhcPs listT ts = inheritLoc ts $ HsExplicitListTy defExt IsPromoted ts {------------------------------------------------------------------------------- .. without direct equivalent -------------------------------------------------------------------------------} -- | By analogy with 'stringE' stringT :: String -> LHsType GhcPs stringT = litT . HsStrTy NoSourceText . fsLit -- | By analogy with 'appsE' appsT :: LHsType GhcPs -> [LHsType GhcPs] -> LHsType GhcPs appsT = foldl' appT -- | Function type -- -- TH only provides 'Language.Haskell.TH.Lib.arrowT'. funT :: LHsType GhcPs -> LHsType GhcPs -> LHsType GhcPs funT a b = inheritLoc a (hsFunTy defExt a b) -- | Tuple type -- -- TH only provides 'Language.Haskell.TH.Lib.tupleT'. -- Signature by analogy with 'tupE'. tupT :: NonEmpty (LHsType GhcPs) -> LHsType GhcPs tupT ts = inheritLoc ts $ HsExplicitTupleTy defExt (NE.toList ts) {------------------------------------------------------------------------------- Patterns -------------------------------------------------------------------------------} -- | Equivalent of 'Language.Haskell.TH.Lib.varP' varP :: LRdrName -> LPat GhcPs varP name = inheritLoc name (VarPat defExt (reLocA name)) -- | Equivalent of 'Language.Haskell.TH.Lib.conP' conP :: LRdrName -> [LPat GhcPs] -> LPat GhcPs #if __GLASGOW_HASKELL__ >= 902 conP con args = inheritLoc con (conPat con (PrefixCon [] args)) #else conP con args = inheritLoc con (conPat con (PrefixCon args)) #endif -- | Equivalent of 'Language.Haskell.TH.Lib.bangP' bangP :: LPat GhcPs -> LPat GhcPs bangP p = inheritLoc p $ BangPat defExt p -- | Equivalent of 'Language.Haskell.TH.Lib.listP' listP :: [LPat GhcPs] -> LPat GhcPs listP xs = inheritLoc xs $ ListPat defExt xs -- | Equivalent of 'Language.Haskell.TH.Lib.wildP' wildP :: LPat GhcPs wildP = inheritLoc noSrcSpan (WildPat defExt) {------------------------------------------------------------------------------- Strictness -------------------------------------------------------------------------------} -- | Approximate equivalent of 'Language.Haskell.TH.Lib.bangType' -- -- The GHC API has no equivalent of 'Language.Haskell.TH.Syntax.BangType'. bangType :: LHsType GhcPs -> LHsType GhcPs bangType t = inheritLoc t $ HsBangTy defExt (HsSrcBang NoSourceText NoSrcUnpack SrcStrict) t {------------------------------------------------------------------------------- Class contexts -------------------------------------------------------------------------------} -- | Equivalent of 'Language.Haskell.TH.Lib.equalP' equalP :: LHsType GhcPs -> LHsType GhcPs -> LHsType GhcPs equalP x y = inheritLoc x $ mkHsOpTy #if __GLASGOW_HASKELL__ >= 904 NotPromoted #endif x (inheritLoc x eqTyCon_RDR) y {------------------------------------------------------------------------------- Constructors -------------------------------------------------------------------------------} -- | Equivalent of 'Language.Haskell.TH.Lib.rec' -- -- NOTE: The GHC AST (but not TH) supports declaring multiple record fields -- with the same type. We do not support this here (since we follow TH). recC :: LRdrName -> [(LRdrName, LHsType GhcPs)] -> LConDecl GhcPs recC = forallRecC [] [] -- | Inverse to 'recC' viewRecC :: LConDecl GhcPs -> Maybe (LRdrName, [(LRdrName, LHsType GhcPs)]) viewRecC (L _ ConDeclH98 { con_name = conName #if __GLASGOW_HASKELL__ >= 902 , con_forall = False #else , con_forall = L _ False #endif , con_ex_tvs = [] , con_mb_cxt = Nothing , con_args = RecCon (L _ fields) } ) = (reLoc conName ,) <$> mapM viewRecField fields where viewRecField :: LConDeclField GhcPs -> Maybe (LRdrName, LHsType GhcPs) viewRecField (L _ ConDeclField { cd_fld_names = [L _ fieldName] , cd_fld_type = ty } ) = Just $ (viewFieldOcc fieldName, ty) viewRecField _otherwise = Nothing viewFieldOcc :: FieldOcc GhcPs -> LRdrName viewFieldOcc (FieldOcc _ (reLoc -> name)) = name #if __GLASGOW_HASKELL__ < 900 viewFieldOcc _ = panic "viewFieldOcc" #endif viewRecC _otherwise = Nothing pattern RecC :: LRdrName -> [(LRdrName, LHsType GhcPs)] -> LConDecl GhcPs pattern RecC conName args <- (viewRecC -> Just (conName, args)) where RecC = recC -- | Equivalent of the combination of 'Language.Haskell.TH.Lib.forallC' and -- 'Language.Haskell.TH.Lib.recC'. forallRecC :: [LRdrName] -- ^ @forallC@ argument: bound type variables -> [LHsType GhcPs] -- ^ @forallC@ argument: context -> LRdrName -- ^ @recC@ argument: record constructor name -> [(LRdrName, LHsType GhcPs)] -- ^ @recC@ argument: record fields -> LConDecl GhcPs forallRecC vars ctxt conName args = inheritLoc conName $ ConDeclH98 { con_ext = defExt , con_name = reLocA conName , con_forall = inheritLoc conName True , con_ex_tvs = map (setDefaultSpecificity . mkBndr) vars , con_mb_cxt = Just (inheritLoc conName ctxt) , con_args = RecCon (inheritLoc conName $ map (uncurry mkRecField) args) , con_doc = Nothing } where mkBndr :: LRdrName -> LHsTyVarBndr GhcPs mkBndr name = inheritLoc name $ userTyVar defExt name mkRecField :: LRdrName -> LHsType GhcPs -> LConDeclField GhcPs mkRecField name ty = inheritLoc name $ ConDeclField { cd_fld_ext = defExt , cd_fld_names = [inheritLoc name $ mkFieldOcc $ reLocA name] , cd_fld_type = ty , cd_fld_doc = Nothing } {------------------------------------------------------------------------------- Type variable binders -------------------------------------------------------------------------------} -- | Equivalent of 'Language.Haskell.TH.Lib.kindedTV' kindedTV :: LRdrName -> LHsType GhcPs -> LHsTyVarBndr GhcPs kindedTV name ty = inheritLoc name (kindedTyVar defExt name ty) {------------------------------------------------------------------------------- .. without direct equivalent -------------------------------------------------------------------------------} tyVarBndrName :: LHsTyVarBndr GhcPs -> LRdrName tyVarBndrName = hsTyVarLName . unLoc {------------------------------------------------------------------------------- Top-level declarations -------------------------------------------------------------------------------} -- | Equivalent of 'Language.Haskell.TH.Lib.sigD' sigD :: LRdrName -> LHsType GhcPs -> LHsDecl GhcPs sigD name ty = inheritLoc name $ SigD defExt sig where sig :: Sig GhcPs sig = TypeSig defExt [reLocA name] $ HsWC defExt (implicitBndrs ty) -- | Equivalent of 'Language.Haskell.TH.Lib.valD' -- -- Currently this offers a simplified API only. valD :: LRdrName -> LHsExpr GhcPs -> LHsDecl GhcPs valD fnName body = inheritLoc fnName $ ValD defExt (unLoc (simpleBinding fnName body)) -- | Equivalent of 'Language.Haskell.TH.Lib.dataD' dataD :: LRdrName -- ^ Datatype name -> [LHsTyVarBndr GhcPs] -- ^ Type arguments -> [LConDecl GhcPs] -- ^ Constructors -> [LHsDerivingClause GhcPs] -- ^ Deriving clauses -> LHsDecl GhcPs dataD typeName tyVars cons derivs = inheritLoc typeName $ TyClD defExt $ DataDecl { tcdDExt = defExt , tcdLName = reLocA typeName , tcdTyVars = mkHsQTvs tyVars , tcdFixity = Prefix , tcdDataDefn = HsDataDefn { dd_ext = defExt , dd_ND = DataType #if __GLASGOW_HASKELL__ >= 902 , dd_ctxt = Nothing #else , dd_ctxt = inheritLoc typeName [] #endif , dd_cType = Nothing , dd_kindSig = Nothing , dd_cons = cons , dd_derivs = inheritLoc typeName derivs } } -- | Inverse to 'dataD' viewDataD :: LHsDecl GhcPs -> Maybe ( LRdrName , [LHsTyVarBndr GhcPs] , [LConDecl GhcPs] , [LHsDerivingClause GhcPs] ) viewDataD (L _ (TyClD _ DataDecl { tcdLName = typeName , tcdTyVars = HsQTvs {hsq_explicit = tyVars} , tcdFixity = Prefix , tcdDataDefn = HsDataDefn { dd_ND = DataType #if __GLASGOW_HASKELL__ >= 902 , dd_ctxt = Nothing #else , dd_ctxt = L _ [] #endif , dd_cType = Nothing , dd_kindSig = Nothing , dd_cons = cons #if __GLASGOW_HASKELL__ >= 902 , dd_derivs = derivs #else , dd_derivs = L _ derivs #endif } } ) ) = Just (reLoc typeName, tyVars, cons, derivs) viewDataD _otherwise = Nothing pattern DataD :: LRdrName -> [LHsTyVarBndr GhcPs] -> [LConDecl GhcPs] -> [LHsDerivingClause GhcPs] -> LHsDecl GhcPs pattern DataD typeName tyVars cons derivs <- (viewDataD -> Just (typeName, tyVars, cons, derivs)) where DataD = dataD -- | Equivalent of 'Language.Haskell.TH.derivClaus' derivClause :: Maybe (LDerivStrategy GhcPs) -> NonEmpty (LHsType GhcPs) -> LHsDerivingClause GhcPs derivClause strat tys = inheritLoc tys $ HsDerivingClause defExt strat $ inheritLoc tys $ #if __GLASGOW_HASKELL__ >= 902 DctMulti defExt $ #endif map implicitBndrs (NE.toList tys) -- | Inverse of 'derivClause' viewDerivClause :: LHsDerivingClause GhcPs -> (Maybe (LDerivStrategy GhcPs), [LHsType GhcPs]) #if __GLASGOW_HASKELL__ >= 902 viewDerivClause (L _ (HsDerivingClause _ mStrat (L _ (DctMulti _ tys)))) = (mStrat, map viewImplicitBndrs tys) viewDerivClause (L _ (HsDerivingClause _ mStrat (L _ (DctSingle _ ty)))) = (mStrat, map viewImplicitBndrs [ty]) #else viewDerivClause (L _ (HsDerivingClause _ mStrat (L _ tys))) = (mStrat, map viewImplicitBndrs tys) #endif #if __GLASGOW_HASKELL__ < 900 viewDerivClause _ = panic "viewDerivClause" #endif pattern DerivClause :: Maybe (LDerivStrategy GhcPs) -> NonEmpty (LHsType GhcPs) -> LHsDerivingClause GhcPs pattern DerivClause strat tys <- (viewDerivClause -> (strat, NE.nonEmpty -> Just tys)) where DerivClause = derivClause -- | Equivalent of 'Language.Haskell.TH.Lib.instanceD' -- -- Unlike in TH, the regular bindings and associated types are separate args. instanceD :: [LHsType GhcPs] -- ^ Context -> LHsType GhcPs -- ^ Head -> [(LRdrName, LHsExpr GhcPs)] -- ^ Bindings -> [LTyFamInstDecl GhcPs] -- ^ Associated types -> LHsDecl GhcPs instanceD ctxt hd binds assocTypes = inheritLoc hd $ InstD defExt $ ClsInstD defExt $ ClsInstDecl { cid_ext = defExt , cid_poly_ty = implicitBndrs (qualT ctxt hd) , cid_binds = listToBag $ map (uncurry simpleBinding) binds , cid_sigs = [] , cid_tyfam_insts = assocTypes , cid_datafam_insts = [] , cid_overlap_mode = Nothing } where qualT :: [LHsType GhcPs] -> LHsType GhcPs -> LHsType GhcPs qualT [] a = a qualT ctx@(c:_) a = inheritLoc c $ HsQualTy defExt #if __GLASGOW_HASKELL__ >= 902 && __GLASGOW_HASKELL__ < 904 (Just (inheritLoc c ctx)) #else (inheritLoc c ctx) #endif a -- | Equivalent of 'Language.Haskell.TH.Lib.classD' classD :: [LHsType GhcPs] -- ^ Class context -> LRdrName -- ^ Class name -> [LHsTyVarBndr GhcPs] -- ^ Type variables -> [(LRdrName, LHsType GhcPs)] -- ^ Method signatures -> LHsDecl GhcPs classD = \ctx name clsVars sigs -> inheritLoc name $ TyClD defExt $ ClassDecl { tcdCExt = defExt #if __GLASGOW_HASKELL__ >= 902 , tcdCtxt = Just (inheritLoc name ctx) #else , tcdCtxt = inheritLoc name ctx #endif , tcdLName = reLocA name , tcdTyVars = mkHsQTvs clsVars , tcdFixity = Prefix , tcdFDs = [] , tcdSigs = map (uncurry classOpSig) sigs , tcdMeths = emptyBag , tcdATs = [] , tcdATDefs = [] , tcdDocs = [] } where classOpSig :: LRdrName -> LHsType GhcPs -> LSig GhcPs classOpSig name ty = inheritLoc name $ ClassOpSig defExt False [reLocA name] (implicitBndrs ty) -- | Approximate equivalent of 'Language.Haskell.TH.Lib.tySynEqn' tySynEqn :: LRdrName -- ^ Type family name -> [LHsType GhcPs] -- ^ Equation LHS -> LHsType GhcPs -- ^ Equation RHS -> LTyFamInstDecl GhcPs tySynEqn name pats val = inheritLoc val $ TyFamInstDecl #if __GLASGOW_HASKELL__ >= 902 defExt $ #else $ implicitBndrs $ #endif FamEqn defExt (reLocA name) #if __GLASGOW_HASKELL__ >= 902 (HsOuterImplicit defExt) #else Nothing #endif (map HsValArg pats) Prefix val {------------------------------------------------------------------------------- Pragmas NOTE: We work with 'LRdrName' everywhere, but 'AnnProvenance' /already/ wraps the @name@ type in @Located@. -------------------------------------------------------------------------------} type AnnProvenancePs = AnnProvenance #if __GLASGOW_HASKELL__ >= 902 GhcPs #else RdrName #endif -- | Equivalent of 'Language.Haskell.TH.Lib.typeAnnotation' typeAnnotation :: LRdrName -> AnnProvenancePs typeAnnotation name = TypeAnnProvenance (reLocA name) -- | Inverse to 'typeAnnotation' viewTypeAnnotation :: AnnProvenancePs -> Maybe LRdrName viewTypeAnnotation (TypeAnnProvenance name) = Just (reLoc name) viewTypeAnnotation _otherwise = Nothing pattern TypeAnnotation :: LRdrName -> AnnProvenancePs pattern TypeAnnotation name <- (viewTypeAnnotation -> Just name) where TypeAnnotation = typeAnnotation -- | Equivalent of 'Language.Haskell.TH.Lib.pragAnnD' pragAnnD :: AnnProvenancePs -> LHsExpr GhcPs -> AnnDecl GhcPs pragAnnD prov value = HsAnnotation defExt NoSourceText prov value viewPragAnnD :: AnnDecl GhcPs -> (AnnProvenancePs, LHsExpr GhcPs) viewPragAnnD (HsAnnotation _ _ prov value) = (prov, value) #if __GLASGOW_HASKELL__ < 900 viewPragAnnD _ = panic "viewPragAnnD" #endif pattern PragAnnD :: AnnProvenancePs -> LHsExpr GhcPs -> AnnDecl GhcPs pattern PragAnnD prov value <- (viewPragAnnD -> (prov, value)) where PragAnnD = pragAnnD {------------------------------------------------------------------------------- Internal auxiliary -------------------------------------------------------------------------------} #if __GLASGOW_HASKELL__ >= 902 implicitBndrs :: LHsType GhcPs -> LHsSigType GhcPs implicitBndrs t = inheritLoc t (HsSig defExt (HsOuterImplicit defExt) t) viewImplicitBndrs :: LHsSigType GhcPs -> LHsType GhcPs viewImplicitBndrs (L _ (HsSig _ _ ty)) = ty #else implicitBndrs :: a -> HsImplicitBndrs GhcPs a implicitBndrs a = HsIB defExt a viewImplicitBndrs :: HsImplicitBndrs GhcPs a -> a viewImplicitBndrs (HsIB _ a) = a #if __GLASGOW_HASKELL__ < 900 viewImplicitBndrs _ = panic "viewImplicitBndrs" #endif #endif -- | Simple binding (without patterns) simpleBinding :: LRdrName -> LHsExpr GhcPs -> LHsBind GhcPs simpleBinding fnName body = inheritLoc fnName $ mkFunBind fnName [match] where grhs :: GRHSs GhcPs (LHsExpr GhcPs) grhs = simpleGHRSs body match :: LMatch GhcPs (LHsExpr GhcPs) match = inheritLoc fnName $ Match defExt (FunRhs (reLocA fnName) Prefix NoSrcStrict) [] grhs -- | Simple guarded RHS (no guards) simpleGHRSs :: LHsExpr GhcPs -> GRHSs GhcPs (LHsExpr GhcPs) simpleGHRSs body = GRHSs defExt [inheritLoc body $ GRHS defExt [] body] (inheritLoc body $ EmptyLocalBinds defExt)