[project @ 1998-01-08 18:03:08 by simonm]
[ghc-hetmet.git] / ghc / compiler / typecheck / TcGenDeriv.lhs
1 %
2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1996
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_Eval_binds,
16         gen_Eq_binds,
17         gen_Ix_binds,
18         gen_Ord_binds,
19         gen_Read_binds,
20         gen_Show_binds,
21         gen_tag_n_con_monobind,
22
23         con2tag_RDR, tag2con_RDR, maxtag_RDR,
24
25         TagThingWanted(..)
26     ) where
27
28 #include "HsVersions.h"
29
30 import HsSyn            ( InPat(..), HsExpr(..), MonoBinds(..), GRHS(..), 
31                           Match(..), GRHSsAndBinds(..), Stmt(..), HsLit(..),
32                           HsBinds(..), DoOrListComp(..),
33                           unguardedRHS
34                         )
35 import RdrHsSyn         ( RdrName(..), varQual, varUnqual, mkOpApp,
36                           RdrNameMonoBinds, RdrNameHsExpr, RdrNamePat
37                         )
38 import BasicTypes       ( IfaceFlavour(..), RecFlag(..) )
39 import FieldLabel       ( fieldLabelName )
40 import Id               ( GenId, isNullaryDataCon, dataConTag,
41                           dataConRawArgTys, fIRST_TAG,
42                           isDataCon, DataCon, ConTag,
43                           dataConFieldLabels, Id )
44 import Maybes           ( maybeToBool )
45 import Name             ( getOccString, getOccName, getSrcLoc, occNameString, 
46                           modAndOcc, OccName, Name )
47
48 import PrimOp           ( PrimOp(..) )
49 import PrelInfo         -- Lots of RdrNames
50 import SrcLoc           ( mkGeneratedSrcLoc, SrcLoc )
51 import TyCon            ( TyCon, isNewTyCon, tyConDataCons, isEnumerationTyCon, maybeTyConSingleCon )
52 import Type             ( isUnpointedType, isUnboxedType, Type )
53 import TysPrim          ( charPrimTy, intPrimTy, wordPrimTy, addrPrimTy,
54                           floatPrimTy, doublePrimTy
55                         )
56 import Util             ( mapAccumL, zipEqual, zipWithEqual,
57                           zipWith3Equal, nOfThem, panic, assertPanic )
58
59 import List             ( partition, intersperse )
60 \end{code}
61
62 %************************************************************************
63 %*                                                                      *
64 \subsection{Generating code, by derivable class}
65 %*                                                                      *
66 %************************************************************************
67
68 %************************************************************************
69 %*                                                                      *
70 \subsubsection{Generating @Eq@ instance declarations}
71 %*                                                                      *
72 %************************************************************************
73
74 Here are the heuristics for the code we generate for @Eq@:
75 \begin{itemize}
76 \item
77   Let's assume we have a data type with some (possibly zero) nullary
78   data constructors and some ordinary, non-nullary ones (the rest,
79   also possibly zero of them).  Here's an example, with both \tr{N}ullary
80   and \tr{O}rdinary data cons.
81 \begin{verbatim}
82 data Foo ... = N1 | N2 ... | Nn | O1 a b | O2 Int | O3 Double b b | ...
83 \end{verbatim}
84
85 \item
86   For the ordinary constructors (if any), we emit clauses to do The
87   Usual Thing, e.g.,:
88
89 \begin{verbatim}
90 (==) (O1 a1 b1)    (O1 a2 b2)    = a1 == a2 && b1 == b2
91 (==) (O2 a1)       (O2 a2)       = a1 == a2
92 (==) (O3 a1 b1 c1) (O3 a2 b2 c2) = a1 == a2 && b1 == b2 && c1 == c2
93 \end{verbatim}
94
95   Note: if we're comparing unboxed things, e.g., if \tr{a1} and
96   \tr{a2} are \tr{Float#}s, then we have to generate
97 \begin{verbatim}
98 case (a1 `eqFloat#` a2) of
99   r -> r
100 \end{verbatim}
101   for that particular test.
102
103 \item
104   If there are any nullary constructors, we emit a catch-all clause of
105   the form:
106
107 \begin{verbatim}
108 (==) a b  = case (con2tag_Foo a) of { a# ->
109             case (con2tag_Foo b) of { b# ->
110             case (a# ==# b#)     of {
111               r -> r
112             }}}
113 \end{verbatim}
114
115   If there aren't any nullary constructors, we emit a simpler
116   catch-all:
117 \begin{verbatim}
118 (==) a b  = False
119 \end{verbatim}
120
121 \item
122   For the @(/=)@ method, we normally just use the default method.
123
124   If the type is an enumeration type, we could/may/should? generate
125   special code that calls @con2tag_Foo@, much like for @(==)@ shown
126   above.
127
128 \item
129   We thought about doing this: If we're also deriving @Ord@ for this
130   tycon, we generate:
131 \begin{verbatim}
132 instance ... Eq (Foo ...) where
133   (==) a b  = case (compare a b) of { _LT -> False; _EQ -> True ; _GT -> False}
134   (/=) a b  = case (compare a b) of { _LT -> True ; _EQ -> False; _GT -> True }
135 \begin{verbatim}
136   However, that requires that \tr{Ord <whatever>} was put in the context
137   for the instance decl, which it probably wasn't, so the decls
138   produced don't get through the typechecker.
139 \end{itemize}
140
141 \begin{code}
142 gen_Eq_binds :: TyCon -> RdrNameMonoBinds
143
144 gen_Eq_binds tycon
145   = let
146         tycon_loc = getSrcLoc tycon
147         (nullary_cons, nonnullary_cons)
148            | isNewTyCon tycon = ([], tyConDataCons tycon)
149            | otherwise        = partition isNullaryDataCon (tyConDataCons tycon)
150
151         rest
152           = if (null nullary_cons) then
153                 case maybeTyConSingleCon tycon of
154                   Just _ -> []
155                   Nothing -> -- if cons don't match, then False
156                      [([a_Pat, b_Pat], false_Expr)]
157             else -- calc. and compare the tags
158                  [([a_Pat, b_Pat],
159                     untag_Expr tycon [(a_RDR,ah_RDR), (b_RDR,bh_RDR)]
160                       (cmp_tags_Expr eqH_Int_RDR ah_RDR bh_RDR true_Expr false_Expr))]
161     in
162     mk_FunMonoBind tycon_loc eq_RDR ((map pats_etc nonnullary_cons) ++ rest)
163             `AndMonoBinds`
164     mk_easy_FunMonoBind tycon_loc ne_RDR [a_Pat, b_Pat] [] (
165         HsApp (HsVar not_RDR) (HsPar (mk_easy_App eq_RDR [a_RDR, b_RDR])))
166   where
167     ------------------------------------------------------------------
168     pats_etc data_con
169       = let
170             con1_pat = ConPatIn data_con_RDR (map VarPatIn as_needed)
171             con2_pat = ConPatIn data_con_RDR (map VarPatIn bs_needed)
172
173             data_con_RDR = qual_orig_name data_con
174             con_arity   = length tys_needed
175             as_needed   = take con_arity as_RDRs
176             bs_needed   = take con_arity bs_RDRs
177             tys_needed  = dataConRawArgTys data_con
178         in
179         ([con1_pat, con2_pat], nested_eq_expr tys_needed as_needed bs_needed)
180       where
181         nested_eq_expr []  [] [] = true_Expr
182         nested_eq_expr tys as bs
183           = foldl1 and_Expr (zipWith3Equal "nested_eq" nested_eq tys as bs)
184           where
185             nested_eq ty a b = HsPar (eq_Expr ty (HsVar a) (HsVar b))
186 \end{code}
187
188 %************************************************************************
189 %*                                                                      *
190 \subsubsection{Generating @Ord@ instance declarations}
191 %*                                                                      *
192 %************************************************************************
193
194 For a derived @Ord@, we concentrate our attentions on @compare@
195 \begin{verbatim}
196 compare :: a -> a -> Ordering
197 data Ordering = LT | EQ | GT deriving ()
198 \end{verbatim}
199
200 We will use the same example data type as above:
201 \begin{verbatim}
202 data Foo ... = N1 | N2 ... | Nn | O1 a b | O2 Int | O3 Double b b | ...
203 \end{verbatim}
204
205 \begin{itemize}
206 \item
207   We do all the other @Ord@ methods with calls to @compare@:
208 \begin{verbatim}
209 instance ... (Ord <wurble> <wurble>) where
210     a <  b  = case (compare a b) of { LT -> True;  EQ -> False; GT -> False }
211     a <= b  = case (compare a b) of { LT -> True;  EQ -> True;  GT -> False }
212     a >= b  = case (compare a b) of { LT -> False; EQ -> True;  GT -> True  }
213     a >  b  = case (compare a b) of { LT -> False; EQ -> False; GT -> True  }
214
215     max a b = case (compare a b) of { LT -> b; EQ -> a;  GT -> a }
216     min a b = case (compare a b) of { LT -> a; EQ -> b;  GT -> b }
217
218     -- compare to come...
219 \end{verbatim}
220
221 \item
222   @compare@ always has two parts.  First, we use the compared
223   data-constructors' tags to deal with the case of different
224   constructors:
225 \begin{verbatim}
226 compare a b = case (con2tag_Foo a) of { a# ->
227               case (con2tag_Foo b) of { b# ->
228               case (a# ==# b#)     of {
229                True  -> cmp_eq a b
230                False -> case (a# <# b#) of
231                          True  -> _LT
232                          False -> _GT
233               }}}
234   where
235     cmp_eq = ... to come ...
236 \end{verbatim}
237
238 \item
239   We are only left with the ``help'' function @cmp_eq@, to deal with
240   comparing data constructors with the same tag.
241
242   For the ordinary constructors (if any), we emit the sorta-obvious
243   compare-style stuff; for our example:
244 \begin{verbatim}
245 cmp_eq (O1 a1 b1) (O1 a2 b2)
246   = case (compare a1 a2) of { LT -> LT; EQ -> compare b1 b2; GT -> GT }
247
248 cmp_eq (O2 a1) (O2 a2)
249   = compare a1 a2
250
251 cmp_eq (O3 a1 b1 c1) (O3 a2 b2 c2)
252   = case (compare a1 a2) of {
253       LT -> LT;
254       GT -> GT;
255       EQ -> case compare b1 b2 of {
256               LT -> LT;
257               GT -> GT;
258               EQ -> compare c1 c2
259             }
260     }
261 \end{verbatim}
262
263   Again, we must be careful about unboxed comparisons.  For example,
264   if \tr{a1} and \tr{a2} were \tr{Int#}s in the 2nd example above, we'd need to
265   generate:
266
267 \begin{verbatim}
268 cmp_eq lt eq gt (O2 a1) (O2 a2)
269   = compareInt# a1 a2
270   -- or maybe the unfolded equivalent
271 \end{verbatim}
272
273 \item
274   For the remaining nullary constructors, we already know that the
275   tags are equal so:
276 \begin{verbatim}
277 cmp_eq _ _ = EQ
278 \end{verbatim}
279 \end{itemize}
280
281 If there is only one constructor in the Data Type we don't need the WildCard Patern. 
282 JJQC-30-Nov-1997
283
284 \begin{code}
285 gen_Ord_binds :: TyCon -> RdrNameMonoBinds
286
287 gen_Ord_binds tycon
288   = defaulted `AndMonoBinds` compare
289   where
290     tycon_loc = getSrcLoc tycon
291     --------------------------------------------------------------------
292     compare = mk_easy_FunMonoBind tycon_loc compare_RDR
293                 [a_Pat, b_Pat]
294                 [cmp_eq]
295             (if maybeToBool (maybeTyConSingleCon tycon) then
296                 cmp_eq_Expr ltTag_Expr eqTag_Expr gtTag_Expr a_Expr b_Expr
297              else
298                 untag_Expr tycon [(a_RDR, ah_RDR), (b_RDR, bh_RDR)]
299                   (cmp_tags_Expr eqH_Int_RDR ah_RDR bh_RDR
300                         -- True case; they are equal
301                         -- If an enumeration type we are done; else
302                         -- recursively compare their components
303                     (if isEnumerationTyCon tycon then
304                         eqTag_Expr
305                      else
306                         cmp_eq_Expr ltTag_Expr eqTag_Expr gtTag_Expr a_Expr b_Expr
307                     )
308                         -- False case; they aren't equal
309                         -- So we need to do a less-than comparison on the tags
310                     (cmp_tags_Expr ltH_Int_RDR ah_RDR bh_RDR ltTag_Expr gtTag_Expr)))
311
312     (nullary_cons, nonnullary_cons)
313        | isNewTyCon tycon = ([], tyConDataCons tycon)
314        | otherwise        = partition isNullaryDataCon (tyConDataCons tycon)
315
316     cmp_eq
317       = mk_FunMonoBind tycon_loc cmp_eq_RDR (map pats_etc nonnullary_cons ++
318           if ((length nonnullary_cons + length nullary_cons) == 1)
319             then []
320             else [([WildPatIn, WildPatIn], 
321           default_rhs)])
322       where
323         pats_etc data_con
324           = ([con1_pat, con2_pat],
325              nested_compare_expr tys_needed as_needed bs_needed)
326           where
327             con1_pat = ConPatIn data_con_RDR (map VarPatIn as_needed)
328             con2_pat = ConPatIn data_con_RDR (map VarPatIn bs_needed)
329
330             data_con_RDR = qual_orig_name data_con
331             con_arity   = length tys_needed
332             as_needed   = take con_arity as_RDRs
333             bs_needed   = take con_arity bs_RDRs
334             tys_needed  = dataConRawArgTys data_con
335
336             nested_compare_expr [ty] [a] [b]
337               = careful_compare_Case ty ltTag_Expr eqTag_Expr gtTag_Expr (HsVar a) (HsVar b)
338
339             nested_compare_expr (ty:tys) (a:as) (b:bs)
340               = let eq_expr = nested_compare_expr tys as bs
341                 in  careful_compare_Case ty ltTag_Expr eq_expr gtTag_Expr (HsVar a) (HsVar b)
342
343         default_rhs | null nullary_cons = impossible_Expr       -- Keep desugarer from complaining about
344                                                                 -- inexhaustive patterns
345                     | otherwise         = eqTag_Expr            -- Some nullary constructors;
346                                                                 -- Tags are equal, no args => return EQ
347     --------------------------------------------------------------------
348
349 defaulted = foldr1 AndMonoBinds [lt, le, ge, gt, max_, min_]
350
351 lt = mk_easy_FunMonoBind mkGeneratedSrcLoc lt_RDR [a_Pat, b_Pat] [] (
352             compare_Case true_Expr  false_Expr false_Expr a_Expr b_Expr)
353 le = mk_easy_FunMonoBind mkGeneratedSrcLoc le_RDR [a_Pat, b_Pat] [] (
354             compare_Case true_Expr  true_Expr  false_Expr a_Expr b_Expr)
355 ge = mk_easy_FunMonoBind mkGeneratedSrcLoc ge_RDR [a_Pat, b_Pat] [] (
356             compare_Case false_Expr true_Expr  true_Expr  a_Expr b_Expr)
357 gt = mk_easy_FunMonoBind mkGeneratedSrcLoc gt_RDR [a_Pat, b_Pat] [] (
358             compare_Case false_Expr false_Expr true_Expr  a_Expr b_Expr)
359
360 max_ = mk_easy_FunMonoBind mkGeneratedSrcLoc max_RDR [a_Pat, b_Pat] [] (
361             compare_Case b_Expr a_Expr a_Expr a_Expr b_Expr)
362 min_ = mk_easy_FunMonoBind mkGeneratedSrcLoc min_RDR [a_Pat, b_Pat] [] (
363             compare_Case a_Expr b_Expr b_Expr a_Expr b_Expr)
364 \end{code}
365
366 %************************************************************************
367 %*                                                                      *
368 \subsubsection{Generating @Enum@ instance declarations}
369 %*                                                                      *
370 %************************************************************************
371
372 @Enum@ can only be derived for enumeration types.  For a type
373 \begin{verbatim}
374 data Foo ... = N1 | N2 | ... | Nn
375 \end{verbatim}
376
377 we use both @con2tag_Foo@ and @tag2con_Foo@ functions, as well as a
378 @maxtag_Foo@ variable (all generated by @gen_tag_n_con_binds@).
379
380 \begin{verbatim}
381 instance ... Enum (Foo ...) where
382     toEnum i = tag2con_Foo i
383
384     enumFrom a = map tag2con_Foo [con2tag_Foo a .. maxtag_Foo]
385
386     -- or, really...
387     enumFrom a
388       = case con2tag_Foo a of
389           a# -> map tag2con_Foo (enumFromTo (I# a#) maxtag_Foo)
390
391    enumFromThen a b
392      = map tag2con_Foo [con2tag_Foo a, con2tag_Foo b .. maxtag_Foo]
393
394     -- or, really...
395     enumFromThen a b
396       = case con2tag_Foo a of { a# ->
397         case con2tag_Foo b of { b# ->
398         map tag2con_Foo (enumFromThenTo (I# a#) (I# b#) maxtag_Foo)
399         }}
400 \end{verbatim}
401
402 For @enumFromTo@ and @enumFromThenTo@, we use the default methods.
403
404 \begin{code}
405 gen_Enum_binds :: TyCon -> RdrNameMonoBinds
406
407 gen_Enum_binds tycon
408   = to_enum             `AndMonoBinds`
409     enum_from           `AndMonoBinds`
410     enum_from_then      `AndMonoBinds`
411     from_enum
412   where
413     tycon_loc = getSrcLoc tycon
414
415     to_enum
416       = mk_easy_FunMonoBind tycon_loc toEnum_RDR [a_Pat] [] $
417         mk_easy_App (tag2con_RDR tycon) [a_RDR]
418
419     enum_from
420       = mk_easy_FunMonoBind tycon_loc enumFrom_RDR [a_Pat] [] $
421           untag_Expr tycon [(a_RDR, ah_RDR)] $
422           HsApp (mk_easy_App map_RDR [tag2con_RDR tycon]) $
423             HsPar (enum_from_to_Expr
424                     (mk_easy_App mkInt_RDR [ah_RDR])
425                     (HsVar (maxtag_RDR tycon)))
426
427     enum_from_then
428       = mk_easy_FunMonoBind tycon_loc enumFromThen_RDR [a_Pat, b_Pat] [] $
429           untag_Expr tycon [(a_RDR, ah_RDR), (b_RDR, bh_RDR)] $
430           HsApp (mk_easy_App map_RDR [tag2con_RDR tycon]) $
431             HsPar (enum_from_then_to_Expr
432                     (mk_easy_App mkInt_RDR [ah_RDR])
433                     (mk_easy_App mkInt_RDR [bh_RDR])
434                     (HsVar (maxtag_RDR tycon)))
435
436     from_enum
437       = mk_easy_FunMonoBind tycon_loc fromEnum_RDR [a_Pat] [] $
438           untag_Expr tycon [(a_RDR, ah_RDR)] $
439           (mk_easy_App mkInt_RDR [ah_RDR])
440 \end{code}
441
442 %************************************************************************
443 %*                                                                      *
444 \subsubsection{Generating @Eval@ instance declarations}
445 %*                                                                      *
446 %************************************************************************
447
448 \begin{code}
449 gen_Eval_binds tycon = EmptyMonoBinds
450 \end{code}
451
452 %************************************************************************
453 %*                                                                      *
454 \subsubsection{Generating @Bounded@ instance declarations}
455 %*                                                                      *
456 %************************************************************************
457
458 \begin{code}
459 gen_Bounded_binds tycon
460   = if isEnumerationTyCon tycon then
461         min_bound_enum `AndMonoBinds` max_bound_enum
462     else
463         ASSERT(length data_cons == 1)
464         min_bound_1con `AndMonoBinds` max_bound_1con
465   where
466     data_cons = tyConDataCons tycon
467     tycon_loc = getSrcLoc tycon
468
469     ----- enum-flavored: ---------------------------
470     min_bound_enum = mk_easy_FunMonoBind tycon_loc minBound_RDR [] [] (HsVar data_con_1_RDR)
471     max_bound_enum = mk_easy_FunMonoBind tycon_loc maxBound_RDR [] [] (HsVar data_con_N_RDR)
472
473     data_con_1    = head data_cons
474     data_con_N    = last data_cons
475     data_con_1_RDR = qual_orig_name data_con_1
476     data_con_N_RDR = qual_orig_name data_con_N
477
478     ----- single-constructor-flavored: -------------
479     arity          = argFieldCount data_con_1
480
481     min_bound_1con = mk_easy_FunMonoBind tycon_loc minBound_RDR [] [] $
482                      mk_easy_App data_con_1_RDR (nOfThem arity minBound_RDR)
483     max_bound_1con = mk_easy_FunMonoBind tycon_loc maxBound_RDR [] [] $
484                      mk_easy_App data_con_1_RDR (nOfThem arity maxBound_RDR)
485 \end{code}
486
487 %************************************************************************
488 %*                                                                      *
489 \subsubsection{Generating @Ix@ instance declarations}
490 %*                                                                      *
491 %************************************************************************
492
493 Deriving @Ix@ is only possible for enumeration types and
494 single-constructor types.  We deal with them in turn.
495
496 For an enumeration type, e.g.,
497 \begin{verbatim}
498     data Foo ... = N1 | N2 | ... | Nn
499 \end{verbatim}
500 things go not too differently from @Enum@:
501 \begin{verbatim}
502 instance ... Ix (Foo ...) where
503     range (a, b)
504       = map tag2con_Foo [con2tag_Foo a .. con2tag_Foo b]
505
506     -- or, really...
507     range (a, b)
508       = case (con2tag_Foo a) of { a# ->
509         case (con2tag_Foo b) of { b# ->
510         map tag2con_Foo (enumFromTo (I# a#) (I# b#))
511         }}
512
513     index c@(a, b) d
514       = if inRange c d
515         then case (con2tag_Foo d -# con2tag_Foo a) of
516                r# -> I# r#
517         else error "Ix.Foo.index: out of range"
518
519     inRange (a, b) c
520       = let
521             p_tag = con2tag_Foo c
522         in
523         p_tag >= con2tag_Foo a && p_tag <= con2tag_Foo b
524
525     -- or, really...
526     inRange (a, b) c
527       = case (con2tag_Foo a)   of { a_tag ->
528         case (con2tag_Foo b)   of { b_tag ->
529         case (con2tag_Foo c)   of { c_tag ->
530         if (c_tag >=# a_tag) then
531           c_tag <=# b_tag
532         else
533           False
534         }}}
535 \end{verbatim}
536 (modulo suitable case-ification to handle the unboxed tags)
537
538 For a single-constructor type (NB: this includes all tuples), e.g.,
539 \begin{verbatim}
540     data Foo ... = MkFoo a b Int Double c c
541 \end{verbatim}
542 we follow the scheme given in Figure~19 of the Haskell~1.2 report
543 (p.~147).
544
545 \begin{code}
546 gen_Ix_binds :: TyCon -> RdrNameMonoBinds
547
548 gen_Ix_binds tycon
549   = if isEnumerationTyCon tycon
550     then enum_ixes
551     else single_con_ixes
552   where
553     tycon_str = getOccString tycon
554     tycon_loc = getSrcLoc tycon
555
556     --------------------------------------------------------------
557     enum_ixes = enum_range `AndMonoBinds`
558                 enum_index `AndMonoBinds` enum_inRange
559
560     enum_range
561       = mk_easy_FunMonoBind tycon_loc range_RDR [TuplePatIn [a_Pat, b_Pat]] [] $
562           untag_Expr tycon [(a_RDR, ah_RDR)] $
563           untag_Expr tycon [(b_RDR, bh_RDR)] $
564           HsApp (mk_easy_App map_RDR [tag2con_RDR tycon]) $
565               HsPar (enum_from_to_Expr
566                         (mk_easy_App mkInt_RDR [ah_RDR])
567                         (mk_easy_App mkInt_RDR [bh_RDR]))
568
569     enum_index
570       = mk_easy_FunMonoBind tycon_loc index_RDR [AsPatIn c_RDR (TuplePatIn [a_Pat, b_Pat]), d_Pat] [] (
571         HsIf (HsPar (mk_easy_App inRange_RDR [c_RDR, d_RDR])) (
572            untag_Expr tycon [(a_RDR, ah_RDR)] (
573            untag_Expr tycon [(d_RDR, dh_RDR)] (
574            let
575                 grhs = unguardedRHS (mk_easy_App mkInt_RDR [c_RDR]) tycon_loc
576            in
577            HsCase
578              (genOpApp (HsVar dh_RDR) minusH_RDR (HsVar ah_RDR))
579              [PatMatch (VarPatIn c_RDR)
580                                 (GRHSMatch (GRHSsAndBindsIn grhs EmptyBinds))]
581              tycon_loc
582            ))
583         ) {-else-} (
584            HsApp (HsVar error_RDR) (HsLit (HsString (_PK_ ("Ix."++tycon_str++".index: out of range\n"))))
585         )
586         tycon_loc)
587
588     enum_inRange
589       = mk_easy_FunMonoBind tycon_loc inRange_RDR [TuplePatIn [a_Pat, b_Pat], c_Pat] [] (
590           untag_Expr tycon [(a_RDR, ah_RDR)] (
591           untag_Expr tycon [(b_RDR, bh_RDR)] (
592           untag_Expr tycon [(c_RDR, ch_RDR)] (
593           HsIf (genOpApp (HsVar ch_RDR) geH_RDR (HsVar ah_RDR)) (
594              (genOpApp (HsVar ch_RDR) leH_RDR (HsVar bh_RDR))
595           ) {-else-} (
596              false_Expr
597           ) tycon_loc))))
598
599     --------------------------------------------------------------
600     single_con_ixes 
601       = single_con_range `AndMonoBinds`
602         single_con_index `AndMonoBinds`
603         single_con_inRange
604
605     data_con
606       = case maybeTyConSingleCon tycon of -- just checking...
607           Nothing -> panic "get_Ix_binds"
608           Just dc -> if (any isUnpointedType (dataConRawArgTys dc)) then
609                          error ("ERROR: Can't derive Ix for a single-constructor type with primitive argument types: "++tycon_str)
610                      else
611                          dc
612
613     con_arity    = argFieldCount data_con
614     data_con_RDR = qual_orig_name data_con
615
616     as_needed = take con_arity as_RDRs
617     bs_needed = take con_arity bs_RDRs
618     cs_needed = take con_arity cs_RDRs
619
620     con_pat  xs  = ConPatIn data_con_RDR (map VarPatIn xs)
621     con_expr     = mk_easy_App data_con_RDR cs_needed
622
623     --------------------------------------------------------------
624     single_con_range
625       = mk_easy_FunMonoBind tycon_loc range_RDR [TuplePatIn [con_pat as_needed, con_pat bs_needed]] [] $
626         HsDo ListComp stmts tycon_loc
627       where
628         stmts = zipWith3Equal "single_con_range" mk_qual as_needed bs_needed cs_needed
629                 ++
630                 [ReturnStmt con_expr]
631
632         mk_qual a b c = BindStmt (VarPatIn c)
633                                  (HsApp (HsVar range_RDR) (ExplicitTuple [HsVar a, HsVar b]))
634                                  tycon_loc
635
636     ----------------
637     single_con_index
638       = mk_easy_FunMonoBind tycon_loc index_RDR [TuplePatIn [con_pat as_needed, con_pat bs_needed], con_pat cs_needed] [range_size] (
639         foldl mk_index (HsLit (HsInt 0)) (zip3 as_needed bs_needed cs_needed))
640       where
641         mk_index multiply_by (l, u, i)
642           = genOpApp (
643                 (HsApp (HsApp (HsVar index_RDR) (ExplicitTuple [HsVar l, HsVar u])) (HsVar i))
644            ) plus_RDR (
645                 genOpApp (
646                     (HsApp (HsVar rangeSize_RDR) (ExplicitTuple [HsVar l, HsVar u]))
647                 ) times_RDR multiply_by
648            )
649
650         range_size
651           = mk_easy_FunMonoBind tycon_loc rangeSize_RDR [TuplePatIn [a_Pat, b_Pat]] [] (
652                 genOpApp (
653                     (HsApp (HsApp (HsVar index_RDR) (ExplicitTuple [a_Expr, b_Expr])) b_Expr)
654                 ) plus_RDR (HsLit (HsInt 1)))
655
656     ------------------
657     single_con_inRange
658       = mk_easy_FunMonoBind tycon_loc inRange_RDR 
659                            [TuplePatIn [con_pat as_needed, con_pat bs_needed], con_pat cs_needed]
660                            [] (
661           foldl1 and_Expr (zipWith3Equal "single_con_inRange" in_range as_needed bs_needed cs_needed))
662       where
663         in_range a b c = HsApp (HsApp (HsVar inRange_RDR) (ExplicitTuple [HsVar a, HsVar b])) (HsVar c)
664 \end{code}
665
666 %************************************************************************
667 %*                                                                      *
668 \subsubsection{Generating @Read@ instance declarations}
669 %*                                                                      *
670 %************************************************************************
671
672 Ignoring all the infix-ery mumbo jumbo (ToDo)
673
674 \begin{code}
675 gen_Read_binds :: TyCon -> RdrNameMonoBinds
676
677 gen_Read_binds tycon
678   = reads_prec `AndMonoBinds` read_list
679   where
680     tycon_loc = getSrcLoc tycon
681     -----------------------------------------------------------------------
682     read_list = mk_easy_FunMonoBind tycon_loc readList_RDR [] []
683                   (HsApp (HsVar readList___RDR) (HsPar (HsApp (HsVar readsPrec_RDR) (HsLit (HsInt 0)))))
684     -----------------------------------------------------------------------
685     reads_prec
686       = let
687             read_con_comprehensions
688               = map read_con (tyConDataCons tycon)
689         in
690         mk_easy_FunMonoBind tycon_loc readsPrec_RDR [a_Pat, b_Pat] [] (
691               foldr1 append_Expr read_con_comprehensions
692         )
693       where
694         read_con data_con   -- note: "b" is the string being "read"
695           = let
696                 data_con_RDR = qual_orig_name data_con
697                 data_con_str= occNameString (getOccName data_con)
698                 con_arity   = argFieldCount data_con
699                 con_expr    = mk_easy_App data_con_RDR as_needed
700                 nullary_con = con_arity == 0
701                 labels      = dataConFieldLabels data_con
702                 lab_fields  = length labels
703
704                 as_needed   = take con_arity as_RDRs
705                 bs_needed   
706                  | lab_fields == 0 = take con_arity bs_RDRs
707                  | otherwise       = take (4*lab_fields + 1) bs_RDRs
708                                        -- (label, '=' and field)*n, (n-1)*',' + '{' + '}'
709                 con_qual
710                   = BindStmt
711                           (TuplePatIn [LitPatIn (HsString data_con_str), d_Pat])
712                           (HsApp (HsVar lex_RDR) c_Expr)
713                           tycon_loc
714
715                 str_qual str res draw_from
716                   = BindStmt
717                        (TuplePatIn [LitPatIn (HsString str), VarPatIn res])
718                        (HsApp (HsVar lex_RDR) draw_from)
719                        tycon_loc
720   
721                 read_label f
722                   = let nm = occNameString (getOccName (fieldLabelName f))
723                     in 
724                         [str_qual nm, str_qual SLIT("=")] 
725                             -- There might be spaces between the label and '='
726
727                 field_quals
728                   | lab_fields == 0 =
729                      snd (mapAccumL mk_qual 
730                                     d_Expr 
731                                     (zipWithEqual "as_needed" 
732                                                   (\ con_field draw_from -> (mk_read_qual con_field,
733                                                                              draw_from))
734                                                   as_needed bs_needed))
735                   | otherwise =
736                      snd $
737                      mapAccumL mk_qual d_Expr
738                         (zipEqual "bs_needed"        
739                            ((str_qual (SLIT("{")):
740                              concat (
741                              intersperse ([str_qual (_CONS_ ',' _NIL_)]) $
742                              zipWithEqual 
743                                 "field_quals"
744                                 (\ as b -> as ++ [b])
745                                     -- The labels
746                                 (map read_label labels)
747                                     -- The fields
748                                 (map mk_read_qual as_needed))) ++ [str_qual (SLIT("}"))])
749                             bs_needed)
750
751                 mk_qual draw_from (f, str_left)
752                   = (HsVar str_left,    -- what to draw from down the line...
753                      f str_left draw_from)
754
755                 mk_read_qual con_field res draw_from =
756                   BindStmt
757                    (TuplePatIn [VarPatIn con_field, VarPatIn res])
758                    (HsApp (HsApp (HsVar readsPrec_RDR) (HsLit (HsInt 10))) draw_from)
759                    tycon_loc
760
761                 result_expr = ExplicitTuple [con_expr, if null bs_needed 
762                                                        then d_Expr 
763                                                        else HsVar (last bs_needed)]
764
765                 stmts = con_qual:field_quals ++ [ReturnStmt result_expr]
766                 
767                 read_paren_arg
768                   = if nullary_con then -- must be False (parens are surely optional)
769                        false_Expr
770                     else -- parens depend on precedence...
771                        HsPar (genOpApp a_Expr gt_RDR (HsLit (HsInt 9)))
772             in
773             HsApp (
774               readParen_Expr read_paren_arg $ HsPar $
775                  HsLam (mk_easy_Match tycon_loc [c_Pat] [] $
776                         HsDo ListComp stmts tycon_loc)
777               ) (HsVar b_RDR)
778
779 \end{code}
780
781 %************************************************************************
782 %*                                                                      *
783 \subsubsection{Generating @Show@ instance declarations}
784 %*                                                                      *
785 %************************************************************************
786
787 Ignoring all the infix-ery mumbo jumbo (ToDo)
788
789 \begin{code}
790 gen_Show_binds :: TyCon -> RdrNameMonoBinds
791
792 gen_Show_binds tycon
793   = shows_prec `AndMonoBinds` show_list
794   where
795     tycon_loc = getSrcLoc tycon
796     -----------------------------------------------------------------------
797     show_list = mk_easy_FunMonoBind tycon_loc showList_RDR [] []
798                   (HsApp (HsVar showList___RDR) (HsPar (HsApp (HsVar showsPrec_RDR) (HsLit (HsInt 0)))))
799     -----------------------------------------------------------------------
800     shows_prec
801       = mk_FunMonoBind tycon_loc showsPrec_RDR (map pats_etc (tyConDataCons tycon))
802       where
803         pats_etc data_con
804           = let
805                 data_con_RDR = qual_orig_name data_con
806                 con_arity    = argFieldCount data_con
807                 bs_needed    = take con_arity bs_RDRs
808                 con_pat      = ConPatIn data_con_RDR (map VarPatIn bs_needed)
809                 nullary_con  = con_arity == 0
810                 labels       = dataConFieldLabels data_con
811                 lab_fields   = length labels
812
813                 show_con
814                   = let nm = occNameString (getOccName data_con)
815                         space_ocurly_maybe
816                           | nullary_con     = _NIL_
817                           | lab_fields == 0 = SLIT(" ")
818                           | otherwise       = SLIT("{")
819
820                     in
821                         mk_showString_app (nm _APPEND_ space_ocurly_maybe)
822
823                 show_all con fs
824                   = let
825                         ccurly_maybe 
826                           | lab_fields > 0  = [mk_showString_app (SLIT("}"))]
827                           | otherwise       = []
828                     in
829                         con:fs ++ ccurly_maybe
830
831                 show_thingies = show_all show_con real_show_thingies_with_labs
832                 
833                 show_label l 
834                   = let nm = occNameString (getOccName (fieldLabelName l)) 
835                     in
836                         mk_showString_app (nm _APPEND_ SLIT("="))
837
838                 mk_showString_app str = HsApp (HsVar showString_RDR)
839                                               (HsLit (HsString str))
840
841                 real_show_thingies =
842                      [ HsApp (HsApp (HsVar showsPrec_RDR) (HsLit (HsInt 10))) (HsVar b)
843                      | b <- bs_needed ]
844
845                 real_show_thingies_with_labs
846                  | lab_fields == 0 = intersperse (HsVar showSpace_RDR) real_show_thingies
847                  | otherwise       = --Assumption: no of fields == no of labelled fields 
848                                      --            (and in same order)
849                     concat $
850                     intersperse ([mk_showString_app (_CONS_ ',' _NIL_ )]) $ -- Using SLIT() is not cool here.
851                     zipWithEqual "gen_Show_binds"
852                                  (\ a b -> [a,b])
853                                  (map show_label labels) 
854                                  real_show_thingies
855                                
856
857             in
858             if nullary_con then  -- skip the showParen junk...
859                 ASSERT(null bs_needed)
860                 ([a_Pat, con_pat], show_con)
861             else
862                 ([a_Pat, con_pat],
863                     showParen_Expr (HsPar (genOpApp a_Expr ge_RDR (HsLit (HsInt 10))))
864                                    (HsPar (nested_compose_Expr show_thingies)))
865 \end{code}
866
867 %************************************************************************
868 %*                                                                      *
869 \subsection{Generating extra binds (@con2tag@ and @tag2con@)}
870 %*                                                                      *
871 %************************************************************************
872
873 \begin{verbatim}
874 data Foo ... = ...
875
876 con2tag_Foo :: Foo ... -> Int#
877 tag2con_Foo :: Int -> Foo ...   -- easier if Int, not Int#
878 maxtag_Foo  :: Int              -- ditto (NB: not unboxed)
879 \end{verbatim}
880
881 The `tags' here start at zero, hence the @fIRST_TAG@ (currently one)
882 fiddling around.
883
884 \begin{code}
885 data TagThingWanted
886   = GenCon2Tag | GenTag2Con | GenMaxTag
887
888 gen_tag_n_con_monobind
889     :: (RdrName,            -- (proto)Name for the thing in question
890         TyCon,              -- tycon in question
891         TagThingWanted)
892     -> RdrNameMonoBinds
893
894 gen_tag_n_con_monobind (rdr_name, tycon, GenCon2Tag)
895   = mk_FunMonoBind (getSrcLoc tycon) rdr_name (map mk_stuff (tyConDataCons tycon))
896   where
897     mk_stuff :: DataCon -> ([RdrNamePat], RdrNameHsExpr)
898
899     mk_stuff var
900       = ASSERT(isDataCon var)
901         ([pat], HsLit (HsIntPrim (toInteger ((dataConTag var) - fIRST_TAG))))
902       where
903         pat    = ConPatIn var_RDR (nOfThem (argFieldCount var) WildPatIn)
904         var_RDR = qual_orig_name var
905
906 gen_tag_n_con_monobind (rdr_name, tycon, GenTag2Con)
907   = mk_FunMonoBind (getSrcLoc tycon) rdr_name (map mk_stuff (tyConDataCons tycon) ++ 
908                                                              [([WildPatIn], impossible_Expr)])
909   where
910     mk_stuff :: DataCon -> ([RdrNamePat], RdrNameHsExpr)
911
912     mk_stuff var
913       = ASSERT(isDataCon var)
914         ([lit_pat], HsVar var_RDR)
915       where
916         lit_pat = ConPatIn mkInt_RDR [LitPatIn (HsIntPrim (toInteger ((dataConTag var) - fIRST_TAG)))]
917         var_RDR  = qual_orig_name var
918
919 gen_tag_n_con_monobind (rdr_name, tycon, GenMaxTag)
920   = mk_easy_FunMonoBind (getSrcLoc tycon) 
921                 rdr_name [] [] (HsApp (HsVar mkInt_RDR) (HsLit (HsIntPrim max_tag)))
922   where
923     max_tag =  case (tyConDataCons tycon) of
924                  data_cons -> toInteger ((length data_cons) - fIRST_TAG)
925
926 \end{code}
927
928 %************************************************************************
929 %*                                                                      *
930 \subsection{Utility bits for generating bindings}
931 %*                                                                      *
932 %************************************************************************
933
934 @mk_easy_FunMonoBind fun pats binds expr@ generates:
935 \begin{verbatim}
936     fun pat1 pat2 ... patN = expr where binds
937 \end{verbatim}
938
939 @mk_FunMonoBind fun [([p1a, p1b, ...], e1), ...]@ is for
940 multi-clause definitions; it generates:
941 \begin{verbatim}
942     fun p1a p1b ... p1N = e1
943     fun p2a p2b ... p2N = e2
944     ...
945     fun pMa pMb ... pMN = eM
946 \end{verbatim}
947
948 \begin{code}
949 mk_easy_FunMonoBind :: SrcLoc -> RdrName -> [RdrNamePat]
950                     -> [RdrNameMonoBinds] -> RdrNameHsExpr
951                     -> RdrNameMonoBinds
952
953 mk_easy_FunMonoBind loc fun pats binds expr
954   = FunMonoBind fun False{-not infix-} [mk_easy_Match loc pats binds expr] loc
955
956 mk_easy_Match loc pats binds expr
957   = mk_match loc pats expr (mkbind binds)
958   where
959     mkbind [] = EmptyBinds
960     mkbind bs = MonoBind (foldr1 AndMonoBinds bs) [] Recursive
961         -- The renamer expects everything in its input to be a
962         -- "recursive" MonoBinds, and it is its job to sort things out
963         -- from there.
964
965 mk_FunMonoBind  :: SrcLoc -> RdrName
966                 -> [([RdrNamePat], RdrNameHsExpr)]
967                 -> RdrNameMonoBinds
968
969 mk_FunMonoBind loc fun [] = panic "TcGenDeriv:mk_FunMonoBind"
970 mk_FunMonoBind loc fun pats_and_exprs
971   = FunMonoBind fun False{-not infix-}
972                 [ mk_match loc p e EmptyBinds | (p,e) <-pats_and_exprs ]
973                 loc
974
975 mk_match loc pats expr binds
976   = foldr PatMatch
977           (GRHSMatch (GRHSsAndBindsIn (unguardedRHS expr loc) binds))
978           (map paren pats)
979   where
980     paren p@(VarPatIn _) = p
981     paren other_p        = ParPatIn other_p
982 \end{code}
983
984 \begin{code}
985 mk_easy_App f xs = foldl HsApp (HsVar f) (map HsVar xs)
986 \end{code}
987
988 ToDo: Better SrcLocs.
989
990 \begin{code}
991 compare_Case, cmp_eq_Expr ::
992           RdrNameHsExpr -> RdrNameHsExpr -> RdrNameHsExpr
993           -> RdrNameHsExpr -> RdrNameHsExpr
994           -> RdrNameHsExpr
995 compare_gen_Case ::
996           RdrName
997           -> RdrNameHsExpr -> RdrNameHsExpr -> RdrNameHsExpr
998           -> RdrNameHsExpr -> RdrNameHsExpr
999           -> RdrNameHsExpr
1000 careful_compare_Case :: -- checks for primitive types...
1001           Type
1002           -> RdrNameHsExpr -> RdrNameHsExpr -> RdrNameHsExpr
1003           -> RdrNameHsExpr -> RdrNameHsExpr
1004           -> RdrNameHsExpr
1005
1006 compare_Case = compare_gen_Case compare_RDR
1007 cmp_eq_Expr = compare_gen_Case cmp_eq_RDR
1008
1009 compare_gen_Case fun lt eq gt a b
1010   = HsCase (HsPar (HsApp (HsApp (HsVar fun) a) b)) {-of-}
1011       [PatMatch (ConPatIn ltTag_RDR [])
1012           (GRHSMatch (GRHSsAndBindsIn (unguardedRHS lt mkGeneratedSrcLoc) EmptyBinds)),
1013
1014        PatMatch (ConPatIn eqTag_RDR [])
1015           (GRHSMatch (GRHSsAndBindsIn (unguardedRHS eq mkGeneratedSrcLoc) EmptyBinds)),
1016
1017        PatMatch (ConPatIn gtTag_RDR [])
1018           (GRHSMatch (GRHSsAndBindsIn (unguardedRHS gt mkGeneratedSrcLoc) EmptyBinds))]
1019        mkGeneratedSrcLoc
1020
1021 careful_compare_Case ty lt eq gt a b
1022   = if not (isUnboxedType ty) then
1023        compare_gen_Case compare_RDR lt eq gt a b
1024
1025     else -- we have to do something special for primitive things...
1026        HsIf (genOpApp a relevant_eq_op b)
1027             eq
1028             (HsIf (genOpApp a relevant_lt_op b) lt gt mkGeneratedSrcLoc)
1029             mkGeneratedSrcLoc
1030   where
1031     relevant_eq_op = assoc_ty_id eq_op_tbl ty
1032     relevant_lt_op = assoc_ty_id lt_op_tbl ty
1033
1034 assoc_ty_id tyids ty 
1035   = if null res then panic "assoc_ty"
1036     else head res
1037   where
1038     res = [id | (ty',id) <- tyids, ty == ty']
1039
1040 eq_op_tbl =
1041     [(charPrimTy,       eqH_Char_RDR)
1042     ,(intPrimTy,        eqH_Int_RDR)
1043     ,(wordPrimTy,       eqH_Word_RDR)
1044     ,(addrPrimTy,       eqH_Addr_RDR)
1045     ,(floatPrimTy,      eqH_Float_RDR)
1046     ,(doublePrimTy,     eqH_Double_RDR)
1047     ]
1048
1049 lt_op_tbl =
1050     [(charPrimTy,       ltH_Char_RDR)
1051     ,(intPrimTy,        ltH_Int_RDR)
1052     ,(wordPrimTy,       ltH_Word_RDR)
1053     ,(addrPrimTy,       ltH_Addr_RDR)
1054     ,(floatPrimTy,      ltH_Float_RDR)
1055     ,(doublePrimTy,     ltH_Double_RDR)
1056     ]
1057
1058 -----------------------------------------------------------------------
1059
1060 and_Expr, append_Expr :: RdrNameHsExpr -> RdrNameHsExpr -> RdrNameHsExpr
1061
1062 and_Expr    a b = genOpApp a and_RDR    b
1063 append_Expr a b = genOpApp a append_RDR b
1064
1065 -----------------------------------------------------------------------
1066
1067 eq_Expr :: Type -> RdrNameHsExpr -> RdrNameHsExpr -> RdrNameHsExpr
1068 eq_Expr ty a b
1069   = if not (isUnboxedType ty) then
1070        genOpApp a eq_RDR  b
1071     else -- we have to do something special for primitive things...
1072        genOpApp a relevant_eq_op b
1073   where
1074     relevant_eq_op = assoc_ty_id eq_op_tbl ty
1075 \end{code}
1076
1077 \begin{code}
1078 argFieldCount :: Id -> Int      -- Works on data and newtype constructors
1079 argFieldCount con = length (dataConRawArgTys con)
1080 \end{code}
1081
1082 \begin{code}
1083 untag_Expr :: TyCon -> [(RdrName, RdrName)] -> RdrNameHsExpr -> RdrNameHsExpr
1084 untag_Expr tycon [] expr = expr
1085 untag_Expr tycon ((untag_this, put_tag_here) : more) expr
1086   = HsCase (HsPar (HsApp (con2tag_Expr tycon) (HsVar untag_this))) {-of-}
1087       [PatMatch (VarPatIn put_tag_here)
1088                         (GRHSMatch (GRHSsAndBindsIn grhs EmptyBinds))]
1089       mkGeneratedSrcLoc
1090   where
1091     grhs = unguardedRHS (untag_Expr tycon more expr) mkGeneratedSrcLoc
1092
1093 cmp_tags_Expr :: RdrName                -- Comparison op
1094              -> RdrName -> RdrName      -- Things to compare
1095              -> RdrNameHsExpr           -- What to return if true
1096              -> RdrNameHsExpr           -- What to return if false
1097              -> RdrNameHsExpr
1098
1099 cmp_tags_Expr op a b true_case false_case
1100   = HsIf (genOpApp (HsVar a) op (HsVar b)) true_case false_case mkGeneratedSrcLoc
1101
1102 enum_from_to_Expr
1103         :: RdrNameHsExpr -> RdrNameHsExpr
1104         -> RdrNameHsExpr
1105 enum_from_then_to_Expr
1106         :: RdrNameHsExpr -> RdrNameHsExpr -> RdrNameHsExpr
1107         -> RdrNameHsExpr
1108
1109 enum_from_to_Expr      f   t2 = HsApp (HsApp (HsVar enumFromTo_RDR) f) t2
1110 enum_from_then_to_Expr f t t2 = HsApp (HsApp (HsApp (HsVar enumFromThenTo_RDR) f) t) t2
1111
1112 showParen_Expr, readParen_Expr
1113         :: RdrNameHsExpr -> RdrNameHsExpr
1114         -> RdrNameHsExpr
1115
1116 showParen_Expr e1 e2 = HsApp (HsApp (HsVar showParen_RDR) e1) e2
1117 readParen_Expr e1 e2 = HsApp (HsApp (HsVar readParen_RDR) e1) e2
1118
1119 nested_compose_Expr :: [RdrNameHsExpr] -> RdrNameHsExpr
1120
1121 nested_compose_Expr [e] = parenify e
1122 nested_compose_Expr (e:es)
1123   = HsApp (HsApp (HsVar compose_RDR) (parenify e)) (nested_compose_Expr es)
1124
1125 -- impossible_Expr is used in case RHSs that should never happen.
1126 -- We generate these to keep the desugarer from complaining that they *might* happen!
1127 impossible_Expr = HsApp (HsVar error_RDR) (HsLit (HsString (_PK_ "Urk! in TcGenDeriv")))
1128
1129 parenify e@(HsVar _) = e
1130 parenify e           = HsPar e
1131
1132 -- genOpApp wraps brackets round the operator application, so that the
1133 -- renamer won't subsequently try to re-associate it. 
1134 -- For some reason the renamer doesn't reassociate it right, and I can't
1135 -- be bothered to find out why just now.
1136
1137 genOpApp e1 op e2 = mkOpApp e1 op e2
1138 \end{code}
1139
1140 \begin{code}
1141 qual_orig_name n = case modAndOcc n of { (m,n) -> Qual m n HiFile }
1142
1143 a_RDR           = varUnqual SLIT("a")
1144 b_RDR           = varUnqual SLIT("b")
1145 c_RDR           = varUnqual SLIT("c")
1146 d_RDR           = varUnqual SLIT("d")
1147 ah_RDR          = varUnqual SLIT("a#")
1148 bh_RDR          = varUnqual SLIT("b#")
1149 ch_RDR          = varUnqual SLIT("c#")
1150 dh_RDR          = varUnqual SLIT("d#")
1151 cmp_eq_RDR      = varUnqual SLIT("cmp_eq")
1152 rangeSize_RDR   = varUnqual SLIT("rangeSize")
1153
1154 as_RDRs         = [ varUnqual (_PK_ ("a"++show i)) | i <- [(1::Int) .. ] ]
1155 bs_RDRs         = [ varUnqual (_PK_ ("b"++show i)) | i <- [(1::Int) .. ] ]
1156 cs_RDRs         = [ varUnqual (_PK_ ("c"++show i)) | i <- [(1::Int) .. ] ]
1157
1158 a_Expr          = HsVar a_RDR
1159 b_Expr          = HsVar b_RDR
1160 c_Expr          = HsVar c_RDR
1161 d_Expr          = HsVar d_RDR
1162 ltTag_Expr      = HsVar ltTag_RDR
1163 eqTag_Expr      = HsVar eqTag_RDR
1164 gtTag_Expr      = HsVar gtTag_RDR
1165 false_Expr      = HsVar false_RDR
1166 true_Expr       = HsVar true_RDR
1167
1168 con2tag_Expr tycon = HsVar (con2tag_RDR tycon)
1169
1170 a_Pat           = VarPatIn a_RDR
1171 b_Pat           = VarPatIn b_RDR
1172 c_Pat           = VarPatIn c_RDR
1173 d_Pat           = VarPatIn d_RDR
1174
1175 con2tag_RDR, tag2con_RDR, maxtag_RDR :: TyCon -> RdrName
1176
1177 con2tag_RDR tycon = varUnqual (SLIT("con2tag_") _APPEND_ occNameString (getOccName tycon) _APPEND_ SLIT("#"))
1178 tag2con_RDR tycon = varUnqual (SLIT("tag2con_") _APPEND_ occNameString (getOccName tycon) _APPEND_ SLIT("#"))
1179 maxtag_RDR tycon  = varUnqual (SLIT("maxtag_")  _APPEND_ occNameString (getOccName tycon) _APPEND_ SLIT("#"))
1180 \end{code}