2 % (c) The GRASP/AQUA Project, Glasgow University, 1993-1996
4 \section[Specialise]{Stamping out overloading, and (optionally) polymorphism}
7 #include "HsVersions.h"
11 SYN_IE(ConstraintVector),
13 isUnboxedSpecialisation,
18 argTysMatchSpecTys_error,
25 import CmdLineOpts ( opt_SpecialiseOverloaded, opt_SpecialiseUnboxed,
28 import Bag ( isEmptyBag, bagToList )
29 import Class ( GenClass{-instance NamedThing-}, GenClassOp {- instance NamedThing -} )
30 import FiniteMap ( emptyFM, addListToFM_C, plusFM_C, keysFM,
33 import Id ( idType, isDictFunId, isConstMethodId_maybe,
34 isDefaultMethodId_maybe,
35 GenId {-instance NamedThing -}
37 import Maybes ( maybeToBool, catMaybes, firstJust )
38 import Name ( OccName, pprNonSym, pprOccName, modAndOcc )
39 import PprStyle ( PprStyle(..) )
40 import PprType ( pprGenType, pprParendGenType, pprMaybeTy,
41 TyCon{-ditto-}, GenType{-ditto-}, GenTyVar
43 import Pretty -- plenty of it
44 import TyCon ( tyConTyVars, TyCon{-instance NamedThing-} )
45 import Type ( splitSigmaTy, mkTyVarTy, mkForAllTys,
46 getTyVar_maybe, isUnboxedType
48 import TyVar ( GenTyVar{-instance Eq-} )
49 import Unique ( Unique{-instance Eq-} )
50 import Util ( equivClasses, zipWithEqual, cmpPString,
51 assertPanic, panic{-ToDo:rm-}
54 cmpType = panic "SpecUtils.cmpType (ToDo: get rid of)"
55 mkSameSpecCon = panic "SpecUtils.mkSameSpecCon (ToDo)"
56 getInstIdModule = panic "SpecUtils.getInstIdModule (ToDo)"
57 specialiseTy :: Type -> [Maybe Type] -> Int -> Type
58 specialiseTy = panic "SpecUtils.specialiseTy (ToDo)"
61 @specialiseCallTys@ works out which type args don't need to be specialised on,
62 based on flags, the overloading constraint vector, and the types.
65 specialiseCallTys :: ConstraintVector -- Tells which type args are overloaded
66 -> [Type] -- Type args
67 -> [Maybe Type] -- Nothings replace non-specialised type args
69 specialiseCallTys cvec tys
70 | opt_SpecialiseAll = map Just tys
71 | otherwise = zipWithEqual "specialiseCallTys" spec_ty_other cvec tys
73 spec_ty_other c ty | (opt_SpecialiseUnboxed && isUnboxedType ty) ||
74 (opt_SpecialiseOverloaded && c)
80 @getIdOverloading@ grabs the type of an Id, and returns a
81 list of its polymorphic variables, and the initial segment of
82 its ThetaType, in which the classes constrain only type variables.
83 For example, if the Id's type is
85 forall a,b,c. Eq a -> Ord [a] -> tau
91 This seems curious at first. For a start, the type above looks odd,
92 because we usually only have dictionary args whose types are of
93 the form (C a) where a is a type variable. But this doesn't hold for
94 the functions arising from instance decls, which sometimes get
95 arguements with types of form (C (T a)) for some type constructor T.
97 Should we specialise wrt this compound-type dictionary? This is
98 a heuristic judgement, as indeed is the fact that we specialise wrt
99 only dictionaries. We choose *not* to specialise wrt compound dictionaries
100 because at the moment the only place they show up is in instance decls,
101 where they are simply plugged into a returned dictionary. So nothing is
102 gained by specialising wrt them.
105 getIdOverloading :: Id
106 -> ([TyVar], [(Class,TyVar)])
108 = (tyvars, tyvar_part_of theta)
110 (tyvars, theta, _) = splitSigmaTy (idType id)
112 tyvar_part_of [] = []
113 tyvar_part_of ((c,ty):theta) = case (getTyVar_maybe ty) of
115 Just tv -> (c, tv) : tyvar_part_of theta
119 type ConstraintVector = [Bool] -- True for constrained tyvar, false otherwise
123 isUnboxedSpecialisation :: [Maybe Type] -> Bool
124 isUnboxedSpecialisation tys
127 is_unboxed (Just ty) = isUnboxedType ty
128 is_unboxed Nothing = False
131 @specialiseConstrTys@ works out which type args don't need to be
132 specialised on. We only speciailise on unboxed types.
135 specialiseConstrTys :: [Type]
138 specialiseConstrTys tys
139 = map maybe_unboxed_ty tys
141 maybe_unboxed_ty ty = case isUnboxedType ty of
147 mkSpecialisedCon :: Id -> [Type] -> Id
148 mkSpecialisedCon con tys
150 then mkSameSpecCon spec_tys con
153 spec_tys = specialiseConstrTys tys
154 spec_reqd = maybeToBool (firstJust spec_tys)
157 @argTysMatchSpecTys@ checks if a list of argument types is consistent
158 with a list of specialising types. An error message is returned if not.
160 argTysMatchSpecTys_error :: [Maybe Type]
163 argTysMatchSpecTys_error spec_tys arg_tys
164 = if match spec_tys arg_tys
166 else Just (ppSep [ppPStr SLIT("Spec and Arg Types Inconsistent:"),
167 ppPStr SLIT("spectys="), ppSep [pprMaybeTy PprDebug ty | ty <- spec_tys],
168 ppPStr SLIT("argtys="), ppSep [pprParendGenType PprDebug ty | ty <- arg_tys]])
170 match (Nothing:spec_tys) (arg:arg_tys)
171 = not (isUnboxedType arg) &&
172 match spec_tys arg_tys
173 match (Just spec:spec_tys) (arg:arg_tys)
174 = case (cmpType True{-properly-} spec arg) of
175 EQ_ -> match spec_tys arg_tys
181 @pprSpecErrs@ prints error and warning information
182 about imported specialisations which do not exist.
185 pprSpecErrs :: FAST_STRING -- module name
186 -> (Bag (Id,[Maybe Type])) -- errors
187 -> (Bag (Id,[Maybe Type])) -- warnings
188 -> (Bag (TyCon,[Maybe Type])) -- errors
191 pprSpecErrs this_mod spec_errs spec_warn spec_tyerrs
192 | not any_errs && not any_warn
197 ppPStr SLIT("SPECIALISATION MESSAGES:"),
198 ppAboves (map pp_module_specs use_modules)
201 any_errs = not (isEmptyBag spec_errs && isEmptyBag spec_tyerrs)
202 any_warn = not (isEmptyBag spec_warn)
204 mk_module_fm get_mod_data errs_bag
205 = addListToFM_C (++) emptyFM errs_list
207 errs_list = map get_mod_data (bagToList errs_bag)
209 tyspecs_fm = mk_module_fm get_ty_data spec_tyerrs
211 iderrs_fm = mk_module_fm (get_id_data True) spec_errs
212 idwarn_fm = mk_module_fm (get_id_data False) spec_warn
213 idspecs_fm = plusFM_C (++) idwarn_fm iderrs_fm
215 get_id_data is_err (id, tys)
216 = (mod_name, [(id_name, id, tys, is_err)])
218 (mod_name, id_name) = get_id_name id
223 {- Don't understand this -- and looks TURGID. SLPJ 4 Nov 96
224 | maybeToBool (isDefaultMethodId_maybe id)
227 | isDictFunId id || maybeToBool (isConstMethodId_maybe id)
228 = let get_mod = getInstIdModule id
236 get_ty_data (ty, tys)
237 = (mod_name, [(ty_name, ty, tys)])
239 (mod_name, ty_name) = modAndOcc ty
241 module_names = concat [keysFM idspecs_fm, keysFM tyspecs_fm]
242 mods = map head (equivClasses _CMP_STRING_ module_names)
244 (unks, known) = if null mods
246 else case _CMP_STRING_ (head mods) _NIL_ of
247 EQ_ -> ([_NIL_], tail mods)
250 use_modules = unks ++ known
252 pp_module_specs :: FAST_STRING -> Pretty
255 = ASSERT (null mod_tyspecs)
256 ppAboves (map (pp_idspec ty_sty (ppPStr SLIT("UNKNOWN:"))) mod_idspecs)
260 ppAboves (map (pp_tyspec ty_sty (pp_module mod)) mod_tyspecs),
261 ppAboves (map (pp_idspec ty_sty (pp_module mod)) mod_idspecs)
268 mod_tyspecs = lookupWithDefaultFM tyspecs_fm [] mod
269 mod_idspecs = lookupWithDefaultFM idspecs_fm [] mod
270 have_specs = not (null mod_tyspecs && null mod_idspecs)
271 ty_sty = PprInterface
274 = ppBesides [ppPStr mod, ppChar ':']
276 pp_tyspec :: PprStyle -> Pretty -> (OccName, TyCon, [Maybe Type]) -> Pretty
278 pp_tyspec sty pp_mod (_, tycon, tys)
280 ppStr "{-# SPECIALIZE data",
281 pprNonSym PprForUser tycon, ppCat (map (pprParendGenType sty) spec_tys),
282 ppStr "-} {- Essential -}"
285 tvs = tyConTyVars tycon
286 (spec_args, tv_maybes) = unzip (map choose_ty (tvs `zip` tys))
287 spec_tys = map (mkForAllTys (catMaybes tv_maybes)) spec_args
289 choose_ty (tv, Nothing) = (mkTyVarTy tv, Just tv)
290 choose_ty (tv, Just ty) = (ty, Nothing)
292 pp_idspec :: PprStyle -> Pretty -> (OccName, Id, [Maybe Type], Bool) -> Pretty
294 pp_idspec sty pp_mod (_, id, tys, is_err)
297 ppStr "{-# SPECIALIZE instance",
298 pprGenType sty spec_ty,
299 ppStr "#-}", pp_essential ]
303 Just (cls, clsty, clsop) = const_method_maybe
306 ppStr "{-# SPECIALIZE",
307 pprNonSym sty clsop, ppStr "::",
308 pprGenType sty spec_ty,
309 ppStr "#-} {- IN instance",
310 pprOccName sty (getOccName cls), pprParendGenType sty clsty,
311 ppStr "-}", pp_essential ]
313 | is_default_method_id
315 Just (cls, clsop, _) = default_method_maybe
319 pprOccName sty (getOccName cls),
320 ppPStr SLIT("EXPLICIT METHOD REQUIRED"),
321 pprNonSym sty clsop, ppStr "::",
322 pprGenType sty spec_ty,
323 ppStr "-}", pp_essential ]
327 ppStr "{-# SPECIALIZE",
328 pprNonSym PprForUser id, ppPStr SLIT("::"),
329 pprGenType sty spec_ty,
330 ppStr "#-}", pp_essential ]
332 spec_ty = specialiseTy (idType id) tys 100 -- HACK to drop all dicts!!!
333 pp_essential = if is_err then ppStr "{- Essential -}" else ppNil
335 const_method_maybe = isConstMethodId_maybe id
336 is_const_method_id = maybeToBool const_method_maybe
338 default_method_maybe = isDefaultMethodId_maybe id
339 is_default_method_id = maybeToBool default_method_maybe