{-# LANGUAGE CPP, FlexibleContexts, MultiWayIf, FlexibleInstances, DeriveDataTypeable #-}
module Var (
Var, CoVar, Id, NcId, DictId, DFunId, EvVar, EqVar, EvId, IpId, JoinId,
TyVar, TypeVar, KindVar, TKVar, TyCoVar,
InVar, InCoVar, InId, InTyVar,
OutVar, OutCoVar, OutId, OutTyVar,
varName, varUnique, varType,
setVarName, setVarUnique, setVarType, updateVarType,
updateVarTypeM,
mkGlobalVar, mkLocalVar, mkExportedLocalVar, mkCoVar,
idInfo, idDetails,
lazySetIdInfo, setIdDetails, globaliseId,
setIdExported, setIdNotExported,
isId, isTyVar, isTcTyVar,
isLocalVar, isLocalId, isCoVar, isNonCoVarId, isTyCoVar,
isGlobalId, isExportedId,
mustHaveLocalBinding,
TyVarBndr(..), ArgFlag(..), TyVarBinder,
binderVar, binderVars, binderArgFlag, binderKind,
isVisibleArgFlag, isInvisibleArgFlag, sameVis,
mkTyVarBinder, mkTyVarBinders,
mkTyVar, mkTcTyVar,
tyVarName, tyVarKind, tcTyVarDetails, setTcTyVarDetails,
setTyVarName, setTyVarUnique, setTyVarKind, updateTyVarKind,
updateTyVarKindM,
nonDetCmpVar
) where
#include "HsVersions.h"
import GhcPrelude
import {-# SOURCE #-} TyCoRep( Type, Kind, pprKind )
import {-# SOURCE #-} TcType( TcTyVarDetails, pprTcTyVarDetails, vanillaSkolemTv )
import {-# SOURCE #-} IdInfo( IdDetails, IdInfo, coVarDetails, isCoVarDetails,
vanillaIdInfo, pprIdDetails )
import Name hiding (varName)
import Unique ( Uniquable, Unique, getKey, getUnique
, mkUniqueGrimily, nonDetCmpUnique )
import Util
import Binary
import DynFlags
import Outputable
import Data.Data
type Id = Var
type CoVar = Id
type NcId = Id
type TyVar = Var
type TKVar = Var
type TypeVar = Var
type KindVar = Var
type EvId = Id
type EvVar = EvId
type DFunId = Id
type DictId = EvId
type IpId = EvId
type EqVar = EvId
type JoinId = Id
type TyCoVar = Id
type InVar = Var
type InTyVar = TyVar
type InCoVar = CoVar
type InId = Id
type OutVar = Var
type OutTyVar = TyVar
type OutCoVar = CoVar
type OutId = Id
data Var
= TyVar {
varName :: !Name,
realUnique :: {-# UNPACK #-} !Int,
varType :: Kind
}
| TcTyVar {
varName :: !Name,
realUnique :: {-# UNPACK #-} !Int,
varType :: Kind,
tc_tv_details :: TcTyVarDetails
}
| Id {
varName :: !Name,
realUnique :: {-# UNPACK #-} !Int,
varType :: Type,
idScope :: IdScope,
id_details :: IdDetails,
id_info :: IdInfo }
data IdScope
= GlobalId
| LocalId ExportFlag
data ExportFlag
= NotExported
| Exported
instance Outputable Var where
ppr var = sdocWithDynFlags $ \dflags ->
getPprStyle $ \ppr_style ->
if | debugStyle ppr_style && (not (gopt Opt_SuppressVarKinds dflags))
-> parens (ppr (varName var) <+> ppr_debug var ppr_style <+>
dcolon <+> pprKind (tyVarKind var))
| otherwise
-> ppr (varName var) <> ppr_debug var ppr_style
ppr_debug :: Var -> PprStyle -> SDoc
ppr_debug (TyVar {}) sty
| debugStyle sty = brackets (text "tv")
ppr_debug (TcTyVar {tc_tv_details = d}) sty
| dumpStyle sty || debugStyle sty = brackets (pprTcTyVarDetails d)
ppr_debug (Id { idScope = s, id_details = d }) sty
| debugStyle sty = brackets (ppr_id_scope s <> pprIdDetails d)
ppr_debug _ _ = empty
ppr_id_scope :: IdScope -> SDoc
ppr_id_scope GlobalId = text "gid"
ppr_id_scope (LocalId Exported) = text "lidx"
ppr_id_scope (LocalId NotExported) = text "lid"
instance NamedThing Var where
getName = varName
instance Uniquable Var where
getUnique = varUnique
instance Eq Var where
a == b = realUnique a == realUnique b
instance Ord Var where
a <= b = realUnique a <= realUnique b
a < b = realUnique a < realUnique b
a >= b = realUnique a >= realUnique b
a > b = realUnique a > realUnique b
a `compare` b = a `nonDetCmpVar` b
nonDetCmpVar :: Var -> Var -> Ordering
nonDetCmpVar a b = varUnique a `nonDetCmpUnique` varUnique b
instance Data Var where
toConstr _ = abstractConstr "Var"
gunfold _ _ = error "gunfold"
dataTypeOf _ = mkNoRepType "Var"
instance HasOccName Var where
occName = nameOccName . varName
varUnique :: Var -> Unique
varUnique var = mkUniqueGrimily (realUnique var)
setVarUnique :: Var -> Unique -> Var
setVarUnique var uniq
= var { realUnique = getKey uniq,
varName = setNameUnique (varName var) uniq }
setVarName :: Var -> Name -> Var
setVarName var new_name
= var { realUnique = getKey (getUnique new_name),
varName = new_name }
setVarType :: Id -> Type -> Id
setVarType id ty = id { varType = ty }
updateVarType :: (Type -> Type) -> Id -> Id
updateVarType f id = id { varType = f (varType id) }
updateVarTypeM :: Monad m => (Type -> m Type) -> Id -> m Id
updateVarTypeM f id = do { ty' <- f (varType id)
; return (id { varType = ty' }) }
data ArgFlag = Required | Specified | Inferred
deriving (Eq, Data)
isVisibleArgFlag :: ArgFlag -> Bool
isVisibleArgFlag Required = True
isVisibleArgFlag _ = False
isInvisibleArgFlag :: ArgFlag -> Bool
isInvisibleArgFlag = not . isVisibleArgFlag
sameVis :: ArgFlag -> ArgFlag -> Bool
sameVis Required Required = True
sameVis Required _ = False
sameVis _ Required = False
sameVis _ _ = True
data TyVarBndr tyvar argf = TvBndr tyvar argf
deriving( Data )
type TyVarBinder = TyVarBndr TyVar ArgFlag
binderVar :: TyVarBndr tv argf -> tv
binderVar (TvBndr v _) = v
binderVars :: [TyVarBndr tv argf] -> [tv]
binderVars tvbs = map binderVar tvbs
binderArgFlag :: TyVarBndr tv argf -> argf
binderArgFlag (TvBndr _ argf) = argf
binderKind :: TyVarBndr TyVar argf -> Kind
binderKind (TvBndr tv _) = tyVarKind tv
mkTyVarBinder :: ArgFlag -> Var -> TyVarBinder
mkTyVarBinder vis var = TvBndr var vis
mkTyVarBinders :: ArgFlag -> [TyVar] -> [TyVarBinder]
mkTyVarBinders vis = map (mkTyVarBinder vis)
tyVarName :: TyVar -> Name
tyVarName = varName
tyVarKind :: TyVar -> Kind
tyVarKind = varType
setTyVarUnique :: TyVar -> Unique -> TyVar
setTyVarUnique = setVarUnique
setTyVarName :: TyVar -> Name -> TyVar
setTyVarName = setVarName
setTyVarKind :: TyVar -> Kind -> TyVar
setTyVarKind tv k = tv {varType = k}
updateTyVarKind :: (Kind -> Kind) -> TyVar -> TyVar
updateTyVarKind update tv = tv {varType = update (tyVarKind tv)}
updateTyVarKindM :: (Monad m) => (Kind -> m Kind) -> TyVar -> m TyVar
updateTyVarKindM update tv
= do { k' <- update (tyVarKind tv)
; return $ tv {varType = k'} }
mkTyVar :: Name -> Kind -> TyVar
mkTyVar name kind = TyVar { varName = name
, realUnique = getKey (nameUnique name)
, varType = kind
}
mkTcTyVar :: Name -> Kind -> TcTyVarDetails -> TyVar
mkTcTyVar name kind details
=
TcTyVar { varName = name,
realUnique = getKey (nameUnique name),
varType = kind,
tc_tv_details = details
}
tcTyVarDetails :: TyVar -> TcTyVarDetails
tcTyVarDetails (TcTyVar { tc_tv_details = details }) = details
tcTyVarDetails (TyVar {}) = vanillaSkolemTv
tcTyVarDetails var = pprPanic "tcTyVarDetails" (ppr var <+> dcolon <+> pprKind (tyVarKind var))
setTcTyVarDetails :: TyVar -> TcTyVarDetails -> TyVar
setTcTyVarDetails tv details = tv { tc_tv_details = details }
instance Outputable tv => Outputable (TyVarBndr tv ArgFlag) where
ppr (TvBndr v Required) = ppr v
ppr (TvBndr v Specified) = char '@' <> ppr v
ppr (TvBndr v Inferred) = braces (ppr v)
instance Outputable ArgFlag where
ppr Required = text "[req]"
ppr Specified = text "[spec]"
ppr Inferred = text "[infrd]"
instance (Binary tv, Binary vis) => Binary (TyVarBndr tv vis) where
put_ bh (TvBndr tv vis) = do { put_ bh tv; put_ bh vis }
get bh = do { tv <- get bh; vis <- get bh; return (TvBndr tv vis) }
instance Binary ArgFlag where
put_ bh Required = putByte bh 0
put_ bh Specified = putByte bh 1
put_ bh Inferred = putByte bh 2
get bh = do
h <- getByte bh
case h of
0 -> return Required
1 -> return Specified
_ -> return Inferred
idInfo :: HasDebugCallStack => Id -> IdInfo
idInfo (Id { id_info = info }) = info
idInfo other = pprPanic "idInfo" (ppr other)
idDetails :: Id -> IdDetails
idDetails (Id { id_details = details }) = details
idDetails other = pprPanic "idDetails" (ppr other)
mkGlobalVar :: IdDetails -> Name -> Type -> IdInfo -> Id
mkGlobalVar details name ty info
= mk_id name ty GlobalId details info
mkLocalVar :: IdDetails -> Name -> Type -> IdInfo -> Id
mkLocalVar details name ty info
= mk_id name ty (LocalId NotExported) details info
mkCoVar :: Name -> Type -> CoVar
mkCoVar name ty = mk_id name ty (LocalId NotExported) coVarDetails vanillaIdInfo
mkExportedLocalVar :: IdDetails -> Name -> Type -> IdInfo -> Id
mkExportedLocalVar details name ty info
= mk_id name ty (LocalId Exported) details info
mk_id :: Name -> Type -> IdScope -> IdDetails -> IdInfo -> Id
mk_id name ty scope details info
= Id { varName = name,
realUnique = getKey (nameUnique name),
varType = ty,
idScope = scope,
id_details = details,
id_info = info }
lazySetIdInfo :: Id -> IdInfo -> Var
lazySetIdInfo id info = id { id_info = info }
setIdDetails :: Id -> IdDetails -> Id
setIdDetails id details = id { id_details = details }
globaliseId :: Id -> Id
globaliseId id = id { idScope = GlobalId }
setIdExported :: Id -> Id
setIdExported id@(Id { idScope = LocalId {} }) = id { idScope = LocalId Exported }
setIdExported id@(Id { idScope = GlobalId }) = id
setIdExported tv = pprPanic "setIdExported" (ppr tv)
setIdNotExported :: Id -> Id
setIdNotExported id = ASSERT( isLocalId id )
id { idScope = LocalId NotExported }
isTyVar :: Var -> Bool
isTyVar (TyVar {}) = True
isTyVar (TcTyVar {}) = True
isTyVar _ = False
isTcTyVar :: Var -> Bool
isTcTyVar (TcTyVar {}) = True
isTcTyVar _ = False
isTyCoVar :: Var -> Bool
isTyCoVar v = isTyVar v || isCoVar v
isId :: Var -> Bool
isId (Id {}) = True
isId _ = False
isCoVar :: Var -> Bool
isCoVar (Id { id_details = details }) = isCoVarDetails details
isCoVar _ = False
isNonCoVarId :: Var -> Bool
isNonCoVarId (Id { id_details = details }) = not (isCoVarDetails details)
isNonCoVarId _ = False
isLocalId :: Var -> Bool
isLocalId (Id { idScope = LocalId _ }) = True
isLocalId _ = False
isLocalVar :: Var -> Bool
isLocalVar v = not (isGlobalId v)
isGlobalId :: Var -> Bool
isGlobalId (Id { idScope = GlobalId }) = True
isGlobalId _ = False
mustHaveLocalBinding :: Var -> Bool
mustHaveLocalBinding var = isLocalVar var
isExportedId :: Var -> Bool
isExportedId (Id { idScope = GlobalId }) = True
isExportedId (Id { idScope = LocalId Exported}) = True
isExportedId _ = False