--- /dev/null
+%
+% (c) The GRASP/AQUA Project, Glasgow University, 1992-1995
+%
+\section[UniTyFuns]{Utility functions for @UniTypes@}
+
+This is one of the modules whose functions know about the internal
+representation of @UniTypes@ (and @TyCons@ and ... ?).
+
+\begin{code}
+#include "HsVersions.h"
+
+module UniTyFuns (
+
+ -- CONSTRUCTION
+ applyTy, applyTyCon, applySynTyCon, applyNonSynTyCon,
+ {-mkSigmaTy,-} glueTyArgs, mkSuperDictSelType, --UNUSED: mkDictFunType,
+ specialiseTy,
+
+ -- DESTRUCTION
+--not exported: expandTySyns,
+ expandVisibleTySyn,
+ getTyVar, getTyVarMaybe, getTyVarTemplateMaybe,
+ splitType, splitForalls, getTauType, splitTyArgs,
+ splitTypeWithDictsAsArgs,
+--not exported/unused: sourceTypes, targetType,
+ funResultTy,
+ splitDictType,
+ kindFromType,
+ getUniDataTyCon, getUniDataTyCon_maybe,
+ getUniDataSpecTyCon, getUniDataSpecTyCon_maybe,
+ unDictifyTy,
+ getMentionedTyCons,
+#ifdef USE_SEMANTIQUE_STRANAL
+ getReferredToTyCons,
+#endif {- Semantique strictness analyser -}
+ getMentionedTyConsAndClassesFromUniType,
+ getMentionedTyConsAndClassesFromTyCon,
+ getMentionedTyConsAndClassesFromClass,
+ getUniTyDescription,
+
+ -- FREE-VARIABLE EXTRACTION
+ extractTyVarsFromTy, extractTyVarsFromTys,
+ extractTyVarTemplatesFromTy,
+
+ -- PREDICATES
+ isTyVarTy, isTyVarTemplateTy,
+ maybeUnpackFunTy, isFunType,
+ isPrimType, isUnboxedDataType, -- UNUSED: isDataConType,
+ isLeakFreeType,
+ maybeBoxedPrimType,
+--UNUSED: hasHigherOrderArg,
+ isDictTy, isGroundTy, isGroundOrTyVarTy,
+ instanceIsExported,
+-- UNUSED: isSynTarget,
+ isTauTy, isForAllTy,
+ maybePurelyLocalTyCon, maybePurelyLocalClass, maybePurelyLocalType,
+ returnsRealWorld, -- HACK courtesy of SLPJ
+#ifdef DPH
+ isProcessorTy,
+ runtimeUnpodizableType,
+#endif {- Data Parallel Haskell -}
+
+ -- SUBSTITUTION
+ applyTypeEnvToTy, applyTypeEnvToThetaTy,
+--not exported : applyTypeEnvToTauTy,
+ mapOverTyVars,
+ -- moved to Subst: applySubstToTauTy, applySubstToTy, applySubstToThetaTy,
+ -- genInstantiateTyUS, -- ToDo: ???
+
+ -- PRETTY PRINTING AND FORCING
+ pprUniType, pprParendUniType, pprMaybeTy,
+ pprTyCon, pprIfaceClass, pprClassOp,
+ getTypeString,
+ typeMaybeString,
+ specMaybeTysSuffix,
+ showTyCon,
+ showTypeCategory,
+
+ -- MATCHING and COMPARISON
+ matchTy, -- UNUSED: matchTys,
+ cmpUniTypeMaybeList,
+
+ -- to make this interface self-sufficient....
+ TyVar, TyVarTemplate, TyCon, Class, UniType, UniqueSupply,
+ IdEnv(..), UniqFM, UnfoldingDetails, PrimKind, TyVarEnv(..),
+ TypeEnv(..), Maybe, PprStyle, PrettyRep, Bag
+ ) where
+
+IMPORT_Trace -- ToDo:rm (debugging)
+
+-- internal modules; allowed to see constructors for type things
+import Class
+import TyVar
+import TyCon
+import UniType
+
+import AbsPrel ( listTyCon, integerTyCon, charPrimTyCon,
+ intPrimTyCon, wordPrimTyCon, addrPrimTyCon,
+ floatPrimTyCon, doublePrimTyCon,
+ realWorldTyCon
+#ifdef DPH
+ , podTyCon
+#endif {- Data Parallel Haskell -}
+ )
+import Bag
+import CLabelInfo ( identToC )
+import CmdLineOpts ( GlobalSwitch(..) )
+import Id ( Id, getIdInfo,
+ getMentionedTyConsAndClassesFromId,
+ getInstantiatedDataConSig,
+ getDataConSig, mkSameSpecCon,
+ DataCon(..)
+ )
+import IdEnv -- ( lookupIdEnv, IdEnv )
+import IdInfo ( ppIdInfo, boringIdInfo, IdInfo, UnfoldingDetails )
+import InstEnv ( ClassInstEnv(..), MatchEnv(..) )
+import ListSetOps ( unionLists )
+import NameTypes ( FullName )
+import Maybes
+import Outputable
+import Pretty
+import PrimKind ( PrimKind(..) )
+import SpecTyFuns ( specialiseConstrTys )
+import TyVarEnv
+import Unique -- used UniqueSupply monadery
+import Util
+\end{code}
+
+%************************************************************************
+%* *
+\subsection[UniTyFuns-construction]{Putting types together}
+%* *
+%************************************************************************
+
+\begin{code}
+applyTy :: SigmaType -> SigmaType -> SigmaType
+
+applyTy (UniSyn _ _ fun_ty) arg_ty = applyTy fun_ty arg_ty
+applyTy fun_ty@(UniForall tyvar ty) arg_ty
+ = instantiateTy [(tyvar,arg_ty)] ty
+#ifdef DEBUG
+applyTy bad_fun_ty arg_ty
+ = pprPanic "applyTy: not a forall type:" (ppAbove (ppr PprDebug bad_fun_ty) (ppr PprDebug arg_ty))
+#endif
+\end{code}
+
+@applyTyCon@ applies a type constructor to a list of tau-types to give
+a type. @applySynTyCon@ and @applyNonSynTyCon@ are similar, but they
+``know'' what sort the type constructor is, so they are a bit lazier.
+This is important in @TcMonoType.lhs@.
+
+\begin{code}
+applyTyCon, applySynTyCon, applyNonSynTyCon :: TyCon -> [TauType] -> TauType
+
+applyTyCon tc tys
+ = ASSERT (if (getTyConArity tc == length tys) then True else pprTrace "applyTyCon" (ppCat [ppr PprDebug tc, ppr PprDebug tys]) False)
+ --false:ASSERT (all isTauTy tys) TauType?? 94/06
+ let
+ result = apply_tycon tc tys
+ in
+ --false:ASSERT (isTauTy result) TauType?? 94/06
+ result
+ where
+ apply_tycon tc@(SynonymTyCon _ _ _ _ _ _) tys = applySynTyCon tc tys
+ apply_tycon tc@(DataTyCon _ _ _ _ _ _ _) tys = applyNonSynTyCon tc tys
+
+ apply_tycon tc@(PrimTyCon _ _ _ _) tys = UniData tc tys
+
+ apply_tycon tc@(TupleTyCon _) tys = UniData tc tys
+ -- The arg types here aren't necessarily tau-types, because we
+ -- may have polymorphic methods in a dictionary.
+
+ -- Original tycon used in type of SpecTyCon
+ apply_tycon tc_spec@(SpecTyCon tc spec_tys) tys
+ = apply_tycon tc (fill_nothings spec_tys tys)
+ where
+ fill_nothings (Just ty:maybes) fills = ty : fill_nothings maybes fills
+ fill_nothings (Nothing:maybes) (ty:fills) = ty : fill_nothings maybes fills
+ fill_nothings [] [] = []
+
+#ifdef DPH
+ apply_tycon tc@(ProcessorTyCon _) tys = UniData tc tys
+#endif {- Data Parallel Haskell -}
+
+
+-----------------
+
+applySynTyCon tycon tys
+ = UniSyn tycon ok_tys (instantiateTauTy (tyvars `zip` ok_tys) template)
+ -- Memo the result of substituting for the tyvars in the template
+ where
+ SynonymTyCon _ _ _ tyvars template _ = tycon
+ -- NB: Matched lazily
+
+#ifdef DEBUG
+ ok_tys = map (verifyTauTy "applyTyConLazily[syn]") tys
+#else
+ ok_tys = tys
+#endif
+
+-----------------
+
+applyNonSynTyCon tycon tys -- We don't expect function tycons;
+ -- but it must be lazy, so we can't check that here!
+#ifdef DEBUG
+ = UniData tycon (map (verifyTauTy "applyTyConLazily[data]") tys)
+#else
+ = UniData tycon tys
+#endif
+\end{code}
+
+@glueTyArgs [ty1,...,tyn] ty@ returns the type
+@ty1 -> ... -> tyn -> ty@. This is the exact reverse of @splitTyArgs@.
+
+\begin{code}
+-- ToDo: DEBUG: say what's true about these types
+glueTyArgs :: [UniType] -> UniType -> UniType
+
+glueTyArgs tys ty = foldr UniFun ty tys
+\end{code}
+
+\begin{code}
+mkSuperDictSelType :: Class -- The input class
+ -> Class -- The superclass
+ -> UniType -- The type of the selector function
+
+mkSuperDictSelType clas@(MkClass _ _ tyvar _ _ _ _ _ _ _) super
+ = UniForall tyvar (UniFun (UniDict clas (UniTyVarTemplate tyvar))
+ (UniDict super (UniTyVarTemplate tyvar)))
+\end{code}
+
+UNUSED: @mkDictFunType@ creates the type of a dictionary function, given:
+the polymorphic type variables, the types of the dict args, the class and
+tautype of the result.
+
+\begin{code}
+{- UNUSED:
+mkDictFunType :: [TyVarTemplate] -> ThetaType -> Class -> TauType -> UniType
+
+mkDictFunType tyvars theta clas tau_ty
+#ifndef DEBUG
+ = mkForallTy tyvars (foldr f (UniDict clas tau_ty) theta)
+#else
+ = mkForallTy tyvars (foldr f (UniDict clas (verifyTauTy "mkDictFunType" tau_ty)) theta)
+#endif
+ where
+ f (clas,tau_ty) sofar = UniFun (UniDict clas tau_ty) sofar
+-}
+\end{code}
+
+\begin{code}
+specialiseTy :: UniType -- The type of the Id of which the SpecId
+ -- is a specialised version
+ -> [Maybe UniType] -- The types at which it is specialised
+ -> Int -- Number of leading dictionary args to ignore
+ -> UniType
+
+specialiseTy main_ty maybe_tys dicts_to_ignore
+ = --false:ASSERT(isTauTy tau) TauType??
+ mkSigmaTy remaining_tyvars
+ (instantiateThetaTy inst_env remaining_theta)
+ (instantiateTauTy inst_env tau)
+ where
+ (tyvars, theta, tau) = splitType main_ty -- A prefix of, but usually all,
+ -- the theta is discarded!
+ remaining_theta = drop dicts_to_ignore theta
+ tyvars_and_maybe_tys = tyvars `zip` maybe_tys
+ remaining_tyvars = [tyvar | (tyvar, Nothing) <- tyvars_and_maybe_tys]
+ inst_env = [(tyvar,ty) | (tyvar, Just ty) <- tyvars_and_maybe_tys]
+\end{code}
+
+%************************************************************************
+%* *
+\subsection[UniTyFuns-destruction]{Taking types apart}
+%* *
+%************************************************************************
+
+@expandVisibleTySyn@ removes any visible type-synonym from the top level of a
+@TauType@. Note that the expansion is recursive.
+
+@expandTySyns@ removes all type-synonyms from a @TauType@.
+
+\begin{code}
+expandVisibleTySyn, expandTySyns :: TauType -> TauType
+
+expandVisibleTySyn (UniSyn con _ tau)
+ | isVisibleSynTyCon con
+ = ASSERT(isTauTy tau)
+ expandVisibleTySyn tau
+expandVisibleTySyn tau
+ = ASSERT(isTauTy tau)
+ tau
+
+expandTySyns (UniSyn _ _ tau) = expandTySyns tau
+expandTySyns (UniFun a b) = UniFun (expandTySyns a) (expandTySyns b)
+expandTySyns (UniData c tys) = UniData c (map expandTySyns tys)
+expandTySyns tau = -- FALSE:WDP 95/03: ASSERT(isTauTy tau)
+ tau
+\end{code}
+
+@getTyVar@ extracts a type variable from a @UniType@ if the latter is
+just a type variable, failing otherwise. @getTyVarMaybe@ is similar,
+except that it returns a @Maybe@ type.
+
+\begin{code}
+getTyVar :: String -> UniType -> TyVar
+getTyVar panic_msg (UniTyVar tyvar) = tyvar
+getTyVar panic_msg other = panic ("getTyVar: " ++ panic_msg)
+
+getTyVarMaybe :: UniType -> Maybe TyVar
+getTyVarMaybe (UniTyVar tyvar) = Just tyvar
+getTyVarMaybe (UniSyn _ _ exp) = getTyVarMaybe exp
+getTyVarMaybe other = Nothing
+
+getTyVarTemplateMaybe :: UniType -> Maybe TyVarTemplate
+getTyVarTemplateMaybe (UniTyVarTemplate tyvar) = Just tyvar
+getTyVarTemplateMaybe (UniSyn _ _ exp) = getTyVarTemplateMaybe exp
+getTyVarTemplateMaybe other = Nothing
+\end{code}
+
+@splitType@ splits a type into three components. The first is the
+bound type variables, the second is the context and the third is the
+tau type. I'll produce specific functions which access particular pieces
+of the type when we see where they are needed.
+
+\begin{code}
+splitType :: UniType -> ([TyVarTemplate], ThetaType, TauType)
+splitType uni_ty
+ = case (split_foralls uni_ty) of { (tyvars, rho_ty) ->
+ case (split_rho_ty rho_ty) of { (theta_ty, tau_ty) ->
+ --false:ASSERT(isTauTy tau_ty) TauType
+ (tyvars, theta_ty, tau_ty)
+ }}
+ where
+ split_foralls (UniForall tyvar uni_ty)
+ = case (split_foralls uni_ty) of { (tyvars,new_ty) ->
+ (tyvar:tyvars, new_ty) }
+
+ split_foralls other_ty = ([], other_ty)
+
+ split_rho_ty (UniFun (UniDict clas ty) ty_body)
+ = case (split_rho_ty ty_body) of { (context,ty_body') ->
+ ((clas, ty) :context, ty_body') }
+
+ split_rho_ty other_ty = ([], other_ty)
+\end{code}
+
+Sometimes we want the dictionaries counted as arguments. We guarantee
+to return {\em some} arguments if there are any, but not necessarily
+{\em all}. In particular, the ``result type'' might be a @UniDict@,
+which might (in the case of a single-classop class) be a function. In
+that case, we strongly avoid returning a @UniDict@ ``in the corner''
+(by @unDictify@ing that type, too).
+
+This seems like a bit of a fudge, frankly, but it does the job.
+
+\begin{code}
+splitTypeWithDictsAsArgs
+ :: UniType -- input
+ -> ([TyVarTemplate],
+ [UniType], -- arg types
+ TauType) -- result type
+
+splitTypeWithDictsAsArgs ty
+ = case (splitType ty) of { (tvs, theta, tau_ty) ->
+ case (splitTyArgs tau_ty) of { (tau_arg_tys, res_ty) ->
+ let
+ result extra_arg_tys res_ty
+ = --false: ASSERT(isTauTy res_ty) TauType
+ (tvs,
+ [ mkDictTy c t | (c,t) <- theta ] ++ tau_arg_tys ++ extra_arg_tys,
+ res_ty)
+ in
+ if not (isDictTy res_ty) then
+ result [] res_ty
+ else
+ let
+ undicted_res_ty = unDictifyTy res_ty
+ (tau_arg_tys', res_ty') = splitTyArgs undicted_res_ty
+ in
+ if (null theta && null tau_arg_tys)
+ || isFunType undicted_res_ty then
+
+ -- (a) The input ty was just a "dictionary" for a
+ -- single-method class with no super-dicts; the
+ -- "dictionary" is just the one method itself; we'd really
+ -- rather give info about that method...
+
+ -- (b) The input ty gave back a "dictionary" for a
+ -- single-method class; if the method itself is a
+ -- function, then we'd jolly well better add its arguments
+ -- onto the whole "arg_tys" list.
+
+ -- There may be excessive paranoia going on here (WDP).
+
+ result tau_arg_tys' res_ty'
+
+ else -- do nothing special...
+ result [] res_ty
+ }}
+\end{code}
+
+@splitForalls@ is similar, but only splits off the forall'd type
+variables.
+
+\begin{code}
+splitForalls :: UniType -> ([TyVarTemplate], RhoType)
+
+splitForalls (UniForall tyvar ty)
+ = case (splitForalls ty) of
+ (tyvars, new_ty) -> (tyvar:tyvars, new_ty)
+splitForalls (UniSyn _ _ ty) = splitForalls ty
+splitForalls other_ty = ([], other_ty)
+\end{code}
+
+And a terribly convenient way to access @splitType@:
+
+\begin{code}
+getTauType :: UniType -> TauType
+getTauType uni_ty
+ = case (splitType uni_ty) of { (_,_,tau_ty) ->
+ --false:ASSERT(isTauTy tau_ty) TauType??? (triggered in ProfMassage)
+ tau_ty }
+\end{code}
+
+@splitTyArgs@ does the same for the arguments of a function type.
+
+\begin{code}
+splitTyArgs :: TauType -> ([TauType], TauType)
+
+splitTyArgs ty
+ = --false: ASSERT(isTauTy ty) TauType???
+ split ty
+ where
+ split (UniSyn _ _ expand) = split expand
+
+ split (UniFun arg result)
+ = case (split result) of { (args, result') ->
+ (arg:args, result') }
+
+ split ty = ([], ty)
+
+funResultTy :: RhoType -- Function type
+ -> Int -- Number of args to which applied
+ -> RhoType -- Result type
+
+funResultTy ty 0 = ty
+funResultTy (UniSyn _ _ expand) n_args = funResultTy expand n_args
+funResultTy ty@(UniDict _ _) n_args = funResultTy (unDictifyTy ty) n_args
+funResultTy (UniFun _ result_ty) n_args = funResultTy result_ty (n_args - 1)
+#ifdef DEBUG
+funResultTy other_ty n_args = panic ("funResultTy:not a fun:"++(ppShow 80 (ppr PprDebug other_ty)))
+#endif
+\end{code}
+
+The type-destructor functions above return dictionary information in
+terms of @UniDict@, a relatively abstract construct. What really
+happens ``under the hood'' is that {\em tuples} (usually) are passed
+around as ordinary arguments. Sometimes we want this ``what's really
+happening'' information.
+
+The interesting case for @getUniDataTyCon_maybe@ is if the argument is
+a dictionary type. Dictionaries are represented by tuples (except for
+size-one dictionaries which are represented by the method itself), so
+@getUniDataTyCon_maybe@ has to figure out which tuple. This is a bit
+unsatisfactory; the information about how dictionaries are represented
+is rather thinly distributed.
+
+@unDictify@ only removes a {\em top-level} @UniDict@. There may be
+buried @UniDicts@ in what is returned.
+
+\begin{code}
+unDictifyTy :: UniType -- Might be a UniDict
+ -> UniType -- Can't be a UniDict
+
+unDictifyTy (UniSyn _ _ expansion) = unDictifyTy expansion
+
+unDictifyTy (UniDict clas ty)
+ = ASSERT(dict_size >= 0)
+ if dict_size == 1 then
+ unDictifyTy (head all_arg_tys) -- just the <whatever> itself
+ -- The extra unDictify is to make sure that
+ -- the result isn't still a dict, which it might be
+ -- if the original guy was a dict with one superdict and
+ -- no methods!
+ else
+ UniData (mkTupleTyCon dict_size) all_arg_tys -- a tuple of 'em
+ -- NB: dict_size can be 0 if the class is
+ -- _CCallable, _CReturnable (and anything else
+ -- *really weird* that the user writes).
+ where
+ (tyvar, super_classes, ops) = getClassSig clas
+ dict_size = length super_classes + length ops
+
+ super_dict_tys = map mk_super_ty super_classes
+ class_op_tys = map mk_op_ty ops
+
+ all_arg_tys = super_dict_tys ++ class_op_tys
+
+ mk_super_ty sc = mkDictTy sc ty
+ mk_op_ty op = instantiateTy [(tyvar,ty)] (getClassOpLocalType op)
+
+unDictifyTy other_ty = other_ty
+\end{code}
+
+\begin{code}
+{- UNUSED:
+sourceTypes :: TauType -> [TauType]
+sourceTypes ty
+ = --false:ASSERT(isTauTy ty)
+ (fst . splitTyArgs) ty
+
+targetType :: TauType -> TauType
+targetType ty
+ = --false: ASSERT(isTauTy ty) TauType??
+ (snd . splitTyArgs) ty
+-}
+\end{code}
+
+Here is a function that tell you if a type has as its target a Synonym.
+If so it returns the relevant constructor and its argument type.
+
+\begin{code}
+{- UNUSED:
+isSynTarget :: UniType -> Maybe (TyCon,Int)
+
+isSynTarget (UniFun _ arg) = case isSynTarget arg of
+ Just (tycon,x) -> Just (tycon,x + 1)
+ Nothing -> Nothing
+isSynTarget (UniSyn tycon _ _) = Just (tycon,0)
+isSynTarget (UniForall _ e) = isSynTarget e
+isSynTarget _ = Nothing
+--isSynTarget (UniTyVarTemplate e) = panic "isSynTarget: got a UniTyVarTemplate!"
+-}
+\end{code}
+
+\begin{code}
+splitDictType :: UniType -> (Class, UniType)
+splitDictType (UniDict clas ty) = (clas, ty)
+splitDictType (UniSyn _ _ ty) = splitDictType ty
+splitDictType other = panic "splitDictTy"
+\end{code}
+
+In @kindFromType@ it can happen that we come across a @TyVarTemplate@,
+for example when figuring out the kinds of the argument of a data
+constructor; inside the @DataCon@ the argument types are in template form.
+
+\begin{code}
+kindFromType :: UniType -> PrimKind
+kindFromType (UniSyn tycon tys expand) = kindFromType expand
+kindFromType (UniData tycon tys) = getTyConKind tycon (map kindFromType tys)
+kindFromType other = PtrKind -- the "default"
+
+isPrimType :: UniType -> Bool
+
+isPrimType (UniSyn tycon tys expand) = isPrimType expand
+#ifdef DPH
+isPrimType (UniData tycon tys) | isPodizedPodTyCon tycon
+ = all isPrimType tys
+#endif {- Data Parallel Haskell}
+isPrimType (UniData tycon tys) = isPrimTyCon tycon
+isPrimType other = False -- the "default"
+
+maybeBoxedPrimType :: UniType -> Maybe (Id{-DataCon-}, UniType)
+
+maybeBoxedPrimType ty
+ = case (getUniDataTyCon_maybe ty) of -- Data type,
+ Just (tycon, tys_applied, [data_con]) -- with exactly one constructor
+ -> case (getInstantiatedDataConSig data_con tys_applied) of
+ (_, [data_con_arg_ty], _) -- Applied to exactly one type,
+ | isPrimType data_con_arg_ty -- which is primitive
+ -> Just (data_con, data_con_arg_ty)
+ other_cases -> Nothing
+ other_cases -> Nothing
+\end{code}
+
+At present there are no unboxed non-primitive types, so
+isUnboxedDataType is the same as isPrimType.
+
+\begin{code}
+isUnboxedDataType :: UniType -> Bool
+
+isUnboxedDataType (UniSyn _ _ expand) = isUnboxedDataType expand
+isUnboxedDataType (UniData tycon _) = not (isBoxedTyCon tycon)
+isUnboxedDataType other = False
+\end{code}
+
+If you want to run @getUniDataTyCon...@ or @UniDataArgTys@ over a
+dictionary-full type, then put the type through @unDictifyTy@ first.
+
+\begin{code}
+getUniDataTyCon_maybe
+ :: TauType
+ -> Maybe (TyCon, -- the type constructor
+ [TauType], -- types to which it is applied
+ [Id]) -- its family of data-constructors
+
+getUniDataTyCon_maybe ty
+ = --false:ASSERT(isTauTy ty) TauType?
+ get ty
+ where
+ get (UniSyn _ _ expand) = get expand
+ get ty@(UniDict _ _) = get (unDictifyTy ty)
+
+ get (UniData tycon arg_tys)
+ = Just (tycon, arg_tys, getTyConDataCons tycon)
+ -- does not returned specialised data constructors
+
+ get other_ty = Nothing
+\end{code}
+
+@getUniDataTyCon@ is just a version which fails noisily.
+\begin{code}
+getUniDataTyCon ty
+ = case getUniDataTyCon_maybe ty of
+ Just stuff -> stuff
+#ifdef DEBUG
+ Nothing -> pprPanic "getUniDataTyCon:" (ppr PprShowAll ty)
+#endif
+\end{code}
+
+@getUniDataSpecTyCon_maybe@ returns an appropriate specialised tycon,
+any remaining (boxed) type arguments, and specialsied constructors.
+\begin{code}
+getUniDataSpecTyCon_maybe
+ :: TauType
+ -> Maybe (TyCon, -- the type constructor
+ [TauType], -- types to which it is applied
+ [Id]) -- its family of data-constructors
+
+getUniDataSpecTyCon_maybe ty
+ = case getUniDataTyCon_maybe ty of
+ Nothing -> Nothing
+ Just unspec@(tycon, tycon_arg_tys, datacons) ->
+ let spec_tys = specialiseConstrTys tycon_arg_tys
+ spec_reqd = maybeToBool (firstJust spec_tys)
+
+ data_cons = getTyConDataCons tycon
+ spec_datacons = map (mkSameSpecCon spec_tys) data_cons
+ spec_tycon = mkSpecTyCon tycon spec_tys
+
+ tys_left = [ty | (spec, ty) <- spec_tys `zip` tycon_arg_tys,
+ not (maybeToBool spec) ]
+ in
+ if spec_reqd
+ then Just (spec_tycon, tys_left, spec_datacons)
+ else Just unspec
+\end{code}
+
+@getUniDataSpecTyCon@ is just a version which fails noisily.
+\begin{code}
+getUniDataSpecTyCon ty
+ = case getUniDataSpecTyCon_maybe ty of
+ Just stuff -> stuff
+ Nothing -> panic ("getUniDataSpecTyCon:"++ (ppShow 80 (ppr PprShowAll ty)))
+\end{code}
+
+@getMentionedTyCons@ maps a type constructor to a list of type
+constructors. If the type constructor is built-in or a @data@ type
+constructor, the list is empty. In the case of synonyms, list
+contains all the type {\em synonym} constructors {\em directly}
+mentioned in the definition of the synonym.
+\begin{code}
+getMentionedTyCons :: TyCon -> [TyCon]
+
+getMentionedTyCons (SynonymTyCon _ _ _ _ expansion _) = get_ty_cons expansion
+ where
+ get_ty_cons (UniTyVar _) = []
+ get_ty_cons (UniTyVarTemplate _)= []
+ get_ty_cons (UniData _ tys) = concat (map get_ty_cons tys)
+ get_ty_cons (UniFun ty1 ty2) = get_ty_cons ty1 ++ get_ty_cons ty2
+ get_ty_cons (UniSyn tycon _ _) = [tycon]
+ get_ty_cons _ = panic "get_ty_cons: unexpected UniType"
+
+getMentionedTyCons other_tycon = []
+\end{code}
+
+Here's a similar thing used in the Semantique strictness analyser:
+\begin{code}
+#ifdef USE_SEMANTIQUE_STRANAL
+getReferredToTyCons :: TauType -> [TyCon]
+getReferredToTyCons (UniTyVar v) = []
+getReferredToTyCons (UniTyVarTemplate v) = []
+getReferredToTyCons (UniData t ts) = t : concat (map getReferredToTyCons ts)
+getReferredToTyCons (UniFun s t) = getReferredToTyCons s ++ getReferredToTyCons t
+getReferredToTyCons (UniSyn _ _ t) = getReferredToTyCons (getTauType t)
+getReferredToTyCons other = panic "getReferredToTyCons: not TauType"
+#endif {- Semantique strictness analyser -}
+\end{code}
+
+This @getMentioned*@ code is for doing interfaces. Tricky point: we
+{\em always} expand synonyms in interfaces, so note the handling of
+@UniSyns@.
+\begin{code}
+getMentionedTyConsAndClassesFromUniType :: UniType -> (Bag TyCon, Bag Class)
+
+getMentionedTyConsAndClassesFromUniType (UniTyVar _) = (emptyBag, emptyBag)
+getMentionedTyConsAndClassesFromUniType (UniTyVarTemplate _) = (emptyBag, emptyBag)
+
+getMentionedTyConsAndClassesFromUniType (UniData tycon arg_tys)
+ = foldr do_arg_ty (unitBag tycon, emptyBag) arg_tys
+ where
+ do_arg_ty ty (ts_sofar, cs_sofar)
+ = case (getMentionedTyConsAndClassesFromUniType ty) of { (ts, cs) ->
+ (ts `unionBags` ts_sofar, cs `unionBags` cs_sofar) }
+
+getMentionedTyConsAndClassesFromUniType (UniFun ty1 ty2)
+ = case (getMentionedTyConsAndClassesFromUniType ty1) of { (ts1, cs1) ->
+ case (getMentionedTyConsAndClassesFromUniType ty2) of { (ts2, cs2) ->
+ (ts1 `unionBags` ts2, cs1 `unionBags` cs2) }}
+
+getMentionedTyConsAndClassesFromUniType (UniSyn tycon _ expansion)
+ = getMentionedTyConsAndClassesFromUniType expansion
+ -- if synonyms were not expanded: (unitBag tycon, emptyBag)
+
+getMentionedTyConsAndClassesFromUniType (UniDict clas ty)
+ = case (getMentionedTyConsAndClassesFromUniType ty) of { (ts, cs) ->
+ (ts, cs `snocBag` clas) }
+
+getMentionedTyConsAndClassesFromUniType (UniForall _ ty)
+ = getMentionedTyConsAndClassesFromUniType ty
+\end{code}
+
+This code could go in @TyCon@, but it's better to keep all the
+``getMentioning'' together.
+\begin{code}
+getMentionedTyConsAndClassesFromTyCon :: TyCon -> (Bag TyCon, Bag Class)
+
+getMentionedTyConsAndClassesFromTyCon tycon@(SynonymTyCon _ _ _ _ ty _)
+ = case (getMentionedTyConsAndClassesFromUniType ty) of { (ts, cs) ->
+ (ts `snocBag` tycon, cs) }
+
+getMentionedTyConsAndClassesFromTyCon tycon@(DataTyCon _ _ _ _ constructors _ _)
+ = foldr do_con (unitBag tycon, emptyBag) constructors
+ -- We don't worry whether this TyCon is exported abstractly
+ -- or not, because even if so, the pragmas probably need
+ -- to know this info.
+ where
+ do_con con (ts_sofar, cs_sofar)
+ = case (getMentionedTyConsAndClassesFromId con) of { (ts, cs) ->
+ (ts `unionBags` ts_sofar, cs `unionBags` cs_sofar) }
+
+getMentionedTyConsAndClassesFromTyCon other
+ = panic "tried to get mentioned tycons and classes from funny tycon"
+\end{code}
+
+\begin{code}
+getMentionedTyConsAndClassesFromClass :: Class -> (Bag TyCon, Bag Class)
+
+getMentionedTyConsAndClassesFromClass clas@(MkClass _ _ _ super_classes _ ops _ _ _ _)
+ = foldr do_op
+ (emptyBag, unitBag clas `unionBags` listToBag super_classes)
+ ops
+ where
+ do_op (MkClassOp _ _ ty) (ts_sofar, cs_sofar)
+ = case (getMentionedTyConsAndClassesFromUniType ty) of { (ts, cs) ->
+ (ts `unionBags` ts_sofar, cs `unionBags` cs_sofar) }
+\end{code}
+
+Grab a name for the type. This is used to determine the type
+description for profiling.
+\begin{code}
+getUniTyDescription :: UniType -> String
+getUniTyDescription ty
+ = case (getTauType ty) of
+ UniFun arg res -> '-' : '>' : fun_result res
+ UniData tycon _ -> _UNPK_ (getOccurrenceName tycon)
+ UniSyn tycon _ _ -> _UNPK_ (getOccurrenceName tycon)
+ UniDict cls uni -> "dict" -- Or from unitype ?
+ UniTyVar _ -> "*" -- Distinguish ?
+ UniTyVarTemplate _-> "*"
+ _ -> panic "getUniTyName: other"
+
+ where
+ fun_result (UniFun _ res) = '>' : fun_result res
+ fun_result other = getUniTyDescription other
+
+\end{code}
+
+%************************************************************************
+%* *
+\subsection[UniTyFuns-fvs]{Extracting free type variables}
+%* *
+%************************************************************************
+
+@extractTyVarsFromTy@ gets the free type variables from a @UniType@.
+The list returned has no duplicates.
+
+\begin{code}
+extractTyVarsFromTys :: [UniType] -> [TyVar]
+extractTyVarsFromTys = foldr (unionLists . extractTyVarsFromTy) []
+
+extractTyVarsFromTy :: UniType -> [TyVar]
+extractTyVarsFromTy ty
+ = get ty []
+ where
+ -- weird arg order so we can foldr easily
+ get (UniTyVar tyvar) free
+ | tyvar `is_elem` free = free
+ | otherwise = tyvar:free
+ get (UniTyVarTemplate _) free = free
+ get (UniFun ty1 ty2) free = get ty1 (get ty2 free)
+ get (UniData tycon tys) free = foldr get free tys
+ get (UniSyn tycon tys ty) free = foldr get free tys
+ get (UniDict clas ty) free = get ty free
+ get (UniForall tyvar ty) free = get ty free
+
+ is_elem = isIn "extractTyVarsFromTy"
+\end{code}
+
+\begin{code}
+extractTyVarTemplatesFromTy :: UniType -> [TyVarTemplate]
+extractTyVarTemplatesFromTy ty
+ = get ty []
+ where
+ get (UniTyVarTemplate tyvar) free
+ | tyvar `is_elem` free = free
+ | otherwise = tyvar:free
+ get (UniTyVar tyvar) free = free
+ get (UniFun ty1 ty2) free = get ty1 (get ty2 free)
+ get (UniData tycon tys) free = foldr get free tys
+ get (UniSyn tycon tys ty) free = foldr get free tys
+ get (UniDict clas ty) free = get ty free
+ get (UniForall tyvar ty) free = get ty free
+
+ is_elem = isIn "extractTyVarTemplatesFromTy"
+\end{code}
+
+%************************************************************************
+%* *
+\subsection[UniTyFuns-predicates]{Predicates (and such) on @UniTypes@}
+%* *
+%************************************************************************
+
+We include functions that return @Maybe@ thingies as ``predicates.''
+
+\begin{code}
+isTyVarTy :: UniType -> Bool
+isTyVarTy (UniTyVar _) = True
+isTyVarTy (UniSyn _ _ expand) = isTyVarTy expand
+isTyVarTy other = False
+
+-- isTyVarTemplateTy only used in Renamer for error checking
+isTyVarTemplateTy :: UniType -> Bool
+isTyVarTemplateTy (UniTyVarTemplate tv) = True
+isTyVarTemplateTy (UniSyn _ _ expand) = isTyVarTemplateTy expand
+isTyVarTemplateTy other = False
+
+maybeUnpackFunTy :: TauType -> Maybe (TauType, TauType)
+
+maybeUnpackFunTy ty
+ = --false: ASSERT(isTauTy ty) TauType??
+ maybe ty
+ where
+ maybe (UniSyn _ _ expand) = maybe expand
+ maybe (UniFun arg result) = Just (arg, result)
+ maybe ty@(UniDict _ _) = maybe (unDictifyTy ty)
+ maybe other = Nothing
+
+isFunType :: TauType -> Bool
+isFunType ty
+ = --false: ASSERT(isTauTy ty) TauType???
+ maybeToBool (maybeUnpackFunTy ty)
+\end{code}
+
+\begin{code}
+{- UNUSED:
+isDataConType :: TauType -> Bool
+
+isDataConType ty
+ = ASSERT(isTauTy ty)
+ is_con_ty ty
+ where
+ is_con_ty (UniData _ _) = True
+ is_con_ty (UniSyn _ _ expand) = is_con_ty expand
+ is_con_ty _ = False
+-}
+\end{code}
+
+SIMON'S NOTES:
+
+leakFree (UniData (DataTyCon ...) tys)
+ = nonrecursive type &&
+ all leakFree (apply constructors to tys)
+
+leakFree (PrimTyCon...) = True
+
+leakFree (TyVar _) = False
+leakFree (UniFun _ _) = False
+
+non-recursive: enumeration types, tuples, primitive types...
+
+END NOTES
+
+The list of @TyCons@ is ones we have already seen (and mustn't see
+again).
+
+\begin{code}
+isLeakFreeType :: [TyCon] -> UniType -> Bool
+
+isLeakFreeType seen (UniSyn _ _ expand) = isLeakFreeType seen expand
+
+isLeakFreeType _ (UniTyVar _) = False -- Utterly unknown
+isLeakFreeType _ (UniTyVarTemplate _) = False
+
+isLeakFreeType _ (UniFun _ _) = False -- Could have leaky free variables
+
+isLeakFreeType _ ty@(UniDict _ _) = True -- I'm prepared to bet that
+ -- we'll never get a space leak
+ -- from a dictionary. But I could
+ -- be wrong... SLPJ
+
+isLeakFreeType seen (UniForall _ ty) = isLeakFreeType seen ty
+
+-- For a data type we must look at all the argument types of all
+-- the constructors. It isn't enough to look merely at the
+-- types to which the type constructor is applied. For example
+--
+-- data Foo a = MkFoo [a]
+--
+-- Is (Foo Int) leak free? No!
+
+isLeakFreeType seen (UniData tycon tycon_arg_tys)
+ | tycon `is_elem` seen = False -- Recursive type! Bale out!
+
+ | isDataTyCon tycon = all data_con_args_leak_free (getTyConDataCons tycon)
+
+ | otherwise = isPrimTyCon tycon && -- was an assert; now just paranoia
+ -- We should have a leak-free-ness predicate on PrimTyCons,
+ -- but that's too big a change for today, so we hack it.
+ -- Return true iff it's one of the tycons we know are leak-free
+ -- 94/10: I hope I don't live to regret taking out
+ -- the first check...
+ {-(tycon `elem` [
+ charPrimTyCon, intPrimTyCon, wordPrimTyCon,
+ addrPrimTyCon, floatPrimTyCon, doublePrimTyCon,
+ byteArrayPrimTyCon, arrayPrimTyCon,
+ mallocPtrPrimTyCon, stablePtrPrimTyCon
+ -- List almost surely incomplete!
+ ])
+ &&-} (all (isLeakFreeType (tycon:seen)) tycon_arg_tys)
+ where
+ data_con_args_leak_free data_con
+ = case (getInstantiatedDataConSig data_con tycon_arg_tys) of { (_,arg_tys,_) ->
+ all (isLeakFreeType (tycon:seen)) arg_tys }
+
+ is_elem = isIn "isLeakFreeType"
+\end{code}
+
+\begin{code}
+{- UNUSED:
+hasHigherOrderArg :: UniType -> Bool
+hasHigherOrderArg ty
+ = case (splitType ty) of { (_, _, tau_ty) ->
+ case (splitTyArgs tau_ty) of { (arg_tys, _) ->
+
+ foldr ((||) . isFunType . expandTySyns) False arg_tys
+ }}
+-}
+\end{code}
+
+\begin{code}
+isDictTy :: UniType -> Bool
+
+isDictTy (UniDict _ _) = True
+isDictTy (UniSyn _ _ expand) = isDictTy expand
+isDictTy _ = False
+
+isTauTy :: UniType -> Bool
+
+isTauTy (UniTyVar v) = True
+isTauTy (UniFun a b) = isTauTy a && isTauTy b
+isTauTy (UniData _ tys) = all isTauTy tys
+isTauTy (UniSyn _ _ ty) = isTauTy ty
+isTauTy (UniDict _ ty) = False
+isTauTy (UniTyVarTemplate _) = False
+isTauTy (UniForall _ _) = False
+
+isForAllTy :: UniType -> Bool
+isForAllTy (UniForall _ _) = True
+isForAllTy (UniSyn _ _ ty) = isForAllTy ty
+isForAllTy _ = False
+\end{code}
+
+NOTE: I haven't thought about this much (ToDo: check).
+\begin{code}
+isGroundOrTyVarTy, isGroundTy :: UniType -> Bool
+
+isGroundOrTyVarTy ty = isGroundTy ty || isTyVarTy ty
+
+isGroundTy (UniTyVar tyvar) = False
+isGroundTy (UniTyVarTemplate _) = False
+isGroundTy (UniFun ty1 ty2) = isGroundTy ty1 && isGroundTy ty2
+isGroundTy (UniData tycon tys) = all isGroundTy tys
+isGroundTy (UniSyn _ _ exp) = isGroundTy exp
+isGroundTy (UniDict clas ty) = isGroundTy ty
+isGroundTy (UniForall tyvar ty) = False -- Safe for the moment
+\end{code}
+
+Broadly speaking, instances are exported (a)~if {\em either} the class
+or {\em OUTERMOST} tycon [arbitrary...] is exported; or (b)~{\em both}
+class and tycon are from PreludeCore [non-std, but convenient] {\em
+and} the instance was defined in this module. BUT: if either the
+class or tycon was defined in this module, but not exported, then
+there is no point exporting the instance.
+
+\begin{code}
+instanceIsExported
+ :: Class -> TauType -- class/"tycon" defining instance
+ -> Bool -- True <=> instance decl in this module
+ -> Bool
+
+instanceIsExported clas ty from_here
+ = --false:ASSERT(isTauTy ty) TauType?? failed compiling IArray
+ if is_core_class then
+ if is_fun_tycon || is_core_tycon then
+ {-if-} from_here
+ else
+ is_exported_tycon
+ || (is_imported_tycon && from_here) -- V NAUGHTY BY HASKELL RULES
+
+ else if is_fun_tycon || is_core_tycon then
+ -- non-Core class; depends on its export flag
+ is_exported_class
+ || (is_imported_class && from_here) -- V NAUGHTY BY HASKELL RULES
+
+ else -- non-Core class & non-Core tycon:
+ -- exported if one of them is, but not if either of them
+ -- is locally-defined *and* not exported
+ if (isLocallyDefined clas && not is_exported_class)
+ || (isLocallyDefined tycon && not is_exported_tycon) then
+ False
+ else
+ is_exported_class || is_exported_tycon
+ where
+ tycon = case getUniDataTyCon_maybe ty of
+ Just (xx,_,_) -> xx
+ Nothing -> panic "instanceIsExported:no tycon"
+
+ is_core_class = fromPreludeCore clas
+ is_core_tycon = fromPreludeCore tycon
+
+ is_fun_tycon = isFunType ty
+
+ is_exported_class = case (getExportFlag clas) of
+ NotExported -> False
+ _ -> True
+
+ is_exported_tycon = case (getExportFlag tycon) of
+ NotExported -> False
+ _ -> True
+
+ is_imported_class = not (isLocallyDefined clas)
+ is_imported_tycon = not (isLocallyDefined tycon)
+\end{code}
+
+\begin{code}
+maybePurelyLocalTyCon :: TyCon -> Maybe [Pretty]
+maybePurelyLocalClass :: Class -> Maybe [Pretty]
+maybePurelyLocalType :: UniType -> Maybe [Pretty]
+
+purely_local tc -- overloaded
+ = if (isLocallyDefined tc && not (isExported tc))
+ then Just (ppr PprForUser tc)
+ else Nothing
+
+--overloaded: merge_maybes :: (a -> Maybe b) -> [a] -> Maybe [b]
+
+merge_maybes f xs
+ = case (catMaybes (map f xs)) of
+ [] -> Nothing -- no hit anywhere along the list
+ xs -> Just xs
+
+maybePurelyLocalTyCon tycon
+ = let
+ mentioned_tycons = fst (getMentionedTyConsAndClassesFromTyCon tycon)
+ -- will include tycon itself
+ in
+ merge_maybes purely_local (bagToList mentioned_tycons)
+
+maybePurelyLocalClass clas
+ = let
+ (mentioned_classes, mentioned_tycons)
+ = getMentionedTyConsAndClassesFromClass clas
+ -- will include clas itself
+
+ tc_stuff = merge_maybes purely_local (bagToList mentioned_tycons)
+ cl_stuff = merge_maybes purely_local (bagToList mentioned_classes)
+ in
+ case (tc_stuff, cl_stuff) of
+ (Nothing, Nothing) -> Nothing
+ (Nothing, Just xs) -> Just xs
+ (Just xs, Nothing) -> Just xs
+ (Just xs, Just ys) -> Just (xs ++ ys)
+
+maybePurelyLocalType ty
+ = let
+ (mentioned_classes, mentioned_tycons)
+ = getMentionedTyConsAndClassesFromUniType ty
+ -- will include ty itself
+
+ tc_stuff = merge_maybes purely_local (bagToList mentioned_tycons)
+ cl_stuff = merge_maybes purely_local (bagToList mentioned_classes)
+ in
+ case (tc_stuff, cl_stuff) of
+ (Nothing, Nothing) -> Nothing
+ (Nothing, Just xs) -> Just xs
+ (Just xs, Nothing) -> Just xs
+ (Just xs, Just ys) -> Just (xs ++ ys)
+\end{code}
+
+A gigantic HACK due to Simon (95/05)
+\begin{code}
+returnsRealWorld :: UniType -> Bool
+
+returnsRealWorld (UniTyVar _) = False
+returnsRealWorld (UniTyVarTemplate _) = False
+returnsRealWorld (UniSyn _ _ exp) = returnsRealWorld exp
+returnsRealWorld (UniDict _ ty) = returnsRealWorld ty
+returnsRealWorld (UniForall _ ty) = returnsRealWorld ty
+returnsRealWorld (UniFun ty1 ty2) = returnsRealWorld ty2
+
+returnsRealWorld (UniData tycon []) = tycon == realWorldTyCon
+returnsRealWorld (UniData tycon tys) = any returnsRealWorld tys
+\end{code}
+
+\begin{code}
+#ifdef DPH
+isProcessorTy :: UniType -> Bool
+isProcessorTy (UniData tycon _) = isProcessorTyCon tycon
+isProcessorTy _ = False
+#endif {- Data Parallel Haskell -}
+\end{code}
+
+Podization of a function @f@ is the compile time specialisation of @f@
+to a form that is equivalent to (map.f) . We can podize {\em some}
+functions at runtime because of the laws concerning map and functional
+composition:
+\begin{verbatim}
+ map (f . g) == (map f) . (map g) etc...
+\end{verbatim}
+i.e If we compose two functions, to create a {\em new} function, then
+we can compose the podized versions in just the same way. There is a
+problem however (as always :-(; We cannot convert between an vanilla
+function, and the podized form (and visa versa) at run-time. The
+predicate below describes the set of all objects that cannot be
+podized at runtime (i.e anything that has a function in it).
+\begin{code}
+#ifdef DPH
+runtimeUnpodizableType:: UniType -> Bool
+runtimeUnpodizableType (UniDict _ _) = True
+runtimeUnpodizableType (UniFun _ _) = True
+runtimeUnpodizableType (UniData _ tys) = any runtimeUnpodizableType tys
+runtimeUnpodizableType (UniSyn _ _ ty) = runtimeUnpodizableType ty
+runtimeUnpodizableType other = False
+#endif {- Data Parallel Haskell -}
+\end{code}
+
+%************************************************************************
+%* *
+\subsection[UniTyFuns-subst]{Substitute in a type}
+%* *
+%************************************************************************
+
+The idea here is to substitute for the TyVars in a type. Note, not
+the TyVarTemplates---that's the job of instantiateTy.
+
+There is a single general function, and two interfaces.
+
+\subsubsection{Interface 1: substitutions}
+%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+NOTE: This has been moved to @Subst@ (mostly for speed reasons).
+
+\subsubsection{Interface 2: Envs}
+%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+\begin{code}
+applyTypeEnvToTy :: TypeEnv -> SigmaType -> SigmaType
+applyTypeEnvToTy tenv ty
+ = mapOverTyVars v_fn ty
+ where
+ v_fn v = case (lookupTyVarEnv tenv v) of
+ Just ty -> ty
+ Nothing -> UniTyVar v
+
+applyTypeEnvToTauTy :: TypeEnv -> TauType -> TauType
+applyTypeEnvToTauTy e ty
+ = ASSERT(isTauTy ty)
+ applyTypeEnvToTy e ty
+
+applyTypeEnvToThetaTy tenv theta
+ = [(clas,
+ ASSERT(isTauTy ty)
+ applyTypeEnvToTauTy tenv ty) | (clas, ty) <- theta]
+\end{code}
+
+\subsubsection{@mapOverTyVars@: does the real work}
+%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+@mapOverTyVars@ is a local function which actually does the work. It does
+no cloning or other checks for shadowing, so be careful when calling
+this on types with Foralls in them.
+
+\begin{code}
+mapOverTyVars :: (TyVar -> UniType) -> UniType -> UniType
+mapOverTyVars v_fn (UniTyVar v) = v_fn v
+mapOverTyVars v_fn (UniFun t1 t2) = UniFun (mapOverTyVars v_fn t1) (mapOverTyVars v_fn t2)
+mapOverTyVars v_fn (UniData con args) = UniData con (map (mapOverTyVars v_fn) args)
+mapOverTyVars v_fn (UniSyn con args ty) = UniSyn con (map (mapOverTyVars v_fn) args) (mapOverTyVars v_fn ty)
+mapOverTyVars v_fn (UniDict clas ty) = UniDict clas (mapOverTyVars v_fn ty)
+mapOverTyVars v_fn (UniForall v ty) = UniForall v (mapOverTyVars v_fn ty)
+mapOverTyVars v_fn (UniTyVarTemplate v) = UniTyVarTemplate v
+\end{code}
+
+%************************************************************************
+%* *
+\subsection[UniTyFuns-ppr]{Pretty-printing @UniTypes@}
+%* *
+%************************************************************************
+
+@pprUniType@ is the std @UniType@ printer; the overloaded @ppr@
+function is defined to use this. @pprParendUniType@ is the same,
+except it puts parens around the type, except for the atomic cases.
+@pprParendUniType@ works just by setting the initial context
+precedence very high. ToDo: what if not a @TauType@?
+\begin{code}
+pprUniType, pprParendUniType :: PprStyle -> UniType -> Pretty
+
+pprUniType sty ty = ppr_ty_init sty tOP_PREC ty
+pprParendUniType sty ty = ppr_ty_init sty tYCON_PREC ty
+
+pprMaybeTy :: PprStyle -> Maybe UniType -> Pretty
+pprMaybeTy PprDebug Nothing = ppStr "*"
+pprMaybeTy PprDebug (Just ty) = pprParendUniType PprDebug ty
+
+getTypeString :: UniType -> [FAST_STRING]
+ -- shallowly magical; converts a type into something
+ -- vaguely close to what can be used in C identifier.
+ -- Don't forget to include the module name!!!
+
+getTypeString ty
+ = let
+ ppr_t = ppr_ty PprForUser (\t -> ppStr "*") tOP_PREC (expandTySyns ty)
+
+ string = _PK_ (tidy (ppShow 1000 ppr_t))
+ in
+ if is_prelude_ty
+ then [string]
+ else [mod, string]
+ where
+ (is_prelude_ty, mod)
+ = case getUniDataTyCon_maybe ty of
+ Nothing -> true_bottom
+ Just (tycon,_,_) ->
+ if fromPreludeCore tycon
+ then true_bottom
+ else (False, fst (getOrigName tycon))
+
+ true_bottom = (True, panic "getTypeString")
+
+ --------------------------------------------------
+ -- tidy: very ad-hoc
+ tidy [] = [] -- done
+
+ tidy (' ' : more)
+ = case more of
+ ' ' : _ -> tidy more
+ '-' : '>' : xs -> '-' : '>' : tidy (no_leading_sps xs)
+ other -> ' ' : tidy more
+
+ tidy (',' : more) = ',' : tidy (no_leading_sps more)
+
+ tidy (x : xs) = x : tidy xs -- catch all
+
+ no_leading_sps [] = []
+ no_leading_sps (' ':xs) = no_leading_sps xs
+ no_leading_sps other = other
+
+typeMaybeString :: Maybe UniType -> [FAST_STRING]
+typeMaybeString Nothing = [SLIT("!")]
+typeMaybeString (Just t) = getTypeString t
+
+specMaybeTysSuffix :: [Maybe UniType] -> FAST_STRING
+specMaybeTysSuffix ty_maybes
+ = let
+ ty_strs = concat (map typeMaybeString ty_maybes)
+ dotted_tys = [ _CONS_ '.' str | str <- ty_strs ]
+ in
+ _CONCAT_ dotted_tys
+\end{code}
+
+Nota Bene: we must assign print-names to the forall'd type variables
+alphabetically, with the first forall'd variable having the alphabetically
+first name. Reason: so anyone reading the type signature printed without
+explicit forall's will be able to reconstruct them in the right order.
+
+\begin{code}
+ppr_ty_init :: PprStyle -> Int -> UniType -> Pretty
+
+ppr_ty_init sty init_prec ty
+ = let (tyvars, _, _) = splitType ty
+ lookup_fn = mk_lookup_tyvar_fn sty tyvars
+ in
+ ppr_ty sty lookup_fn init_prec ty
+
+mk_lookup_tyvar_fn :: PprStyle -> [TyVarTemplate] -> (TyVarTemplate -> Pretty)
+
+mk_lookup_tyvar_fn sty tyvars
+ = tv_lookup_fn
+ where
+ tv_lookup_fn :: TyVarTemplate -> Pretty
+ tv_lookup_fn tyvar
+ = let
+ pp_tyvar_styish = ppr sty tyvar
+
+ assocs = [ pp | (tv, pp) <- tvs_n_pprs, tv == tyvar ]
+
+ pp_tyvar_canonical
+ = case assocs of
+ [] -> pprPanic "pprUniType: bad tyvar lookup:" (ppr sty tyvar)
+ -- sometimes, in printing monomorphic types,
+ -- (usually in debugging), we won't have the tyvar
+ -- in our list; so we just ppr it anyway...
+ x:_ -> x
+ in
+ case sty of
+ PprInterface _ -> pp_tyvar_canonical
+ PprForC _ -> ppChar '*'
+ PprUnfolding _ -> case assocs of
+ x:_ -> ppBeside x (ppPStr SLIT("$z1"))
+ _ -> ppPStr SLIT("z$z1")
+ PprForUser -> case assocs of
+ x:_ -> x
+ _ -> pp_tyvar_styish
+ debuggish -> pp_tyvar_styish
+
+ tvs_n_pprs = tyvars `zip` tyvar_pretties
+
+ tyvar_pretties = letter_pprs {- a..y -} ++ number_pprs {- z0 ... zN -}
+
+ letter_pprs = map (\ c -> ppChar c ) ['a' .. 'y']
+ number_pprs = map (\ n -> ppBeside (ppChar 'z') (ppInt n))
+ ([0 .. ] :: [Int])
+\end{code}
+
+\begin{code}
+ppr_ty :: PprStyle -> (TyVarTemplate -> Pretty) -> Int -> UniType -> Pretty
+
+ppr_ty sty lookup_fn ctxt_prec (UniTyVarTemplate tyvar) = lookup_fn tyvar
+
+ppr_ty sty lookup_fn ctxt_prec (UniTyVar tyvar) = ppr sty tyvar
+
+ppr_ty sty lookup_fn ctxt_prec ty
+ = case sty of
+ PprForUser -> context_onward
+ PprInterface _ -> context_onward
+ _ ->
+ (if null tyvars then id else ppBeside (ppr_forall sty tyvars))
+ context_onward
+ where
+ (tyvars, context, tau_ty) = splitType ty
+
+ context_onward =
+ if (null pretty_context_pieces) then
+ ppr_tau_ty sty lookup_fn ctxt_prec tau_ty
+ else
+ ppCat (pretty_context_pieces
+ ++ [connector sty, ppr_tau_ty sty lookup_fn ctxt_prec tau_ty]) -- ToDo: dubious
+
+ pretty_context_pieces = ppr_context sty context
+
+ ppr_forall :: PprStyle -> [TyVarTemplate] -> Pretty
+
+ ppr_forall _ [] = ppNil
+ ppr_forall sty tyvars
+ = ppBesides [ppPStr SLIT("_forall_ "), ppIntersperse pp'SP{-'-} pp_tyvars,
+ ppPStr SLIT(" =>")]
+ where
+ pp_tyvars = map lookup_fn tyvars
+
+ ppr_context :: PprStyle -> [(Class, UniType)] -> [Pretty]
+
+ ppr_context _ [] = []
+ ppr_context sty context@(c:cs)
+ = case sty of
+ PprForUser -> userish
+ PprInterface _ -> userish
+ _ -> hackerish
+ where
+ userish
+ = [if (context `lengthExceeds` (1::Int)) then
+ ppBesides [ ppLparen,
+ ppIntersperse pp'SP{-'-} (map (ppr_kappa_tau PprForUser) context),
+ ppRparen]
+ else
+ ppr_kappa_tau PprForUser (head context)
+ ]
+ hackerish
+ = (ppr_kappa_tau sty c) : (map ( pin_on_arrow . (ppr_kappa_tau sty) ) cs)
+
+ connector PprForUser = ppPStr SLIT("=>")
+ connector (PprInterface _) = ppPStr SLIT("=>")
+ connector other_sty = ppPStr SLIT("->")
+
+ ppr_kappa_tau :: PprStyle -> (Class, UniType) -> Pretty
+
+ ppr_kappa_tau sty (clas, ty)
+ = let
+ pp_ty = ppr_tau_ty sty lookup_fn ctxt_prec ty
+ user_ish = ppCat [ppr PprForUser clas, pp_ty]
+ hack_ish = ppBesides [ppStr "{{", ppr sty clas, ppSP, pp_ty, ppStr "}}"]
+ in
+ case sty of
+ PprForUser -> user_ish
+ PprInterface _ -> user_ish
+ _ -> hack_ish
+
+ pin_on_arrow p = ppBeside (ppPStr SLIT("-> ")) p
+\end{code}
+
+@ppr_tau_ty@ takes an @Int@ that is the precedence of the context.
+The precedence levels are:
+\begin{description}
+\item[0:] What we start with.
+\item[1:] Function application (@UniFuns@).
+\item[2:] Type constructors.
+\end{description}
+
+A non-exported help function that really does the printing:
+\begin{code}
+tOP_PREC = (0 :: Int)
+fUN_PREC = (1 :: Int)
+tYCON_PREC = (2 :: Int)
+
+ppr_tau_ty :: PprStyle -> (TyVarTemplate -> Pretty) -> Int -> UniType -> Pretty
+
+-- a quite special case, for printing instance decls in interfaces:
+ppr_tau_ty sty@(PprInterface _) lookup_fn ctxt_prec (UniDict clas ty)
+ = ppCat [ppr PprForUser clas, ppr_ty sty lookup_fn tYCON_PREC ty]
+
+ppr_tau_ty sty lookup_fn ctxt_prec (UniSyn _ _ expansion)
+ | case sty of { PprForUser -> False; _ -> True }
+ = ppr_tau_ty sty lookup_fn ctxt_prec expansion -- always expand types in an interface
+
+-- .....................
+
+ppr_tau_ty sty lookup_fn ctxt_prec (UniTyVarTemplate tyvar) = lookup_fn tyvar
+
+ppr_tau_ty sty lookup_fn ctxt_prec (UniTyVar tyvar) = ppr sty tyvar
+
+ppr_tau_ty sty lookup_fn ctxt_prec (UniFun ty1 ty2)
+ -- we fiddle the precedences passed to left/right branches,
+ -- so that right associativity comes out nicely...
+
+ = let p1 = ppr_tau_ty sty lookup_fn fUN_PREC ty1
+ p2 = ppr_tau_ty sty lookup_fn tOP_PREC ty2
+ in
+ if ctxt_prec < fUN_PREC then -- no parens needed
+ ppCat [p1, ppBeside (ppPStr SLIT("-> ")) p2]
+ else
+ ppCat [ppBeside ppLparen p1, ppBesides [ppPStr SLIT("-> "), p2, ppRparen]]
+
+-- Special printing for list and tuple types.
+-- we can re-set the precedence to tOP_PREC
+
+ppr_tau_ty sty lookup_fn ctxt_prec (UniData tycon tys)
+ = if tycon == listTyCon then
+ ppBesides [ppLbrack, ppr_tau_ty sty lookup_fn tOP_PREC (head tys), ppRbrack]
+
+ else if (tycon == (TupleTyCon (length tys))) then
+ ppBesides [ppLparen, ppIntersperse pp'SP{-'-} (map (ppr_tau_ty sty lookup_fn tOP_PREC) tys), ppRparen]
+#ifdef DPH
+ else if (tycon == podTyCon) then
+ pprPodshort sty lookup_fn tOP_PREC (head tys)
+
+ else if (tycon == (ProcessorTyCon ((length tys)-1))) then
+ ppBesides [ppStr "(|",
+ ppIntersperse pp'SP{-'-}
+ (map (ppr_tau_ty sty lookup_fn tOP_PREC) (init tys)),
+ ppSemi ,
+ ppr_tau_ty sty lookup_fn tOP_PREC (last tys),
+ ppStr "|)"]
+#endif {- Data Parallel Haskell -}
+ else
+ ppr_tycon_and_tys sty lookup_fn ctxt_prec tycon tys
+
+ppr_tau_ty sty lookup_fn ctxt_prec (UniSyn tycon tys expansion)
+ = ppBeside
+ (ppr_tycon_and_tys sty lookup_fn ctxt_prec tycon tys)
+ (ifPprShowAll sty (ppCat [ppStr " {- expansion:", ppr_ty sty lookup_fn ctxt_prec expansion, ppStr "-}"]))
+
+-- For SPECIALIZE instance error messages ...
+ppr_tau_ty sty@PprForUser lookup_fn ctxt_prec (UniDict clas ty)
+ = if ctxt_prec < tYCON_PREC then
+ ppCat [ppr sty clas, ppr_ty sty lookup_fn tYCON_PREC ty]
+ else
+ ppBesides [ppStr "(", ppr sty clas, ppSP, ppr_ty sty lookup_fn tYCON_PREC ty, ppStr ")"]
+
+ppr_tau_ty sty lookup_fn ctxt_prec (UniDict clas ty)
+ = ppBesides [ppStr "{{", ppr sty clas, ppSP, ppr_ty sty lookup_fn tYCON_PREC ty, ppStr "}}"]
+
+ppr_tau_ty sty lookup_fn ctxt_prec other_ty -- must a be UniForall (ToDo: something?)
+ = ppBesides [ppLparen, ppr_ty sty lookup_fn ctxt_prec other_ty, ppRparen]
+
+-- code shared for UniDatas and UniSyns
+ppr_tycon_and_tys :: PprStyle -> (TyVarTemplate -> Pretty) -> Int -> TyCon -> [UniType] -> Pretty
+
+ppr_tycon_and_tys sty lookup_fn ctxt_prec tycon tys
+ = let pp_tycon = ppr (case sty of PprInterface _ -> PprForUser; _ -> sty) tycon
+ in
+ if null tys then
+ pp_tycon
+ else if ctxt_prec < tYCON_PREC then -- no parens needed
+ ppCat [pp_tycon, ppIntersperse ppSP (map (ppr_tau_ty sty lookup_fn tYCON_PREC) tys) ]
+ else
+ ppBesides [ ppLparen, pp_tycon, ppSP,
+ ppIntersperse ppSP (map (ppr_tau_ty sty lookup_fn tYCON_PREC) tys), ppRparen ]
+\end{code}
+
+\begin{code}
+#ifdef DPH
+pprPodshort :: PprStyle -> (TyVarTemplate-> Pretty) -> Int -> UniType -> Pretty
+pprPodshort sty lookup_fn ctxt_prec (UniData tycon tys)
+ | (tycon == (ProcessorTyCon ((length tys)-1)))
+ = ppBesides [ppStr "<<",
+ ppIntersperse pp'SP{-'-}
+ (map (ppr_tau_ty sty lookup_fn tOP_PREC) (init tys)),
+ ppSemi ,
+ ppr_tau_ty sty lookup_fn tOP_PREC (last tys),
+ ppStr ">>"]
+pprPodshort sty lookup_fn ctxt_prec ty
+ = ppBesides [ppStr "<<",
+ ppr_tau_ty sty lookup_fn tOP_PREC ty,
+ ppStr ">>"]
+#endif {- Data Parallel Haskell -}
+\end{code}
+
+\begin{code}
+showTyCon :: PprStyle -> TyCon -> String
+showTyCon sty tycon
+ = ppShow 80 (pprTyCon sty tycon [])
+
+pprTyCon :: PprStyle -> TyCon -> [[Maybe UniType]] -> Pretty
+-- with "PprInterface", we print out for interfaces
+
+pprTyCon sty@(PprInterface sw_chkr) (SynonymTyCon k n a vs exp unabstract) specs
+ = ASSERT (null specs)
+ let
+ lookup_fn = mk_lookup_tyvar_fn sty vs
+ pp_tyvars = map lookup_fn vs
+ pp_abstract = if unabstract || (sw_chkr OmitInterfacePragmas)
+ then ppNil
+ else ppStr "{-# GHC_PRAGMA _ABSTRACT_ #-}"
+ in
+ ppCat [ppPStr SLIT("type"), ppr sty n, ppIntersperse ppSP pp_tyvars,
+ ppEquals, ppr_ty sty lookup_fn tOP_PREC exp, pp_abstract]
+
+pprTyCon sty@(PprInterface sw_chkr) this_tycon@(DataTyCon k n a vs cons derivings unabstract) specs
+ = ppHang (ppCat [ppPStr SLIT("data"),
+ -- pprContext sty context,
+ ppr sty n,
+ ppIntersperse ppSP (map lookup_fn vs)])
+ 4
+ (ppCat [pp_unabstract_condecls,
+ pp_pragma])
+ -- NB: we do not print deriving info in interfaces
+ where
+ lookup_fn = mk_lookup_tyvar_fn sty vs
+
+ yes_we_print_condecls
+ = unabstract
+ && not (null cons) -- we know what they are
+ && (case (getExportFlag n) of
+ ExportAbs -> False
+ other -> True)
+
+ yes_we_print_pragma_condecls
+ = not yes_we_print_condecls
+ && not (sw_chkr OmitInterfacePragmas)
+ && not (null cons)
+ && not (maybeToBool (maybePurelyLocalTyCon this_tycon))
+ {- && not (any (dataConMentionsNonPreludeTyCon this_tycon) cons) -}
+
+ yes_we_print_pragma_specs
+ = not (null specs)
+
+ pp_unabstract_condecls
+ = if yes_we_print_condecls
+ then ppCat [ppSP, ppEquals, pp_condecls]
+ else ppNil
+
+ pp_pragma_condecls
+ = if yes_we_print_pragma_condecls
+ then pp_condecls
+ else ppNil
+
+ pp_pragma_specs
+ = if yes_we_print_pragma_specs
+ then pp_specs
+ else ppNil
+
+ pp_pragma
+ = if (yes_we_print_pragma_condecls || yes_we_print_pragma_specs)
+ then ppCat [ppStr "\t{-# GHC_PRAGMA", pp_pragma_condecls, pp_pragma_specs, ppStr "#-}"]
+ else ppNil
+
+ pp_condecls
+ = let
+ (c:cs) = cons
+ in
+ ppCat ((ppr_con c) : (map ppr_next_con cs))
+ where
+ ppr_con con
+ = let
+ (_, _, con_arg_tys, _) = getDataConSig con
+ in
+ ppCat [pprNonOp PprForUser con, -- the data con's name...
+ ppIntersperse ppSP (map (ppr_ty sty lookup_fn tYCON_PREC) con_arg_tys)]
+
+ ppr_next_con con = ppCat [ppChar '|', ppr_con con]
+
+ pp_specs
+ = ppBesides [ppStr "_SPECIALISE_ ", pp_the_list [
+ ppCat [ppLbrack, ppInterleave ppComma (map pp_maybe ty_maybes), ppRbrack]
+ | ty_maybes <- specs ]]
+
+ pp_the_list [p] = p
+ pp_the_list (p:ps) = ppAbove (ppBeside p ppComma) (pp_the_list ps)
+
+ pp_maybe Nothing = pp_NONE
+ pp_maybe (Just ty) = pprParendUniType sty ty
+
+ pp_NONE = ppStr "_N_"
+
+pprTyCon (PprInterface _) (TupleTyCon a) specs
+ = ASSERT (null specs)
+ ppCat [ ppStr "{- Tuple", ppInt a, ppStr "-}" ]
+
+pprTyCon (PprInterface _) (PrimTyCon k n a kind_fn) specs
+ = ASSERT (null specs)
+ ppCat [ ppStr "{- data", ppr PprForUser n, ppStr " *built-in* -}" ]
+
+#ifdef DPH
+pprTyCon (PprInterface _) (ProcessorTyCon a) specs
+ = ppCat [ ppStr "{- Processor", ppInt a, ppStr "-}" ]
+#endif {- Data Parallel Haskell -}
+
+-- regular printing (ToDo: probably update)
+
+pprTyCon sty (SynonymTyCon k n a vs exp unabstract) [{-no specs-}]
+ = ppBeside (ppr sty n)
+ (ifPprShowAll sty
+ (ppCat [ ppStr " {-", ppInt a, interpp'SP sty vs,
+ pprParendUniType sty exp,
+ if unabstract then ppNil else ppStr "_ABSTRACT_", ppStr "-}"]))
+
+pprTyCon sty tycon@(DataTyCon k n a vs cons derivings unabstract) [{-no specs-}]
+ = case sty of
+ PprDebug -> pp_tycon_and_uniq
+ PprShowAll -> pp_tycon_and_uniq
+ _ -> pp_tycon
+ where
+ pp_tycon_and_uniq = ppBesides [pp_tycon, ppStr "{-", pprUnique k, ppStr "-}"]
+ pp_tycon
+ = let
+ pp_name = ppr sty n
+ in
+ if codeStyle sty || tycon /= listTyCon
+ then pp_name
+ else ppBesides [ppLbrack, interpp'SP sty vs, ppRbrack]
+
+{-ppBeside-} -- pp_tycon
+{- SOMETIMES:
+ (ifPprShowAll sty
+ (ppCat [ ppStr " {-", ppInt a, interppSP sty vs,
+ interpp'SP PprForUser cons,
+ ppStr "deriving (", interpp'SP PprForUser derivings,
+ ppStr ")-}" ]))
+-}
+
+pprTyCon sty (TupleTyCon a) [{-no specs-}]
+ = ppBeside (ppPStr SLIT("Tuple")) (ppInt a)
+
+pprTyCon sty (PrimTyCon k n a kind_fn) [{-no specs-}]
+ = ppr sty n
+
+pprTyCon sty (SpecTyCon tc ty_maybes) []
+ = ppBeside (pprTyCon sty tc [])
+ (if (codeStyle sty)
+ then identToC tys_stuff
+ else ppPStr tys_stuff)
+ where
+ tys_stuff = specMaybeTysSuffix ty_maybes
+
+#ifdef DPH
+pprTyCon sty (ProcessorTyCon a) [] = ppBeside (ppStr "Processor") (ppInt a)
+
+pprTyCon sty (PodizedPodTyCon dim tc) []
+ = ppBesides [ ppr sty tc, ppStr "Podized", ppr sty dim]
+#endif {- Data Parallel Haskell -}
+\end{code}
+
+\begin{code}
+pprIfaceClass :: (GlobalSwitch -> Bool) -> (Id -> Id) -> IdEnv UnfoldingDetails -> Class -> Pretty
+
+pprIfaceClass sw_chker better_id_fn inline_env
+ (MkClass k n tyvar super_classes sdsels ops sels defms insts links)
+ = let
+ sdsel_infos = map (getIdInfo . better_id_fn) sdsels
+ in
+ ppAboves [ ppCat [ppPStr SLIT("class"), ppr_theta tyvar super_classes,
+ ppr sty n, lookup_fn tyvar,
+ if null sdsel_infos
+ || omit_iface_pragmas
+ || (any boringIdInfo sdsel_infos)
+ -- ToDo: really should be "all bor..."
+ -- but then parsing is more tedious,
+ -- and this is really as good in practice.
+ then ppNil
+ else pp_sdsel_pragmas (sdsels `zip` sdsel_infos),
+ if (null ops)
+ then ppNil
+ else ppPStr SLIT("where")],
+ ppNest 8 (ppAboves
+ [ ppr_op op (better_id_fn sel) (better_id_fn defm)
+ | (op,sel,defm) <- zip3 ops sels defms]) ]
+ where
+ sty = PprInterface sw_chker
+ omit_iface_pragmas = sw_chker OmitInterfacePragmas
+
+ lookup_fn = mk_lookup_tyvar_fn sty [tyvar]
+
+ ppr_theta :: TyVarTemplate -> [Class] -> Pretty
+ ppr_theta tv [] = ppNil
+ ppr_theta tv super_classes
+ = ppBesides [ppLparen,
+ ppIntersperse pp'SP{-'-} (map ppr_assert super_classes),
+ ppStr ") =>"]
+ where
+ ppr_assert (MkClass _ n _ _ _ _ _ _ _ _) = ppCat [ppr sty n, lookup_fn tv]
+
+ pp_sdsel_pragmas sdsels_and_infos
+ = ppCat [ppStr "{-# GHC_PRAGMA {-superdicts-}",
+ ppIntersperse pp'SP{-'-}
+ [ppIdInfo sty sdsel False{-NO specs-} better_id_fn inline_env info
+ | (sdsel, info) <- sdsels_and_infos ],
+ ppStr "#-}"]
+
+ ppr_op op opsel_id defm_id
+ = let
+ stuff = ppBeside (ppChar '\t') (ppr_class_op sty [tyvar] op)
+ in
+ if omit_iface_pragmas
+ then stuff
+ else ppAbove stuff
+ (ppCat [ppStr "\t {-# GHC_PRAGMA", ppAbove pp_opsel pp_defm, ppStr "#-}"])
+ where
+ pp_opsel = ppCat [ppPStr SLIT("{-meth-}"), ppIdInfo sty opsel_id False{-no specs-} better_id_fn inline_env (getIdInfo opsel_id)]
+ pp_defm = ppCat [ppPStr SLIT("\t\t{-defm-}"), ppIdInfo sty defm_id False{-no specs-} better_id_fn inline_env (getIdInfo defm_id)]
+\end{code}
+
+\begin{code}
+pprClassOp :: PprStyle -> ClassOp -> Pretty
+
+pprClassOp sty op = ppr_class_op sty [] op
+
+ppr_class_op sty tyvars (MkClassOp op_name i ty)
+ = case sty of
+ PprForC _ -> pp_C
+ PprForAsm _ _ _ -> pp_C
+ PprInterface _ -> ppCat [pp_user, ppPStr SLIT("::"), ppr_ty sty lookup_fn tOP_PREC ty]
+ PprShowAll -> ppCat [pp_user, ppPStr SLIT("::"), ppr_ty PprDebug lookup_fn tOP_PREC ty]
+ _ -> pp_user
+ where
+ (local_tyvars,_,_) = splitType ty
+ lookup_fn = mk_lookup_tyvar_fn sty (tyvars ++ local_tyvars)
+
+ pp_C = ppPStr op_name
+ pp_user = if isAvarop op_name
+ then ppBesides [ppLparen, pp_C, ppRparen]
+ else pp_C
+\end{code}
+
+%************************************************************************
+%* *
+\subsection[UniTyFuns-matching]{@matchTy@}
+%* *
+%************************************************************************
+
+Matching is a {\em unidirectional} process, matching a type against a
+template (which is just a type with type variables in it). The matcher
+assumes that there are no repeated type variables in the template, so that
+it simply returns a mapping of type variables to types.
+
+\begin{code}
+matchTy :: UniType -- Template
+ -> UniType -- Proposed instance of template
+ -> Maybe [(TyVarTemplate,UniType)] -- Matching substitution
+
+matchTy (UniTyVarTemplate v) ty = Just [(v,ty)]
+matchTy (UniTyVar _) ty = panic "matchTy: unexpected TyVar (need TyVarTemplates)"
+
+matchTy (UniFun fun1 arg1) (UniFun fun2 arg2) = matchTys [fun1, arg1] [fun2, arg2]
+
+matchTy ty1@(UniData con1 args1) ty2@(UniData con2 args2) | con1 == con2
+ = matchTys args1 args2 -- Same constructors, just match the arguments
+
+-- with type synonyms, we have to be careful
+-- for the exact same reasons as in the unifier.
+-- Please see the considerable commentary there
+-- before changing anything here! (WDP 95/05)
+
+-- If just one or the other is a "visible" synonym (they all are at
+-- the moment...), just expand it.
+
+matchTy (UniSyn con1 args1 ty1) ty2
+ | isVisibleSynTyCon con1
+ = matchTy ty1 ty2
+matchTy ty1 (UniSyn con2 args2 ty2)
+ | isVisibleSynTyCon con2
+ = matchTy ty1 ty2
+
+matchTy (UniSyn con1 args1 ty1) (UniSyn con2 args2 ty2)
+ -- if we get here, both synonyms must be "abstract"
+ -- (NB: not done yet)
+ = if (con1 == con2) then
+ -- Good news! Same synonym constructors, so we can shortcut
+ -- by unifying their arguments and ignoring their expansions.
+ matchTys args1 args2
+ else
+ -- Never mind. Just expand them and try again
+ matchTy ty1 ty2
+
+-- Catch-all fails
+matchTy templ ty = Nothing
+\end{code}
+
+@matchTys@ matches corresponding elements of a list of templates and
+types.
+
+\begin{code}
+matchTys :: [UniType] -> [UniType] -> Maybe [(TyVarTemplate, UniType)]
+
+matchTys [] [] = Just []
+matchTys (templ:templs) (ty:tys)
+ = case (matchTy templ ty) of
+ Nothing -> Nothing
+ Just subst -> case (matchTys templs tys) of
+ Nothing -> Nothing
+ Just subst2 -> Just (subst ++ subst2)
+#ifdef DEBUG
+matchTys [] tys
+ = pprPanic "matchTys: out of templates!; tys:" (ppr PprDebug tys)
+matchTys tmpls []
+ = pprPanic "matchTys: out of types!; templates:" (ppr PprDebug tmpls)
+#endif
+\end{code}
+
+%************************************************************************
+%* *
+\subsection[UniTyFuns-misc]{Misc @UniType@ functions}
+%* *
+%************************************************************************
+
+\begin{code}
+cmpUniTypeMaybeList :: [Maybe UniType] -> [Maybe UniType] -> TAG_
+cmpUniTypeMaybeList [] [] = EQ_
+cmpUniTypeMaybeList (x:xs) [] = GT_
+cmpUniTypeMaybeList [] (y:ys) = LT_
+cmpUniTypeMaybeList (x:xs) (y:ys)
+ = case cmp_maybe_ty x y of { EQ_ -> cmpUniTypeMaybeList xs ys; other -> other }
+
+cmp_maybe_ty Nothing Nothing = EQ_
+cmp_maybe_ty (Just x) Nothing = GT_
+cmp_maybe_ty Nothing (Just y) = LT_
+cmp_maybe_ty (Just x) (Just y) = cmpUniType True{-properly-} x y
+\end{code}
+
+Identity function if the type is a @TauType@; panics otherwise.
+\begin{code}
+#ifdef DEBUG
+verifyTauTy :: String -> TauType -> TauType
+
+verifyTauTy caller ty@(UniDict _ _) = pprPanic (caller++":verifyTauTy:dict") (ppr PprShowAll ty)
+verifyTauTy caller ty@(UniForall _ _) = pprPanic (caller++":verifyTauTy:forall") (ppr PprShowAll ty)
+verifyTauTy caller (UniSyn tycon tys expansion) = UniSyn tycon tys (verifyTauTy caller expansion)
+verifyTauTy caller tau_ty = tau_ty
+
+#endif {- DEBUG -}
+\end{code}
+
+\begin{code}
+showTypeCategory :: UniType -> Char
+ {-
+ {C,I,F,D} char, int, float, double
+ T tuple
+ S other single-constructor type
+ {c,i,f,d} unboxed ditto
+ t *unpacked* tuple
+ s *unpacked" single-cons...
+
+ v void#
+ a primitive array
+
+ E enumeration type
+ + dictionary, unless it's a ...
+ L List
+ > function
+ M other (multi-constructor) data-con type
+ . other type
+ - reserved for others to mark as "uninteresting"
+ -}
+showTypeCategory ty
+ = if isDictTy ty
+ then '+'
+ else
+ case getUniDataTyCon_maybe ty of
+ Nothing -> if isFunType ty
+ then '>'
+ else '.'
+
+ Just (tycon,_,_) ->
+ if maybeToBool (maybeCharLikeTyCon tycon) then 'C'
+ else if maybeToBool (maybeIntLikeTyCon tycon) then 'I'
+ else if maybeToBool (maybeFloatLikeTyCon tycon) then 'F'
+ else if maybeToBool (maybeDoubleLikeTyCon tycon) then 'D'
+ else if tycon == integerTyCon then 'J'
+ else if tycon == charPrimTyCon then 'c'
+ else if (tycon == intPrimTyCon || tycon == wordPrimTyCon
+ || tycon == addrPrimTyCon) then 'i'
+ else if tycon == floatPrimTyCon then 'f'
+ else if tycon == doublePrimTyCon then 'd'
+ else if isPrimTyCon tycon {- array, we hope -} then 'A'
+ else if isEnumerationTyCon tycon then 'E'
+ else if isTupleTyCon tycon then 'T'
+ else if maybeToBool (maybeSingleConstructorTyCon tycon) then 'S'
+ else if tycon == listTyCon then 'L'
+ else 'M' -- oh, well...
+\end{code}