-The details of one specialisation, held in an @Id@'s
-@SpecEnv@ are as follows:
-\begin{code}
-data SpecInfo
- = SpecInfo [Maybe UniType] -- Instance types; no free type variables in here
- Int -- No. of dictionaries to eat
- Id -- Specialised version
-\end{code}
-
-For example, if \tr{f} has this @SpecInfo@:
-\begin{verbatim}
- SpecInfo [Just t1, Nothing, Just t3] 2 f'
-\end{verbatim}
-then
-\begin{verbatim}
- f t1 t2 t3 d1 d2 ===> f t2
-\end{verbatim}
-The \tr{Nothings} identify type arguments in which the specialised
-version is polymorphic.
-
-\begin{code}
-data SpecEnv = SpecEnv [SpecInfo]
-
-mkSpecEnv = SpecEnv
-nullSpecEnv = SpecEnv []
-addOneToSpecEnv (SpecEnv xs) x = SpecEnv (x : xs)
-
-lookupConstMethodId :: SpecEnv -> UniType -> Maybe Id
- -- slight variant on "lookupSpecEnv" below
-
-lookupConstMethodId (SpecEnv spec_infos) spec_ty
- = firstJust (map try spec_infos)
- where
- try (SpecInfo (Just ty:nothings) _ const_meth_id)
- = ASSERT(all nothing_is_nothing nothings)
- case (cmpUniType True{-properly-} ty spec_ty) of
- EQ_ -> Just const_meth_id
- _ -> Nothing
-
- nothing_is_nothing Nothing = True -- debugging only
- nothing_is_nothing _ = panic "nothing_is_nothing!"
-
-lookupSpecId :: Id -- *un*specialised Id
- -> [Maybe UniType] -- types to which it is to be specialised
- -> Id -- specialised Id
-
-lookupSpecId unspec_id ty_maybes
- = case (getInfo (getIdInfo unspec_id)) of { SpecEnv spec_infos ->
-
- case (firstJust (map try spec_infos)) of
- Just id -> id
- Nothing -> error ("ERROR: There is some confusion about a value specialised to a type;\ndetails follow (and more info in the User's Guide):\n\t"++(ppShow 80 (ppr PprDebug unspec_id)))
- }
- where
- try (SpecInfo template_maybes _ id)
- | and (zipWith same template_maybes ty_maybes)
- && length template_maybes == length ty_maybes = Just id
- | otherwise = Nothing
-
- same Nothing Nothing = True
- same (Just ty1) (Just ty2) = ty1 == ty2
- same _ _ = False
-
-lookupSpecEnv :: SpecEnv
- -> [UniType]
- -> Maybe (Id,
- [UniType],
- Int)
-
-lookupSpecEnv (SpecEnv []) _ = Nothing -- rather common case
-
-lookupSpecEnv spec_env [] = Nothing -- another common case
-
- -- This can happen even if there is a non-empty spec_env, because
- -- of eta reduction. For example, we might have a defn
- --
- -- f = /\a -> \d -> g a d
- -- which gets transformed to
- -- f = g
- --
- -- Now g isn't applied to any arguments
-
-lookupSpecEnv se@(SpecEnv spec_infos) spec_tys
- = select_match spec_infos
- where
- select_match [] -- no matching spec_infos
- = Nothing
- select_match (SpecInfo ty_maybes toss spec_id : rest)
- = case (match ty_maybes spec_tys) of
- Nothing -> select_match rest
- Just tys_left -> select_next [(spec_id,tys_left,toss)] (length tys_left) toss rest
-
- -- Ambiguity can only arise as a result of specialisations with
- -- an explicit spec_id. The best match is deemed to be the match
- -- with least polymorphism i.e. has the least number of tys left.
- -- This is a non-critical approximation. The only type arguments
- -- where there may be some discretion is for non-overloaded boxed
- -- types. Unboxed types must be matched and we insist that we
- -- always specialise on overloaded types (and discard all the dicts).
-
- select_next best _ toss []
- = case best of
- [match] -> Just match -- Unique best match
- ambig -> pprPanic "Ambiguous Specialisation:\n"
- (ppAboves [ppStr "(check specialisations with explicit spec ids)",
- ppCat (ppStr "between spec ids:" :
- map (ppr PprDebug) [id | (id, _, _) <- ambig]),
- pp_stuff])
-
- select_next best tnum dnum (SpecInfo ty_maybes toss spec_id : rest)
- = ASSERT(dnum == toss)
- case (match ty_maybes spec_tys) of
- Nothing -> select_next best tnum dnum rest
- Just tys_left ->
- let tys_len = length tys_left in
- case _tagCmp tnum tys_len of
- _LT -> select_next [(spec_id,tys_left,toss)] tys_len dnum rest -- better match
- _EQ -> select_next ((spec_id,tys_left,toss):best) tnum dnum rest -- equivalent match
- _GT -> select_next best tnum dnum rest -- worse match
-
-
- match [{-out of templates-}] [] = Just []
-
- match (Nothing:ty_maybes) (spec_ty:spec_tys)
- = case (isUnboxedDataType spec_ty) of
- True -> Nothing -- Can only match boxed type against
- -- type argument which has not been
- -- specialised on
- False -> case match ty_maybes spec_tys of
- Nothing -> Nothing
- Just tys -> Just (spec_ty:tys)
-
- match (Just ty:ty_maybes) (spec_ty:spec_tys)
- = case (cmpUniType True{-properly-} ty spec_ty) of
- EQ_ -> match ty_maybes spec_tys
- other -> Nothing
-
- match [] _ = pprPanic "lookupSpecEnv1\n" pp_stuff
- -- This is a Real Problem
-
- match _ [] = pprPanic "lookupSpecEnv2\n" pp_stuff
- -- Partial eta abstraction might make this happen;
- -- meanwhile let's leave in the check
-
- pp_stuff = ppAbove (pp_specs PprDebug True (\x->x) nullIdEnv se) (ppr PprDebug spec_tys)
-\end{code}
-