{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE UndecidableInstances #-}
module HsImpExp where
import GhcPrelude
import Module ( ModuleName )
import HsDoc ( HsDocString )
import OccName ( HasOccName(..), isTcOcc, isSymOcc )
import BasicTypes ( SourceText(..), StringLiteral(..), pprWithSourceText )
import FieldLabel ( FieldLbl(..) )
import Outputable
import FastString
import SrcLoc
import HsExtension
import Data.Data
type LImportDecl name = Located (ImportDecl name)
data ImportDecl name
= ImportDecl {
ideclSourceSrc :: SourceText,
ideclName :: Located ModuleName,
ideclPkgQual :: Maybe StringLiteral,
ideclSource :: Bool,
ideclSafe :: Bool,
ideclQualified :: Bool,
ideclImplicit :: Bool,
ideclAs :: Maybe (Located ModuleName),
ideclHiding :: Maybe (Bool, Located [LIE name])
}
deriving instance (DataId name) => Data (ImportDecl name)
simpleImportDecl :: ModuleName -> ImportDecl name
simpleImportDecl mn = ImportDecl {
ideclSourceSrc = NoSourceText,
ideclName = noLoc mn,
ideclPkgQual = Nothing,
ideclSource = False,
ideclSafe = False,
ideclImplicit = False,
ideclQualified = False,
ideclAs = Nothing,
ideclHiding = Nothing
}
instance (OutputableBndrId pass) => Outputable (ImportDecl pass) 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, pp_pkg pkg, ppr mod', 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 False = empty
pp_qual True = text "qualified"
pp_safe False = empty
pp_safe True = text "safe"
pp_as Nothing = empty
pp_as (Just a) = text "as" <+> ppr a
ppr_imp True = case mSrcText of
NoSourceText -> text "{-# SOURCE #-}"
SourceText src -> text src <+> text "#-}"
ppr_imp False = 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 (Located name)
| IEPattern (Located name)
| IEType (Located name)
deriving (Eq,Data)
type LIEWrappedName name = Located (IEWrappedName name)
type LIE name = Located (IE name)
data IE name
= IEVar (LIEWrappedName (IdP name))
| IEThingAbs (LIEWrappedName (IdP name))
| IEThingAll (LIEWrappedName (IdP name))
| IEThingWith (LIEWrappedName (IdP name))
IEWildcard
[LIEWrappedName (IdP name)]
[Located (FieldLbl (IdP name))]
| IEModuleContents (Located ModuleName)
| IEGroup Int HsDocString
| IEDoc HsDocString
| IEDocNamed String
deriving instance (Eq name, Eq (IdP name)) => Eq (IE name)
deriving instance (DataId name) => Data (IE name)
data IEWildcard = NoIEWildcard | IEWildcard Int deriving (Eq, Data)
ieName :: IE pass -> IdP pass
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 pass -> [IdP pass]
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 _ ) = []
ieWrappedName :: IEWrappedName name -> name
ieWrappedName (IEName (L _ n)) = n
ieWrappedName (IEPattern (L _ n)) = n
ieWrappedName (IEType (L _ n)) = n
ieLWrappedName :: LIEWrappedName name -> Located name
ieLWrappedName (L l n) = L l (ieWrappedName n)
replaceWrappedName :: IEWrappedName name1 -> name2 -> IEWrappedName name2
replaceWrappedName (IEName (L l _)) n = IEName (L l n)
replaceWrappedName (IEPattern (L l _)) n = IEPattern (L l n)
replaceWrappedName (IEType (L l _)) n = IEType (L l n)
replaceLWrappedName :: LIEWrappedName name1 -> name2 -> LIEWrappedName name2
replaceLWrappedName (L l n) n' = L l (replaceWrappedName n n')
instance (OutputableBndrId pass) => Outputable (IE pass) where
ppr (IEVar var) = ppr (unLoc var)
ppr (IEThingAbs thing) = ppr (unLoc thing)
ppr (IEThingAll thing) = hcat [ppr (unLoc thing), text "(..)"]
ppr (IEThingWith thing wc withs flds)
= ppr (unLoc thing) <> parens (fsep (punctuate comma
(ppWiths ++
map (ppr . flLabel . unLoc) flds)))
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
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