[project @ 2002-09-27 08:20:43 by simonpj]
[ghc-hetmet.git] / ghc / compiler / typecheck / TcGenDeriv.lhs
1 %
2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
3 %
4 \section[TcGenDeriv]{Generating derived instance declarations}
5
6 This module is nominally ``subordinate'' to @TcDeriv@, which is the
7 ``official'' interface to deriving-related things.
8
9 This is where we do all the grimy bindings' generation.
10
11 \begin{code}
12 module TcGenDeriv (
13         gen_Bounded_binds,
14         gen_Enum_binds,
15         gen_Eq_binds,
16         gen_Ix_binds,
17         gen_Ord_binds,
18         gen_Read_binds,
19         gen_Show_binds,
20         gen_tag_n_con_monobind,
21
22         con2tag_RDR, tag2con_RDR, maxtag_RDR,
23
24         TagThingWanted(..)
25     ) where
26
27 #include "HsVersions.h"
28
29 import HsSyn            ( Pat(..), HsConDetails(..), HsExpr(..), MonoBinds(..),
30                           Match(..), GRHSs(..), Stmt(..), HsLit(..),
31                           HsBinds(..), HsType(..), HsStmtContext(..),
32                           unguardedRHS, mkSimpleMatch, mkMonoBind, andMonoBindList, placeHolderType
33                         )
34 import RdrName          ( RdrName, mkUnqual, nameRdrName, getRdrName )
35 import RdrHsSyn         ( mkHsOpApp, RdrNameMonoBinds, RdrNameHsExpr, RdrNamePat, mkHsDo )
36 import BasicTypes       ( RecFlag(..), Fixity(..), FixityDirection(..)
37                         , maxPrecedence
38                         , Boxity(..)
39                         )
40 import FieldLabel       ( fieldLabelName )
41 import DataCon          ( isNullaryDataCon, dataConTag,
42                           dataConOrigArgTys, dataConSourceArity, fIRST_TAG,
43                           DataCon, 
44                           dataConFieldLabels )
45 import Name             ( getOccString, getOccName, getSrcLoc, occNameString, 
46                           occNameUserString, varName,
47                           Name, NamedThing(..), 
48                           isDataSymOcc, isSymOcc
49                         )
50
51 import HscTypes         ( FixityEnv, lookupFixity )
52 import PrelInfo         -- Lots of Names
53 import PrimOp           -- Lots of Names
54 import SrcLoc           ( generatedSrcLoc, SrcLoc )
55 import TyCon            ( TyCon, isNewTyCon, tyConDataCons, isEnumerationTyCon,
56                           maybeTyConSingleCon, tyConFamilySize
57                         )
58 import TcType           ( isUnLiftedType, tcEqType, Type )
59 import TysPrim          ( charPrimTy, intPrimTy, wordPrimTy, addrPrimTy,
60                           floatPrimTy, doublePrimTy
61                         )
62 import Util             ( zipWithEqual, isSingleton,
63                           zipWith3Equal, nOfThem, zipEqual )
64 import Panic            ( panic, assertPanic )
65 import Maybes           ( maybeToBool )
66 import Char             ( ord, isAlpha )
67 import Constants
68 import List             ( partition, intersperse )
69 import FastString
70 import OccName
71 \end{code}
72
73 %************************************************************************
74 %*                                                                      *
75 \subsection{Generating code, by derivable class}
76 %*                                                                      *
77 %************************************************************************
78
79 %************************************************************************
80 %*                                                                      *
81 \subsubsection{Generating @Eq@ instance declarations}
82 %*                                                                      *
83 %************************************************************************
84
85 Here are the heuristics for the code we generate for @Eq@:
86 \begin{itemize}
87 \item
88   Let's assume we have a data type with some (possibly zero) nullary
89   data constructors and some ordinary, non-nullary ones (the rest,
90   also possibly zero of them).  Here's an example, with both \tr{N}ullary
91   and \tr{O}rdinary data cons.
92 \begin{verbatim}
93 data Foo ... = N1 | N2 ... | Nn | O1 a b | O2 Int | O3 Double b b | ...
94 \end{verbatim}
95
96 \item
97   For the ordinary constructors (if any), we emit clauses to do The
98   Usual Thing, e.g.,:
99
100 \begin{verbatim}
101 (==) (O1 a1 b1)    (O1 a2 b2)    = a1 == a2 && b1 == b2
102 (==) (O2 a1)       (O2 a2)       = a1 == a2
103 (==) (O3 a1 b1 c1) (O3 a2 b2 c2) = a1 == a2 && b1 == b2 && c1 == c2
104 \end{verbatim}
105
106   Note: if we're comparing unlifted things, e.g., if \tr{a1} and
107   \tr{a2} are \tr{Float#}s, then we have to generate
108 \begin{verbatim}
109 case (a1 `eqFloat#` a2) of
110   r -> r
111 \end{verbatim}
112   for that particular test.
113
114 \item
115   If there are any nullary constructors, we emit a catch-all clause of
116   the form:
117
118 \begin{verbatim}
119 (==) a b  = case (con2tag_Foo a) of { a# ->
120             case (con2tag_Foo b) of { b# ->
121             case (a# ==# b#)     of {
122               r -> r
123             }}}
124 \end{verbatim}
125
126   If there aren't any nullary constructors, we emit a simpler
127   catch-all:
128 \begin{verbatim}
129 (==) a b  = False
130 \end{verbatim}
131
132 \item
133   For the @(/=)@ method, we normally just use the default method.
134
135   If the type is an enumeration type, we could/may/should? generate
136   special code that calls @con2tag_Foo@, much like for @(==)@ shown
137   above.
138
139 \item
140   We thought about doing this: If we're also deriving @Ord@ for this
141   tycon, we generate:
142 \begin{verbatim}
143 instance ... Eq (Foo ...) where
144   (==) a b  = case (compare a b) of { _LT -> False; _EQ -> True ; _GT -> False}
145   (/=) a b  = case (compare a b) of { _LT -> True ; _EQ -> False; _GT -> True }
146 \begin{verbatim}
147   However, that requires that \tr{Ord <whatever>} was put in the context
148   for the instance decl, which it probably wasn't, so the decls
149   produced don't get through the typechecker.
150 \end{itemize}
151
152
153 deriveEq :: RdrName                             -- Class
154          -> RdrName                             -- Type constructor
155          -> [ (RdrName, [RdrType]) ]    -- Constructors
156          -> (RdrContext,                -- Context for the inst decl
157              [RdrBind],                 -- Binds in the inst decl
158              [RdrBind])                 -- Extra value bindings outside
159
160 deriveEq clas tycon constrs 
161   = (context, [eq_bind, ne_bind], [])
162   where
163     context = [(clas, [ty]) | (_, tys) <- constrs, ty <- tys]
164
165     ne_bind = mkBind 
166     (nullary_cons, non_nullary_cons) = partition is_nullary constrs
167     is_nullary (_, args) = null args
168
169 \begin{code}
170 gen_Eq_binds :: TyCon -> RdrNameMonoBinds
171
172 gen_Eq_binds tycon
173   = let
174         tycon_loc = getSrcLoc tycon
175         (nullary_cons, nonnullary_cons)
176            | isNewTyCon tycon = ([], tyConDataCons tycon)
177            | otherwise        = partition isNullaryDataCon (tyConDataCons tycon)
178
179         rest
180           = if (null nullary_cons) then
181                 case maybeTyConSingleCon tycon of
182                   Just _ -> []
183                   Nothing -> -- if cons don't match, then False
184                      [([wildPat, wildPat], false_Expr)]
185             else -- calc. and compare the tags
186                  [([a_Pat, b_Pat],
187                     untag_Expr tycon [(a_RDR,ah_RDR), (b_RDR,bh_RDR)]
188                                (genOpApp (HsVar ah_RDR) eqInt_RDR (HsVar bh_RDR)))]
189     in
190     mk_FunMonoBind tycon_loc eq_RDR ((map pats_etc nonnullary_cons) ++ rest)
191             `AndMonoBinds`
192     mk_easy_FunMonoBind tycon_loc ne_RDR [a_Pat, b_Pat] [] (
193         HsApp (HsVar not_RDR) (HsPar (mkHsVarApps eq_RDR [a_RDR, b_RDR])))
194   where
195     ------------------------------------------------------------------
196     pats_etc data_con
197       = let
198             con1_pat = mkConPat data_con_RDR as_needed
199             con2_pat = mkConPat data_con_RDR bs_needed
200
201             data_con_RDR = getRdrName data_con
202             con_arity   = length tys_needed
203             as_needed   = take con_arity as_RDRs
204             bs_needed   = take con_arity bs_RDRs
205             tys_needed  = dataConOrigArgTys data_con
206         in
207         ([con1_pat, con2_pat], nested_eq_expr tys_needed as_needed bs_needed)
208       where
209         nested_eq_expr []  [] [] = true_Expr
210         nested_eq_expr tys as bs
211           = foldl1 and_Expr (zipWith3Equal "nested_eq" nested_eq tys as bs)
212           where
213             nested_eq ty a b = HsPar (eq_Expr ty (HsVar a) (HsVar b))
214 \end{code}
215
216 %************************************************************************
217 %*                                                                      *
218 \subsubsection{Generating @Ord@ instance declarations}
219 %*                                                                      *
220 %************************************************************************
221
222 For a derived @Ord@, we concentrate our attentions on @compare@
223 \begin{verbatim}
224 compare :: a -> a -> Ordering
225 data Ordering = LT | EQ | GT deriving ()
226 \end{verbatim}
227
228 We will use the same example data type as above:
229 \begin{verbatim}
230 data Foo ... = N1 | N2 ... | Nn | O1 a b | O2 Int | O3 Double b b | ...
231 \end{verbatim}
232
233 \begin{itemize}
234 \item
235   We do all the other @Ord@ methods with calls to @compare@:
236 \begin{verbatim}
237 instance ... (Ord <wurble> <wurble>) where
238     a <  b  = case (compare a b) of { LT -> True;  EQ -> False; GT -> False }
239     a <= b  = case (compare a b) of { LT -> True;  EQ -> True;  GT -> False }
240     a >= b  = case (compare a b) of { LT -> False; EQ -> True;  GT -> True  }
241     a >  b  = case (compare a b) of { LT -> False; EQ -> False; GT -> True  }
242
243     max a b = case (compare a b) of { LT -> b; EQ -> a;  GT -> a }
244     min a b = case (compare a b) of { LT -> a; EQ -> b;  GT -> b }
245
246     -- compare to come...
247 \end{verbatim}
248
249 \item
250   @compare@ always has two parts.  First, we use the compared
251   data-constructors' tags to deal with the case of different
252   constructors:
253 \begin{verbatim}
254 compare a b = case (con2tag_Foo a) of { a# ->
255               case (con2tag_Foo b) of { b# ->
256               case (a# ==# b#)     of {
257                True  -> cmp_eq a b
258                False -> case (a# <# b#) of
259                          True  -> _LT
260                          False -> _GT
261               }}}
262   where
263     cmp_eq = ... to come ...
264 \end{verbatim}
265
266 \item
267   We are only left with the ``help'' function @cmp_eq@, to deal with
268   comparing data constructors with the same tag.
269
270   For the ordinary constructors (if any), we emit the sorta-obvious
271   compare-style stuff; for our example:
272 \begin{verbatim}
273 cmp_eq (O1 a1 b1) (O1 a2 b2)
274   = case (compare a1 a2) of { LT -> LT; EQ -> compare b1 b2; GT -> GT }
275
276 cmp_eq (O2 a1) (O2 a2)
277   = compare a1 a2
278
279 cmp_eq (O3 a1 b1 c1) (O3 a2 b2 c2)
280   = case (compare a1 a2) of {
281       LT -> LT;
282       GT -> GT;
283       EQ -> case compare b1 b2 of {
284               LT -> LT;
285               GT -> GT;
286               EQ -> compare c1 c2
287             }
288     }
289 \end{verbatim}
290
291   Again, we must be careful about unlifted comparisons.  For example,
292   if \tr{a1} and \tr{a2} were \tr{Int#}s in the 2nd example above, we'd need to
293   generate:
294
295 \begin{verbatim}
296 cmp_eq lt eq gt (O2 a1) (O2 a2)
297   = compareInt# a1 a2
298   -- or maybe the unfolded equivalent
299 \end{verbatim}
300
301 \item
302   For the remaining nullary constructors, we already know that the
303   tags are equal so:
304 \begin{verbatim}
305 cmp_eq _ _ = EQ
306 \end{verbatim}
307 \end{itemize}
308
309 If there is only one constructor in the Data Type we don't need the WildCard Pattern. 
310 JJQC-30-Nov-1997
311
312 \begin{code}
313 gen_Ord_binds :: TyCon -> RdrNameMonoBinds
314
315 gen_Ord_binds tycon
316   = compare     -- `AndMonoBinds` compare       
317                 -- The default declaration in PrelBase handles this
318   where
319     tycon_loc = getSrcLoc tycon
320     --------------------------------------------------------------------
321     compare = mk_easy_FunMonoBind tycon_loc compare_RDR
322                 [a_Pat, b_Pat]
323                 [cmp_eq]
324             (if maybeToBool (maybeTyConSingleCon tycon) then
325
326 --              cmp_eq_Expr ltTag_Expr eqTag_Expr gtTag_Expr a_Expr b_Expr
327 -- Weird.  Was: case (cmp a b) of { LT -> LT; EQ -> EQ; GT -> GT }
328
329                 cmp_eq_Expr a_Expr b_Expr
330              else
331                 untag_Expr tycon [(a_RDR, ah_RDR), (b_RDR, bh_RDR)]
332                   (cmp_tags_Expr eqInt_RDR ah_RDR bh_RDR
333                         -- True case; they are equal
334                         -- If an enumeration type we are done; else
335                         -- recursively compare their components
336                     (if isEnumerationTyCon tycon then
337                         eqTag_Expr
338                      else
339 --                      cmp_eq_Expr ltTag_Expr eqTag_Expr gtTag_Expr a_Expr b_Expr
340 -- Ditto
341                         cmp_eq_Expr a_Expr b_Expr
342                     )
343                         -- False case; they aren't equal
344                         -- So we need to do a less-than comparison on the tags
345                     (cmp_tags_Expr ltInt_RDR ah_RDR bh_RDR ltTag_Expr gtTag_Expr)))
346
347     tycon_data_cons = tyConDataCons tycon
348     (nullary_cons, nonnullary_cons)
349        | isNewTyCon tycon = ([], tyConDataCons tycon)
350        | otherwise        = partition isNullaryDataCon tycon_data_cons
351
352     cmp_eq =
353        mk_FunMonoBind tycon_loc 
354                       cmp_eq_RDR 
355                       (if null nonnullary_cons && isSingleton nullary_cons then
356                            -- catch this specially to avoid warnings
357                            -- about overlapping patterns from the desugarer.
358                           let 
359                            data_con     = head nullary_cons
360                            data_con_RDR = getRdrName data_con
361                            pat          = mkNullaryConPat data_con_RDR
362                           in
363                           [([pat,pat], eqTag_Expr)]
364                        else
365                           map pats_etc nonnullary_cons ++
366                           -- leave out wildcards to silence desugarer.
367                           (if isSingleton tycon_data_cons then
368                               []
369                            else
370                               [([wildPat, wildPat], default_rhs)]))
371       where
372         pats_etc data_con
373           = ([con1_pat, con2_pat],
374              nested_compare_expr tys_needed as_needed bs_needed)
375           where
376             con1_pat = mkConPat data_con_RDR as_needed
377             con2_pat = mkConPat data_con_RDR bs_needed
378
379             data_con_RDR = getRdrName data_con
380             con_arity   = length tys_needed
381             as_needed   = take con_arity as_RDRs
382             bs_needed   = take con_arity bs_RDRs
383             tys_needed  = dataConOrigArgTys data_con
384
385             nested_compare_expr [ty] [a] [b]
386               = careful_compare_Case ty ltTag_Expr eqTag_Expr gtTag_Expr (HsVar a) (HsVar b)
387
388             nested_compare_expr (ty:tys) (a:as) (b:bs)
389               = let eq_expr = nested_compare_expr tys as bs
390                 in  careful_compare_Case ty ltTag_Expr eq_expr gtTag_Expr (HsVar a) (HsVar b)
391
392         default_rhs | null nullary_cons = impossible_Expr       -- Keep desugarer from complaining about
393                                                                 -- inexhaustive patterns
394                     | otherwise         = eqTag_Expr            -- Some nullary constructors;
395                                                                 -- Tags are equal, no args => return EQ
396 \end{code}
397
398 %************************************************************************
399 %*                                                                      *
400 \subsubsection{Generating @Enum@ instance declarations}
401 %*                                                                      *
402 %************************************************************************
403
404 @Enum@ can only be derived for enumeration types.  For a type
405 \begin{verbatim}
406 data Foo ... = N1 | N2 | ... | Nn
407 \end{verbatim}
408
409 we use both @con2tag_Foo@ and @tag2con_Foo@ functions, as well as a
410 @maxtag_Foo@ variable (all generated by @gen_tag_n_con_binds@).
411
412 \begin{verbatim}
413 instance ... Enum (Foo ...) where
414     succ x   = toEnum (1 + fromEnum x)
415     pred x   = toEnum (fromEnum x - 1)
416
417     toEnum i = tag2con_Foo i
418
419     enumFrom a = map tag2con_Foo [con2tag_Foo a .. maxtag_Foo]
420
421     -- or, really...
422     enumFrom a
423       = case con2tag_Foo a of
424           a# -> map tag2con_Foo (enumFromTo (I# a#) maxtag_Foo)
425
426    enumFromThen a b
427      = map tag2con_Foo [con2tag_Foo a, con2tag_Foo b .. maxtag_Foo]
428
429     -- or, really...
430     enumFromThen a b
431       = case con2tag_Foo a of { a# ->
432         case con2tag_Foo b of { b# ->
433         map tag2con_Foo (enumFromThenTo (I# a#) (I# b#) maxtag_Foo)
434         }}
435 \end{verbatim}
436
437 For @enumFromTo@ and @enumFromThenTo@, we use the default methods.
438
439 \begin{code}
440 gen_Enum_binds :: TyCon -> RdrNameMonoBinds
441
442 gen_Enum_binds tycon
443   = succ_enum           `AndMonoBinds`
444     pred_enum           `AndMonoBinds`
445     to_enum             `AndMonoBinds`
446     enum_from           `AndMonoBinds`
447     enum_from_then      `AndMonoBinds`
448     from_enum
449   where
450     tycon_loc = getSrcLoc tycon
451     occ_nm    = getOccString tycon
452
453     succ_enum
454       = mk_easy_FunMonoBind tycon_loc succ_RDR [a_Pat] [] $
455         untag_Expr tycon [(a_RDR, ah_RDR)] $
456         HsIf (mkHsApps eq_RDR [HsVar (maxtag_RDR tycon),
457                                mkHsVarApps mkInt_RDR [ah_RDR]])
458              (illegal_Expr "succ" occ_nm "tried to take `succ' of last tag in enumeration")
459              (HsApp (HsVar (tag2con_RDR tycon))
460                     (mkHsApps plus_RDR [mkHsVarApps mkInt_RDR [ah_RDR],
461                                         mkHsIntLit 1]))
462              tycon_loc
463                     
464     pred_enum
465       = mk_easy_FunMonoBind tycon_loc pred_RDR [a_Pat] [] $
466         untag_Expr tycon [(a_RDR, ah_RDR)] $
467         HsIf (mkHsApps eq_RDR [mkHsIntLit 0,
468                                mkHsVarApps mkInt_RDR [ah_RDR]])
469              (illegal_Expr "pred" occ_nm "tried to take `pred' of first tag in enumeration")
470              (HsApp (HsVar (tag2con_RDR tycon))
471                            (mkHsApps plus_RDR [mkHsVarApps mkInt_RDR [ah_RDR],
472                                                HsLit (HsInt (-1))]))
473              tycon_loc
474
475     to_enum
476       = mk_easy_FunMonoBind tycon_loc toEnum_RDR [a_Pat] [] $
477         HsIf (mkHsApps and_RDR
478                 [mkHsApps ge_RDR [HsVar a_RDR, mkHsIntLit 0],
479                  mkHsApps le_RDR [HsVar a_RDR, HsVar (maxtag_RDR tycon)]])
480              (mkHsVarApps (tag2con_RDR tycon) [a_RDR])
481              (illegal_toEnum_tag occ_nm (maxtag_RDR tycon))
482              tycon_loc
483
484     enum_from
485       = mk_easy_FunMonoBind tycon_loc enumFrom_RDR [a_Pat] [] $
486           untag_Expr tycon [(a_RDR, ah_RDR)] $
487           mkHsApps map_RDR 
488                 [HsVar (tag2con_RDR tycon),
489                  HsPar (enum_from_to_Expr
490                             (mkHsVarApps mkInt_RDR [ah_RDR])
491                             (HsVar (maxtag_RDR tycon)))]
492
493     enum_from_then
494       = mk_easy_FunMonoBind tycon_loc enumFromThen_RDR [a_Pat, b_Pat] [] $
495           untag_Expr tycon [(a_RDR, ah_RDR), (b_RDR, bh_RDR)] $
496           HsApp (mkHsVarApps map_RDR [tag2con_RDR tycon]) $
497             HsPar (enum_from_then_to_Expr
498                     (mkHsVarApps mkInt_RDR [ah_RDR])
499                     (mkHsVarApps mkInt_RDR [bh_RDR])
500                     (HsIf  (mkHsApps gt_RDR [mkHsVarApps mkInt_RDR [ah_RDR],
501                                              mkHsVarApps mkInt_RDR [bh_RDR]])
502                            (mkHsIntLit 0)
503                            (HsVar (maxtag_RDR tycon))
504                            tycon_loc))
505
506     from_enum
507       = mk_easy_FunMonoBind tycon_loc fromEnum_RDR [a_Pat] [] $
508           untag_Expr tycon [(a_RDR, ah_RDR)] $
509           (mkHsVarApps mkInt_RDR [ah_RDR])
510 \end{code}
511
512 %************************************************************************
513 %*                                                                      *
514 \subsubsection{Generating @Bounded@ instance declarations}
515 %*                                                                      *
516 %************************************************************************
517
518 \begin{code}
519 gen_Bounded_binds tycon
520   = if isEnumerationTyCon tycon then
521         min_bound_enum `AndMonoBinds` max_bound_enum
522     else
523         ASSERT(isSingleton data_cons)
524         min_bound_1con `AndMonoBinds` max_bound_1con
525   where
526     data_cons = tyConDataCons tycon
527     tycon_loc = getSrcLoc tycon
528
529     ----- enum-flavored: ---------------------------
530     min_bound_enum = mk_easy_FunMonoBind tycon_loc minBound_RDR [] [] (HsVar data_con_1_RDR)
531     max_bound_enum = mk_easy_FunMonoBind tycon_loc maxBound_RDR [] [] (HsVar data_con_N_RDR)
532
533     data_con_1    = head data_cons
534     data_con_N    = last data_cons
535     data_con_1_RDR = getRdrName data_con_1
536     data_con_N_RDR = getRdrName data_con_N
537
538     ----- single-constructor-flavored: -------------
539     arity          = dataConSourceArity data_con_1
540
541     min_bound_1con = mk_easy_FunMonoBind tycon_loc minBound_RDR [] [] $
542                      mkHsVarApps data_con_1_RDR (nOfThem arity minBound_RDR)
543     max_bound_1con = mk_easy_FunMonoBind tycon_loc maxBound_RDR [] [] $
544                      mkHsVarApps data_con_1_RDR (nOfThem arity maxBound_RDR)
545 \end{code}
546
547 %************************************************************************
548 %*                                                                      *
549 \subsubsection{Generating @Ix@ instance declarations}
550 %*                                                                      *
551 %************************************************************************
552
553 Deriving @Ix@ is only possible for enumeration types and
554 single-constructor types.  We deal with them in turn.
555
556 For an enumeration type, e.g.,
557 \begin{verbatim}
558     data Foo ... = N1 | N2 | ... | Nn
559 \end{verbatim}
560 things go not too differently from @Enum@:
561 \begin{verbatim}
562 instance ... Ix (Foo ...) where
563     range (a, b)
564       = map tag2con_Foo [con2tag_Foo a .. con2tag_Foo b]
565
566     -- or, really...
567     range (a, b)
568       = case (con2tag_Foo a) of { a# ->
569         case (con2tag_Foo b) of { b# ->
570         map tag2con_Foo (enumFromTo (I# a#) (I# b#))
571         }}
572
573     index c@(a, b) d
574       = if inRange c d
575         then case (con2tag_Foo d -# con2tag_Foo a) of
576                r# -> I# r#
577         else error "Ix.Foo.index: out of range"
578
579     inRange (a, b) c
580       = let
581             p_tag = con2tag_Foo c
582         in
583         p_tag >= con2tag_Foo a && p_tag <= con2tag_Foo b
584
585     -- or, really...
586     inRange (a, b) c
587       = case (con2tag_Foo a)   of { a_tag ->
588         case (con2tag_Foo b)   of { b_tag ->
589         case (con2tag_Foo c)   of { c_tag ->
590         if (c_tag >=# a_tag) then
591           c_tag <=# b_tag
592         else
593           False
594         }}}
595 \end{verbatim}
596 (modulo suitable case-ification to handle the unlifted tags)
597
598 For a single-constructor type (NB: this includes all tuples), e.g.,
599 \begin{verbatim}
600     data Foo ... = MkFoo a b Int Double c c
601 \end{verbatim}
602 we follow the scheme given in Figure~19 of the Haskell~1.2 report
603 (p.~147).
604
605 \begin{code}
606 gen_Ix_binds :: TyCon -> RdrNameMonoBinds
607
608 gen_Ix_binds tycon
609   = if isEnumerationTyCon tycon
610     then enum_ixes
611     else single_con_ixes
612   where
613     tycon_str = getOccString tycon
614     tycon_loc = getSrcLoc tycon
615
616     --------------------------------------------------------------
617     enum_ixes = enum_range `AndMonoBinds`
618                 enum_index `AndMonoBinds` enum_inRange
619
620     enum_range
621       = mk_easy_FunMonoBind tycon_loc range_RDR 
622                 [TuplePat [a_Pat, b_Pat] Boxed] [] $
623           untag_Expr tycon [(a_RDR, ah_RDR)] $
624           untag_Expr tycon [(b_RDR, bh_RDR)] $
625           HsApp (mkHsVarApps map_RDR [tag2con_RDR tycon]) $
626               HsPar (enum_from_to_Expr
627                         (mkHsVarApps mkInt_RDR [ah_RDR])
628                         (mkHsVarApps mkInt_RDR [bh_RDR]))
629
630     enum_index
631       = mk_easy_FunMonoBind tycon_loc index_RDR 
632                 [AsPat c_RDR (TuplePat [a_Pat, wildPat] Boxed), 
633                                 d_Pat] [] (
634         HsIf (HsPar (mkHsVarApps inRange_RDR [c_RDR, d_RDR])) (
635            untag_Expr tycon [(a_RDR, ah_RDR)] (
636            untag_Expr tycon [(d_RDR, dh_RDR)] (
637            let
638                 rhs = mkHsVarApps mkInt_RDR [c_RDR]
639            in
640            HsCase
641              (genOpApp (HsVar dh_RDR) minusInt_RDR (HsVar ah_RDR))
642              [mkSimpleMatch [VarPat c_RDR] rhs placeHolderType tycon_loc]
643              tycon_loc
644            ))
645         ) {-else-} (
646            HsApp (HsVar error_RDR) (HsLit (HsString (mkFastString ("Ix."++tycon_str++".index: out of range\n"))))
647         )
648         tycon_loc)
649
650     enum_inRange
651       = mk_easy_FunMonoBind tycon_loc inRange_RDR 
652           [TuplePat [a_Pat, b_Pat] Boxed, c_Pat] [] (
653           untag_Expr tycon [(a_RDR, ah_RDR)] (
654           untag_Expr tycon [(b_RDR, bh_RDR)] (
655           untag_Expr tycon [(c_RDR, ch_RDR)] (
656           HsIf (genOpApp (HsVar ch_RDR) geInt_RDR (HsVar ah_RDR)) (
657              (genOpApp (HsVar ch_RDR) leInt_RDR (HsVar bh_RDR))
658           ) {-else-} (
659              false_Expr
660           ) tycon_loc))))
661
662     --------------------------------------------------------------
663     single_con_ixes 
664       = single_con_range `AndMonoBinds`
665         single_con_index `AndMonoBinds`
666         single_con_inRange
667
668     data_con
669       = case maybeTyConSingleCon tycon of -- just checking...
670           Nothing -> panic "get_Ix_binds"
671           Just dc -> if (any isUnLiftedType (dataConOrigArgTys dc)) then
672                          error ("ERROR: Can't derive Ix for a single-constructor type with primitive argument types: "++tycon_str)
673                      else
674                          dc
675
676     con_arity    = dataConSourceArity data_con
677     data_con_RDR = getRdrName data_con
678
679     as_needed = take con_arity as_RDRs
680     bs_needed = take con_arity bs_RDRs
681     cs_needed = take con_arity cs_RDRs
682
683     con_pat  xs  = mkConPat data_con_RDR xs
684     con_expr     = mkHsVarApps data_con_RDR cs_needed
685
686     --------------------------------------------------------------
687     single_con_range
688       = mk_easy_FunMonoBind tycon_loc range_RDR 
689           [TuplePat [con_pat as_needed, con_pat bs_needed] Boxed] [] $
690         mkHsDo ListComp stmts tycon_loc
691       where
692         stmts = zipWith3Equal "single_con_range" mk_qual as_needed bs_needed cs_needed
693                 ++
694                 [ResultStmt con_expr tycon_loc]
695
696         mk_qual a b c = BindStmt (VarPat c)
697                                  (HsApp (HsVar range_RDR) 
698                                         (ExplicitTuple [HsVar a, HsVar b] Boxed))
699                                  tycon_loc
700
701     ----------------
702     single_con_index
703       = mk_easy_FunMonoBind tycon_loc index_RDR 
704                 [TuplePat [con_pat as_needed, con_pat bs_needed] Boxed, 
705                  con_pat cs_needed] [range_size] (
706         foldl mk_index (mkHsIntLit 0) (zip3 as_needed bs_needed cs_needed))
707       where
708         mk_index multiply_by (l, u, i)
709           = genOpApp (
710                (mkHsApps index_RDR [ExplicitTuple [HsVar l, HsVar u] Boxed,  
711                                     HsVar i])
712            ) plus_RDR (
713                 genOpApp (
714                     (HsApp (HsVar rangeSize_RDR) 
715                            (ExplicitTuple [HsVar l, HsVar u] Boxed))
716                 ) times_RDR multiply_by
717            )
718
719         range_size
720           = mk_easy_FunMonoBind tycon_loc rangeSize_RDR 
721                         [TuplePat [a_Pat, b_Pat] Boxed] [] (
722                 genOpApp (
723                     (mkHsApps index_RDR [ExplicitTuple [a_Expr, b_Expr] Boxed,
724                                          b_Expr])
725                 ) plus_RDR (mkHsIntLit 1))
726
727     ------------------
728     single_con_inRange
729       = mk_easy_FunMonoBind tycon_loc inRange_RDR 
730                 [TuplePat [con_pat as_needed, con_pat bs_needed] Boxed, 
731                  con_pat cs_needed]
732                            [] (
733           foldl1 and_Expr (zipWith3Equal "single_con_inRange" in_range as_needed bs_needed cs_needed))
734       where
735         in_range a b c = mkHsApps inRange_RDR [ExplicitTuple [HsVar a, HsVar b] Boxed,
736                                                HsVar c]
737 \end{code}
738
739 %************************************************************************
740 %*                                                                      *
741 \subsubsection{Generating @Read@ instance declarations}
742 %*                                                                      *
743 %************************************************************************
744
745 Example
746
747   infix 4 %%
748   data T = Int %% Int
749          | T1 { f1 :: Int }
750          | T2 Int
751
752
753 instance Read T where
754   readPrec =
755     parens
756     ( prec 4 (
757         do x           <- ReadP.step Read.readPrec
758            Symbol "%%" <- Lex.lex
759            y           <- ReadP.step Read.readPrec
760            return (x %% y))
761       +++
762       prec appPrec (
763         do Ident "T1" <- Lex.lex
764            Punc '{' <- Lex.lex
765            Ident "f1" <- Lex.lex
766            Punc '=' <- Lex.lex
767            x          <- ReadP.reset Read.readPrec
768            Punc '}' <- Lex.lex
769            return (T1 { f1 = x }))
770       +++
771       prec appPrec (
772         do Ident "T2" <- Lex.lexP
773            x          <- ReadP.step Read.readPrec
774            return (T2 x))
775     )
776
777   readListPrec = readListPrecDefault
778   readList     = readListDefault
779
780
781 \begin{code}
782 gen_Read_binds :: FixityEnv -> TyCon -> RdrNameMonoBinds
783
784 gen_Read_binds get_fixity tycon
785   = read_prec `AndMonoBinds` default_binds
786   where
787     -----------------------------------------------------------------------
788     default_binds 
789         = mk_easy_FunMonoBind loc readList_RDR     [] [] (HsVar readListDefault_RDR)
790                 `AndMonoBinds`
791           mk_easy_FunMonoBind loc readListPrec_RDR [] [] (HsVar readListPrecDefault_RDR)
792     -----------------------------------------------------------------------
793
794     loc       = getSrcLoc tycon
795     data_cons = tyConDataCons tycon
796     (nullary_cons, non_nullary_cons) = partition isNullaryDataCon data_cons
797     
798     read_prec = mk_easy_FunMonoBind loc readPrec_RDR [] [] 
799                                     (HsApp (HsVar parens_RDR) read_cons)
800
801     read_cons             = foldr1 mk_alt (read_nullary_cons ++ read_non_nullary_cons)
802     read_non_nullary_cons = map read_non_nullary_con non_nullary_cons
803     
804     read_nullary_cons 
805       = case nullary_cons of
806             []    -> []
807             [con] -> [mkHsDo DoExpr [bindLex (ident_pat (data_con_str con)),
808                                      result_stmt con []] loc]
809             _     -> [HsApp (HsVar choose_RDR) 
810                             (ExplicitList placeHolderType (map mk_pair nullary_cons))]
811     
812     mk_pair con = ExplicitTuple [HsLit (data_con_str con),
813                                  HsApp (HsVar returnM_RDR) (HsVar (getRdrName con))]
814                                 Boxed
815     
816     read_non_nullary_con data_con
817       = mkHsApps prec_RDR [mkHsIntLit prec, mkHsDo DoExpr stmts loc]
818       where
819         stmts | is_infix          = infix_stmts
820               | length labels > 0 = lbl_stmts
821               | otherwise         = prefix_stmts
822      
823         prefix_stmts            -- T a b c
824           = [bindLex (ident_pat (data_con_str data_con))]
825             ++ map read_arg as_needed
826             ++ [result_stmt data_con as_needed]
827          
828         infix_stmts             -- a %% b
829           = [read_arg a1, 
830              bindLex (symbol_pat (data_con_str data_con)),
831              read_arg a2,
832              result_stmt data_con [a1,a2]]
833      
834         lbl_stmts               -- T { f1 = a, f2 = b }
835           = [bindLex (ident_pat (data_con_str data_con)),
836              read_punc "{"]
837             ++ concat (intersperse [read_punc ","] field_stmts)
838             ++ [read_punc "}", result_stmt data_con as_needed]
839      
840         field_stmts  = zipWithEqual "lbl_stmts" read_field labels as_needed
841      
842         con_arity    = dataConSourceArity data_con
843         nullary_con  = con_arity == 0
844         labels       = dataConFieldLabels data_con
845         lab_fields   = length labels
846         dc_nm        = getName data_con
847         is_infix     = isDataSymOcc (getOccName dc_nm)
848         as_needed    = take con_arity as_RDRs
849         (a1:a2:_)    = as_needed
850         prec         = getPrec is_infix get_fixity dc_nm
851
852     ------------------------------------------------------------------------
853     --          Helpers
854     ------------------------------------------------------------------------
855     mk_alt e1 e2     = genOpApp e1 alt_RDR e2
856     bindLex pat      = BindStmt pat (HsVar lexP_RDR) loc
857     result_stmt c as = ResultStmt (HsApp (HsVar returnM_RDR) (con_app c as)) loc
858     con_app c as     = mkHsVarApps (getRdrName c) as
859     
860     punc_pat s   = ConPatIn punc_RDR  (PrefixCon [LitPat (mkHsString s)])         -- Punc 'c'
861     ident_pat s  = ConPatIn ident_RDR (PrefixCon [LitPat s])                      -- Ident "foo"
862     symbol_pat s = ConPatIn symbol_RDR (PrefixCon [LitPat s])                     -- Symbol ">>"
863     
864     data_con_str con = mkHsString (occNameUserString (getOccName con))
865     
866     read_punc c = bindLex (punc_pat c)
867     read_arg a  = BindStmt (VarPat a) (mkHsVarApps step_RDR [readPrec_RDR]) loc
868     
869     read_field lbl a = read_lbl lbl ++
870                        [read_punc "=",
871                         BindStmt (VarPat a) (mkHsVarApps reset_RDR [readPrec_RDR]) loc]
872
873         -- When reading field labels we might encounter
874         --      a = 3
875         -- or   (#) = 4
876         -- Note the parens!
877     read_lbl lbl | isAlpha (head lbl_str) 
878                  = [bindLex (ident_pat lbl_lit)]
879                  | otherwise
880                  = [read_punc "(", 
881                     bindLex (symbol_pat lbl_lit),
882                     read_punc ")"]
883                  where  
884                    lbl_str = occNameUserString (getOccName (fieldLabelName lbl)) 
885                    lbl_lit = mkHsString lbl_str
886 \end{code}
887
888
889 %************************************************************************
890 %*                                                                      *
891 \subsubsection{Generating @Show@ instance declarations}
892 %*                                                                      *
893 %************************************************************************
894
895 Example
896
897     infixr 5 :^:
898
899     data Tree a =  Leaf a  |  Tree a :^: Tree a
900
901     instance (Show a) => Show (Tree a) where
902
903         showsPrec d (Leaf m) = showParen (d > app_prec) showStr
904           where
905              showStr = showString "Leaf " . showsPrec (app_prec+1) m
906
907         showsPrec d (u :^: v) = showParen (d > up_prec) showStr
908           where
909              showStr = showsPrec (up_prec+1) u . 
910                        showString " :^: "      .
911                        showsPrec (up_prec+1) v
912                 -- Note: right-associativity of :^: ignored
913
914     up_prec  = 5    -- Precedence of :^:
915     app_prec = 10   -- Application has precedence one more than
916                     -- the most tightly-binding operator
917
918 \begin{code}
919 gen_Show_binds :: FixityEnv -> TyCon -> RdrNameMonoBinds
920
921 gen_Show_binds get_fixity tycon
922   = shows_prec `AndMonoBinds` show_list
923   where
924     tycon_loc = getSrcLoc tycon
925     -----------------------------------------------------------------------
926     show_list = mk_easy_FunMonoBind tycon_loc showList_RDR [] []
927                   (HsApp (HsVar showList___RDR) (HsPar (HsApp (HsVar showsPrec_RDR) (mkHsIntLit 0))))
928     -----------------------------------------------------------------------
929     shows_prec = mk_FunMonoBind tycon_loc showsPrec_RDR (map pats_etc (tyConDataCons tycon))
930       where
931         pats_etc data_con
932           | nullary_con =  -- skip the showParen junk...
933              ASSERT(null bs_needed)
934              ([wildPat, con_pat], mk_showString_app con_str)
935           | otherwise   =
936              ([a_Pat, con_pat],
937                   showParen_Expr (HsPar (genOpApp a_Expr ge_RDR (HsLit (HsInt con_prec_plus_one))))
938                                  (HsPar (nested_compose_Expr show_thingies)))
939             where
940              data_con_RDR  = getRdrName data_con
941              con_arity     = dataConSourceArity data_con
942              bs_needed     = take con_arity bs_RDRs
943              con_pat       = mkConPat data_con_RDR bs_needed
944              nullary_con   = con_arity == 0
945              labels        = dataConFieldLabels data_con
946              lab_fields    = length labels
947              record_syntax = lab_fields > 0
948
949              dc_nm          = getName data_con
950              dc_occ_nm      = getOccName data_con
951              con_str        = occNameUserString dc_occ_nm
952
953              show_thingies 
954                 | is_infix      = [show_arg1, mk_showString_app (" " ++ con_str ++ " "), show_arg2]
955                 | record_syntax = mk_showString_app (con_str ++ " {") : 
956                                   show_record_args ++ [mk_showString_app "}"]
957                 | otherwise     = mk_showString_app (con_str ++ " ") : show_prefix_args
958                 
959              show_label l = mk_showString_app (the_name ++ " = ")
960                         -- Note the spaces around the "=" sign.  If we don't have them
961                         -- then we get Foo { x=-1 } and the "=-" parses as a single
962                         -- lexeme.  Only the space after the '=' is necessary, but
963                         -- it seems tidier to have them both sides.
964                  where
965                    occ_nm   = getOccName (fieldLabelName l)
966                    nm       = occNameUserString occ_nm
967
968                    is_op    = isSymOcc occ_nm       -- Legal, but rare.
969                    the_name 
970                      | is_op     = '(':nm ++ ")"
971                      | otherwise = nm
972
973              show_args = [ mkHsApps showsPrec_RDR [HsLit (HsInt arg_prec), HsVar b]
974                          | b <- bs_needed ]
975              (show_arg1:show_arg2:_) = show_args
976              show_prefix_args = intersperse (HsVar showSpace_RDR) show_args
977
978                 --  Assumption for record syntax: no of fields == no of labelled fields 
979                 --            (and in same order)
980              show_record_args = concat $
981                                 intersperse [mk_showString_app ", "] $
982                                 [ [show_label lbl, arg] 
983                                 | (lbl,arg) <- zipEqual "gen_Show_binds" 
984                                                         labels show_args ]
985                                
986                 -- Fixity stuff
987              is_infix = isDataSymOcc dc_occ_nm
988              con_prec_plus_one = 1 + getPrec is_infix get_fixity dc_nm
989              arg_prec | record_syntax = 0       -- Record fields don't need parens
990                       | otherwise     = con_prec_plus_one
991
992 mk_showString_app str = HsApp (HsVar showString_RDR) (HsLit (mkHsString str))
993 \end{code}
994
995 \begin{code}
996 getPrec :: Bool -> FixityEnv -> Name -> Integer
997 getPrec is_infix get_fixity nm 
998   | not is_infix   = appPrecedence
999   | otherwise      = getPrecedence get_fixity nm
1000                   
1001 appPrecedence :: Integer
1002 appPrecedence = fromIntegral maxPrecedence + 1
1003   -- One more than the precedence of the most 
1004   -- tightly-binding operator
1005
1006 getPrecedence :: FixityEnv -> Name -> Integer
1007 getPrecedence get_fixity nm 
1008    = case lookupFixity get_fixity nm of
1009         Fixity x _ -> fromIntegral x
1010
1011 isLRAssoc :: FixityEnv -> Name -> (Bool, Bool)
1012 isLRAssoc get_fixity nm =
1013      case lookupFixity get_fixity nm of
1014        Fixity _ InfixN -> (False, False)
1015        Fixity _ InfixR -> (False, True)
1016        Fixity _ InfixL -> (True,  False)
1017 \end{code}
1018
1019
1020 %************************************************************************
1021 %*                                                                      *
1022 \subsection{Generating extra binds (@con2tag@ and @tag2con@)}
1023 %*                                                                      *
1024 %************************************************************************
1025
1026 \begin{verbatim}
1027 data Foo ... = ...
1028
1029 con2tag_Foo :: Foo ... -> Int#
1030 tag2con_Foo :: Int -> Foo ...   -- easier if Int, not Int#
1031 maxtag_Foo  :: Int              -- ditto (NB: not unlifted)
1032 \end{verbatim}
1033
1034 The `tags' here start at zero, hence the @fIRST_TAG@ (currently one)
1035 fiddling around.
1036
1037 \begin{code}
1038 data TagThingWanted
1039   = GenCon2Tag | GenTag2Con | GenMaxTag
1040
1041 gen_tag_n_con_monobind
1042     :: (RdrName,            -- (proto)Name for the thing in question
1043         TyCon,              -- tycon in question
1044         TagThingWanted)
1045     -> RdrNameMonoBinds
1046
1047 gen_tag_n_con_monobind (rdr_name, tycon, GenCon2Tag)
1048   | lots_of_constructors
1049   = mk_FunMonoBind (getSrcLoc tycon) rdr_name 
1050         [([VarPat a_RDR], HsApp getTag_Expr a_Expr)]
1051
1052   | otherwise
1053   = mk_FunMonoBind (getSrcLoc tycon) rdr_name (map mk_stuff (tyConDataCons tycon))
1054
1055   where
1056     lots_of_constructors = tyConFamilySize tycon > mAX_FAMILY_SIZE_FOR_VEC_RETURNS
1057
1058     mk_stuff :: DataCon -> ([RdrNamePat], RdrNameHsExpr)
1059     mk_stuff var
1060       = ([pat], HsLit (HsIntPrim (toInteger ((dataConTag var) - fIRST_TAG))))
1061       where
1062         pat    = ConPatIn var_RDR (PrefixCon (nOfThem (dataConSourceArity var) wildPat))
1063         var_RDR = getRdrName var
1064
1065 gen_tag_n_con_monobind (rdr_name, tycon, GenTag2Con)
1066   = mk_FunMonoBind (getSrcLoc tycon) rdr_name 
1067         [([mkConPat mkInt_RDR [a_RDR]], 
1068            ExprWithTySig (HsApp tagToEnum_Expr a_Expr) 
1069                          (HsTyVar (getRdrName tycon)))]
1070
1071 gen_tag_n_con_monobind (rdr_name, tycon, GenMaxTag)
1072   = mk_easy_FunMonoBind (getSrcLoc tycon) 
1073                 rdr_name [] [] (HsApp (HsVar mkInt_RDR) (HsLit (HsIntPrim max_tag)))
1074   where
1075     max_tag =  case (tyConDataCons tycon) of
1076                  data_cons -> toInteger ((length data_cons) - fIRST_TAG)
1077
1078 \end{code}
1079
1080 %************************************************************************
1081 %*                                                                      *
1082 \subsection{Utility bits for generating bindings}
1083 %*                                                                      *
1084 %************************************************************************
1085
1086 @mk_easy_FunMonoBind fun pats binds expr@ generates:
1087 \begin{verbatim}
1088     fun pat1 pat2 ... patN = expr where binds
1089 \end{verbatim}
1090
1091 @mk_FunMonoBind fun [([p1a, p1b, ...], e1), ...]@ is for
1092 multi-clause definitions; it generates:
1093 \begin{verbatim}
1094     fun p1a p1b ... p1N = e1
1095     fun p2a p2b ... p2N = e2
1096     ...
1097     fun pMa pMb ... pMN = eM
1098 \end{verbatim}
1099
1100 \begin{code}
1101 mk_easy_FunMonoBind :: SrcLoc -> RdrName -> [RdrNamePat]
1102                     -> [RdrNameMonoBinds] -> RdrNameHsExpr
1103                     -> RdrNameMonoBinds
1104
1105 mk_easy_FunMonoBind loc fun pats binds expr
1106   = FunMonoBind fun False{-not infix-} [mk_easy_Match loc pats binds expr] loc
1107
1108 mk_easy_Match loc pats binds expr
1109   = mk_match loc pats expr (mkMonoBind (andMonoBindList binds) [] Recursive)
1110         -- The renamer expects everything in its input to be a
1111         -- "recursive" MonoBinds, and it is its job to sort things out
1112         -- from there.
1113
1114 mk_FunMonoBind  :: SrcLoc -> RdrName
1115                 -> [([RdrNamePat], RdrNameHsExpr)]
1116                 -> RdrNameMonoBinds
1117
1118 mk_FunMonoBind loc fun [] = panic "TcGenDeriv:mk_FunMonoBind"
1119 mk_FunMonoBind loc fun pats_and_exprs
1120   = FunMonoBind fun False{-not infix-}
1121                 [ mk_match loc p e EmptyBinds | (p,e) <-pats_and_exprs ]
1122                 loc
1123
1124 mk_match loc pats expr binds
1125   = Match (map paren pats) Nothing 
1126           (GRHSs (unguardedRHS expr loc) binds placeHolderType)
1127   where
1128     paren p@(VarPat _) = p
1129     paren other_p      = ParPat other_p
1130 \end{code}
1131
1132 \begin{code}
1133 mkHsApps    f xs = foldl HsApp (HsVar f) xs
1134 mkHsVarApps f xs = foldl HsApp (HsVar f) (map HsVar xs)
1135
1136 mkHsIntLit n = HsLit (HsInt n)
1137 mkHsString s = HsString (mkFastString s)
1138 mkHsChar c   = HsChar   (ord c)
1139
1140 mkConPat con vars   = ConPatIn con (PrefixCon (map VarPat vars))
1141 mkNullaryConPat con = ConPatIn con (PrefixCon [])
1142 \end{code}
1143
1144 ToDo: Better SrcLocs.
1145
1146 \begin{code}
1147 compare_gen_Case ::
1148           RdrName
1149           -> RdrNameHsExpr -> RdrNameHsExpr -> RdrNameHsExpr
1150           -> RdrNameHsExpr -> RdrNameHsExpr
1151           -> RdrNameHsExpr
1152 careful_compare_Case :: -- checks for primitive types...
1153           Type
1154           -> RdrNameHsExpr -> RdrNameHsExpr -> RdrNameHsExpr
1155           -> RdrNameHsExpr -> RdrNameHsExpr
1156           -> RdrNameHsExpr
1157
1158 cmp_eq_Expr a b = HsApp (HsApp (HsVar cmp_eq_RDR) a) b
1159         -- Was: compare_gen_Case cmp_eq_RDR
1160
1161 compare_gen_Case fun lt eq gt a b
1162   = HsCase (HsPar (HsApp (HsApp (HsVar fun) a) b)) {-of-}
1163       [mkSimpleMatch [mkNullaryConPat ltTag_RDR] lt placeHolderType generatedSrcLoc,
1164        mkSimpleMatch [mkNullaryConPat eqTag_RDR] eq placeHolderType generatedSrcLoc,
1165        mkSimpleMatch [mkNullaryConPat gtTag_RDR] gt placeHolderType generatedSrcLoc]
1166       generatedSrcLoc
1167
1168 careful_compare_Case ty lt eq gt a b
1169   | not (isUnLiftedType ty) =
1170        compare_gen_Case compare_RDR lt eq gt a b
1171   | otherwise               =
1172          -- we have to do something special for primitive things...
1173        HsIf (genOpApp a relevant_eq_op b)
1174             eq
1175             (HsIf (genOpApp a relevant_lt_op b) lt gt generatedSrcLoc)
1176             generatedSrcLoc
1177   where
1178     relevant_eq_op = assoc_ty_id eq_op_tbl ty
1179     relevant_lt_op = assoc_ty_id lt_op_tbl ty
1180
1181 assoc_ty_id tyids ty 
1182   = if null res then panic "assoc_ty"
1183     else head res
1184   where
1185     res = [id | (ty',id) <- tyids, ty `tcEqType` ty']
1186
1187 eq_op_tbl =
1188     [(charPrimTy,       eqChar_RDR)
1189     ,(intPrimTy,        eqInt_RDR)
1190     ,(wordPrimTy,       eqWord_RDR)
1191     ,(addrPrimTy,       eqAddr_RDR)
1192     ,(floatPrimTy,      eqFloat_RDR)
1193     ,(doublePrimTy,     eqDouble_RDR)
1194     ]
1195
1196 lt_op_tbl =
1197     [(charPrimTy,       ltChar_RDR)
1198     ,(intPrimTy,        ltInt_RDR)
1199     ,(wordPrimTy,       ltWord_RDR)
1200     ,(addrPrimTy,       ltAddr_RDR)
1201     ,(floatPrimTy,      ltFloat_RDR)
1202     ,(doublePrimTy,     ltDouble_RDR)
1203     ]
1204
1205 -----------------------------------------------------------------------
1206
1207 and_Expr, append_Expr :: RdrNameHsExpr -> RdrNameHsExpr -> RdrNameHsExpr
1208
1209 and_Expr    a b = genOpApp a and_RDR    b
1210 append_Expr a b = genOpApp a append_RDR b
1211
1212 -----------------------------------------------------------------------
1213
1214 eq_Expr :: Type -> RdrNameHsExpr -> RdrNameHsExpr -> RdrNameHsExpr
1215 eq_Expr ty a b = genOpApp a eq_op b
1216  where
1217    eq_op
1218     | not (isUnLiftedType ty) = eq_RDR
1219     | otherwise               =
1220          -- we have to do something special for primitive things...
1221         assoc_ty_id eq_op_tbl ty
1222
1223 \end{code}
1224
1225 \begin{code}
1226 untag_Expr :: TyCon -> [(RdrName, RdrName)] -> RdrNameHsExpr -> RdrNameHsExpr
1227 untag_Expr tycon [] expr = expr
1228 untag_Expr tycon ((untag_this, put_tag_here) : more) expr
1229   = HsCase (HsPar (HsApp (con2tag_Expr tycon) (HsVar untag_this))) {-of-}
1230       [mkSimpleMatch [VarPat put_tag_here] (untag_Expr tycon more expr) placeHolderType generatedSrcLoc]
1231       generatedSrcLoc
1232
1233 cmp_tags_Expr :: RdrName                -- Comparison op
1234              -> RdrName -> RdrName      -- Things to compare
1235              -> RdrNameHsExpr           -- What to return if true
1236              -> RdrNameHsExpr           -- What to return if false
1237              -> RdrNameHsExpr
1238
1239 cmp_tags_Expr op a b true_case false_case
1240   = HsIf (genOpApp (HsVar a) op (HsVar b)) true_case false_case generatedSrcLoc
1241
1242 enum_from_to_Expr
1243         :: RdrNameHsExpr -> RdrNameHsExpr
1244         -> RdrNameHsExpr
1245 enum_from_then_to_Expr
1246         :: RdrNameHsExpr -> RdrNameHsExpr -> RdrNameHsExpr
1247         -> RdrNameHsExpr
1248
1249 enum_from_to_Expr      f   t2 = HsApp (HsApp (HsVar enumFromTo_RDR) f) t2
1250 enum_from_then_to_Expr f t t2 = HsApp (HsApp (HsApp (HsVar enumFromThenTo_RDR) f) t) t2
1251
1252 showParen_Expr
1253         :: RdrNameHsExpr -> RdrNameHsExpr
1254         -> RdrNameHsExpr
1255
1256 showParen_Expr e1 e2 = HsApp (HsApp (HsVar showParen_RDR) e1) e2
1257
1258 nested_compose_Expr :: [RdrNameHsExpr] -> RdrNameHsExpr
1259
1260 nested_compose_Expr [e] = parenify e
1261 nested_compose_Expr (e:es)
1262   = HsApp (HsApp (HsVar compose_RDR) (parenify e)) (nested_compose_Expr es)
1263
1264 -- impossible_Expr is used in case RHSs that should never happen.
1265 -- We generate these to keep the desugarer from complaining that they *might* happen!
1266 impossible_Expr = HsApp (HsVar error_RDR) (HsLit (HsString (mkFastString "Urk! in TcGenDeriv")))
1267
1268 -- illegal_Expr is used when signalling error conditions in the RHS of a derived
1269 -- method. It is currently only used by Enum.{succ,pred}
1270 illegal_Expr meth tp msg = 
1271    HsApp (HsVar error_RDR) (HsLit (HsString (mkFastString (meth ++ '{':tp ++ "}: " ++ msg))))
1272
1273 -- illegal_toEnum_tag is an extended version of illegal_Expr, which also allows you
1274 -- to include the value of a_RDR in the error string.
1275 illegal_toEnum_tag tp maxtag =
1276    HsApp (HsVar error_RDR) 
1277          (HsApp (HsApp (HsVar append_RDR)
1278                        (HsLit (HsString (mkFastString ("toEnum{" ++ tp ++ "}: tag (")))))
1279                        (HsApp (HsApp (HsApp 
1280                            (HsVar showsPrec_RDR)
1281                            (mkHsIntLit 0))
1282                            (HsVar a_RDR))
1283                            (HsApp (HsApp 
1284                                (HsVar append_RDR)
1285                                (HsLit (HsString (mkFastString ") is outside of enumeration's range (0,"))))
1286                                (HsApp (HsApp (HsApp 
1287                                         (HsVar showsPrec_RDR)
1288                                         (mkHsIntLit 0))
1289                                         (HsVar maxtag))
1290                                         (HsLit (HsString (mkFastString ")")))))))
1291
1292 parenify e@(HsVar _) = e
1293 parenify e           = HsPar e
1294
1295 -- genOpApp wraps brackets round the operator application, so that the
1296 -- renamer won't subsequently try to re-associate it. 
1297 -- For some reason the renamer doesn't reassociate it right, and I can't
1298 -- be bothered to find out why just now.
1299
1300 genOpApp e1 op e2 = mkHsOpApp e1 op e2
1301 \end{code}
1302
1303 \begin{code}
1304 varUnqual n     = mkUnqual OccName.varName n
1305
1306 zz_a_RDR        = varUnqual FSLIT("_a")
1307 a_RDR           = varUnqual FSLIT("a")
1308 b_RDR           = varUnqual FSLIT("b")
1309 c_RDR           = varUnqual FSLIT("c")
1310 d_RDR           = varUnqual FSLIT("d")
1311 ah_RDR          = varUnqual FSLIT("a#")
1312 bh_RDR          = varUnqual FSLIT("b#")
1313 ch_RDR          = varUnqual FSLIT("c#")
1314 dh_RDR          = varUnqual FSLIT("d#")
1315 cmp_eq_RDR      = varUnqual FSLIT("cmp_eq")
1316 rangeSize_RDR   = varUnqual FSLIT("rangeSize")
1317
1318 as_RDRs         = [ varUnqual (mkFastString ("a"++show i)) | i <- [(1::Int) .. ] ]
1319 bs_RDRs         = [ varUnqual (mkFastString ("b"++show i)) | i <- [(1::Int) .. ] ]
1320 cs_RDRs         = [ varUnqual (mkFastString ("c"++show i)) | i <- [(1::Int) .. ] ]
1321
1322 zz_a_Expr       = HsVar zz_a_RDR
1323 a_Expr          = HsVar a_RDR
1324 b_Expr          = HsVar b_RDR
1325 c_Expr          = HsVar c_RDR
1326 d_Expr          = HsVar d_RDR
1327 ltTag_Expr      = HsVar ltTag_RDR
1328 eqTag_Expr      = HsVar eqTag_RDR
1329 gtTag_Expr      = HsVar gtTag_RDR
1330 false_Expr      = HsVar false_RDR
1331 true_Expr       = HsVar true_RDR
1332
1333 getTag_Expr     = HsVar getTag_RDR
1334 tagToEnum_Expr  = HsVar tagToEnum_RDR
1335 con2tag_Expr tycon = HsVar (con2tag_RDR tycon)
1336
1337 wildPat         = WildPat placeHolderType
1338 zz_a_Pat        = VarPat zz_a_RDR
1339 a_Pat           = VarPat a_RDR
1340 b_Pat           = VarPat b_RDR
1341 c_Pat           = VarPat c_RDR
1342 d_Pat           = VarPat d_RDR
1343
1344 con2tag_RDR, tag2con_RDR, maxtag_RDR :: TyCon -> RdrName
1345
1346 con2tag_RDR tycon = varUnqual (mkFastString ("con2tag_" ++ occNameString (getOccName tycon) ++ "#"))
1347 tag2con_RDR tycon = varUnqual (mkFastString ("tag2con_" ++ occNameString (getOccName tycon) ++ "#"))
1348 maxtag_RDR tycon  = varUnqual (mkFastString ("maxtag_"  ++ occNameString (getOccName tycon) ++ "#"))
1349 \end{code}
1350
1351 RdrNames for PrimOps.  Can't be done in PrelNames, because PrimOp imports
1352 PrelNames, so PrelNames can't import PrimOp.
1353
1354 \begin{code}
1355 minusInt_RDR  = nameRdrName minusIntName
1356 eqInt_RDR     = nameRdrName eqIntName
1357 ltInt_RDR     = nameRdrName ltIntName
1358 geInt_RDR     = nameRdrName geIntName
1359 leInt_RDR     = nameRdrName leIntName
1360 eqChar_RDR    = nameRdrName eqCharName
1361 eqWord_RDR    = nameRdrName eqWordName
1362 eqAddr_RDR    = nameRdrName eqAddrName
1363 eqFloat_RDR   = nameRdrName eqFloatName
1364 eqDouble_RDR  = nameRdrName eqDoubleName
1365 ltChar_RDR    = nameRdrName ltCharName
1366 ltWord_RDR    = nameRdrName ltWordName
1367 ltAddr_RDR    = nameRdrName ltAddrName
1368 ltFloat_RDR   = nameRdrName ltFloatName
1369 ltDouble_RDR  = nameRdrName ltDoubleName
1370 tagToEnum_RDR = nameRdrName tagToEnumName                   
1371 \end{code}