module GHC.Hs.ImpExp where
import GHC.Prelude
import GHC.Unit.Module ( ModuleName, IsBootInterface(..) )
import GHC.Hs.Doc ( HsDocString )
import GHC.Types.SourceText ( SourceText(..), StringLiteral(..), pprWithSourceText )
import GHC.Types.FieldLabel ( FieldLabel )
import GHC.Utils.Outputable
import GHC.Utils.Panic
import GHC.Data.FastString
import GHC.Types.SrcLoc
import Language.Haskell.Syntax.Extension
import GHC.Hs.Extension
import GHC.Parser.Annotation
import GHC.Types.Name
import Data.Data
import Data.Maybe
type LImportDecl pass = XRec pass (ImportDecl pass)
type instance Anno (ImportDecl (GhcPass p)) = SrcSpanAnnA
data ImportDeclQualifiedStyle
= QualifiedPre
| QualifiedPost
| NotQualified
deriving (Eq, Data)
importDeclQualifiedStyle :: Maybe EpaAnchor
-> Maybe EpaAnchor
-> (Maybe EpaAnchor, ImportDeclQualifiedStyle)
importDeclQualifiedStyle mPre mPost =
if isJust mPre then (mPre, QualifiedPre)
else if isJust mPost then (mPost,QualifiedPost) else (Nothing, NotQualified)
isImportDeclQualified :: ImportDeclQualifiedStyle -> Bool
isImportDeclQualified NotQualified = False
isImportDeclQualified _ = True
data ImportDecl pass
= ImportDecl {
ideclExt :: XCImportDecl pass,
ideclSourceSrc :: SourceText,
ideclName :: XRec pass ModuleName,
ideclPkgQual :: Maybe StringLiteral,
ideclSource :: IsBootInterface,
ideclSafe :: Bool,
ideclQualified :: ImportDeclQualifiedStyle,
ideclImplicit :: Bool,
ideclAs :: Maybe (XRec pass ModuleName),
ideclHiding :: Maybe (Bool, XRec pass [LIE pass])
}
| XImportDecl !(XXImportDecl pass)
type instance XCImportDecl GhcPs = EpAnn' EpAnnImportDecl
type instance XCImportDecl GhcRn = NoExtField
type instance XCImportDecl GhcTc = NoExtField
type instance XXImportDecl (GhcPass _) = NoExtCon
type instance Anno ModuleName = SrcSpan
type instance Anno [LocatedA (IE (GhcPass p))] = SrcSpanAnnL
data EpAnnImportDecl = EpAnnImportDecl
{ importDeclAnnImport :: EpaAnchor
, importDeclAnnPragma :: Maybe (EpaAnchor, EpaAnchor)
, importDeclAnnSafe :: Maybe EpaAnchor
, importDeclAnnQualified :: Maybe EpaAnchor
, importDeclAnnPackage :: Maybe EpaAnchor
, importDeclAnnAs :: Maybe EpaAnchor
} deriving (Data)
simpleImportDecl :: ModuleName -> ImportDecl GhcPs
simpleImportDecl mn = ImportDecl {
ideclExt = noAnn,
ideclSourceSrc = NoSourceText,
ideclName = noLoc mn,
ideclPkgQual = Nothing,
ideclSource = NotBoot,
ideclSafe = False,
ideclImplicit = False,
ideclQualified = NotQualified,
ideclAs = Nothing,
ideclHiding = Nothing
}
instance (OutputableBndrId p
, Outputable (Anno (IE (GhcPass p))))
=> Outputable (ImportDecl (GhcPass p)) where
ppr (ImportDecl { ideclSourceSrc = mSrcText, ideclName = mod'
, ideclPkgQual = pkg
, ideclSource = from, ideclSafe = safe
, ideclQualified = qual, ideclImplicit = implicit
, ideclAs = as, ideclHiding = spec })
= hang (hsep [text "import", ppr_imp from, pp_implicit implicit, pp_safe safe,
pp_qual qual False, pp_pkg pkg, ppr mod', pp_qual qual True, pp_as as])
4 (pp_spec spec)
where
pp_implicit False = empty
pp_implicit True = ptext (sLit ("(implicit)"))
pp_pkg Nothing = empty
pp_pkg (Just (StringLiteral st p _))
= pprWithSourceText st (doubleQuotes (ftext p))
pp_qual QualifiedPre False = text "qualified"
pp_qual QualifiedPost True = text "qualified"
pp_qual QualifiedPre True = empty
pp_qual QualifiedPost False = empty
pp_qual NotQualified _ = empty
pp_safe False = empty
pp_safe True = text "safe"
pp_as Nothing = empty
pp_as (Just a) = text "as" <+> ppr a
ppr_imp IsBoot = case mSrcText of
NoSourceText -> text "{-# SOURCE #-}"
SourceText src -> text src <+> text "#-}"
ppr_imp NotBoot = empty
pp_spec Nothing = empty
pp_spec (Just (False, (L _ ies))) = ppr_ies ies
pp_spec (Just (True, (L _ ies))) = text "hiding" <+> ppr_ies ies
ppr_ies [] = text "()"
ppr_ies ies = char '(' <+> interpp'SP ies <+> char ')'
data IEWrappedName name
= IEName (LocatedN name)
| IEPattern EpaAnchor (LocatedN name)
| IEType EpaAnchor (LocatedN name)
deriving (Eq,Data)
type LIEWrappedName name = LocatedA (IEWrappedName name)
type LIE pass = XRec pass (IE pass)
type instance Anno (IE (GhcPass p)) = SrcSpanAnnA
data IE pass
= IEVar (XIEVar pass) (LIEWrappedName (IdP pass))
| IEThingAbs (XIEThingAbs pass) (LIEWrappedName (IdP pass))
| IEThingAll (XIEThingAll pass) (LIEWrappedName (IdP pass))
| IEThingWith (XIEThingWith pass)
(LIEWrappedName (IdP pass))
IEWildcard
[LIEWrappedName (IdP pass)]
| IEModuleContents (XIEModuleContents pass) (XRec pass ModuleName)
| IEGroup (XIEGroup pass) Int HsDocString
| IEDoc (XIEDoc pass) HsDocString
| IEDocNamed (XIEDocNamed pass) String
| XIE !(XXIE pass)
type instance XIEVar GhcPs = NoExtField
type instance XIEVar GhcRn = NoExtField
type instance XIEVar GhcTc = NoExtField
type instance XIEThingAbs (GhcPass _) = EpAnn
type instance XIEThingAll (GhcPass _) = EpAnn
type instance XIEThingWith (GhcPass 'Parsed) = EpAnn
type instance XIEThingWith (GhcPass 'Renamed) = [Located FieldLabel]
type instance XIEThingWith (GhcPass 'Typechecked) = NoExtField
type instance XIEModuleContents GhcPs = EpAnn
type instance XIEModuleContents GhcRn = NoExtField
type instance XIEModuleContents GhcTc = NoExtField
type instance XIEGroup (GhcPass _) = NoExtField
type instance XIEDoc (GhcPass _) = NoExtField
type instance XIEDocNamed (GhcPass _) = NoExtField
type instance XXIE (GhcPass _) = NoExtCon
type instance Anno (LocatedA (IE (GhcPass p))) = SrcSpanAnnA
data IEWildcard = NoIEWildcard | IEWildcard Int deriving (Eq, Data)
ieName :: IE (GhcPass p) -> IdP (GhcPass p)
ieName (IEVar _ (L _ n)) = ieWrappedName n
ieName (IEThingAbs _ (L _ n)) = ieWrappedName n
ieName (IEThingWith _ (L _ n) _ _) = ieWrappedName n
ieName (IEThingAll _ (L _ n)) = ieWrappedName n
ieName _ = panic "ieName failed pattern match!"
ieNames :: IE (GhcPass p) -> [IdP (GhcPass p)]
ieNames (IEVar _ (L _ n) ) = [ieWrappedName n]
ieNames (IEThingAbs _ (L _ n) ) = [ieWrappedName n]
ieNames (IEThingAll _ (L _ n) ) = [ieWrappedName n]
ieNames (IEThingWith _ (L _ n) _ ns) = ieWrappedName n
: map (ieWrappedName . unLoc) ns
ieNames (IEModuleContents {}) = []
ieNames (IEGroup {}) = []
ieNames (IEDoc {}) = []
ieNames (IEDocNamed {}) = []
ieWrappedLName :: IEWrappedName name -> LocatedN name
ieWrappedLName (IEName ln) = ln
ieWrappedLName (IEPattern _ ln) = ln
ieWrappedLName (IEType _ ln) = ln
ieWrappedName :: IEWrappedName name -> name
ieWrappedName = unLoc . ieWrappedLName
lieWrappedName :: LIEWrappedName name -> name
lieWrappedName (L _ n) = ieWrappedName n
ieLWrappedName :: LIEWrappedName name -> LocatedN name
ieLWrappedName (L _ n) = ieWrappedLName n
replaceWrappedName :: IEWrappedName name1 -> name2 -> IEWrappedName name2
replaceWrappedName (IEName (L l _)) n = IEName (L l n)
replaceWrappedName (IEPattern r (L l _)) n = IEPattern r (L l n)
replaceWrappedName (IEType r (L l _)) n = IEType r (L l n)
replaceLWrappedName :: LIEWrappedName name1 -> name2 -> LIEWrappedName name2
replaceLWrappedName (L l n) n' = L l (replaceWrappedName n n')
instance OutputableBndrId p => Outputable (IE (GhcPass p)) where
ppr (IEVar _ var) = ppr (unLoc var)
ppr (IEThingAbs _ thing) = ppr (unLoc thing)
ppr (IEThingAll _ thing) = hcat [ppr (unLoc thing), text "(..)"]
ppr (IEThingWith flds thing wc withs)
= ppr (unLoc thing) <> parens (fsep (punctuate comma
(ppWiths ++ ppFields) ))
where
ppWiths =
case wc of
NoIEWildcard ->
map (ppr . unLoc) withs
IEWildcard pos ->
let (bs, as) = splitAt pos (map (ppr . unLoc) withs)
in bs ++ [text ".."] ++ as
ppFields =
case ghcPass @p of
GhcRn -> map ppr flds
_ -> []
ppr (IEModuleContents _ mod')
= text "module" <+> ppr mod'
ppr (IEGroup _ n _) = text ("<IEGroup: " ++ show n ++ ">")
ppr (IEDoc _ doc) = ppr doc
ppr (IEDocNamed _ string) = text ("<IEDocNamed: " ++ string ++ ">")
instance (HasOccName name) => HasOccName (IEWrappedName name) where
occName w = occName (ieWrappedName w)
instance (OutputableBndr name) => OutputableBndr (IEWrappedName name) where
pprBndr bs w = pprBndr bs (ieWrappedName w)
pprPrefixOcc w = pprPrefixOcc (ieWrappedName w)
pprInfixOcc w = pprInfixOcc (ieWrappedName w)
instance (OutputableBndr name) => Outputable (IEWrappedName name) where
ppr (IEName n) = pprPrefixOcc (unLoc n)
ppr (IEPattern _ n) = text "pattern" <+> pprPrefixOcc (unLoc n)
ppr (IEType _ n) = text "type" <+> pprPrefixOcc (unLoc n)
pprImpExp :: (HasOccName name, OutputableBndr name) => name -> SDoc
pprImpExp name = type_pref <+> pprPrefixOcc name
where
occ = occName name
type_pref | isTcOcc occ && isSymOcc occ = text "type"
| otherwise = empty