module GHC.Builtin.Utils (
isKnownKeyName,
lookupKnownKeyName,
lookupKnownNameInfo,
knownKeyNames,
wiredInIds, ghcPrimIds,
primOpRules, builtinRules,
ghcPrimExports,
ghcPrimDeclDocs,
primOpId,
maybeCharLikeCon, maybeIntLikeCon,
isNumericClass, isStandardClass
) where
#include "HsVersions.h"
import GHC.Prelude
import GHC.Builtin.Uniques
import GHC.Builtin.PrimOps
import GHC.Builtin.Types
import GHC.Builtin.Types.Literals ( typeNatTyCons )
import GHC.Builtin.Types.Prim
import GHC.Builtin.Names.TH ( templateHaskellNames )
import GHC.Builtin.Names
import GHC.Core.ConLike ( ConLike(..) )
import GHC.Core.Opt.ConstantFold
import GHC.Core.DataCon
import GHC.Core.Class
import GHC.Core.TyCon
import GHC.Types.Avail
import GHC.Types.Basic
import GHC.Types.Id
import GHC.Types.Name
import GHC.Types.Name.Env
import GHC.Types.Id.Make
import GHC.Types.Unique.FM
import GHC.Types.TyThing
import GHC.Types.Unique ( isValidKnownKeyUnique )
import GHC.Utils.Outputable
import GHC.Utils.Misc as Utils
import GHC.Utils.Panic
import GHC.Hs.Doc
import GHC.Unit.Module.ModIface (IfaceExport)
import Control.Applicative ((<|>))
import Data.List ( intercalate , find )
import Data.Array
import Data.Maybe
import qualified Data.Map as Map
knownKeyNames :: [Name]
knownKeyNames
| debugIsOn
, Just badNamesStr <- knownKeyNamesOkay all_names
= panic ("badAllKnownKeyNames:\n" ++ badNamesStr)
| otherwise
= all_names
where
all_names =
tupleTyConName BoxedTuple 1 : tupleDataConName Boxed 1 :
concat [ concatMap wired_tycon_kk_names primTyCons
, concatMap wired_tycon_kk_names wiredInTyCons
, concatMap wired_tycon_kk_names typeNatTyCons
, map idName wiredInIds
, map (idName . primOpId) allThePrimOps
, map (idName . primOpWrapperId) allThePrimOps
, basicKnownKeyNames
, templateHaskellNames
]
wired_tycon_kk_names :: TyCon -> [Name]
wired_tycon_kk_names tc =
tyConName tc : (rep_names tc ++ implicits)
where implicits = concatMap thing_kk_names (implicitTyConThings tc)
wired_datacon_kk_names :: DataCon -> [Name]
wired_datacon_kk_names dc =
dataConName dc : rep_names (promoteDataCon dc)
thing_kk_names :: TyThing -> [Name]
thing_kk_names (ATyCon tc) = wired_tycon_kk_names tc
thing_kk_names (AConLike (RealDataCon dc)) = wired_datacon_kk_names dc
thing_kk_names thing = [getName thing]
rep_names tc = case tyConRepName_maybe tc of
Just n -> [n]
Nothing -> []
knownKeyNamesOkay :: [Name] -> Maybe String
knownKeyNamesOkay all_names
| ns@(_:_) <- filter (not . isValidKnownKeyUnique . getUnique) all_names
= Just $ " Out-of-range known-key uniques: ["
++ intercalate ", " (map (occNameString . nameOccName) ns) ++
"]"
| null badNamesPairs
= Nothing
| otherwise
= Just badNamesStr
where
namesEnv = foldl' (\m n -> extendNameEnv_Acc (:) Utils.singleton m n n)
emptyUFM all_names
badNamesEnv = filterNameEnv (\ns -> ns `lengthExceeds` 1) namesEnv
badNamesPairs = nonDetUFMToList badNamesEnv
badNamesStrs = map pairToStr badNamesPairs
badNamesStr = unlines badNamesStrs
pairToStr (uniq, ns) = " " ++
show uniq ++
": [" ++
intercalate ", " (map (occNameString . nameOccName) ns) ++
"]"
lookupKnownKeyName :: Unique -> Maybe Name
lookupKnownKeyName u =
knownUniqueName u <|> lookupUFM_Directly knownKeysMap u
isKnownKeyName :: Name -> Bool
isKnownKeyName n =
isJust (knownUniqueName $ nameUnique n) || elemUFM n knownKeysMap
knownKeysMap :: UniqFM Name Name
knownKeysMap = listToIdentityUFM knownKeyNames
lookupKnownNameInfo :: Name -> SDoc
lookupKnownNameInfo name = case lookupNameEnv knownNamesInfo name of
Nothing -> empty
Just doc -> vcat [text "{-", doc, text "-}"]
knownNamesInfo :: NameEnv SDoc
knownNamesInfo = unitNameEnv coercibleTyConName $
vcat [ text "Coercible is a special constraint with custom solving rules."
, text "It is not a class."
, text "Please see section `The Coercible constraint`"
, text "of the user's guide for details." ]
primOpIds :: Array Int Id
primOpIds = array (1,maxPrimOpTag) [ (primOpTag op, mkPrimOpId op)
| op <- allThePrimOps ]
primOpId :: PrimOp -> Id
primOpId op = primOpIds ! primOpTag op
ghcPrimExports :: [IfaceExport]
ghcPrimExports
= map (avail . idName) ghcPrimIds ++
map (avail . idName . primOpId) allThePrimOps ++
[ availTC n [n] []
| tc <- exposedPrimTyCons, let n = tyConName tc ]
ghcPrimDeclDocs :: DeclDocMap
ghcPrimDeclDocs = DeclDocMap $ Map.fromList $ mapMaybe findName primOpDocs
where
names = map idName ghcPrimIds ++
map (idName . primOpId) allThePrimOps ++
map tyConName exposedPrimTyCons
findName (nameStr, doc)
| Just name <- find ((nameStr ==) . getOccString) names
= Just (name, mkHsDocString doc)
| otherwise = Nothing
maybeCharLikeCon, maybeIntLikeCon :: DataCon -> Bool
maybeCharLikeCon con = con `hasKey` charDataConKey
maybeIntLikeCon con = con `hasKey` intDataConKey
isNumericClass, isStandardClass :: Class -> Bool
isNumericClass clas = classKey clas `is_elem` numericClassKeys
isStandardClass clas = classKey clas `is_elem` standardClassKeys
is_elem :: Eq a => a -> [a] -> Bool
is_elem = isIn "is_X_Class"