{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE ViewPatterns #-}
module Convert( convertToHsExpr, convertToPat, convertToHsDecls,
convertToHsType,
thRdrNameGuesses ) where
import GhcPrelude
import HsSyn as Hs
import PrelNames
import RdrName
import qualified Name
import Module
import RdrHsSyn
import OccName
import SrcLoc
import Type
import qualified Coercion ( Role(..) )
import TysWiredIn
import BasicTypes as Hs
import ForeignCall
import Unique
import ErrUtils
import Bag
import Lexeme
import Util
import FastString
import Outputable
import MonadUtils ( foldrM )
import qualified Data.ByteString as BS
import Control.Monad( unless, liftM, ap )
import Data.Maybe( catMaybes, isNothing )
import Language.Haskell.TH as TH hiding (sigP)
import Language.Haskell.TH.Syntax as TH
convertToHsDecls :: SrcSpan -> [TH.Dec] -> Either MsgDoc [LHsDecl GhcPs]
convertToHsDecls loc ds = initCvt loc (fmap catMaybes (mapM cvt_dec ds))
where
cvt_dec d = wrapMsg "declaration" d (cvtDec d)
convertToHsExpr :: SrcSpan -> TH.Exp -> Either MsgDoc (LHsExpr GhcPs)
convertToHsExpr loc e
= initCvt loc $ wrapMsg "expression" e $ cvtl e
convertToPat :: SrcSpan -> TH.Pat -> Either MsgDoc (LPat GhcPs)
convertToPat loc p
= initCvt loc $ wrapMsg "pattern" p $ cvtPat p
convertToHsType :: SrcSpan -> TH.Type -> Either MsgDoc (LHsType GhcPs)
convertToHsType loc t
= initCvt loc $ wrapMsg "type" t $ cvtType t
newtype CvtM a = CvtM { unCvtM :: SrcSpan -> Either MsgDoc (SrcSpan, a) }
instance Functor CvtM where
fmap = liftM
instance Applicative CvtM where
pure x = CvtM $ \loc -> Right (loc,x)
(<*>) = ap
instance Monad CvtM where
(CvtM m) >>= k = CvtM $ \loc -> case m loc of
Left err -> Left err
Right (loc',v) -> unCvtM (k v) loc'
initCvt :: SrcSpan -> CvtM a -> Either MsgDoc a
initCvt loc (CvtM m) = fmap snd (m loc)
force :: a -> CvtM ()
force a = a `seq` return ()
failWith :: MsgDoc -> CvtM a
failWith m = CvtM (\_ -> Left m)
getL :: CvtM SrcSpan
getL = CvtM (\loc -> Right (loc,loc))
setL :: SrcSpan -> CvtM ()
setL loc = CvtM (\_ -> Right (loc, ()))
returnL :: HasSrcSpan a => SrcSpanLess a -> CvtM a
returnL x = CvtM (\loc -> Right (loc, cL loc x))
returnJustL :: HasSrcSpan a => SrcSpanLess a -> CvtM (Maybe a)
returnJustL = fmap Just . returnL
wrapParL :: HasSrcSpan a =>
(a -> SrcSpanLess a) -> SrcSpanLess a -> CvtM (SrcSpanLess a)
wrapParL add_par x = CvtM (\loc -> Right (loc, add_par (cL loc x)))
wrapMsg :: (Show a, TH.Ppr a) => String -> a -> CvtM b -> CvtM b
wrapMsg what item (CvtM m)
= CvtM (\loc -> case m loc of
Left err -> Left (err $$ getPprStyle msg)
Right v -> Right v)
where
msg sty = hang (text "When splicing a TH" <+> text what <> colon)
2 (if debugStyle sty
then text (show item)
else text (pprint item))
wrapL :: HasSrcSpan a => CvtM (SrcSpanLess a) -> CvtM a
wrapL (CvtM m) = CvtM (\loc -> case m loc of
Left err -> Left err
Right (loc',v) -> Right (loc',cL loc v))
cvtDecs :: [TH.Dec] -> CvtM [LHsDecl GhcPs]
cvtDecs = fmap catMaybes . mapM cvtDec
cvtDec :: TH.Dec -> CvtM (Maybe (LHsDecl GhcPs))
cvtDec (TH.ValD pat body ds)
| TH.VarP s <- pat
= do { s' <- vNameL s
; cl' <- cvtClause (mkPrefixFunRhs s') (Clause [] body ds)
; returnJustL $ Hs.ValD noExt $ mkFunBind s' [cl'] }
| otherwise
= do { pat' <- cvtPat pat
; body' <- cvtGuard body
; ds' <- cvtLocalDecs (text "a where clause") ds
; returnJustL $ Hs.ValD noExt $
PatBind { pat_lhs = pat'
, pat_rhs = GRHSs noExt body' (noLoc ds')
, pat_ext = noExt
, pat_ticks = ([],[]) } }
cvtDec (TH.FunD nm cls)
| null cls
= failWith (text "Function binding for"
<+> quotes (text (TH.pprint nm))
<+> text "has no equations")
| otherwise
= do { nm' <- vNameL nm
; cls' <- mapM (cvtClause (mkPrefixFunRhs nm')) cls
; returnJustL $ Hs.ValD noExt $ mkFunBind nm' cls' }
cvtDec (TH.SigD nm typ)
= do { nm' <- vNameL nm
; ty' <- cvtType typ
; returnJustL $ Hs.SigD noExt
(TypeSig noExt [nm'] (mkLHsSigWcType ty')) }
cvtDec (TH.InfixD fx nm)
= do { nm' <- vcNameL nm
; returnJustL (Hs.SigD noExt (FixSig noExt
(FixitySig noExt [nm'] (cvtFixity fx)))) }
cvtDec (PragmaD prag)
= cvtPragmaD prag
cvtDec (TySynD tc tvs rhs)
= do { (_, tc', tvs') <- cvt_tycl_hdr [] tc tvs
; rhs' <- cvtType rhs
; returnJustL $ TyClD noExt $
SynDecl { tcdSExt = noExt, tcdLName = tc', tcdTyVars = tvs'
, tcdFixity = Prefix
, tcdRhs = rhs' } }
cvtDec (DataD ctxt tc tvs ksig constrs derivs)
= do { let isGadtCon (GadtC _ _ _) = True
isGadtCon (RecGadtC _ _ _) = True
isGadtCon (ForallC _ _ c) = isGadtCon c
isGadtCon _ = False
isGadtDecl = all isGadtCon constrs
isH98Decl = all (not . isGadtCon) constrs
; unless (isGadtDecl || isH98Decl)
(failWith (text "Cannot mix GADT constructors with Haskell 98"
<+> text "constructors"))
; unless (isNothing ksig || isGadtDecl)
(failWith (text "Kind signatures are only allowed on GADTs"))
; (ctxt', tc', tvs') <- cvt_tycl_hdr ctxt tc tvs
; ksig' <- cvtKind `traverse` ksig
; cons' <- mapM cvtConstr constrs
; derivs' <- cvtDerivs derivs
; let defn = HsDataDefn { dd_ext = noExt
, dd_ND = DataType, dd_cType = Nothing
, dd_ctxt = ctxt'
, dd_kindSig = ksig'
, dd_cons = cons', dd_derivs = derivs' }
; returnJustL $ TyClD noExt (DataDecl
{ tcdDExt = noExt
, tcdLName = tc', tcdTyVars = tvs'
, tcdFixity = Prefix
, tcdDataDefn = defn }) }
cvtDec (NewtypeD ctxt tc tvs ksig constr derivs)
= do { (ctxt', tc', tvs') <- cvt_tycl_hdr ctxt tc tvs
; ksig' <- cvtKind `traverse` ksig
; con' <- cvtConstr constr
; derivs' <- cvtDerivs derivs
; let defn = HsDataDefn { dd_ext = noExt
, dd_ND = NewType, dd_cType = Nothing
, dd_ctxt = ctxt'
, dd_kindSig = ksig'
, dd_cons = [con']
, dd_derivs = derivs' }
; returnJustL $ TyClD noExt (DataDecl
{ tcdDExt = noExt
, tcdLName = tc', tcdTyVars = tvs'
, tcdFixity = Prefix
, tcdDataDefn = defn }) }
cvtDec (ClassD ctxt cl tvs fds decs)
= do { (cxt', tc', tvs') <- cvt_tycl_hdr ctxt cl tvs
; fds' <- mapM cvt_fundep fds
; (binds', sigs', fams', ats', adts') <- cvt_ci_decs (text "a class declaration") decs
; unless (null adts')
(failWith $ (text "Default data instance declarations"
<+> text "are not allowed:")
$$ (Outputable.ppr adts'))
; at_defs <- mapM cvt_at_def ats'
; returnJustL $ TyClD noExt $
ClassDecl { tcdCExt = noExt
, tcdCtxt = cxt', tcdLName = tc', tcdTyVars = tvs'
, tcdFixity = Prefix
, tcdFDs = fds', tcdSigs = Hs.mkClassOpSigs sigs'
, tcdMeths = binds'
, tcdATs = fams', tcdATDefs = at_defs, tcdDocs = [] }
}
where
cvt_at_def :: LTyFamInstDecl GhcPs -> CvtM (LTyFamDefltEqn GhcPs)
cvt_at_def decl = case RdrHsSyn.mkATDefault decl of
Right (def, _) -> return def
Left (_, msg) -> failWith msg
cvtDec (InstanceD o ctxt ty decs)
= do { let doc = text "an instance declaration"
; (binds', sigs', fams', ats', adts') <- cvt_ci_decs doc decs
; unless (null fams') (failWith (mkBadDecMsg doc fams'))
; ctxt' <- cvtContext ctxt
; (dL->L loc ty') <- cvtType ty
; let inst_ty' = mkHsQualTy ctxt loc ctxt' $ cL loc ty'
; returnJustL $ InstD noExt $ ClsInstD noExt $
ClsInstDecl { cid_ext = noExt, cid_poly_ty = mkLHsSigType inst_ty'
, cid_binds = binds'
, cid_sigs = Hs.mkClassOpSigs sigs'
, cid_tyfam_insts = ats', cid_datafam_insts = adts'
, cid_overlap_mode = fmap (cL loc . overlap) o } }
where
overlap pragma =
case pragma of
TH.Overlaps -> Hs.Overlaps (SourceText "OVERLAPS")
TH.Overlappable -> Hs.Overlappable (SourceText "OVERLAPPABLE")
TH.Overlapping -> Hs.Overlapping (SourceText "OVERLAPPING")
TH.Incoherent -> Hs.Incoherent (SourceText "INCOHERENT")
cvtDec (ForeignD ford)
= do { ford' <- cvtForD ford
; returnJustL $ ForD noExt ford' }
cvtDec (DataFamilyD tc tvs kind)
= do { (_, tc', tvs') <- cvt_tycl_hdr [] tc tvs
; result <- cvtMaybeKindToFamilyResultSig kind
; returnJustL $ TyClD noExt $ FamDecl noExt $
FamilyDecl noExt DataFamily tc' tvs' Prefix result Nothing }
cvtDec (DataInstD ctxt bndrs tys ksig constrs derivs)
= do { (ctxt', tc', bndrs', typats') <- cvt_datainst_hdr ctxt bndrs tys
; ksig' <- cvtKind `traverse` ksig
; cons' <- mapM cvtConstr constrs
; derivs' <- cvtDerivs derivs
; let defn = HsDataDefn { dd_ext = noExt
, dd_ND = DataType, dd_cType = Nothing
, dd_ctxt = ctxt'
, dd_kindSig = ksig'
, dd_cons = cons', dd_derivs = derivs' }
; returnJustL $ InstD noExt $ DataFamInstD
{ dfid_ext = noExt
, dfid_inst = DataFamInstDecl { dfid_eqn = mkHsImplicitBndrs $
FamEqn { feqn_ext = noExt
, feqn_tycon = tc'
, feqn_bndrs = bndrs'
, feqn_pats = typats'
, feqn_rhs = defn
, feqn_fixity = Prefix } }}}
cvtDec (NewtypeInstD ctxt bndrs tys ksig constr derivs)
= do { (ctxt', tc', bndrs', typats') <- cvt_datainst_hdr ctxt bndrs tys
; ksig' <- cvtKind `traverse` ksig
; con' <- cvtConstr constr
; derivs' <- cvtDerivs derivs
; let defn = HsDataDefn { dd_ext = noExt
, dd_ND = NewType, dd_cType = Nothing
, dd_ctxt = ctxt'
, dd_kindSig = ksig'
, dd_cons = [con'], dd_derivs = derivs' }
; returnJustL $ InstD noExt $ DataFamInstD
{ dfid_ext = noExt
, dfid_inst = DataFamInstDecl { dfid_eqn = mkHsImplicitBndrs $
FamEqn { feqn_ext = noExt
, feqn_tycon = tc'
, feqn_bndrs = bndrs'
, feqn_pats = typats'
, feqn_rhs = defn
, feqn_fixity = Prefix } }}}
cvtDec (TySynInstD eqn)
= do { (dL->L _ eqn') <- cvtTySynEqn eqn
; returnJustL $ InstD noExt $ TyFamInstD
{ tfid_ext = noExt
, tfid_inst = TyFamInstDecl { tfid_eqn = eqn' } } }
cvtDec (OpenTypeFamilyD head)
= do { (tc', tyvars', result', injectivity') <- cvt_tyfam_head head
; returnJustL $ TyClD noExt $ FamDecl noExt $
FamilyDecl noExt OpenTypeFamily tc' tyvars' Prefix result' injectivity'
}
cvtDec (ClosedTypeFamilyD head eqns)
= do { (tc', tyvars', result', injectivity') <- cvt_tyfam_head head
; eqns' <- mapM cvtTySynEqn eqns
; returnJustL $ TyClD noExt $ FamDecl noExt $
FamilyDecl noExt (ClosedTypeFamily (Just eqns')) tc' tyvars' Prefix
result' injectivity' }
cvtDec (TH.RoleAnnotD tc roles)
= do { tc' <- tconNameL tc
; let roles' = map (noLoc . cvtRole) roles
; returnJustL $ Hs.RoleAnnotD noExt (RoleAnnotDecl noExt tc' roles') }
cvtDec (TH.StandaloneDerivD ds cxt ty)
= do { cxt' <- cvtContext cxt
; ds' <- traverse cvtDerivStrategy ds
; (dL->L loc ty') <- cvtType ty
; let inst_ty' = mkHsQualTy cxt loc cxt' $ cL loc ty'
; returnJustL $ DerivD noExt $
DerivDecl { deriv_ext =noExt
, deriv_strategy = ds'
, deriv_type = mkLHsSigWcType inst_ty'
, deriv_overlap_mode = Nothing } }
cvtDec (TH.DefaultSigD nm typ)
= do { nm' <- vNameL nm
; ty' <- cvtType typ
; returnJustL $ Hs.SigD noExt
$ ClassOpSig noExt True [nm'] (mkLHsSigType ty')}
cvtDec (TH.PatSynD nm args dir pat)
= do { nm' <- cNameL nm
; args' <- cvtArgs args
; dir' <- cvtDir nm' dir
; pat' <- cvtPat pat
; returnJustL $ Hs.ValD noExt $ PatSynBind noExt $
PSB noExt nm' args' pat' dir' }
where
cvtArgs (TH.PrefixPatSyn args) = Hs.PrefixCon <$> mapM vNameL args
cvtArgs (TH.InfixPatSyn a1 a2) = Hs.InfixCon <$> vNameL a1 <*> vNameL a2
cvtArgs (TH.RecordPatSyn sels)
= do { sels' <- mapM vNameL sels
; vars' <- mapM (vNameL . mkNameS . nameBase) sels
; return $ Hs.RecCon $ zipWith RecordPatSynField sels' vars' }
cvtDir _ Unidir = return Unidirectional
cvtDir _ ImplBidir = return ImplicitBidirectional
cvtDir n (ExplBidir cls) =
do { ms <- mapM (cvtClause (mkPrefixFunRhs n)) cls
; return $ ExplicitBidirectional $ mkMatchGroup FromSource ms }
cvtDec (TH.PatSynSigD nm ty)
= do { nm' <- cNameL nm
; ty' <- cvtPatSynSigTy ty
; returnJustL $ Hs.SigD noExt $ PatSynSig noExt [nm'] (mkLHsSigType ty')}
cvtDec (TH.ImplicitParamBindD _ _)
= failWith (text "Implicit parameter binding only allowed in let or where")
cvtTySynEqn :: TySynEqn -> CvtM (LTyFamInstEqn GhcPs)
cvtTySynEqn (TySynEqn mb_bndrs lhs rhs)
= do { mb_bndrs' <- traverse (mapM cvt_tv) mb_bndrs
; (head_ty, args) <- split_ty_app lhs
; case head_ty of
ConT nm -> do { nm' <- tconNameL nm
; rhs' <- cvtType rhs
; let args' = map wrap_tyarg args
; returnL $ mkHsImplicitBndrs
$ FamEqn { feqn_ext = noExt
, feqn_tycon = nm'
, feqn_bndrs = mb_bndrs'
, feqn_pats = args'
, feqn_fixity = Prefix
, feqn_rhs = rhs' } }
InfixT t1 nm t2 -> do { nm' <- tconNameL nm
; args' <- mapM cvtType [t1,t2]
; rhs' <- cvtType rhs
; returnL $ mkHsImplicitBndrs
$ FamEqn { feqn_ext = noExt
, feqn_tycon = nm'
, feqn_bndrs = mb_bndrs'
, feqn_pats =
(map HsValArg args') ++ args
, feqn_fixity = Hs.Infix
, feqn_rhs = rhs' } }
_ -> failWith $ text "Invalid type family instance LHS:"
<+> text (show lhs)
}
cvt_ci_decs :: MsgDoc -> [TH.Dec]
-> CvtM (LHsBinds GhcPs,
[LSig GhcPs],
[LFamilyDecl GhcPs],
[LTyFamInstDecl GhcPs],
[LDataFamInstDecl GhcPs])
cvt_ci_decs doc decs
= do { decs' <- cvtDecs decs
; let (ats', bind_sig_decs') = partitionWith is_tyfam_inst decs'
; let (adts', no_ats') = partitionWith is_datafam_inst bind_sig_decs'
; let (sigs', prob_binds') = partitionWith is_sig no_ats'
; let (binds', prob_fams') = partitionWith is_bind prob_binds'
; let (fams', bads) = partitionWith is_fam_decl prob_fams'
; unless (null bads) (failWith (mkBadDecMsg doc bads))
; return (listToBag binds', sigs', fams', ats', adts') }
cvt_tycl_hdr :: TH.Cxt -> TH.Name -> [TH.TyVarBndr]
-> CvtM ( LHsContext GhcPs
, Located RdrName
, LHsQTyVars GhcPs)
cvt_tycl_hdr cxt tc tvs
= do { cxt' <- cvtContext cxt
; tc' <- tconNameL tc
; tvs' <- cvtTvs tvs
; return (cxt', tc', tvs')
}
cvt_datainst_hdr :: TH.Cxt -> Maybe [TH.TyVarBndr] -> TH.Type
-> CvtM ( LHsContext GhcPs
, Located RdrName
, Maybe [LHsTyVarBndr GhcPs]
, HsTyPats GhcPs)
cvt_datainst_hdr cxt bndrs tys
= do { cxt' <- cvtContext cxt
; bndrs' <- traverse (mapM cvt_tv) bndrs
; (head_ty, args) <- split_ty_app tys
; case head_ty of
ConT nm -> do { nm' <- tconNameL nm
; let args' = map wrap_tyarg args
; return (cxt', nm', bndrs', args') }
InfixT t1 nm t2 -> do { nm' <- tconNameL nm
; args' <- mapM cvtType [t1,t2]
; return (cxt', nm', bndrs',
((map HsValArg args') ++ args)) }
_ -> failWith $ text "Invalid type instance header:"
<+> text (show tys) }
cvt_tyfam_head :: TypeFamilyHead
-> CvtM ( Located RdrName
, LHsQTyVars GhcPs
, Hs.LFamilyResultSig GhcPs
, Maybe (Hs.LInjectivityAnn GhcPs))
cvt_tyfam_head (TypeFamilyHead tc tyvars result injectivity)
= do {(_, tc', tyvars') <- cvt_tycl_hdr [] tc tyvars
; result' <- cvtFamilyResultSig result
; injectivity' <- traverse cvtInjectivityAnnotation injectivity
; return (tc', tyvars', result', injectivity') }
is_fam_decl :: LHsDecl GhcPs -> Either (LFamilyDecl GhcPs) (LHsDecl GhcPs)
is_fam_decl (dL->L loc (TyClD _ (FamDecl { tcdFam = d }))) = Left (cL loc d)
is_fam_decl decl = Right decl
is_tyfam_inst :: LHsDecl GhcPs -> Either (LTyFamInstDecl GhcPs) (LHsDecl GhcPs)
is_tyfam_inst (dL->L loc (Hs.InstD _ (TyFamInstD { tfid_inst = d })))
= Left (cL loc d)
is_tyfam_inst decl
= Right decl
is_datafam_inst :: LHsDecl GhcPs
-> Either (LDataFamInstDecl GhcPs) (LHsDecl GhcPs)
is_datafam_inst (dL->L loc (Hs.InstD _ (DataFamInstD { dfid_inst = d })))
= Left (cL loc d)
is_datafam_inst decl
= Right decl
is_sig :: LHsDecl GhcPs -> Either (LSig GhcPs) (LHsDecl GhcPs)
is_sig (dL->L loc (Hs.SigD _ sig)) = Left (cL loc sig)
is_sig decl = Right decl
is_bind :: LHsDecl GhcPs -> Either (LHsBind GhcPs) (LHsDecl GhcPs)
is_bind (dL->L loc (Hs.ValD _ bind)) = Left (cL loc bind)
is_bind decl = Right decl
is_ip_bind :: TH.Dec -> Either (String, TH.Exp) TH.Dec
is_ip_bind (TH.ImplicitParamBindD n e) = Left (n, e)
is_ip_bind decl = Right decl
mkBadDecMsg :: Outputable a => MsgDoc -> [a] -> MsgDoc
mkBadDecMsg doc bads
= sep [ text "Illegal declaration(s) in" <+> doc <> colon
, nest 2 (vcat (map Outputable.ppr bads)) ]
cvtConstr :: TH.Con -> CvtM (LConDecl GhcPs)
cvtConstr (NormalC c strtys)
= do { c' <- cNameL c
; tys' <- mapM cvt_arg strtys
; returnL $ mkConDeclH98 c' Nothing Nothing (PrefixCon tys') }
cvtConstr (RecC c varstrtys)
= do { c' <- cNameL c
; args' <- mapM cvt_id_arg varstrtys
; returnL $ mkConDeclH98 c' Nothing Nothing
(RecCon (noLoc args')) }
cvtConstr (InfixC st1 c st2)
= do { c' <- cNameL c
; st1' <- cvt_arg st1
; st2' <- cvt_arg st2
; returnL $ mkConDeclH98 c' Nothing Nothing (InfixCon st1' st2') }
cvtConstr (ForallC tvs ctxt con)
= do { tvs' <- cvtTvs tvs
; ctxt' <- cvtContext ctxt
; (dL->L _ con') <- cvtConstr con
; returnL $ add_forall tvs' ctxt' con' }
where
add_cxt lcxt Nothing = Just lcxt
add_cxt (dL->L loc cxt1) (Just (dL->L _ cxt2))
= Just (cL loc (cxt1 ++ cxt2))
add_forall tvs' cxt' con@(ConDeclGADT { con_qvars = qvars, con_mb_cxt = cxt })
= con { con_forall = noLoc $ not (null all_tvs)
, con_qvars = mkHsQTvs all_tvs
, con_mb_cxt = add_cxt cxt' cxt }
where
all_tvs = hsQTvExplicit tvs' ++ hsQTvExplicit qvars
add_forall tvs' cxt' con@(ConDeclH98 { con_ex_tvs = ex_tvs, con_mb_cxt = cxt })
= con { con_forall = noLoc $ not (null all_tvs)
, con_ex_tvs = all_tvs
, con_mb_cxt = add_cxt cxt' cxt }
where
all_tvs = hsQTvExplicit tvs' ++ ex_tvs
add_forall _ _ (XConDecl _) = panic "cvtConstr"
cvtConstr (GadtC c strtys ty)
= do { c' <- mapM cNameL c
; args <- mapM cvt_arg strtys
; (dL->L _ ty') <- cvtType ty
; c_ty <- mk_arr_apps args ty'
; returnL $ fst $ mkGadtDecl c' c_ty}
cvtConstr (RecGadtC c varstrtys ty)
= do { c' <- mapM cNameL c
; ty' <- cvtType ty
; rec_flds <- mapM cvt_id_arg varstrtys
; let rec_ty = noLoc (HsFunTy noExt
(noLoc $ HsRecTy noExt rec_flds) ty')
; returnL $ fst $ mkGadtDecl c' rec_ty }
cvtSrcUnpackedness :: TH.SourceUnpackedness -> SrcUnpackedness
cvtSrcUnpackedness NoSourceUnpackedness = NoSrcUnpack
cvtSrcUnpackedness SourceNoUnpack = SrcNoUnpack
cvtSrcUnpackedness SourceUnpack = SrcUnpack
cvtSrcStrictness :: TH.SourceStrictness -> SrcStrictness
cvtSrcStrictness NoSourceStrictness = NoSrcStrict
cvtSrcStrictness SourceLazy = SrcLazy
cvtSrcStrictness SourceStrict = SrcStrict
cvt_arg :: (TH.Bang, TH.Type) -> CvtM (LHsType GhcPs)
cvt_arg (Bang su ss, ty)
= do { ty'' <- cvtType ty
; let ty' = parenthesizeHsType appPrec ty''
su' = cvtSrcUnpackedness su
ss' = cvtSrcStrictness ss
; returnL $ HsBangTy noExt (HsSrcBang NoSourceText su' ss') ty' }
cvt_id_arg :: (TH.Name, TH.Bang, TH.Type) -> CvtM (LConDeclField GhcPs)
cvt_id_arg (i, str, ty)
= do { (dL->L li i') <- vNameL i
; ty' <- cvt_arg (str,ty)
; return $ noLoc (ConDeclField
{ cd_fld_ext = noExt
, cd_fld_names
= [cL li $ FieldOcc noExt (cL li i')]
, cd_fld_type = ty'
, cd_fld_doc = Nothing}) }
cvtDerivs :: [TH.DerivClause] -> CvtM (HsDeriving GhcPs)
cvtDerivs cs = do { cs' <- mapM cvtDerivClause cs
; returnL cs' }
cvt_fundep :: FunDep -> CvtM (LHsFunDep GhcPs)
cvt_fundep (FunDep xs ys) = do { xs' <- mapM tNameL xs
; ys' <- mapM tNameL ys
; returnL (xs', ys') }
cvtForD :: Foreign -> CvtM (ForeignDecl GhcPs)
cvtForD (ImportF callconv safety from nm ty)
| callconv == TH.Prim || callconv == TH.JavaScript
= mk_imp (CImport (noLoc (cvt_conv callconv)) (noLoc safety') Nothing
(CFunction (StaticTarget (SourceText from)
(mkFastString from) Nothing
True))
(noLoc $ quotedSourceText from))
| Just impspec <- parseCImport (noLoc (cvt_conv callconv)) (noLoc safety')
(mkFastString (TH.nameBase nm))
from (noLoc $ quotedSourceText from)
= mk_imp impspec
| otherwise
= failWith $ text (show from) <+> text "is not a valid ccall impent"
where
mk_imp impspec
= do { nm' <- vNameL nm
; ty' <- cvtType ty
; return (ForeignImport { fd_i_ext = noExt
, fd_name = nm'
, fd_sig_ty = mkLHsSigType ty'
, fd_fi = impspec })
}
safety' = case safety of
Unsafe -> PlayRisky
Safe -> PlaySafe
Interruptible -> PlayInterruptible
cvtForD (ExportF callconv as nm ty)
= do { nm' <- vNameL nm
; ty' <- cvtType ty
; let e = CExport (noLoc (CExportStatic (SourceText as)
(mkFastString as)
(cvt_conv callconv)))
(noLoc (SourceText as))
; return $ ForeignExport { fd_e_ext = noExt
, fd_name = nm'
, fd_sig_ty = mkLHsSigType ty'
, fd_fe = e } }
cvt_conv :: TH.Callconv -> CCallConv
cvt_conv TH.CCall = CCallConv
cvt_conv TH.StdCall = StdCallConv
cvt_conv TH.CApi = CApiConv
cvt_conv TH.Prim = PrimCallConv
cvt_conv TH.JavaScript = JavaScriptCallConv
cvtPragmaD :: Pragma -> CvtM (Maybe (LHsDecl GhcPs))
cvtPragmaD (InlineP nm inline rm phases)
= do { nm' <- vNameL nm
; let dflt = dfltActivation inline
; let src TH.NoInline = "{-# NOINLINE"
src TH.Inline = "{-# INLINE"
src TH.Inlinable = "{-# INLINABLE"
; let ip = InlinePragma { inl_src = SourceText $ src inline
, inl_inline = cvtInline inline
, inl_rule = cvtRuleMatch rm
, inl_act = cvtPhases phases dflt
, inl_sat = Nothing }
; returnJustL $ Hs.SigD noExt $ InlineSig noExt nm' ip }
cvtPragmaD (SpecialiseP nm ty inline phases)
= do { nm' <- vNameL nm
; ty' <- cvtType ty
; let src TH.NoInline = "{-# SPECIALISE NOINLINE"
src TH.Inline = "{-# SPECIALISE INLINE"
src TH.Inlinable = "{-# SPECIALISE INLINE"
; let (inline', dflt,srcText) = case inline of
Just inline1 -> (cvtInline inline1, dfltActivation inline1,
src inline1)
Nothing -> (NoUserInline, AlwaysActive,
"{-# SPECIALISE")
; let ip = InlinePragma { inl_src = SourceText srcText
, inl_inline = inline'
, inl_rule = Hs.FunLike
, inl_act = cvtPhases phases dflt
, inl_sat = Nothing }
; returnJustL $ Hs.SigD noExt $ SpecSig noExt nm' [mkLHsSigType ty'] ip }
cvtPragmaD (SpecialiseInstP ty)
= do { ty' <- cvtType ty
; returnJustL $ Hs.SigD noExt $
SpecInstSig noExt (SourceText "{-# SPECIALISE") (mkLHsSigType ty') }
cvtPragmaD (RuleP nm ty_bndrs tm_bndrs lhs rhs phases)
= do { let nm' = mkFastString nm
; let act = cvtPhases phases AlwaysActive
; ty_bndrs' <- traverse (mapM cvt_tv) ty_bndrs
; tm_bndrs' <- mapM cvtRuleBndr tm_bndrs
; lhs' <- cvtl lhs
; rhs' <- cvtl rhs
; returnJustL $ Hs.RuleD noExt
$ HsRules { rds_ext = noExt
, rds_src = SourceText "{-# RULES"
, rds_rules = [noLoc $
HsRule { rd_ext = noExt
, rd_name = (noLoc (quotedSourceText nm,nm'))
, rd_act = act
, rd_tyvs = ty_bndrs'
, rd_tmvs = tm_bndrs'
, rd_lhs = lhs'
, rd_rhs = rhs' }] }
}
cvtPragmaD (AnnP target exp)
= do { exp' <- cvtl exp
; target' <- case target of
ModuleAnnotation -> return ModuleAnnProvenance
TypeAnnotation n -> do
n' <- tconName n
return (TypeAnnProvenance (noLoc n'))
ValueAnnotation n -> do
n' <- vcName n
return (ValueAnnProvenance (noLoc n'))
; returnJustL $ Hs.AnnD noExt
$ HsAnnotation noExt (SourceText "{-# ANN") target' exp'
}
cvtPragmaD (LineP line file)
= do { setL (srcLocSpan (mkSrcLoc (fsLit file) line 1))
; return Nothing
}
cvtPragmaD (CompleteP cls mty)
= do { cls' <- noLoc <$> mapM cNameL cls
; mty' <- traverse tconNameL mty
; returnJustL $ Hs.SigD noExt
$ CompleteMatchSig noExt NoSourceText cls' mty' }
dfltActivation :: TH.Inline -> Activation
dfltActivation TH.NoInline = NeverActive
dfltActivation _ = AlwaysActive
cvtInline :: TH.Inline -> Hs.InlineSpec
cvtInline TH.NoInline = Hs.NoInline
cvtInline TH.Inline = Hs.Inline
cvtInline TH.Inlinable = Hs.Inlinable
cvtRuleMatch :: TH.RuleMatch -> RuleMatchInfo
cvtRuleMatch TH.ConLike = Hs.ConLike
cvtRuleMatch TH.FunLike = Hs.FunLike
cvtPhases :: TH.Phases -> Activation -> Activation
cvtPhases AllPhases dflt = dflt
cvtPhases (FromPhase i) _ = ActiveAfter NoSourceText i
cvtPhases (BeforePhase i) _ = ActiveBefore NoSourceText i
cvtRuleBndr :: TH.RuleBndr -> CvtM (Hs.LRuleBndr GhcPs)
cvtRuleBndr (RuleVar n)
= do { n' <- vNameL n
; return $ noLoc $ Hs.RuleBndr noExt n' }
cvtRuleBndr (TypedRuleVar n ty)
= do { n' <- vNameL n
; ty' <- cvtType ty
; return $ noLoc $ Hs.RuleBndrSig noExt n' $ mkLHsSigWcType ty' }
cvtLocalDecs :: MsgDoc -> [TH.Dec] -> CvtM (HsLocalBinds GhcPs)
cvtLocalDecs doc ds
= case partitionWith is_ip_bind ds of
([], []) -> return (EmptyLocalBinds noExt)
([], _) -> do
ds' <- cvtDecs ds
let (binds, prob_sigs) = partitionWith is_bind ds'
let (sigs, bads) = partitionWith is_sig prob_sigs
unless (null bads) (failWith (mkBadDecMsg doc bads))
return (HsValBinds noExt (ValBinds noExt (listToBag binds) sigs))
(ip_binds, []) -> do
binds <- mapM (uncurry cvtImplicitParamBind) ip_binds
return (HsIPBinds noExt (IPBinds noExt binds))
((_:_), (_:_)) ->
failWith (text "Implicit parameters mixed with other bindings")
cvtClause :: HsMatchContext RdrName
-> TH.Clause -> CvtM (Hs.LMatch GhcPs (LHsExpr GhcPs))
cvtClause ctxt (Clause ps body wheres)
= do { ps' <- cvtPats ps
; let pps = map (parenthesizePat appPrec) ps'
; g' <- cvtGuard body
; ds' <- cvtLocalDecs (text "a where clause") wheres
; returnL $ Hs.Match noExt ctxt pps (GRHSs noExt g' (noLoc ds')) }
cvtImplicitParamBind :: String -> TH.Exp -> CvtM (LIPBind GhcPs)
cvtImplicitParamBind n e = do
n' <- wrapL (ipName n)
e' <- cvtl e
returnL (IPBind noExt (Left n') e')
cvtl :: TH.Exp -> CvtM (LHsExpr GhcPs)
cvtl e = wrapL (cvt e)
where
cvt (VarE s) = do { s' <- vName s; return $ HsVar noExt (noLoc s') }
cvt (ConE s) = do { s' <- cName s; return $ HsVar noExt (noLoc s') }
cvt (LitE l)
| overloadedLit l = go cvtOverLit (HsOverLit noExt)
(hsOverLitNeedsParens appPrec)
| otherwise = go cvtLit (HsLit noExt)
(hsLitNeedsParens appPrec)
where
go :: (Lit -> CvtM (l GhcPs))
-> (l GhcPs -> HsExpr GhcPs)
-> (l GhcPs -> Bool)
-> CvtM (HsExpr GhcPs)
go cvt_lit mk_expr is_compound_lit = do
l' <- cvt_lit l
let e' = mk_expr l'
return $ if is_compound_lit l' then HsPar noExt (noLoc e') else e'
cvt (AppE x@(LamE _ _) y) = do { x' <- cvtl x; y' <- cvtl y
; return $ HsApp noExt (mkLHsPar x')
(mkLHsPar y')}
cvt (AppE x y) = do { x' <- cvtl x; y' <- cvtl y
; return $ HsApp noExt (mkLHsPar x')
(mkLHsPar y')}
cvt (AppTypeE e t) = do { e' <- cvtl e
; t' <- cvtType t
; let tp = parenthesizeHsType appPrec t'
; return $ HsAppType noExt e'
$ mkHsWildCardBndrs tp }
cvt (LamE [] e) = cvt e
cvt (LamE ps e) = do { ps' <- cvtPats ps; e' <- cvtl e
; let pats = map (parenthesizePat appPrec) ps'
; return $ HsLam noExt (mkMatchGroup FromSource
[mkSimpleMatch LambdaExpr
pats e'])}
cvt (LamCaseE ms) = do { ms' <- mapM (cvtMatch CaseAlt) ms
; return $ HsLamCase noExt
(mkMatchGroup FromSource ms')
}
cvt (TupE [e]) = do { e' <- cvtl e; return $ HsPar noExt e' }
cvt (TupE es) = do { es' <- mapM cvtl es
; return $ ExplicitTuple noExt
(map (noLoc . (Present noExt)) es')
Boxed }
cvt (UnboxedTupE es) = do { es' <- mapM cvtl es
; return $ ExplicitTuple noExt
(map (noLoc . (Present noExt)) es')
Unboxed }
cvt (UnboxedSumE e alt arity) = do { e' <- cvtl e
; unboxedSumChecks alt arity
; return $ ExplicitSum noExt
alt arity e'}
cvt (CondE x y z) = do { x' <- cvtl x; y' <- cvtl y; z' <- cvtl z;
; return $ HsIf noExt (Just noSyntaxExpr) x' y' z' }
cvt (MultiIfE alts)
| null alts = failWith (text "Multi-way if-expression with no alternatives")
| otherwise = do { alts' <- mapM cvtpair alts
; return $ HsMultiIf noExt alts' }
cvt (LetE ds e) = do { ds' <- cvtLocalDecs (text "a let expression") ds
; e' <- cvtl e; return $ HsLet noExt (noLoc ds') e'}
cvt (CaseE e ms) = do { e' <- cvtl e; ms' <- mapM (cvtMatch CaseAlt) ms
; return $ HsCase noExt e'
(mkMatchGroup FromSource ms') }
cvt (DoE ss) = cvtHsDo DoExpr ss
cvt (MDoE ss) = cvtHsDo MDoExpr ss
cvt (CompE ss) = cvtHsDo ListComp ss
cvt (ArithSeqE dd) = do { dd' <- cvtDD dd
; return $ ArithSeq noExt Nothing dd' }
cvt (ListE xs)
| Just s <- allCharLs xs = do { l' <- cvtLit (StringL s)
; return (HsLit noExt l') }
| otherwise = do { xs' <- mapM cvtl xs
; return $ ExplicitList noExt Nothing xs'
}
cvt (InfixE (Just x) s (Just y)) =
do { x' <- cvtl x
; s' <- cvtl s
; y' <- cvtl y
; let px = parenthesizeHsExpr opPrec x'
py = parenthesizeHsExpr opPrec y'
; wrapParL (HsPar noExt)
$ OpApp noExt px s' py }
cvt (InfixE Nothing s (Just y)) = do { s' <- cvtl s; y' <- cvtl y
; wrapParL (HsPar noExt) $
SectionR noExt s' y' }
cvt (InfixE (Just x) s Nothing ) = do { x' <- cvtl x; s' <- cvtl s
; wrapParL (HsPar noExt) $
SectionL noExt x' s' }
cvt (InfixE Nothing s Nothing ) = do { s' <- cvtl s
; return $ HsPar noExt s' }
cvt (UInfixE x s y) = do { x' <- cvtl x
; let x'' = case unLoc x' of
OpApp {} -> x'
_ -> mkLHsPar x'
; cvtOpApp x'' s y }
cvt (ParensE e) = do { e' <- cvtl e; return $ HsPar noExt e' }
cvt (SigE e t) = do { e' <- cvtl e; t' <- cvtType t
; let pe = parenthesizeHsExpr sigPrec e'
; return $ ExprWithTySig noExt pe (mkLHsSigWcType t') }
cvt (RecConE c flds) = do { c' <- cNameL c
; flds' <- mapM (cvtFld (mkFieldOcc . noLoc)) flds
; return $ mkRdrRecordCon c' (HsRecFields flds' Nothing) }
cvt (RecUpdE e flds) = do { e' <- cvtl e
; flds'
<- mapM (cvtFld (mkAmbiguousFieldOcc . noLoc))
flds
; return $ mkRdrRecordUpd e' flds' }
cvt (StaticE e) = fmap (HsStatic noExt) $ cvtl e
cvt (UnboundVarE s) = do
{ s' <- vcName s
; return $ HsVar noExt (noLoc s') }
cvt (LabelE s) = do { return $ HsOverLabel noExt Nothing (fsLit s) }
cvt (ImplicitParamVarE n) = do { n' <- ipName n; return $ HsIPVar noExt n' }
cvtFld :: (RdrName -> t) -> (TH.Name, TH.Exp)
-> CvtM (LHsRecField' t (LHsExpr GhcPs))
cvtFld f (v,e)
= do { v' <- vNameL v; e' <- cvtl e
; return (noLoc $ HsRecField { hsRecFieldLbl = fmap f v'
, hsRecFieldArg = e'
, hsRecPun = False}) }
cvtDD :: Range -> CvtM (ArithSeqInfo GhcPs)
cvtDD (FromR x) = do { x' <- cvtl x; return $ From x' }
cvtDD (FromThenR x y) = do { x' <- cvtl x; y' <- cvtl y; return $ FromThen x' y' }
cvtDD (FromToR x y) = do { x' <- cvtl x; y' <- cvtl y; return $ FromTo x' y' }
cvtDD (FromThenToR x y z) = do { x' <- cvtl x; y' <- cvtl y; z' <- cvtl z; return $ FromThenTo x' y' z' }
cvtOpApp :: LHsExpr GhcPs -> TH.Exp -> TH.Exp -> CvtM (HsExpr GhcPs)
cvtOpApp x op1 (UInfixE y op2 z)
= do { l <- wrapL $ cvtOpApp x op1 y
; cvtOpApp l op2 z }
cvtOpApp x op y
= do { op' <- cvtl op
; y' <- cvtl y
; return (OpApp noExt x op' y') }
cvtHsDo :: HsStmtContext Name.Name -> [TH.Stmt] -> CvtM (HsExpr GhcPs)
cvtHsDo do_or_lc stmts
| null stmts = failWith (text "Empty stmt list in do-block")
| otherwise
= do { stmts' <- cvtStmts stmts
; let Just (stmts'', last') = snocView stmts'
; last'' <- case last' of
(dL->L loc (BodyStmt _ body _ _))
-> return (cL loc (mkLastStmt body))
_ -> failWith (bad_last last')
; return $ HsDo noExt do_or_lc (noLoc (stmts'' ++ [last''])) }
where
bad_last stmt = vcat [ text "Illegal last statement of" <+> pprAStmtContext do_or_lc <> colon
, nest 2 $ Outputable.ppr stmt
, text "(It should be an expression.)" ]
cvtStmts :: [TH.Stmt] -> CvtM [Hs.LStmt GhcPs (LHsExpr GhcPs)]
cvtStmts = mapM cvtStmt
cvtStmt :: TH.Stmt -> CvtM (Hs.LStmt GhcPs (LHsExpr GhcPs))
cvtStmt (NoBindS e) = do { e' <- cvtl e; returnL $ mkBodyStmt e' }
cvtStmt (TH.BindS p e) = do { p' <- cvtPat p; e' <- cvtl e; returnL $ mkBindStmt p' e' }
cvtStmt (TH.LetS ds) = do { ds' <- cvtLocalDecs (text "a let binding") ds
; returnL $ LetStmt noExt (noLoc ds') }
cvtStmt (TH.ParS dss) = do { dss' <- mapM cvt_one dss
; returnL $ ParStmt noExt dss' noExpr noSyntaxExpr }
where
cvt_one ds = do { ds' <- cvtStmts ds
; return (ParStmtBlock noExt ds' undefined noSyntaxExpr) }
cvtStmt (TH.RecS ss) = do { ss' <- mapM cvtStmt ss; returnL (mkRecStmt ss') }
cvtMatch :: HsMatchContext RdrName
-> TH.Match -> CvtM (Hs.LMatch GhcPs (LHsExpr GhcPs))
cvtMatch ctxt (TH.Match p body decs)
= do { p' <- cvtPat p
; let lp = case p' of
(dL->L loc SigPat{}) -> cL loc (ParPat NoExt p')
_ -> p'
; g' <- cvtGuard body
; decs' <- cvtLocalDecs (text "a where clause") decs
; returnL $ Hs.Match noExt ctxt [lp] (GRHSs noExt g' (noLoc decs')) }
cvtGuard :: TH.Body -> CvtM [LGRHS GhcPs (LHsExpr GhcPs)]
cvtGuard (GuardedB pairs) = mapM cvtpair pairs
cvtGuard (NormalB e) = do { e' <- cvtl e
; g' <- returnL $ GRHS noExt [] e'; return [g'] }
cvtpair :: (TH.Guard, TH.Exp) -> CvtM (LGRHS GhcPs (LHsExpr GhcPs))
cvtpair (NormalG ge,rhs) = do { ge' <- cvtl ge; rhs' <- cvtl rhs
; g' <- returnL $ mkBodyStmt ge'
; returnL $ GRHS noExt [g'] rhs' }
cvtpair (PatG gs,rhs) = do { gs' <- cvtStmts gs; rhs' <- cvtl rhs
; returnL $ GRHS noExt gs' rhs' }
cvtOverLit :: Lit -> CvtM (HsOverLit GhcPs)
cvtOverLit (IntegerL i)
= do { force i; return $ mkHsIntegral (mkIntegralLit i) }
cvtOverLit (RationalL r)
= do { force r; return $ mkHsFractional (mkFractionalLit r) }
cvtOverLit (StringL s)
= do { let { s' = mkFastString s }
; force s'
; return $ mkHsIsString (quotedSourceText s) s'
}
cvtOverLit _ = panic "Convert.cvtOverLit: Unexpected overloaded literal"
allCharLs :: [TH.Exp] -> Maybe String
allCharLs xs
= case xs of
LitE (CharL c) : ys -> go [c] ys
_ -> Nothing
where
go cs [] = Just (reverse cs)
go cs (LitE (CharL c) : ys) = go (c:cs) ys
go _ _ = Nothing
cvtLit :: Lit -> CvtM (HsLit GhcPs)
cvtLit (IntPrimL i) = do { force i; return $ HsIntPrim NoSourceText i }
cvtLit (WordPrimL w) = do { force w; return $ HsWordPrim NoSourceText w }
cvtLit (FloatPrimL f)
= do { force f; return $ HsFloatPrim noExt (mkFractionalLit f) }
cvtLit (DoublePrimL f)
= do { force f; return $ HsDoublePrim noExt (mkFractionalLit f) }
cvtLit (CharL c) = do { force c; return $ HsChar NoSourceText c }
cvtLit (CharPrimL c) = do { force c; return $ HsCharPrim NoSourceText c }
cvtLit (StringL s) = do { let { s' = mkFastString s }
; force s'
; return $ HsString (quotedSourceText s) s' }
cvtLit (StringPrimL s) = do { let { s' = BS.pack s }
; force s'
; return $ HsStringPrim NoSourceText s' }
cvtLit _ = panic "Convert.cvtLit: Unexpected literal"
quotedSourceText :: String -> SourceText
quotedSourceText s = SourceText $ "\"" ++ s ++ "\""
cvtPats :: [TH.Pat] -> CvtM [Hs.LPat GhcPs]
cvtPats pats = mapM cvtPat pats
cvtPat :: TH.Pat -> CvtM (Hs.LPat GhcPs)
cvtPat pat = wrapL (cvtp pat)
cvtp :: TH.Pat -> CvtM (Hs.Pat GhcPs)
cvtp (TH.LitP l)
| overloadedLit l = do { l' <- cvtOverLit l
; return (mkNPat (noLoc l') Nothing) }
| otherwise = do { l' <- cvtLit l; return $ Hs.LitPat noExt l' }
cvtp (TH.VarP s) = do { s' <- vName s
; return $ Hs.VarPat noExt (noLoc s') }
cvtp (TupP [p]) = do { p' <- cvtPat p; return $ ParPat noExt p' }
cvtp (TupP ps) = do { ps' <- cvtPats ps
; return $ TuplePat noExt ps' Boxed }
cvtp (UnboxedTupP ps) = do { ps' <- cvtPats ps
; return $ TuplePat noExt ps' Unboxed }
cvtp (UnboxedSumP p alt arity)
= do { p' <- cvtPat p
; unboxedSumChecks alt arity
; return $ SumPat noExt p' alt arity }
cvtp (ConP s ps) = do { s' <- cNameL s; ps' <- cvtPats ps
; let pps = map (parenthesizePat appPrec) ps'
; return $ ConPatIn s' (PrefixCon pps) }
cvtp (InfixP p1 s p2) = do { s' <- cNameL s; p1' <- cvtPat p1; p2' <- cvtPat p2
; wrapParL (ParPat noExt) $
ConPatIn s' $
InfixCon (parenthesizePat opPrec p1')
(parenthesizePat opPrec p2') }
cvtp (UInfixP p1 s p2) = do { p1' <- cvtPat p1; cvtOpAppP p1' s p2 }
cvtp (ParensP p) = do { p' <- cvtPat p;
; case unLoc p' of
ParPat {} -> return $ unLoc p'
_ -> return $ ParPat noExt p' }
cvtp (TildeP p) = do { p' <- cvtPat p; return $ LazyPat noExt p' }
cvtp (BangP p) = do { p' <- cvtPat p; return $ BangPat noExt p' }
cvtp (TH.AsP s p) = do { s' <- vNameL s; p' <- cvtPat p
; return $ AsPat noExt s' p' }
cvtp TH.WildP = return $ WildPat noExt
cvtp (RecP c fs) = do { c' <- cNameL c; fs' <- mapM cvtPatFld fs
; return $ ConPatIn c'
$ Hs.RecCon (HsRecFields fs' Nothing) }
cvtp (ListP ps) = do { ps' <- cvtPats ps
; return
$ ListPat noExt ps'}
cvtp (SigP p t) = do { p' <- cvtPat p; t' <- cvtType t
; return $ SigPat noExt p' (mkLHsSigWcType t') }
cvtp (ViewP e p) = do { e' <- cvtl e; p' <- cvtPat p
; return $ ViewPat noExt e' p'}
cvtPatFld :: (TH.Name, TH.Pat) -> CvtM (LHsRecField GhcPs (LPat GhcPs))
cvtPatFld (s,p)
= do { (dL->L ls s') <- vNameL s
; p' <- cvtPat p
; return (noLoc $ HsRecField { hsRecFieldLbl
= cL ls $ mkFieldOcc (cL ls s')
, hsRecFieldArg = p'
, hsRecPun = False}) }
cvtOpAppP :: Hs.LPat GhcPs -> TH.Name -> TH.Pat -> CvtM (Hs.Pat GhcPs)
cvtOpAppP x op1 (UInfixP y op2 z)
= do { l <- wrapL $ cvtOpAppP x op1 y
; cvtOpAppP l op2 z }
cvtOpAppP x op y
= do { op' <- cNameL op
; y' <- cvtPat y
; return (ConPatIn op' (InfixCon x y')) }
cvtTvs :: [TH.TyVarBndr] -> CvtM (LHsQTyVars GhcPs)
cvtTvs tvs = do { tvs' <- mapM cvt_tv tvs; return (mkHsQTvs tvs') }
cvt_tv :: TH.TyVarBndr -> CvtM (LHsTyVarBndr GhcPs)
cvt_tv (TH.PlainTV nm)
= do { nm' <- tNameL nm
; returnL $ UserTyVar noExt nm' }
cvt_tv (TH.KindedTV nm ki)
= do { nm' <- tNameL nm
; ki' <- cvtKind ki
; returnL $ KindedTyVar noExt nm' ki' }
cvtRole :: TH.Role -> Maybe Coercion.Role
cvtRole TH.NominalR = Just Coercion.Nominal
cvtRole TH.RepresentationalR = Just Coercion.Representational
cvtRole TH.PhantomR = Just Coercion.Phantom
cvtRole TH.InferR = Nothing
cvtContext :: TH.Cxt -> CvtM (LHsContext GhcPs)
cvtContext tys = do { preds' <- mapM cvtPred tys; returnL preds' }
cvtPred :: TH.Pred -> CvtM (LHsType GhcPs)
cvtPred = cvtType
cvtDerivClause :: TH.DerivClause
-> CvtM (LHsDerivingClause GhcPs)
cvtDerivClause (TH.DerivClause ds ctxt)
= do { ctxt' <- fmap (map mkLHsSigType) <$> cvtContext ctxt
; ds' <- traverse cvtDerivStrategy ds
; returnL $ HsDerivingClause noExt ds' ctxt' }
cvtDerivStrategy :: TH.DerivStrategy -> CvtM (Hs.LDerivStrategy GhcPs)
cvtDerivStrategy TH.StockStrategy = returnL Hs.StockStrategy
cvtDerivStrategy TH.AnyclassStrategy = returnL Hs.AnyclassStrategy
cvtDerivStrategy TH.NewtypeStrategy = returnL Hs.NewtypeStrategy
cvtDerivStrategy (TH.ViaStrategy ty) = do
ty' <- cvtType ty
returnL $ Hs.ViaStrategy (mkLHsSigType ty')
cvtType :: TH.Type -> CvtM (LHsType GhcPs)
cvtType = cvtTypeKind "type"
cvtTypeKind :: String -> TH.Type -> CvtM (LHsType GhcPs)
cvtTypeKind ty_str ty
= do { (head_ty, tys') <- split_ty_app ty
; let m_normals = mapM extract_normal tys'
where extract_normal (HsValArg ty) = Just ty
extract_normal _ = Nothing
; case head_ty of
TupleT n
| Just normals <- m_normals
, normals `lengthIs` n
-> if n==1 then return (head normals)
else returnL (HsTupleTy noExt
HsBoxedOrConstraintTuple normals)
| n == 1
-> failWith (ptext (sLit ("Illegal 1-tuple " ++ ty_str ++ " constructor")))
| otherwise
-> mk_apps
(HsTyVar noExt NotPromoted (noLoc (getRdrName (tupleTyCon Boxed n))))
tys'
UnboxedTupleT n
| Just normals <- m_normals
, normals `lengthIs` n
-> returnL (HsTupleTy noExt HsUnboxedTuple normals)
| otherwise
-> mk_apps
(HsTyVar noExt NotPromoted (noLoc (getRdrName (tupleTyCon Unboxed n))))
tys'
UnboxedSumT n
| n < 2
-> failWith $
vcat [ text "Illegal sum arity:" <+> text (show n)
, nest 2 $
text "Sums must have an arity of at least 2" ]
| Just normals <- m_normals
, normals `lengthIs` n
-> returnL (HsSumTy noExt normals)
| otherwise
-> mk_apps
(HsTyVar noExt NotPromoted (noLoc (getRdrName (sumTyCon n))))
tys'
ArrowT
| Just normals <- m_normals
, [x',y'] <- normals -> do
x'' <- case unLoc x' of
HsFunTy{} -> returnL (HsParTy noExt x')
HsForAllTy{} -> returnL (HsParTy noExt x')
HsQualTy{} -> returnL (HsParTy noExt x')
_ -> return $
parenthesizeHsType sigPrec x'
let y'' = parenthesizeHsType sigPrec y'
returnL (HsFunTy noExt x'' y'')
| otherwise
-> mk_apps
(HsTyVar noExt NotPromoted (noLoc (getRdrName funTyCon)))
tys'
ListT
| Just normals <- m_normals
, [x'] <- normals -> do
returnL (HsListTy noExt x')
| otherwise
-> mk_apps
(HsTyVar noExt NotPromoted (noLoc (getRdrName listTyCon)))
tys'
VarT nm -> do { nm' <- tNameL nm
; mk_apps (HsTyVar noExt NotPromoted nm') tys' }
ConT nm -> do { nm' <- tconName nm
;
let prom = if isRdrDataCon nm'
then IsPromoted
else NotPromoted
; mk_apps (HsTyVar noExt prom (noLoc nm')) tys'}
ForallT tvs cxt ty
| null tys'
-> do { tvs' <- cvtTvs tvs
; cxt' <- cvtContext cxt
; let pcxt = parenthesizeHsContext funPrec cxt'
; ty' <- cvtType ty
; loc <- getL
; let hs_ty = mkHsForAllTy tvs loc tvs' rho_ty
rho_ty = mkHsQualTy cxt loc pcxt ty'
; return hs_ty }
SigT ty ki
-> do { ty' <- cvtType ty
; ki' <- cvtKind ki
; mk_apps (HsKindSig noExt ty' ki') tys'
}
LitT lit
-> mk_apps (HsTyLit noExt (cvtTyLit lit)) tys'
WildCardT
-> mk_apps mkAnonWildCardTy tys'
InfixT t1 s t2
-> do { s' <- tconName s
; t1' <- cvtType t1
; t2' <- cvtType t2
; mk_apps
(HsTyVar noExt NotPromoted (noLoc s'))
([HsValArg t1', HsValArg t2'] ++ tys')
}
UInfixT t1 s t2
-> do { t2' <- cvtType t2
; t <- cvtOpAppT t1 s t2'
; mk_apps (unLoc t) tys'
}
ParensT t
-> do { t' <- cvtType t
; mk_apps (HsParTy noExt t') tys'
}
PromotedT nm -> do { nm' <- cName nm
; mk_apps (HsTyVar noExt IsPromoted (noLoc nm'))
tys' }
PromotedTupleT n
| n == 1
-> failWith (ptext (sLit ("Illegal promoted 1-tuple " ++ ty_str)))
| Just normals <- m_normals
, normals `lengthIs` n
-> returnL (HsExplicitTupleTy noExt normals)
| otherwise
-> mk_apps
(HsTyVar noExt IsPromoted (noLoc (getRdrName (tupleDataCon Boxed n))))
tys'
PromotedNilT
-> mk_apps (HsExplicitListTy noExt IsPromoted []) tys'
PromotedConsT
| Just normals <- m_normals
, [ty1, dL->L _ (HsExplicitListTy _ ip tys2)] <- normals
-> do
returnL (HsExplicitListTy noExt ip (ty1:tys2))
| otherwise
-> mk_apps
(HsTyVar noExt IsPromoted (noLoc (getRdrName consDataCon)))
tys'
StarT
-> mk_apps
(HsTyVar noExt NotPromoted (noLoc (getRdrName liftedTypeKindTyCon)))
tys'
ConstraintT
-> mk_apps
(HsTyVar noExt NotPromoted (noLoc (getRdrName constraintKindTyCon)))
tys'
EqualityT
| Just normals <- m_normals
, [x',y'] <- normals ->
let px = parenthesizeHsType opPrec x'
py = parenthesizeHsType opPrec y'
in returnL (HsOpTy noExt px (noLoc eqTyCon_RDR) py)
| otherwise ->
mk_apps (HsTyVar noExt NotPromoted
(noLoc eqTyCon_RDR)) tys'
ImplicitParamT n t
-> do { n' <- wrapL $ ipName n
; t' <- cvtType t
; returnL (HsIParamTy noExt n' t')
}
_ -> failWith (ptext (sLit ("Malformed " ++ ty_str)) <+> text (show ty))
}
mk_apps :: HsType GhcPs -> [LHsTypeArg GhcPs] -> CvtM (LHsType GhcPs)
mk_apps head_ty type_args = do
head_ty' <- returnL head_ty
let phead_ty :: LHsType GhcPs
phead_ty = parenthesizeHsType sigPrec head_ty'
go :: [LHsTypeArg GhcPs] -> CvtM (LHsType GhcPs)
go [] = pure head_ty'
go (arg:args) =
case arg of
HsValArg ty -> do p_ty <- add_parens ty
mk_apps (HsAppTy noExt phead_ty p_ty) args
HsTypeArg l ki -> do p_ki <- add_parens ki
mk_apps (HsAppKindTy l phead_ty p_ki) args
HsArgPar _ -> mk_apps (HsParTy noExt phead_ty) args
go type_args
where
add_parens lt@(dL->L _ t)
| hsTypeNeedsParens appPrec t = returnL (HsParTy noExt lt)
| otherwise = return lt
wrap_tyarg :: LHsTypeArg GhcPs -> LHsTypeArg GhcPs
wrap_tyarg (HsValArg ty) = HsValArg $ parenthesizeHsType appPrec ty
wrap_tyarg (HsTypeArg l ki) = HsTypeArg l $ parenthesizeHsType appPrec ki
wrap_tyarg ta@(HsArgPar {}) = ta
mk_arr_apps :: [LHsType GhcPs] -> HsType GhcPs -> CvtM (LHsType GhcPs)
mk_arr_apps tys return_ty = foldrM go return_ty tys >>= returnL
where go :: LHsType GhcPs -> HsType GhcPs -> CvtM (HsType GhcPs)
go arg ret_ty = do { ret_ty_l <- returnL ret_ty
; return (HsFunTy noExt arg ret_ty_l) }
split_ty_app :: TH.Type -> CvtM (TH.Type, [LHsTypeArg GhcPs])
split_ty_app ty = go ty []
where
go (AppT f a) as' = do { a' <- cvtType a; go f (HsValArg a':as') }
go (AppKindT ty ki) as' = do { ki' <- cvtKind ki
; go ty (HsTypeArg noSrcSpan ki':as') }
go (ParensT t) as' = do { loc <- getL; go t (HsArgPar loc: as') }
go f as = return (f,as)
cvtTyLit :: TH.TyLit -> HsTyLit
cvtTyLit (TH.NumTyLit i) = HsNumTy NoSourceText i
cvtTyLit (TH.StrTyLit s) = HsStrTy NoSourceText (fsLit s)
cvtOpAppT :: TH.Type -> TH.Name -> LHsType GhcPs -> CvtM (LHsType GhcPs)
cvtOpAppT (UInfixT x op2 y) op1 z
= do { l <- cvtOpAppT y op1 z
; cvtOpAppT x op2 l }
cvtOpAppT x op y
= do { op' <- tconNameL op
; x' <- cvtType x
; returnL (mkHsOpTy x' op' y) }
cvtKind :: TH.Kind -> CvtM (LHsKind GhcPs)
cvtKind = cvtTypeKind "kind"
cvtMaybeKindToFamilyResultSig :: Maybe TH.Kind
-> CvtM (LFamilyResultSig GhcPs)
cvtMaybeKindToFamilyResultSig Nothing = returnL (Hs.NoSig noExt)
cvtMaybeKindToFamilyResultSig (Just ki) = do { ki' <- cvtKind ki
; returnL (Hs.KindSig noExt ki') }
cvtFamilyResultSig :: TH.FamilyResultSig -> CvtM (Hs.LFamilyResultSig GhcPs)
cvtFamilyResultSig TH.NoSig = returnL (Hs.NoSig noExt)
cvtFamilyResultSig (TH.KindSig ki) = do { ki' <- cvtKind ki
; returnL (Hs.KindSig noExt ki') }
cvtFamilyResultSig (TH.TyVarSig bndr) = do { tv <- cvt_tv bndr
; returnL (Hs.TyVarSig noExt tv) }
cvtInjectivityAnnotation :: TH.InjectivityAnn
-> CvtM (Hs.LInjectivityAnn GhcPs)
cvtInjectivityAnnotation (TH.InjectivityAnn annLHS annRHS)
= do { annLHS' <- tNameL annLHS
; annRHS' <- mapM tNameL annRHS
; returnL (Hs.InjectivityAnn annLHS' annRHS') }
cvtPatSynSigTy :: TH.Type -> CvtM (LHsType GhcPs)
cvtPatSynSigTy (ForallT univs reqs (ForallT exis provs ty))
| null exis, null provs = cvtType (ForallT univs reqs ty)
| null univs, null reqs = do { l <- getL
; ty' <- cvtType (ForallT exis provs ty)
; return $ cL l (HsQualTy { hst_ctxt = cL l []
, hst_xqual = noExt
, hst_body = ty' }) }
| null reqs = do { l <- getL
; univs' <- hsQTvExplicit <$> cvtTvs univs
; ty' <- cvtType (ForallT exis provs ty)
; let forTy = HsForAllTy
{ hst_bndrs = univs'
, hst_xforall = noExt
, hst_body = cL l cxtTy }
cxtTy = HsQualTy { hst_ctxt = cL l []
, hst_xqual = noExt
, hst_body = ty' }
; return $ cL l forTy }
| otherwise = cvtType (ForallT univs reqs (ForallT exis provs ty))
cvtPatSynSigTy ty = cvtType ty
cvtFixity :: TH.Fixity -> Hs.Fixity
cvtFixity (TH.Fixity prec dir) = Hs.Fixity NoSourceText prec (cvt_dir dir)
where
cvt_dir TH.InfixL = Hs.InfixL
cvt_dir TH.InfixR = Hs.InfixR
cvt_dir TH.InfixN = Hs.InfixN
overloadedLit :: Lit -> Bool
overloadedLit (IntegerL _) = True
overloadedLit (RationalL _) = True
overloadedLit _ = False
unboxedSumChecks :: TH.SumAlt -> TH.SumArity -> CvtM ()
unboxedSumChecks alt arity
| alt > arity
= failWith $ text "Sum alternative" <+> text (show alt)
<+> text "exceeds its arity," <+> text (show arity)
| alt <= 0
= failWith $ vcat [ text "Illegal sum alternative:" <+> text (show alt)
, nest 2 $ text "Sum alternatives must start from 1" ]
| arity < 2
= failWith $ vcat [ text "Illegal sum arity:" <+> text (show arity)
, nest 2 $ text "Sums must have an arity of at least 2" ]
| otherwise
= return ()
mkHsForAllTy :: [TH.TyVarBndr]
-> SrcSpan
-> LHsQTyVars GhcPs
-> LHsType GhcPs
-> LHsType GhcPs
mkHsForAllTy tvs loc tvs' rho_ty
| null tvs = rho_ty
| otherwise = cL loc $ HsForAllTy { hst_bndrs = hsQTvExplicit tvs'
, hst_xforall = noExt
, hst_body = rho_ty }
mkHsQualTy :: TH.Cxt
-> SrcSpan
-> LHsContext GhcPs
-> LHsType GhcPs
-> LHsType GhcPs
mkHsQualTy ctxt loc ctxt' ty
| null ctxt = ty
| otherwise = cL loc $ HsQualTy { hst_xqual = noExt
, hst_ctxt = ctxt'
, hst_body = ty }
vNameL, cNameL, vcNameL, tNameL, tconNameL :: TH.Name -> CvtM (Located RdrName)
vName, cName, vcName, tName, tconName :: TH.Name -> CvtM RdrName
vNameL n = wrapL (vName n)
vName n = cvtName OccName.varName n
cNameL n = wrapL (cName n)
cName n = cvtName OccName.dataName n
vcNameL n = wrapL (vcName n)
vcName n = if isVarName n then vName n else cName n
tNameL n = wrapL (tName n)
tName n = cvtName OccName.tvName n
tconNameL n = wrapL (tconName n)
tconName n = cvtName OccName.tcClsName n
ipName :: String -> CvtM HsIPName
ipName n
= do { unless (okVarOcc n) (failWith (badOcc OccName.varName n))
; return (HsIPName (fsLit n)) }
cvtName :: OccName.NameSpace -> TH.Name -> CvtM RdrName
cvtName ctxt_ns (TH.Name occ flavour)
| not (okOcc ctxt_ns occ_str) = failWith (badOcc ctxt_ns occ_str)
| otherwise
= do { loc <- getL
; let rdr_name = thRdrName loc ctxt_ns occ_str flavour
; force rdr_name
; return rdr_name }
where
occ_str = TH.occString occ
okOcc :: OccName.NameSpace -> String -> Bool
okOcc ns str
| OccName.isVarNameSpace ns = okVarOcc str
| OccName.isDataConNameSpace ns = okConOcc str
| otherwise = okTcOcc str
isVarName :: TH.Name -> Bool
isVarName (TH.Name occ _)
= case TH.occString occ of
"" -> False
(c:_) -> startsVarId c || startsVarSym c
badOcc :: OccName.NameSpace -> String -> SDoc
badOcc ctxt_ns occ
= text "Illegal" <+> pprNameSpace ctxt_ns
<+> text "name:" <+> quotes (text occ)
thRdrName :: SrcSpan -> OccName.NameSpace -> String -> TH.NameFlavour -> RdrName
thRdrName loc ctxt_ns th_occ th_name
= case th_name of
TH.NameG th_ns pkg mod -> thOrigRdrName th_occ th_ns pkg mod
TH.NameQ mod -> (mkRdrQual $! mk_mod mod) $! occ
TH.NameL uniq -> nameRdrName $! (((Name.mkInternalName $! mk_uniq uniq) $! occ) loc)
TH.NameU uniq -> nameRdrName $! (((Name.mkSystemNameAt $! mk_uniq uniq) $! occ) loc)
TH.NameS | Just name <- isBuiltInOcc_maybe occ -> nameRdrName $! name
| otherwise -> mkRdrUnqual $! occ
where
occ :: OccName.OccName
occ = mk_occ ctxt_ns th_occ
thOrigRdrName :: String -> TH.NameSpace -> PkgName -> ModName -> RdrName
thOrigRdrName occ th_ns pkg mod =
let occ' = mk_occ (mk_ghc_ns th_ns) occ
in case isBuiltInOcc_maybe occ' of
Just name -> nameRdrName name
Nothing -> (mkOrig $! (mkModule (mk_pkg pkg) (mk_mod mod))) $! occ'
thRdrNameGuesses :: TH.Name -> [RdrName]
thRdrNameGuesses (TH.Name occ flavour)
| TH.NameG th_ns pkg mod <- flavour = [ thOrigRdrName occ_str th_ns pkg mod]
| otherwise = [ thRdrName noSrcSpan gns occ_str flavour
| gns <- guessed_nss]
where
guessed_nss
| isLexCon (mkFastString occ_str) = [OccName.tcName, OccName.dataName]
| otherwise = [OccName.varName, OccName.tvName]
occ_str = TH.occString occ
mk_occ :: OccName.NameSpace -> String -> OccName.OccName
mk_occ ns occ = OccName.mkOccName ns occ
mk_ghc_ns :: TH.NameSpace -> OccName.NameSpace
mk_ghc_ns TH.DataName = OccName.dataName
mk_ghc_ns TH.TcClsName = OccName.tcClsName
mk_ghc_ns TH.VarName = OccName.varName
mk_mod :: TH.ModName -> ModuleName
mk_mod mod = mkModuleName (TH.modString mod)
mk_pkg :: TH.PkgName -> UnitId
mk_pkg pkg = stringToUnitId (TH.pkgString pkg)
mk_uniq :: Int -> Unique
mk_uniq u = mkUniqueGrimily u