2 % (c) The GRASP/AQUA Project, Glasgow University, 1993-1996
4 \section[Specialise]{Stamping out overloading, and (optionally) polymorphism}
11 isUnboxedSpecialisation,
16 argTysMatchSpecTys_error,
21 #include "HsVersions.h"
23 import CmdLineOpts ( opt_SpecialiseOverloaded, opt_SpecialiseUnboxed,
24 opt_SpecialiseAll, opt_PprUserLength
26 import Bag ( isEmptyBag, bagToList, Bag )
27 import Class ( Class )
28 import FiniteMap ( emptyFM, addListToFM_C, plusFM_C, keysFM,
31 import Id ( idType, isDictFunId,
32 isDefaultMethodId_maybe,
35 import Maybes ( maybeToBool, catMaybes, firstJust )
36 import Name ( OccName, pprOccName, modAndOcc, NamedThing(..) )
38 import PprType ( pprGenType, pprParendGenType, pprMaybeTy,
41 import TyCon ( tyConTyVars )
42 import Type ( mkSigmaTy, instantiateTauTy, instantiateThetaTy,
43 splitSigmaTy, mkTyVarTy, mkForAllTys,
44 getTyVar_maybe, isUnboxedType, Type
46 import TyVar ( TyVar, mkTyVarEnv )
47 import Util ( equivClasses, zipWithEqual,
48 assertPanic, panic{-ToDo:rm-}
52 cmpType = panic "SpecUtils.cmpType (ToDo: get rid of)"
53 getInstIdModule = panic "SpecUtils.getInstIdModule (ToDo)"
54 mkSameSpecCon = panic "SpecUtils.mkSameSpecCon (ToDo)"
59 specialiseTy :: Type -- The type of the Id of which the SpecId
60 -- is a specialised version
61 -> [Maybe Type] -- The types at which it is specialised
62 -> Int -- Number of leading dictionary args to ignore
65 specialiseTy main_ty maybe_tys dicts_to_ignore
66 = mkSigmaTy remaining_tyvars
67 (instantiateThetaTy inst_env remaining_theta)
68 (instantiateTauTy inst_env tau)
70 (tyvars, theta, tau) = splitSigmaTy main_ty -- A prefix of, but usually all,
71 -- the theta is discarded!
72 remaining_theta = drop dicts_to_ignore theta
73 tyvars_and_maybe_tys = tyvars `zip` maybe_tys
74 remaining_tyvars = [tyvar | (tyvar, Nothing) <- tyvars_and_maybe_tys]
75 inst_env = mkTyVarEnv [(tyvar,ty) | (tyvar, Just ty) <- tyvars_and_maybe_tys]
79 @specialiseCallTys@ works out which type args don't need to be specialised on,
80 based on flags, the overloading constraint vector, and the types.
83 specialiseCallTys :: ConstraintVector -- Tells which type args are overloaded
84 -> [Type] -- Type args
85 -> [Maybe Type] -- Nothings replace non-specialised type args
87 specialiseCallTys cvec tys
88 | opt_SpecialiseAll = map Just tys
89 | otherwise = zipWithEqual "specialiseCallTys" spec_ty_other cvec tys
91 spec_ty_other c ty | (opt_SpecialiseUnboxed && isUnboxedType ty) ||
92 (opt_SpecialiseOverloaded && c)
98 @getIdOverloading@ grabs the type of an Id, and returns a
99 list of its polymorphic variables, and the initial segment of
100 its ThetaType, in which the classes constrain only type variables.
101 For example, if the Id's type is
103 forall a,b,c. Eq a -> Ord [a] -> tau
109 This seems curious at first. For a start, the type above looks odd,
110 because we usually only have dictionary args whose types are of
111 the form (C a) where a is a type variable. But this doesn't hold for
112 the functions arising from instance decls, which sometimes get
113 arguements with types of form (C (T a)) for some type constructor T.
115 Should we specialise wrt this compound-type dictionary? This is
116 a heuristic judgement, as indeed is the fact that we specialise wrt
117 only dictionaries. We choose *not* to specialise wrt compound dictionaries
118 because at the moment the only place they show up is in instance decls,
119 where they are simply plugged into a returned dictionary. So nothing is
120 gained by specialising wrt them.
123 getIdOverloading :: Id
124 -> ([TyVar], [(Class,TyVar)])
125 getIdOverloading = panic "getIdOverloading"
127 -- Looks suspicious to me; and I'm not sure what corresponds to
128 -- (Class,TyVar) pairs in the multi-param type class world.
131 = (tyvars, tyvar_part_of theta)
133 (tyvars, theta, _) = splitSigmaTy (idType id)
135 tyvar_part_of [] = []
136 tyvar_part_of ((c,ty):theta) = case (getTyVar_maybe ty) of
138 Just tv -> (c, tv) : tyvar_part_of theta
143 type ConstraintVector = [Bool] -- True for constrained tyvar, false otherwise
147 isUnboxedSpecialisation :: [Maybe Type] -> Bool
148 isUnboxedSpecialisation tys
151 is_unboxed (Just ty) = isUnboxedType ty
152 is_unboxed Nothing = False
155 @specialiseConstrTys@ works out which type args don't need to be
156 specialised on. We only speciailise on unboxed types.
159 specialiseConstrTys :: [Type]
162 specialiseConstrTys tys
163 = map maybe_unboxed_ty tys
165 maybe_unboxed_ty ty = case isUnboxedType ty of
171 mkSpecialisedCon :: Id -> [Type] -> Id
172 mkSpecialisedCon con tys
174 then mkSameSpecCon spec_tys con
177 spec_tys = specialiseConstrTys tys
178 spec_reqd = maybeToBool (firstJust spec_tys)
181 @argTysMatchSpecTys@ checks if a list of argument types is consistent
182 with a list of specialising types. An error message is returned if not.
184 argTysMatchSpecTys_error :: [Maybe Type]
187 argTysMatchSpecTys_error spec_tys arg_tys
188 = if match spec_tys arg_tys
190 else Just (sep [ptext SLIT("Spec and Arg Types Inconsistent:"),
191 ptext SLIT("spectys="), sep [pprMaybeTy ty | ty <- spec_tys],
192 ptext SLIT("argtys="), sep [pprParendGenType ty | ty <- arg_tys]])
194 match (Nothing:spec_tys) (arg:arg_tys)
195 = not (isUnboxedType arg) &&
196 match spec_tys arg_tys
197 match (Just spec:spec_tys) (arg:arg_tys)
198 = case (cmpType True{-properly-} spec arg) of
199 EQ -> match spec_tys arg_tys
205 @pprSpecErrs@ prints error and warning information
206 about imported specialisations which do not exist.
209 pprSpecErrs :: FAST_STRING -- module name
210 -> (Bag (Id,[Maybe Type])) -- errors
211 -> (Bag (Id,[Maybe Type])) -- warnings
212 -> (Bag (TyCon,[Maybe Type])) -- errors
215 pprSpecErrs this_mod spec_errs spec_warn spec_tyerrs
216 | not any_errs && not any_warn
221 ptext SLIT("SPECIALISATION MESSAGES:"),
222 vcat (map pp_module_specs use_modules)
225 any_errs = not (isEmptyBag spec_errs && isEmptyBag spec_tyerrs)
226 any_warn = not (isEmptyBag spec_warn)
228 mk_module_fm get_mod_data errs_bag
229 = addListToFM_C (++) emptyFM errs_list
231 errs_list = map get_mod_data (bagToList errs_bag)
233 tyspecs_fm = mk_module_fm get_ty_data spec_tyerrs
235 iderrs_fm = mk_module_fm (get_id_data True) spec_errs
236 idwarn_fm = mk_module_fm (get_id_data False) spec_warn
237 idspecs_fm = plusFM_C (++) idwarn_fm iderrs_fm
239 get_id_data is_err (id, tys)
240 = (mod_name, [(id_name, id, tys, is_err)])
242 (mod_name, id_name) = get_id_name id
247 {- Don't understand this -- and looks TURGID. SLPJ 4 Nov 96
248 | maybeToBool (isDefaultMethodId_maybe id)
251 | isDictFunId id || maybeToBool (isConstMethodId_maybe id)
252 = let get_mod = getInstIdModule id
260 get_ty_data (ty, tys)
261 = (mod_name, [(ty_name, ty, tys)])
263 (mod_name, ty_name) = modAndOcc ty
265 module_names = concat [keysFM idspecs_fm, keysFM tyspecs_fm]
266 mods = map head (equivClasses compare module_names)
268 (unks, known) = if null mods
270 else case head mods `compare` _NIL_ of
271 EQ -> ([_NIL_], tail mods)
274 use_modules = unks ++ known
276 pp_module_specs :: FAST_STRING -> SDoc
279 = ASSERT (null mod_tyspecs)
280 vcat (map (pp_idspec (ptext SLIT("UNKNOWN:"))) mod_idspecs)
284 vcat (map (pp_tyspec (pp_module mod)) mod_tyspecs),
285 vcat (map (pp_idspec (pp_module mod)) mod_idspecs)
292 mod_tyspecs = lookupWithDefaultFM tyspecs_fm [] mod
293 mod_idspecs = lookupWithDefaultFM idspecs_fm [] mod
294 have_specs = not (null mod_tyspecs && null mod_idspecs)
297 = hcat [ptext mod, char ':']
299 pp_tyspec :: SDoc -> (OccName, TyCon, [Maybe Type]) -> SDoc
301 pp_tyspec pp_mod (_, tycon, tys)
303 text "{-# SPECIALIZE data",
304 ppr tycon, hsep (map pprParendGenType spec_tys),
305 text "-} {- Essential -}"
308 tvs = tyConTyVars tycon
309 (spec_args, tv_maybes) = unzip (map choose_ty (tvs `zip` tys))
310 spec_tys = map (mkForAllTys (catMaybes tv_maybes)) spec_args
312 choose_ty (tv, Nothing) = (mkTyVarTy tv, Just tv)
313 choose_ty (tv, Just ty) = (ty, Nothing)
315 pp_idspec :: SDoc -> (OccName, Id, [Maybe Type], Bool) -> SDoc
316 pp_idspec = error "pp_idspec"
320 pp_idspec pp_mod (_, id, tys, is_err)
323 text "{-# SPECIALIZE instance",
325 text "#-}", pp_essential ]
329 Just (cls, clsty, clsop) = const_method_maybe
332 text "{-# SPECIALIZE",
333 ppr clsop, text "::",
335 text "#-} {- IN instance",
336 pprOccName (getOccName cls), pprParendGenType clsty,
337 text "-}", pp_essential ]
339 | is_default_method_id
341 Just (cls, clsop, _) = default_method_maybe
345 pprOccName (getOccName cls),
346 ptext SLIT("EXPLICIT METHOD REQUIRED"),
347 ppr clsop, text "::",
349 text "-}", pp_essential ]
353 text "{-# SPECIALIZE",
354 ppr id, ptext SLIT("::"),
356 text "#-}", pp_essential ]
358 spec_ty = specialiseTy (idType id) tys 100 -- HACK to drop all dicts!!!
359 pp_essential = if is_err then text "{- Essential -}" else empty
361 const_method_maybe = isConstMethodId_maybe id
362 is_const_method_id = maybeToBool const_method_maybe
364 default_method_maybe = isDefaultMethodId_maybe id
365 is_default_method_id = maybeToBool default_method_maybe