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