%
% (c) The University of Glasgow 2006
% (c) The GRASP/AQUA Project, Glasgow University, 19921998
%
\section{@Vars@: Variables}
\begin{code}
module Var (
Var,
varName, varUnique, varType,
setVarName, setVarUnique, setVarType,
mkGlobalVar, mkLocalVar, mkExportedLocalVar,
idInfo, idDetails,
lazySetIdInfo, setIdDetails, globaliseId,
setIdExported, setIdNotExported,
isCoVar, isId, isTyVar, isTcTyVar,
isLocalVar, isLocalId,
isGlobalId, isExportedId,
mustHaveLocalBinding,
TyVar,
mkTyVar, mkTcTyVar, mkWildCoVar,
tyVarName, tyVarKind, tcTyVarDetails,
setTyVarName, setTyVarUnique, setTyVarKind,
CoVar,
mkCoVar,
coVarName,
setCoVarUnique, setCoVarName,
Id, DictId
) where
#include "HsVersions.h"
import TypeRep( Type, Kind )
import TcType( TcTyVarDetails, pprTcTyVarDetails )
import IdInfo( IdDetails, IdInfo, pprIdDetails )
import TypeRep( isCoercionKind )
import Name hiding (varName)
import Unique
import FastTypes
import FastString
import Outputable
\end{code}
%************************************************************************
%* *
\subsection{The main data type declarations}
%* *
%************************************************************************
Every @Var@ has a @Unique@, to uniquify it and for fast comparison, a
@Type@, and an @IdInfo@ (nonessential info about it, e.g.,
strictness). The essential info about different kinds of @Vars@ is
in its @VarDetails@.
\begin{code}
data Var
= TyVar {
varName :: !Name,
realUnique :: FastInt,
varType :: Kind,
isCoercionVar :: Bool
}
| TcTyVar {
varName :: !Name,
realUnique :: FastInt,
varType :: Kind,
tcTyVarDetails :: TcTyVarDetails }
| Id {
varName :: !Name,
realUnique :: FastInt,
varType :: Type,
idScope :: IdScope,
id_details :: IdDetails,
id_info :: IdInfo }
data IdScope
= GlobalId
| LocalId ExportFlag
data ExportFlag
= NotExported
| Exported
\end{code}
Note [GlobalId/LocalId]
~~~~~~~~~~~~~~~~~~~~~~~
A GlobalId is
* always a constant (toplevel)
* imported, or data constructor, or primop, or record selector
* has a Unique that is globally unique across the whole
GHC invocation (a single invocation may compile multiple modules)
* never treated as a candidate by the freevariable finder;
it's a constant!
A LocalId is
* bound within an expression (lambda, case, local let(rec))
* or defined at top level in the module being compiled
* always treated as a candidate by the freevariable finder
After CoreTidy, toplevel LocalIds are turned into GlobalIds
\begin{code}
instance Outputable Var where
ppr var = ppr (varName var) <+> ifPprDebug (brackets (ppr_debug var))
ppr_debug :: Var -> SDoc
ppr_debug (TyVar {}) = ptext (sLit "tv")
ppr_debug (TcTyVar {tcTyVarDetails = d}) = pprTcTyVarDetails d
ppr_debug (Id { idScope = s, id_details = d }) = ppr_id_scope s <> pprIdDetails d
ppr_id_scope :: IdScope -> SDoc
ppr_id_scope GlobalId = ptext (sLit "gid")
ppr_id_scope (LocalId Exported) = ptext (sLit "lidx")
ppr_id_scope (LocalId NotExported) = ptext (sLit "lid")
instance Show Var where
showsPrec p var = showsPrecSDoc p (ppr var)
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 = varUnique a `compare` varUnique b
\end{code}
\begin{code}
varUnique :: Var -> Unique
varUnique var = mkUniqueGrimily (iBox (realUnique var))
setVarUnique :: Var -> Unique -> Var
setVarUnique var uniq
= var { realUnique = getKeyFastInt uniq,
varName = setNameUnique (varName var) uniq }
setVarName :: Var -> Name -> Var
setVarName var new_name
= var { realUnique = getKeyFastInt (getUnique new_name),
varName = new_name }
setVarType :: Id -> Type -> Id
setVarType id ty = id { varType = ty }
\end{code}
%************************************************************************
%* *
\subsection{Type variables}
%* *
%************************************************************************
\begin{code}
type TyVar = Var
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}
\end{code}
\begin{code}
mkTyVar :: Name -> Kind -> TyVar
mkTyVar name kind = ASSERT( not (isCoercionKind kind ) )
TyVar { varName = name
, realUnique = getKeyFastInt (nameUnique name)
, varType = kind
, isCoercionVar = False
}
mkTcTyVar :: Name -> Kind -> TcTyVarDetails -> TyVar
mkTcTyVar name kind details
=
TcTyVar { varName = name,
realUnique = getKeyFastInt (nameUnique name),
varType = kind,
tcTyVarDetails = details
}
\end{code}
%************************************************************************
%* *
\subsection{Coercion variables}
%* *
%************************************************************************
\begin{code}
type CoVar = TyVar
coVarName :: CoVar -> Name
coVarName = varName
setCoVarUnique :: CoVar -> Unique -> CoVar
setCoVarUnique = setVarUnique
setCoVarName :: CoVar -> Name -> CoVar
setCoVarName = setVarName
mkCoVar :: Name -> Kind -> CoVar
mkCoVar name kind = ASSERT( isCoercionKind kind )
TyVar { varName = name
, realUnique = getKeyFastInt (nameUnique name)
, varType = kind
, isCoercionVar = True
}
mkWildCoVar :: Kind -> TyVar
mkWildCoVar = mkCoVar (mkSysTvName (mkBuiltinUnique 1) (fsLit "co_wild"))
\end{code}
%************************************************************************
%* *
\subsection{Ids}
%* *
%************************************************************************
\begin{code}
type Id = Var
type DictId = Var
idInfo :: 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
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 = getKeyFastInt (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 }
\end{code}
%************************************************************************
%* *
\subsection{Predicates over variables}
%* *
%************************************************************************
\begin{code}
isTyVar :: Var -> Bool
isTyVar (TyVar {}) = True
isTyVar (TcTyVar {}) = True
isTyVar _ = False
isTcTyVar :: Var -> Bool
isTcTyVar (TcTyVar {}) = True
isTcTyVar _ = False
isId :: Var -> Bool
isId (Id {}) = True
isId _ = False
isLocalId :: Var -> Bool
isLocalId (Id { idScope = LocalId _ }) = True
isLocalId _ = False
isCoVar :: Var -> Bool
isCoVar (v@(TyVar {})) = isCoercionVar v
isCoVar (TcTyVar {varType = kind}) = isCoercionKind kind
isCoVar _ = 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
\end{code}