2 module Generics ( mkTyConGenInfo, mkGenericRhs,
3 validGenericInstanceType, validGenericMethodType
7 import RnHsSyn ( RenamedHsExpr )
8 import HsSyn ( HsExpr(..), InPat(..), mkSimpleMatch )
10 import Type ( Type, isUnLiftedType, applyTys, tyVarsOfType, tyVarsOfTypes,
11 mkTyVarTys, mkForAllTys, mkTyConApp, splitFunTys,
13 splitSigmaTy, getTyVar, splitTyConApp_maybe, funTyCon
16 import DataCon ( DataCon, dataConOrigArgTys, dataConWrapId, dataConId )
18 import TyCon ( TyCon, tyConTyVars, tyConDataConsIfAvailable,
19 tyConGenInfo, isNewTyCon, newTyConRep, isBoxedTupleTyCon
21 import Name ( Name, mkSysLocalName )
22 import CoreSyn ( mkLams, Expr(..), CoreExpr, AltCon(..), Note(..),
23 mkConApp, Alt, mkTyApps, mkVarApps )
24 import BasicTypes ( EP(..), Boxity(..) )
26 import VarSet ( isEmptyVarSet )
27 import Id ( Id, mkTemplateLocal, idType, idName,
28 mkTemplateLocalsNum, mkId
30 import TysWiredIn ( genericTyCons,
31 genUnitTyCon, genUnitDataCon, plusTyCon, inrDataCon,
32 inlDataCon, crossTyCon, crossDataCon
34 import IdInfo ( vanillaIdInfo, setUnfoldingInfo )
35 import CoreUnfold ( mkTopUnfolding )
37 import Unique ( mkBuiltinUnique )
38 import SrcLoc ( builtinSrcLoc )
39 import Maybes ( expectJust )
42 #include "HsVersions.h"
45 Roadmap of what's where in the Generics work.
46 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
52 Checks that HsNumTy has a "1" in it.
54 TcInstDcls.mkGenericInstance:
55 Checks for invalid type patterns, such as f {| Int |}
58 Checks for a method type that is too complicated;
59 e.g. has for-alls or lists in it
60 We could lift this restriction
62 TcClassDecl.mkDefMethRhs
63 Checks that the instance type is simple, in an instance decl
64 where we let the compiler fill in a generic method.
65 e.g. instance C (T Int)
66 is not valid if C has generic methods.
68 TcClassDecl.checkGenericClassIsUnary
69 Checks that we don't have generic methods in a multi-parameter class
71 TcClassDecl.checkDefaultBinds
72 Checks that all the equations for a method in a class decl
73 are generic, or all are non-generic
77 Checking that the type constructors which are present in Generic
78 patterns (not Unit, this is done differently) is done in mk_inst_info
79 (TcInstDecls) in a call to tcHsType (TcMonoBinds). This means that
80 HsOpTy is tied to Generic definitions which is not a very good design
81 feature, indeed a bug. However, the check is easy to move from
82 tcHsType back to mk_inst_info and everything will be fine. Also see
87 Making generic information to put into a tycon. Constructs the
88 representation type, which, I think, are not used later. Perhaps it is
89 worth removing them from the GI datatype. Although it does get used in
90 the construction of conversion functions (internally).
94 Just stores generic information, accessible by tyConGenInfo or tyConGenIds.
98 Defines generic and other type and data constructors.
100 This is sadly incomplete, but will be added to.
103 Bugs & shortcomings of existing implementation:
104 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
106 2. Another pretty big bug I dscovered at the last minute when I was
107 testing the code is that at the moment the type variable of the class
108 is scoped over the entire declaration, including the patterns. For
109 instance, if I have the following code,
113 er {| Plus a b |} (Inl x) (Inl y) = er x y
114 er {| Plus a b |} (Inr x) (Inr y) = er x y
115 er {| Plus a b |} _ _ = False
117 and I print out the types of the generic patterns, I get the
118 following. Note that all the variable names for "a" are the same,
119 while for "b" they are all different.
122 [std.Generics.Plus{-33u,i-} a{-r6Z-} b{-r7g-},
123 std.Generics.Plus{-33u,i-} a{-r6Z-} b{-r7m-},
124 std.Generics.Plus{-33u,i-} a{-r6Z-} b{-r7p-}]
126 This is a bug as if I change the code to
128 er {| Plus c b |} (Inl x) (Inl y) = er x y
130 all the names come out to be different.
132 Thus, all the types (Plus a b) come out to be different, so I cannot
133 compare them and test whether they are all the same and thus cannot
134 return an error if the type variables are different.
136 Temporary fix/hack. I am not checking for this, I just assume they are
137 the same, see line "check_ty = True" in TcInstDecls. When we resolve
138 the issue with variables, though - I assume that we will make them to
139 be the same in all the type patterns, jus uncomment the check and
140 everything should work smoothly.
142 Hence, I have also left the rather silly construction of:
143 * extracting all the type variables from all the types
144 * putting them *all* into the environment
145 * typechecking all the types
146 * selecting one of them and using it as the instance_ty.
148 (the alternative is to make sure that all the types are the same,
149 taking one, extracting its variables, putting them into the environment,
150 type checking it, using it as the instance_ty)
152 6. What happens if we do not supply all of the generic patterns? At
153 the moment, the compiler crashes with an error message "Non-exhaustive
154 patterns in a generic declaration"
157 What has not been addressed:
158 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
160 Contexts. In the generated instance declarations for the 3 primitive
161 type constructors, we need contexts. It is unclear what those should
162 be. At the moment, we always say eg. (Eq a, Eq b) => Eq (Plus a b)
164 Type application. We have type application in expressions
165 (essentially) on the lhs of an equation. Do we want to allow it on the
168 Scoping of type variables in a generic definition. At the moment, (see
169 TcInstDecls) we extract the type variables inside the type patterns
170 and add them to the environment. See my bug #2 above. This seems pretty
175 %************************************************************************
177 \subsection{Getting the representation type out}
179 %************************************************************************
182 validGenericInstanceType :: Type -> Bool
183 -- Checks for validity of the type pattern in a generic
184 -- declaration. It's ok to have
186 -- but it's not OK to have
189 validGenericInstanceType inst_ty
190 = case splitTyConApp_maybe inst_ty of
191 Just (tycon, tys) -> all isTyVarTy tys && tycon `elem` genericTyCons
194 validGenericMethodType :: Type -> Bool
195 -- At the moment we only allow method types built from
199 -- * an arbitrary type not involving the class type variables
200 validGenericMethodType ty = valid ty
203 | isTyVarTy ty = True
204 | not (null arg_tys) = all valid arg_tys && valid res_ty
205 | no_tyvars_in_ty = True
206 | otherwise = isBoxedTupleTyCon tc && all valid tys
208 (arg_tys, res_ty) = splitFunTys ty
209 no_tyvars_in_ty = isEmptyVarSet (tyVarsOfType ty)
210 Just (tc,tys) = splitTyConApp_maybe ty
214 %************************************************************************
216 \subsection{Generating representation types}
218 %************************************************************************
221 mkTyConGenInfo :: TyCon -> Name -> Name -> Maybe (EP Id)
222 -- mkTyConGenInfo is called twice
223 -- once from TysWiredIn for Tuples
224 -- once the typechecker TcTyDecls
225 -- to generate generic types and conversion functions for all datatypes.
227 -- Must only be called with an algebraic type.
229 -- The two names are the names constructed by the renamer
230 -- for the fromT and toT conversion functions.
232 mkTyConGenInfo tycon from_name to_name
233 | null datacons -- Abstractly imported types don't have
234 = Nothing -- to/from operations, (and should not need them)
236 -- If any of the constructor has an unboxed type as argument
237 -- then we can't build the embedding-projection pair, because
238 -- it relies on instantiating *polymorphic* sum and product types
239 -- at the argument types of the constructors
240 | any (any isUnLiftedType . dataConOrigArgTys) datacons
244 = Just (EP { fromEP = mkId from_name from_ty from_id_info,
245 toEP = mkId to_name to_ty to_id_info })
247 tyvars = tyConTyVars tycon -- [a, b, c]
248 datacons = tyConDataConsIfAvailable tycon -- [C, D]
249 tycon_ty = mkTyConApp tycon tyvar_tys -- T a b c
250 tyvar_tys = mkTyVarTys tyvars
252 from_id_info = vanillaIdInfo `setUnfoldingInfo` mkTopUnfolding from_fn
253 to_id_info = vanillaIdInfo `setUnfoldingInfo` mkTopUnfolding to_fn
255 from_ty = mkForAllTys tyvars (mkFunTy tycon_ty rep_ty)
256 to_ty = mkForAllTys tyvars (mkFunTy rep_ty tycon_ty)
258 (from_fn, to_fn, rep_ty)
260 = ( mkLams tyvars $ Lam x $ Note (Coerce newrep_ty tycon_ty) (Var x),
261 Var (dataConWrapId the_datacon),
265 = ( mkLams tyvars $ Lam x $ Case (Var x) x from_alts,
266 mkLams tyvars $ Lam rep_var to_inner,
270 x = mkTemplateLocal 1 tycon_ty
272 ----------------------
274 [the_datacon] = datacons
275 newrep_ty = applyTys (expectJust "mkGenTyConInfo" (newTyConRep tycon)) tyvar_tys
277 ----------------------
279 -- Recurse over the sum first
280 -- The "2" is the first free unique
281 (from_alts, to_inner, rep_var) = mk_sum_stuff 2 tyvars datacons
285 ----------------------------------------------------
287 ----------------------------------------------------
288 mk_sum_stuff :: Int -- Base for generating unique names
289 -> [TyVar] -- Type variables over which the tycon is abstracted
290 -> [DataCon] -- The data constructors
291 -> ([Alt Id], CoreExpr, Id)
293 -- For example, given
294 -- data T = C | D Int Int Int
296 -- mk_sum_stuff v [C,D] = ([C -> Inl Unit, D a b c -> Inr (a :*: (b :*: c))],
297 -- case cd of { Inl u -> C;
298 -- Inr abc -> case abc of { a :*: bc ->
299 -- case bc of { b :*: c ->
303 mk_sum_stuff i tyvars [datacon]
304 = ([from_alt], to_body_fn app_exp, rep_var)
306 types = dataConOrigArgTys datacon
307 datacon_vars = mkTemplateLocalsNum i types
308 new_i = i + length types
309 app_exp = mkVarApps (Var (dataConId datacon)) (tyvars ++ datacon_vars)
310 from_alt = (DataAlt datacon, datacon_vars, from_alt_rhs)
312 (_, from_alt_rhs, to_body_fn, rep_var) = mk_prod_stuff new_i datacon_vars
314 mk_sum_stuff i tyvars datacons
315 = (wrap inlDataCon l_from_alts ++ wrap inrDataCon r_from_alts,
316 Case (Var rep_var) rep_var [(DataAlt inlDataCon, [l_rep_var], l_to_body),
317 (DataAlt inrDataCon, [r_rep_var], r_to_body)],
320 (l_datacons, r_datacons) = splitInHalf datacons
321 (l_from_alts, l_to_body, l_rep_var) = mk_sum_stuff (i+2) tyvars l_datacons
322 (r_from_alts, r_to_body, r_rep_var) = mk_sum_stuff (i+2) tyvars r_datacons
323 rep_tys = [idType l_rep_var, idType r_rep_var]
324 rep_ty = mkTyConApp plusTyCon rep_tys
325 rep_var = mkTemplateLocal i rep_ty
327 wrap :: DataCon -> [Alt Id] -> [Alt Id]
328 -- Wrap an application of the Inl or Inr constructor round each alternative
330 = [(dc, args, App datacon_app rhs) | (dc,args,rhs) <- alts]
332 datacon_app = mkTyApps (Var (dataConWrapId datacon)) rep_tys
335 -- This constructs the c_of datatype from a DataCon and a Type
336 -- The identity function at the moment.
337 cOfConstr :: DataCon -> Type -> Type
341 ----------------------------------------------------
342 -- Dealing with products
343 ----------------------------------------------------
344 mk_prod_stuff :: Int -- Base for unique names
345 -> [Id] -- arg-ids; args of the original user-defined constructor
346 -- They are bound enclosing from_rhs
347 -- Please bind these in the to_body_fn
348 -> (Int, -- Depleted unique-name supply
349 CoreExpr, -- from-rhs: puts together the representation from the arg_ids
350 CoreExpr -> CoreExpr, -- to_body_fn: takes apart the representation
351 Id) -- The rep-id; please bind this to the representation
354 -- mk_prod_stuff [a,b,c] = ( a :*: (b :*: c),
355 -- \x -> case abc of { a :*: bc ->
356 -- case bc of { b :*: c ->
360 -- We need to use different uqiques in the branches
361 -- because the returned to_body_fns are nested.
362 -- Hence the returned unqique-name supply
364 mk_prod_stuff i [] -- Unit case
366 Var (dataConWrapId genUnitDataCon),
368 mkTemplateLocal i (mkTyConApp genUnitTyCon []))
370 mk_prod_stuff i [arg_var] -- Singleton case
371 = (i, Var arg_var, \x -> x, arg_var)
373 mk_prod_stuff i arg_vars -- Two or more
375 mkConApp crossDataCon (map Type rep_tys ++ [l_alt_rhs, r_alt_rhs]),
376 \x -> Case (Var rep_var) rep_var
377 [(DataAlt crossDataCon, [l_rep_var, r_rep_var], l_to_body_fn (r_to_body_fn x))],
380 (l_arg_vars, r_arg_vars) = splitInHalf arg_vars
381 (l_i, l_alt_rhs, l_to_body_fn, l_rep_var) = mk_prod_stuff (i+1) l_arg_vars
382 (r_i, r_alt_rhs, r_to_body_fn, r_rep_var) = mk_prod_stuff l_i r_arg_vars
383 rep_var = mkTemplateLocal i (mkTyConApp crossTyCon rep_tys)
384 rep_tys = [idType l_rep_var, idType r_rep_var]
387 A little utility function
390 splitInHalf :: [a] -> ([a],[a])
391 splitInHalf list = (left, right)
393 half = length list `div` 2
394 left = take half list
395 right = drop half list
398 %************************************************************************
400 \subsection{Generating the RHS of a generic default method}
402 %************************************************************************
404 Generating the Generic default method. Uses the bimaps to generate the
405 actual method. All of this is rather incomplete, but it would be nice
406 to make even this work.
409 mkGenericRhs :: Id -> TyVar -> TyCon -> RenamedHsExpr
410 mkGenericRhs sel_id tyvar tycon
411 = HsApp (toEP bimap) (HsVar (idName sel_id))
413 -- Initialising the "Environment" with the from/to functions
414 -- on the datatype (actually tycon) in question
415 Just (EP from to) = tyConGenInfo tycon -- Caller checked this will succeed
416 ep = EP (HsVar (idName from)) (HsVar (idName to))
418 -- Takes out the ForAll and the Class rstrictions in front of the
419 -- type of the method.
420 (_,_,op_ty) = splitSigmaTy (idType sel_id)
422 -- Now we probably have a tycon in front
423 -- of us, quite probably a FunTyCon.
424 bimap = generate_bimap (tyvar, ep) op_ty
426 -- EP is the environment of to/from bimaps, but as we only have one type
427 -- variable at the moment, there is only one EP.
430 generate_bimap :: (TyVar, EP RenamedHsExpr) -> Type -> EP RenamedHsExpr
431 -- Top level case - splitting the TyCon.
432 generate_bimap (tv,ep) ty | isTyVarTy ty = ASSERT( getTyVar "Generics.generate_bimap" ty == tv) ep
433 | otherwise = bimapApp (tv,ep) (splitTyConApp_maybe ty)
436 bimapApp :: (TyVar, EP RenamedHsExpr) -> Maybe (TyCon, [Type]) -> EP RenamedHsExpr
437 bimapApp ep Nothing = panic "TcClassDecl: Type Application!"
438 bimapApp ep (Just (tycon, ty_args))
439 | tycon == funTyCon = bimapArrow arg_eps
440 | isBoxedTupleTyCon tycon = bimapTuple arg_eps
441 | otherwise = -- Otherwise validGenericMethodType will
442 -- have checked that the type is a constant type
443 ASSERT( isEmptyVarSet (tyVarsOfTypes ty_args) )
446 arg_eps = map (generate_bimap ep) ty_args
449 bimapArrow [ep1, ep2]
450 = EP { fromEP = mk_hs_lam [VarPatIn g1, VarPatIn g2] from_body,
451 toEP = mk_hs_lam [VarPatIn g1, VarPatIn g2] to_body }
453 from_body = fromEP ep2 `HsApp` (HsPar $ HsVar g1 `HsApp` (HsPar $ toEP ep1 `HsApp` HsVar g2))
454 to_body = toEP ep2 `HsApp` (HsPar $ HsVar g1 `HsApp` (HsPar $ fromEP ep1 `HsApp` HsVar g2))
458 = EP { fromEP = mk_hs_lam [tuple_pat] from_body,
459 toEP = mk_hs_lam [tuple_pat] to_body }
461 names = take (length eps) genericNames
462 tuple_pat = TuplePatIn (map VarPatIn names) Boxed
463 eps_w_names = eps `zip` names
464 to_body = ExplicitTuple [toEP ep `HsApp` HsVar g | (ep,g) <- eps_w_names] Boxed
465 from_body = ExplicitTuple [fromEP ep `HsApp` HsVar g | (ep,g) <- eps_w_names] Boxed
468 genericNames :: [Name]
469 genericNames = [mkSysLocalName (mkBuiltinUnique i) (_PK_ ('g' : show i)) | i <- [1..]]
470 (g1:g2:g3:_) = genericNames
472 mk_hs_lam pats body = HsPar (HsLam (mkSimpleMatch pats body Nothing builtinSrcLoc))
473 idexpr = mk_hs_lam [VarPatIn g3] (HsVar g3)