Reorganisation of the source tree
[ghc-hetmet.git] / ghc / compiler / typecheck / TcGenDeriv.lhs
diff --git a/ghc/compiler/typecheck/TcGenDeriv.lhs b/ghc/compiler/typecheck/TcGenDeriv.lhs
deleted file mode 100644 (file)
index 40e091d..0000000
+++ /dev/null
@@ -1,1480 +0,0 @@
-%
-% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
-%
-\section[TcGenDeriv]{Generating derived instance declarations}
-
-This module is nominally ``subordinate'' to @TcDeriv@, which is the
-``official'' interface to deriving-related things.
-
-This is where we do all the grimy bindings' generation.
-
-\begin{code}
-module TcGenDeriv (
-       gen_Bounded_binds,
-       gen_Enum_binds,
-       gen_Eq_binds,
-       gen_Ix_binds,
-       gen_Ord_binds,
-       gen_Read_binds,
-       gen_Show_binds,
-       gen_Data_binds,
-       gen_Typeable_binds,
-       gen_tag_n_con_monobind,
-
-       con2tag_RDR, tag2con_RDR, maxtag_RDR,
-
-       TagThingWanted(..)
-    ) where
-
-#include "HsVersions.h"
-
-import HsSyn
-import RdrName         ( RdrName, mkVarUnqual, getRdrName, mkRdrUnqual,
-                          mkDerivedRdrName )
-import BasicTypes      ( Fixity(..), maxPrecedence, Boxity(..) )
-import DataCon         ( isNullarySrcDataCon, dataConTag,
-                         dataConOrigArgTys, dataConSourceArity, fIRST_TAG,
-                         DataCon, dataConName, dataConIsInfix,
-                         dataConFieldLabels )
-import Name            ( getOccString, getSrcLoc, Name, NamedThing(..) )
-
-import HscTypes                ( FixityEnv, lookupFixity )
-import PrelInfo
-import PrelNames
-import MkId            ( eRROR_ID )
-import PrimOp          ( PrimOp(..) )
-import SrcLoc          ( Located(..), noLoc, srcLocSpan )
-import TyCon           ( TyCon, isNewTyCon, tyConDataCons, isEnumerationTyCon, tyConArity,
-                         maybeTyConSingleCon, tyConFamilySize, tyConTyVars, tyConName
-                       )
-import TcType          ( isUnLiftedType, tcEqType, Type )
-import TysPrim         ( charPrimTy, intPrimTy, wordPrimTy, addrPrimTy, floatPrimTy, doublePrimTy,
-                         intPrimTyCon )
-import TysWiredIn      ( charDataCon, intDataCon, floatDataCon, doubleDataCon,
-                         intDataCon_RDR, true_RDR, false_RDR )
-import Util            ( zipWithEqual, isSingleton,
-                         zipWith3Equal, nOfThem, zipEqual )
-import Constants
-import List            ( partition, intersperse )
-import Outputable
-import FastString
-import OccName
-import Bag
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsection{Generating code, by derivable class}
-%*                                                                     *
-%************************************************************************
-
-%************************************************************************
-%*                                                                     *
-\subsubsection{Generating @Eq@ instance declarations}
-%*                                                                     *
-%************************************************************************
-
-Here are the heuristics for the code we generate for @Eq@:
-\begin{itemize}
-\item
-  Let's assume we have a data type with some (possibly zero) nullary
-  data constructors and some ordinary, non-nullary ones (the rest,
-  also possibly zero of them).  Here's an example, with both \tr{N}ullary
-  and \tr{O}rdinary data cons.
-\begin{verbatim}
-data Foo ... = N1 | N2 ... | Nn | O1 a b | O2 Int | O3 Double b b | ...
-\end{verbatim}
-
-\item
-  For the ordinary constructors (if any), we emit clauses to do The
-  Usual Thing, e.g.,:
-
-\begin{verbatim}
-(==) (O1 a1 b1)           (O1 a2 b2)    = a1 == a2 && b1 == b2
-(==) (O2 a1)      (O2 a2)       = a1 == a2
-(==) (O3 a1 b1 c1) (O3 a2 b2 c2) = a1 == a2 && b1 == b2 && c1 == c2
-\end{verbatim}
-
-  Note: if we're comparing unlifted things, e.g., if \tr{a1} and
-  \tr{a2} are \tr{Float#}s, then we have to generate
-\begin{verbatim}
-case (a1 `eqFloat#` a2) of
-  r -> r
-\end{verbatim}
-  for that particular test.
-
-\item
-  If there are any nullary constructors, we emit a catch-all clause of
-  the form:
-
-\begin{verbatim}
-(==) a b  = case (con2tag_Foo a) of { a# ->
-           case (con2tag_Foo b) of { b# ->
-           case (a# ==# b#)     of {
-             r -> r
-           }}}
-\end{verbatim}
-
-  If there aren't any nullary constructors, we emit a simpler
-  catch-all:
-\begin{verbatim}
-(==) a b  = False
-\end{verbatim}
-
-\item
-  For the @(/=)@ method, we normally just use the default method.
-
-  If the type is an enumeration type, we could/may/should? generate
-  special code that calls @con2tag_Foo@, much like for @(==)@ shown
-  above.
-
-\item
-  We thought about doing this: If we're also deriving @Ord@ for this
-  tycon, we generate:
-\begin{verbatim}
-instance ... Eq (Foo ...) where
-  (==) a b  = case (compare a b) of { _LT -> False; _EQ -> True ; _GT -> False}
-  (/=) a b  = case (compare a b) of { _LT -> True ; _EQ -> False; _GT -> True }
-\begin{verbatim}
-  However, that requires that \tr{Ord <whatever>} was put in the context
-  for the instance decl, which it probably wasn't, so the decls
-  produced don't get through the typechecker.
-\end{itemize}
-
-
-\begin{code}
-gen_Eq_binds :: TyCon -> LHsBinds RdrName
-
-gen_Eq_binds tycon
-  = let
-       tycon_loc = getSrcSpan tycon
-
-        (nullary_cons, nonnullary_cons)
-           | isNewTyCon tycon = ([], tyConDataCons tycon)
-           | otherwise       = partition isNullarySrcDataCon (tyConDataCons tycon)
-
-       rest
-         = if (null nullary_cons) then
-               case maybeTyConSingleCon tycon of
-                 Just _ -> []
-                 Nothing -> -- if cons don't match, then False
-                    [([nlWildPat, nlWildPat], false_Expr)]
-           else -- calc. and compare the tags
-                [([a_Pat, b_Pat],
-                   untag_Expr tycon [(a_RDR,ah_RDR), (b_RDR,bh_RDR)]
-                              (genOpApp (nlHsVar ah_RDR) eqInt_RDR (nlHsVar bh_RDR)))]
-    in
-    listToBag [
-      mk_FunBind tycon_loc eq_RDR ((map pats_etc nonnullary_cons) ++ rest),
-      mk_easy_FunBind tycon_loc ne_RDR [a_Pat, b_Pat] (
-       nlHsApp (nlHsVar not_RDR) (nlHsPar (nlHsVarApps eq_RDR [a_RDR, b_RDR])))
-    ]
-  where
-    ------------------------------------------------------------------
-    pats_etc data_con
-      = let
-           con1_pat = nlConVarPat data_con_RDR as_needed
-           con2_pat = nlConVarPat data_con_RDR bs_needed
-
-           data_con_RDR = getRdrName data_con
-           con_arity   = length tys_needed
-           as_needed   = take con_arity as_RDRs
-           bs_needed   = take con_arity bs_RDRs
-           tys_needed  = dataConOrigArgTys data_con
-       in
-       ([con1_pat, con2_pat], nested_eq_expr tys_needed as_needed bs_needed)
-      where
-       nested_eq_expr []  [] [] = true_Expr
-       nested_eq_expr tys as bs
-         = foldl1 and_Expr (zipWith3Equal "nested_eq" nested_eq tys as bs)
-         where
-           nested_eq ty a b = nlHsPar (eq_Expr tycon ty (nlHsVar a) (nlHsVar b))
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsubsection{Generating @Ord@ instance declarations}
-%*                                                                     *
-%************************************************************************
-
-For a derived @Ord@, we concentrate our attentions on @compare@
-\begin{verbatim}
-compare :: a -> a -> Ordering
-data Ordering = LT | EQ | GT deriving ()
-\end{verbatim}
-
-We will use the same example data type as above:
-\begin{verbatim}
-data Foo ... = N1 | N2 ... | Nn | O1 a b | O2 Int | O3 Double b b | ...
-\end{verbatim}
-
-\begin{itemize}
-\item
-  We do all the other @Ord@ methods with calls to @compare@:
-\begin{verbatim}
-instance ... (Ord <wurble> <wurble>) where
-    a <  b  = case (compare a b) of { LT -> True;  EQ -> False; GT -> False }
-    a <= b  = case (compare a b) of { LT -> True;  EQ -> True;  GT -> False }
-    a >= b  = case (compare a b) of { LT -> False; EQ -> True;  GT -> True  }
-    a >  b  = case (compare a b) of { LT -> False; EQ -> False; GT -> True  }
-
-    max a b = case (compare a b) of { LT -> b; EQ -> a;  GT -> a }
-    min a b = case (compare a b) of { LT -> a; EQ -> b;  GT -> b }
-
-    -- compare to come...
-\end{verbatim}
-
-\item
-  @compare@ always has two parts.  First, we use the compared
-  data-constructors' tags to deal with the case of different
-  constructors:
-\begin{verbatim}
-compare a b = case (con2tag_Foo a) of { a# ->
-             case (con2tag_Foo b) of { b# ->
-             case (a# ==# b#)     of {
-              True  -> cmp_eq a b
-              False -> case (a# <# b#) of
-                        True  -> _LT
-                        False -> _GT
-             }}}
-  where
-    cmp_eq = ... to come ...
-\end{verbatim}
-
-\item
-  We are only left with the ``help'' function @cmp_eq@, to deal with
-  comparing data constructors with the same tag.
-
-  For the ordinary constructors (if any), we emit the sorta-obvious
-  compare-style stuff; for our example:
-\begin{verbatim}
-cmp_eq (O1 a1 b1) (O1 a2 b2)
-  = case (compare a1 a2) of { LT -> LT; EQ -> compare b1 b2; GT -> GT }
-
-cmp_eq (O2 a1) (O2 a2)
-  = compare a1 a2
-
-cmp_eq (O3 a1 b1 c1) (O3 a2 b2 c2)
-  = case (compare a1 a2) of {
-      LT -> LT;
-      GT -> GT;
-      EQ -> case compare b1 b2 of {
-             LT -> LT;
-             GT -> GT;
-             EQ -> compare c1 c2
-           }
-    }
-\end{verbatim}
-
-  Again, we must be careful about unlifted comparisons.  For example,
-  if \tr{a1} and \tr{a2} were \tr{Int#}s in the 2nd example above, we'd need to
-  generate:
-
-\begin{verbatim}
-cmp_eq lt eq gt (O2 a1) (O2 a2)
-  = compareInt# a1 a2
-  -- or maybe the unfolded equivalent
-\end{verbatim}
-
-\item
-  For the remaining nullary constructors, we already know that the
-  tags are equal so:
-\begin{verbatim}
-cmp_eq _ _ = EQ
-\end{verbatim}
-\end{itemize}
-
-If there is only one constructor in the Data Type we don't need the WildCard Pattern. 
-JJQC-30-Nov-1997
-
-\begin{code}
-gen_Ord_binds :: TyCon -> LHsBinds RdrName
-
-gen_Ord_binds tycon
-  = unitBag compare    -- `AndMonoBinds` compare       
-               -- The default declaration in PrelBase handles this
-  where
-    tycon_loc = getSrcSpan tycon
-    --------------------------------------------------------------------
-
-    compare = L tycon_loc (mkFunBind (L tycon_loc compare_RDR) compare_matches)
-    compare_matches = [mkMatch [a_Pat, b_Pat] compare_rhs cmp_eq_binds]
-    cmp_eq_binds    = HsValBinds (ValBindsIn (unitBag cmp_eq) [])
-
-    compare_rhs
-       | single_con_type = cmp_eq_Expr a_Expr b_Expr
-       | otherwise
-       = untag_Expr tycon [(a_RDR, ah_RDR), (b_RDR, bh_RDR)]
-                 (cmp_tags_Expr eqInt_RDR ah_RDR bh_RDR
-                       (cmp_eq_Expr a_Expr b_Expr)     -- True case
-                       -- False case; they aren't equal
-                       -- So we need to do a less-than comparison on the tags
-                       (cmp_tags_Expr ltInt_RDR ah_RDR bh_RDR ltTag_Expr gtTag_Expr))
-
-    tycon_data_cons = tyConDataCons tycon
-    single_con_type = isSingleton tycon_data_cons
-    (nullary_cons, nonnullary_cons)
-       | isNewTyCon tycon = ([], tyConDataCons tycon)
-       | otherwise       = partition isNullarySrcDataCon tycon_data_cons
-
-    cmp_eq = mk_FunBind tycon_loc cmp_eq_RDR cmp_eq_match
-    cmp_eq_match
-      | isEnumerationTyCon tycon
-                          -- We know the tags are equal, so if it's an enumeration TyCon,
-                          -- then there is nothing left to do
-                          -- Catch this specially to avoid warnings
-                          -- about overlapping patterns from the desugarer,
-                          -- and to avoid unnecessary pattern-matching
-      = [([nlWildPat,nlWildPat], eqTag_Expr)]
-      | otherwise
-      = map pats_etc nonnullary_cons ++
-       (if single_con_type then        -- Omit wildcards when there's just one 
-             []                        -- constructor, to silence desugarer
-       else
-              [([nlWildPat, nlWildPat], default_rhs)])
-
-      where
-       pats_etc data_con
-         = ([con1_pat, con2_pat],
-            nested_compare_expr tys_needed as_needed bs_needed)
-         where
-           con1_pat = nlConVarPat data_con_RDR as_needed
-           con2_pat = nlConVarPat data_con_RDR bs_needed
-
-           data_con_RDR = getRdrName data_con
-           con_arity   = length tys_needed
-           as_needed   = take con_arity as_RDRs
-           bs_needed   = take con_arity bs_RDRs
-           tys_needed  = dataConOrigArgTys data_con
-
-           nested_compare_expr [ty] [a] [b]
-             = careful_compare_Case tycon ty eqTag_Expr (nlHsVar a) (nlHsVar b)
-
-           nested_compare_expr (ty:tys) (a:as) (b:bs)
-             = let eq_expr = nested_compare_expr tys as bs
-               in  careful_compare_Case tycon ty eq_expr (nlHsVar a) (nlHsVar b)
-
-       default_rhs | null nullary_cons = impossible_Expr       -- Keep desugarer from complaining about
-                                                               -- inexhaustive patterns
-                   | otherwise         = eqTag_Expr            -- Some nullary constructors;
-                                                               -- Tags are equal, no args => return EQ
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsubsection{Generating @Enum@ instance declarations}
-%*                                                                     *
-%************************************************************************
-
-@Enum@ can only be derived for enumeration types.  For a type
-\begin{verbatim}
-data Foo ... = N1 | N2 | ... | Nn
-\end{verbatim}
-
-we use both @con2tag_Foo@ and @tag2con_Foo@ functions, as well as a
-@maxtag_Foo@ variable (all generated by @gen_tag_n_con_binds@).
-
-\begin{verbatim}
-instance ... Enum (Foo ...) where
-    succ x   = toEnum (1 + fromEnum x)
-    pred x   = toEnum (fromEnum x - 1)
-
-    toEnum i = tag2con_Foo i
-
-    enumFrom a = map tag2con_Foo [con2tag_Foo a .. maxtag_Foo]
-
-    -- or, really...
-    enumFrom a
-      = case con2tag_Foo a of
-         a# -> map tag2con_Foo (enumFromTo (I# a#) maxtag_Foo)
-
-   enumFromThen a b
-     = map tag2con_Foo [con2tag_Foo a, con2tag_Foo b .. maxtag_Foo]
-
-    -- or, really...
-    enumFromThen a b
-      = case con2tag_Foo a of { a# ->
-       case con2tag_Foo b of { b# ->
-       map tag2con_Foo (enumFromThenTo (I# a#) (I# b#) maxtag_Foo)
-       }}
-\end{verbatim}
-
-For @enumFromTo@ and @enumFromThenTo@, we use the default methods.
-
-\begin{code}
-gen_Enum_binds :: TyCon -> LHsBinds RdrName
-
-gen_Enum_binds tycon
-  = listToBag [
-       succ_enum,
-       pred_enum,
-       to_enum,
-       enum_from,
-       enum_from_then,
-       from_enum
-    ]
-  where
-    tycon_loc = getSrcSpan tycon
-    occ_nm    = getOccString tycon
-
-    succ_enum
-      = mk_easy_FunBind tycon_loc succ_RDR [a_Pat] $
-       untag_Expr tycon [(a_RDR, ah_RDR)] $
-       nlHsIf (nlHsApps eq_RDR [nlHsVar (maxtag_RDR tycon),
-                              nlHsVarApps intDataCon_RDR [ah_RDR]])
-            (illegal_Expr "succ" occ_nm "tried to take `succ' of last tag in enumeration")
-            (nlHsApp (nlHsVar (tag2con_RDR tycon))
-                   (nlHsApps plus_RDR [nlHsVarApps intDataCon_RDR [ah_RDR],
-                                       nlHsIntLit 1]))
-                   
-    pred_enum
-      = mk_easy_FunBind tycon_loc pred_RDR [a_Pat] $
-       untag_Expr tycon [(a_RDR, ah_RDR)] $
-       nlHsIf (nlHsApps eq_RDR [nlHsIntLit 0,
-                              nlHsVarApps intDataCon_RDR [ah_RDR]])
-            (illegal_Expr "pred" occ_nm "tried to take `pred' of first tag in enumeration")
-            (nlHsApp (nlHsVar (tag2con_RDR tycon))
-                          (nlHsApps plus_RDR [nlHsVarApps intDataCon_RDR [ah_RDR],
-                                              nlHsLit (HsInt (-1))]))
-
-    to_enum
-      = mk_easy_FunBind tycon_loc toEnum_RDR [a_Pat] $
-       nlHsIf (nlHsApps and_RDR
-               [nlHsApps ge_RDR [nlHsVar a_RDR, nlHsIntLit 0],
-                 nlHsApps le_RDR [nlHsVar a_RDR, nlHsVar (maxtag_RDR tycon)]])
-             (nlHsVarApps (tag2con_RDR tycon) [a_RDR])
-            (illegal_toEnum_tag occ_nm (maxtag_RDR tycon))
-
-    enum_from
-      = mk_easy_FunBind tycon_loc enumFrom_RDR [a_Pat] $
-         untag_Expr tycon [(a_RDR, ah_RDR)] $
-         nlHsApps map_RDR 
-               [nlHsVar (tag2con_RDR tycon),
-                nlHsPar (enum_from_to_Expr
-                           (nlHsVarApps intDataCon_RDR [ah_RDR])
-                           (nlHsVar (maxtag_RDR tycon)))]
-
-    enum_from_then
-      = mk_easy_FunBind tycon_loc enumFromThen_RDR [a_Pat, b_Pat] $
-         untag_Expr tycon [(a_RDR, ah_RDR), (b_RDR, bh_RDR)] $
-         nlHsApp (nlHsVarApps map_RDR [tag2con_RDR tycon]) $
-           nlHsPar (enum_from_then_to_Expr
-                   (nlHsVarApps intDataCon_RDR [ah_RDR])
-                   (nlHsVarApps intDataCon_RDR [bh_RDR])
-                   (nlHsIf  (nlHsApps gt_RDR [nlHsVarApps intDataCon_RDR [ah_RDR],
-                                            nlHsVarApps intDataCon_RDR [bh_RDR]])
-                          (nlHsIntLit 0)
-                          (nlHsVar (maxtag_RDR tycon))
-                          ))
-
-    from_enum
-      = mk_easy_FunBind tycon_loc fromEnum_RDR [a_Pat] $
-         untag_Expr tycon [(a_RDR, ah_RDR)] $
-         (nlHsVarApps intDataCon_RDR [ah_RDR])
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsubsection{Generating @Bounded@ instance declarations}
-%*                                                                     *
-%************************************************************************
-
-\begin{code}
-gen_Bounded_binds tycon
-  = if isEnumerationTyCon tycon then
-       listToBag [ min_bound_enum, max_bound_enum ]
-    else
-       ASSERT(isSingleton data_cons)
-       listToBag [ min_bound_1con, max_bound_1con ]
-  where
-    data_cons = tyConDataCons tycon
-    tycon_loc = getSrcSpan tycon
-
-    ----- enum-flavored: ---------------------------
-    min_bound_enum = mkVarBind tycon_loc minBound_RDR (nlHsVar data_con_1_RDR)
-    max_bound_enum = mkVarBind tycon_loc maxBound_RDR (nlHsVar data_con_N_RDR)
-
-    data_con_1   = head data_cons
-    data_con_N   = last data_cons
-    data_con_1_RDR = getRdrName data_con_1
-    data_con_N_RDR = getRdrName data_con_N
-
-    ----- single-constructor-flavored: -------------
-    arity         = dataConSourceArity data_con_1
-
-    min_bound_1con = mkVarBind tycon_loc minBound_RDR $
-                    nlHsVarApps data_con_1_RDR (nOfThem arity minBound_RDR)
-    max_bound_1con = mkVarBind tycon_loc maxBound_RDR $
-                    nlHsVarApps data_con_1_RDR (nOfThem arity maxBound_RDR)
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsubsection{Generating @Ix@ instance declarations}
-%*                                                                     *
-%************************************************************************
-
-Deriving @Ix@ is only possible for enumeration types and
-single-constructor types.  We deal with them in turn.
-
-For an enumeration type, e.g.,
-\begin{verbatim}
-    data Foo ... = N1 | N2 | ... | Nn
-\end{verbatim}
-things go not too differently from @Enum@:
-\begin{verbatim}
-instance ... Ix (Foo ...) where
-    range (a, b)
-      = map tag2con_Foo [con2tag_Foo a .. con2tag_Foo b]
-
-    -- or, really...
-    range (a, b)
-      = case (con2tag_Foo a) of { a# ->
-       case (con2tag_Foo b) of { b# ->
-       map tag2con_Foo (enumFromTo (I# a#) (I# b#))
-       }}
-
-    -- Generate code for unsafeIndex, becuase using index leads
-    -- to lots of redundant range tests
-    unsafeIndex c@(a, b) d
-      = case (con2tag_Foo d -# con2tag_Foo a) of
-              r# -> I# r#
-
-    inRange (a, b) c
-      = let
-           p_tag = con2tag_Foo c
-       in
-       p_tag >= con2tag_Foo a && p_tag <= con2tag_Foo b
-
-    -- or, really...
-    inRange (a, b) c
-      = case (con2tag_Foo a)   of { a_tag ->
-       case (con2tag_Foo b)   of { b_tag ->
-       case (con2tag_Foo c)   of { c_tag ->
-       if (c_tag >=# a_tag) then
-         c_tag <=# b_tag
-       else
-         False
-       }}}
-\end{verbatim}
-(modulo suitable case-ification to handle the unlifted tags)
-
-For a single-constructor type (NB: this includes all tuples), e.g.,
-\begin{verbatim}
-    data Foo ... = MkFoo a b Int Double c c
-\end{verbatim}
-we follow the scheme given in Figure~19 of the Haskell~1.2 report
-(p.~147).
-
-\begin{code}
-gen_Ix_binds :: TyCon -> LHsBinds RdrName
-
-gen_Ix_binds tycon
-  = if isEnumerationTyCon tycon
-    then enum_ixes
-    else single_con_ixes
-  where
-    tycon_loc = getSrcSpan tycon
-
-    --------------------------------------------------------------
-    enum_ixes = listToBag [ enum_range, enum_index, enum_inRange ]
-
-    enum_range
-      = mk_easy_FunBind tycon_loc range_RDR [nlTuplePat [a_Pat, b_Pat] Boxed] $
-         untag_Expr tycon [(a_RDR, ah_RDR)] $
-         untag_Expr tycon [(b_RDR, bh_RDR)] $
-         nlHsApp (nlHsVarApps map_RDR [tag2con_RDR tycon]) $
-             nlHsPar (enum_from_to_Expr
-                       (nlHsVarApps intDataCon_RDR [ah_RDR])
-                       (nlHsVarApps intDataCon_RDR [bh_RDR]))
-
-    enum_index
-      = mk_easy_FunBind tycon_loc unsafeIndex_RDR 
-               [noLoc (AsPat (noLoc c_RDR) 
-                          (nlTuplePat [a_Pat, nlWildPat] Boxed)), 
-                               d_Pat] (
-          untag_Expr tycon [(a_RDR, ah_RDR)] (
-          untag_Expr tycon [(d_RDR, dh_RDR)] (
-          let
-               rhs = nlHsVarApps intDataCon_RDR [c_RDR]
-          in
-          nlHsCase
-            (genOpApp (nlHsVar dh_RDR) minusInt_RDR (nlHsVar ah_RDR))
-            [mkSimpleHsAlt (nlVarPat c_RDR) rhs]
-          ))
-       )
-
-    enum_inRange
-      = mk_easy_FunBind tycon_loc inRange_RDR [nlTuplePat [a_Pat, b_Pat] Boxed, c_Pat] $
-         untag_Expr tycon [(a_RDR, ah_RDR)] (
-         untag_Expr tycon [(b_RDR, bh_RDR)] (
-         untag_Expr tycon [(c_RDR, ch_RDR)] (
-         nlHsIf (genOpApp (nlHsVar ch_RDR) geInt_RDR (nlHsVar ah_RDR)) (
-            (genOpApp (nlHsVar ch_RDR) leInt_RDR (nlHsVar bh_RDR))
-         ) {-else-} (
-            false_Expr
-         ))))
-
-    --------------------------------------------------------------
-    single_con_ixes 
-      = listToBag [single_con_range, single_con_index, single_con_inRange]
-
-    data_con
-      =        case maybeTyConSingleCon tycon of -- just checking...
-         Nothing -> panic "get_Ix_binds"
-         Just dc | any isUnLiftedType (dataConOrigArgTys dc)
-                 -> pprPanic "Can't derive Ix for a single-constructor type with primitive argument types:" (ppr tycon)
-                 | otherwise -> dc
-
-    con_arity    = dataConSourceArity data_con
-    data_con_RDR = getRdrName data_con
-
-    as_needed = take con_arity as_RDRs
-    bs_needed = take con_arity bs_RDRs
-    cs_needed = take con_arity cs_RDRs
-
-    con_pat  xs  = nlConVarPat data_con_RDR xs
-    con_expr     = nlHsVarApps data_con_RDR cs_needed
-
-    --------------------------------------------------------------
-    single_con_range
-      = mk_easy_FunBind tycon_loc range_RDR 
-         [nlTuplePat [con_pat as_needed, con_pat bs_needed] Boxed] $
-       nlHsDo ListComp stmts con_expr
-      where
-       stmts = zipWith3Equal "single_con_range" mk_qual as_needed bs_needed cs_needed
-
-       mk_qual a b c = noLoc $ mkBindStmt (nlVarPat c)
-                                (nlHsApp (nlHsVar range_RDR) 
-                                       (nlTuple [nlHsVar a, nlHsVar b] Boxed))
-
-    ----------------
-    single_con_index
-      = mk_easy_FunBind tycon_loc unsafeIndex_RDR 
-               [nlTuplePat [con_pat as_needed, con_pat bs_needed] Boxed, 
-                con_pat cs_needed] 
-               (mk_index (zip3 as_needed bs_needed cs_needed))
-      where
-       -- index (l1,u1) i1 + rangeSize (l1,u1) * (index (l2,u2) i2 + ...)
-       mk_index []        = nlHsIntLit 0
-       mk_index [(l,u,i)] = mk_one l u i
-       mk_index ((l,u,i) : rest)
-         = genOpApp (
-               mk_one l u i
-           ) plus_RDR (
-               genOpApp (
-                   (nlHsApp (nlHsVar unsafeRangeSize_RDR) 
-                          (nlTuple [nlHsVar l, nlHsVar u] Boxed))
-               ) times_RDR (mk_index rest)
-          )
-       mk_one l u i
-         = nlHsApps unsafeIndex_RDR [nlTuple [nlHsVar l, nlHsVar u] Boxed, nlHsVar i]
-
-    ------------------
-    single_con_inRange
-      = mk_easy_FunBind tycon_loc inRange_RDR 
-               [nlTuplePat [con_pat as_needed, con_pat bs_needed] Boxed, 
-                con_pat cs_needed] $
-         foldl1 and_Expr (zipWith3Equal "single_con_inRange" in_range as_needed bs_needed cs_needed)
-      where
-       in_range a b c = nlHsApps inRange_RDR [nlTuple [nlHsVar a, nlHsVar b] Boxed,
-                                              nlHsVar c]
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsubsection{Generating @Read@ instance declarations}
-%*                                                                     *
-%************************************************************************
-
-Example
-
-  infix 4 %%
-  data T = Int %% Int
-        | T1 { f1 :: Int }
-        | T2 Int
-
-
-instance Read T where
-  readPrec =
-    parens
-    ( prec 4 (
-        do x           <- ReadP.step Read.readPrec
-           Symbol "%%" <- Lex.lex
-           y           <- ReadP.step Read.readPrec
-           return (x %% y))
-      +++
-      prec appPrec (
-       do Ident "T1" <- Lex.lex
-          Punc '{' <- Lex.lex
-          Ident "f1" <- Lex.lex
-          Punc '=' <- Lex.lex
-          x          <- ReadP.reset Read.readPrec
-          Punc '}' <- Lex.lex
-          return (T1 { f1 = x }))
-      +++
-      prec appPrec (
-        do Ident "T2" <- Lex.lexP
-           x          <- ReadP.step Read.readPrec
-           return (T2 x))
-    )
-
-  readListPrec = readListPrecDefault
-  readList     = readListDefault
-
-
-\begin{code}
-gen_Read_binds :: FixityEnv -> TyCon -> LHsBinds RdrName
-
-gen_Read_binds get_fixity tycon
-  = listToBag [read_prec, default_readlist, default_readlistprec]
-  where
-    -----------------------------------------------------------------------
-    default_readlist 
-       = mkVarBind loc readList_RDR     (nlHsVar readListDefault_RDR)
-
-    default_readlistprec
-       = mkVarBind loc readListPrec_RDR (nlHsVar readListPrecDefault_RDR)
-    -----------------------------------------------------------------------
-
-    loc       = getSrcSpan tycon
-    data_cons = tyConDataCons tycon
-    (nullary_cons, non_nullary_cons) = partition isNullarySrcDataCon data_cons
-    
-    read_prec = mkVarBind loc readPrec_RDR
-                             (nlHsApp (nlHsVar parens_RDR) read_cons)
-
-    read_cons            = foldr1 mk_alt (read_nullary_cons ++ read_non_nullary_cons)
-    read_non_nullary_cons = map read_non_nullary_con non_nullary_cons
-    
-    read_nullary_cons 
-      = case nullary_cons of
-           []    -> []
-           [con] -> [nlHsDo DoExpr [bindLex (ident_pat (data_con_str con))]
-                                   (result_expr con [])]
-            _     -> [nlHsApp (nlHsVar choose_RDR) 
-                           (nlList (map mk_pair nullary_cons))]
-    
-    mk_pair con = nlTuple [nlHsLit (mkHsString (data_con_str con)),
-                                  nlHsApp (nlHsVar returnM_RDR) (nlHsVar (getRdrName con))]
-                                  Boxed
-    
-    read_non_nullary_con data_con
-      = nlHsApps prec_RDR [nlHsIntLit prec, nlHsDo DoExpr stmts body]
-      where
-               stmts | is_infix          = infix_stmts
-             | length labels > 0 = lbl_stmts
-             | otherwise         = prefix_stmts
-     
-       body = result_expr data_con as_needed
-       con_str = data_con_str data_con
-       
-               prefix_stmts            -- T a b c
-                 = [bindLex (ident_pat (wrapOpParens con_str))]
-                   ++ read_args
-        
-               infix_stmts             -- a %% b, or  a `T` b 
-                 = [read_a1]
-           ++  (if isSym con_str
-                then [bindLex (symbol_pat con_str)]
-                else [read_punc "`", bindLex (ident_pat con_str), read_punc "`"])
-           ++ [read_a2]
-     
-               lbl_stmts               -- T { f1 = a, f2 = b }
-                 = [bindLex (ident_pat (wrapOpParens con_str)),
-                    read_punc "{"]
-                   ++ concat (intersperse [read_punc ","] field_stmts)
-                   ++ [read_punc "}"]
-     
-               field_stmts  = zipWithEqual "lbl_stmts" read_field labels as_needed
-     
-               con_arity    = dataConSourceArity data_con
-               labels       = dataConFieldLabels data_con
-               dc_nm        = getName data_con
-               is_infix     = dataConIsInfix data_con
-               as_needed    = take con_arity as_RDRs
-       read_args    = zipWithEqual "gen_Read_binds" read_arg as_needed (dataConOrigArgTys data_con)
-               (read_a1:read_a2:_) = read_args
-               prec         = getPrec is_infix get_fixity dc_nm
-
-    ------------------------------------------------------------------------
-    --         Helpers
-    ------------------------------------------------------------------------
-    mk_alt e1 e2     = genOpApp e1 alt_RDR e2
-    bindLex pat             = noLoc (mkBindStmt pat (nlHsVar lexP_RDR))
-    con_app c as     = nlHsVarApps (getRdrName c) as
-    result_expr c as = nlHsApp (nlHsVar returnM_RDR) (con_app c as)
-    
-    punc_pat s   = nlConPat punc_RDR   [nlLitPat (mkHsString s)]  -- Punc 'c'
-    ident_pat s  = nlConPat ident_RDR  [nlLitPat (mkHsString s)]  -- Ident "foo"
-    symbol_pat s = nlConPat symbol_RDR [nlLitPat (mkHsString s)]  -- Symbol ">>"
-    
-    data_con_str con = occNameString (getOccName con)
-    
-    read_punc c = bindLex (punc_pat c)
-    read_arg a ty 
-       | isUnLiftedType ty = pprPanic "Error in deriving:" (text "Can't read unlifted types yet:" <+> ppr ty)
-       | otherwise = noLoc (mkBindStmt (nlVarPat a) (nlHsVarApps step_RDR [readPrec_RDR]))
-    
-    read_field lbl a = read_lbl lbl ++
-                      [read_punc "=",
-                       noLoc (mkBindStmt (nlVarPat a) (nlHsVarApps reset_RDR [readPrec_RDR]))]
-
-       -- When reading field labels we might encounter
-       --      a  = 3
-       --      _a = 3
-       -- or   (#) = 4
-       -- Note the parens!
-    read_lbl lbl | isSym lbl_str 
-                = [read_punc "(", 
-                   bindLex (symbol_pat lbl_str),
-                   read_punc ")"]
-                | otherwise
-                = [bindLex (ident_pat lbl_str)]
-                where  
-                  lbl_str = occNameString (getOccName lbl) 
-\end{code}
-
-
-%************************************************************************
-%*                                                                     *
-\subsubsection{Generating @Show@ instance declarations}
-%*                                                                     *
-%************************************************************************
-
-Example
-
-    infixr 5 :^:
-
-    data Tree a =  Leaf a  |  Tree a :^: Tree a
-
-    instance (Show a) => Show (Tree a) where
-
-        showsPrec d (Leaf m) = showParen (d > app_prec) showStr
-          where
-             showStr = showString "Leaf " . showsPrec (app_prec+1) m
-
-        showsPrec d (u :^: v) = showParen (d > up_prec) showStr
-          where
-             showStr = showsPrec (up_prec+1) u . 
-                       showString " :^: "      .
-                       showsPrec (up_prec+1) v
-                -- Note: right-associativity of :^: ignored
-
-    up_prec  = 5    -- Precedence of :^:
-    app_prec = 10   -- Application has precedence one more than
-                   -- the most tightly-binding operator
-
-\begin{code}
-gen_Show_binds :: FixityEnv -> TyCon -> LHsBinds RdrName
-
-gen_Show_binds get_fixity tycon
-  = listToBag [shows_prec, show_list]
-  where
-    tycon_loc = getSrcSpan tycon
-    -----------------------------------------------------------------------
-    show_list = mkVarBind tycon_loc showList_RDR
-                 (nlHsApp (nlHsVar showList___RDR) (nlHsPar (nlHsApp (nlHsVar showsPrec_RDR) (nlHsIntLit 0))))
-    -----------------------------------------------------------------------
-    shows_prec = mk_FunBind tycon_loc showsPrec_RDR (map pats_etc (tyConDataCons tycon))
-      where
-       pats_etc data_con
-         | nullary_con =  -- skip the showParen junk...
-            ASSERT(null bs_needed)
-            ([nlWildPat, con_pat], mk_showString_app con_str)
-         | otherwise   =
-            ([a_Pat, con_pat],
-                 showParen_Expr (nlHsPar (genOpApp a_Expr ge_RDR (nlHsLit (HsInt con_prec_plus_one))))
-                                (nlHsPar (nested_compose_Expr show_thingies)))
-           where
-            data_con_RDR  = getRdrName data_con
-            con_arity     = dataConSourceArity data_con
-            bs_needed     = take con_arity bs_RDRs
-            arg_tys       = dataConOrigArgTys data_con         -- Correspond 1-1 with bs_needed
-            con_pat       = nlConVarPat data_con_RDR bs_needed
-            nullary_con   = con_arity == 0
-             labels        = dataConFieldLabels data_con
-            lab_fields    = length labels
-            record_syntax = lab_fields > 0
-
-            dc_nm          = getName data_con
-            dc_occ_nm      = getOccName data_con
-             con_str        = occNameString dc_occ_nm
-            op_con_str     = wrapOpParens con_str
-            backquote_str  = wrapOpBackquotes con_str
-
-            show_thingies 
-               | is_infix      = [show_arg1, mk_showString_app (" " ++ backquote_str ++ " "), show_arg2]
-               | record_syntax = mk_showString_app (op_con_str ++ " {") : 
-                                 show_record_args ++ [mk_showString_app "}"]
-               | otherwise     = mk_showString_app (op_con_str ++ " ") : show_prefix_args
-                
-            show_label l = mk_showString_app (nm ++ " = ")
-                       -- Note the spaces around the "=" sign.  If we don't have them
-                       -- then we get Foo { x=-1 } and the "=-" parses as a single
-                       -- lexeme.  Only the space after the '=' is necessary, but
-                       -- it seems tidier to have them both sides.
-                where
-                  occ_nm   = getOccName l
-                  nm       = wrapOpParens (occNameString occ_nm)
-
-             show_args                      = zipWith show_arg bs_needed arg_tys
-            (show_arg1:show_arg2:_) = show_args
-            show_prefix_args        = intersperse (nlHsVar showSpace_RDR) show_args
-
-               --  Assumption for record syntax: no of fields == no of labelled fields 
-               --            (and in same order)
-            show_record_args = concat $
-                               intersperse [mk_showString_app ", "] $
-                               [ [show_label lbl, arg] 
-                               | (lbl,arg) <- zipEqual "gen_Show_binds" 
-                                                       labels show_args ]
-                              
-               -- Generates (showsPrec p x) for argument x, but it also boxes
-               -- the argument first if necessary.  Note that this prints unboxed
-               -- things without any '#' decorations; could change that if need be
-            show_arg b arg_ty = nlHsApps showsPrec_RDR [nlHsLit (HsInt arg_prec), 
-                                                        box_if_necy "Show" tycon (nlHsVar b) arg_ty]
-
-               -- Fixity stuff
-            is_infix = dataConIsInfix data_con
-             con_prec_plus_one = 1 + getPrec is_infix get_fixity dc_nm
-            arg_prec | record_syntax = 0       -- Record fields don't need parens
-                     | otherwise     = con_prec_plus_one
-
-wrapOpParens :: String -> String
-wrapOpParens s | isSym s   = '(' : s ++ ")"
-              | otherwise = s
-
-wrapOpBackquotes :: String -> String
-wrapOpBackquotes s | isSym s   = s
-                  | otherwise = '`' : s ++ "`"
-
-isSym :: String -> Bool
-isSym ""     = False
-isSym (c:cs) = startsVarSym c || startsConSym c
-
-mk_showString_app str = nlHsApp (nlHsVar showString_RDR) (nlHsLit (mkHsString str))
-\end{code}
-
-\begin{code}
-getPrec :: Bool -> FixityEnv -> Name -> Integer
-getPrec is_infix get_fixity nm 
-  | not is_infix   = appPrecedence
-  | otherwise      = getPrecedence get_fixity nm
-                 
-appPrecedence :: Integer
-appPrecedence = fromIntegral maxPrecedence + 1
-  -- One more than the precedence of the most 
-  -- tightly-binding operator
-
-getPrecedence :: FixityEnv -> Name -> Integer
-getPrecedence get_fixity nm 
-   = case lookupFixity get_fixity nm of
-        Fixity x _ -> fromIntegral x
-\end{code}
-
-
-%************************************************************************
-%*                                                                     *
-\subsection{Typeable}
-%*                                                                     *
-%************************************************************************
-
-From the data type
-
-       data T a b = ....
-
-we generate
-
-       instance Typeable2 T where
-               typeOf2 _ = mkTyConApp (mkTyConRep "T") []
-
-We are passed the Typeable2 class as well as T
-
-\begin{code}
-gen_Typeable_binds :: TyCon -> LHsBinds RdrName
-gen_Typeable_binds tycon
-  = unitBag $
-       mk_easy_FunBind tycon_loc 
-               (mk_typeOf_RDR tycon)   -- Name of appropriate type0f function
-               [nlWildPat] 
-               (nlHsApps mkTypeRep_RDR [tycon_rep, nlList []])
-  where
-    tycon_loc = getSrcSpan tycon
-    tycon_rep = nlHsVar mkTyConRep_RDR `nlHsApp` nlHsLit (mkHsString (showSDoc (ppr tycon)))
-
-mk_typeOf_RDR :: TyCon -> RdrName
--- Use the arity of the TyCon to make the right typeOfn function
-mk_typeOf_RDR tycon = varQual_RDR tYPEABLE (mkFastString ("typeOf" ++ suffix))
-               where
-                 arity = tyConArity tycon
-                 suffix | arity == 0 = ""
-                        | otherwise  = show arity
-\end{code}
-
-
-
-%************************************************************************
-%*                                                                     *
-\subsection{Data}
-%*                                                                     *
-%************************************************************************
-
-From the data type
-
-  data T a b = T1 a b | T2
-
-we generate
-
-  $cT1 = mkDataCon $dT "T1" Prefix
-  $cT2 = mkDataCon $dT "T2" Prefix
-  $dT  = mkDataType "Module.T" [] [$con_T1, $con_T2]
-  -- the [] is for field labels.
-
-  instance (Data a, Data b) => Data (T a b) where
-    gfoldl k z (T1 a b) = z T `k` a `k` b
-    gfoldl k z T2          = z T2
-    -- ToDo: add gmapT,Q,M, gfoldr
-    gunfold k z c = case conIndex c of
-                       I# 1# -> k (k (z T1))
-                       I# 2# -> z T2
-
-    toConstr (T1 _ _) = $cT1
-    toConstr T2              = $cT2
-    
-    dataTypeOf _ = $dT
-
-\begin{code}
-gen_Data_binds :: FixityEnv
-              -> TyCon 
-              -> (LHsBinds RdrName,    -- The method bindings
-                  LHsBinds RdrName)    -- Auxiliary bindings
-gen_Data_binds fix_env tycon
-  = (listToBag [gfoldl_bind, gunfold_bind, toCon_bind, dataTypeOf_bind],
-               -- Auxiliary definitions: the data type and constructors
-     datatype_bind `consBag` listToBag (map mk_con_bind data_cons))
-  where
-    tycon_loc  = getSrcSpan tycon
-    tycon_name = tyConName tycon
-    data_cons  = tyConDataCons tycon
-    n_cons     = length data_cons
-    one_constr = n_cons == 1
-
-       ------------ gfoldl
-    gfoldl_bind = mk_FunBind tycon_loc gfoldl_RDR (map gfoldl_eqn data_cons)
-    gfoldl_eqn con = ([nlVarPat k_RDR, nlVarPat z_RDR, nlConVarPat con_name as_needed], 
-                      foldl mk_k_app (nlHsVar z_RDR `nlHsApp` nlHsVar con_name) as_needed)
-                  where
-                    con_name ::  RdrName
-                    con_name = getRdrName con
-                    as_needed = take (dataConSourceArity con) as_RDRs
-                    mk_k_app e v = nlHsPar (nlHsOpApp e k_RDR (nlHsVar v))
-
-       ------------ gunfold
-    gunfold_bind = mk_FunBind tycon_loc
-                              gunfold_RDR
-                              [([k_Pat, z_Pat, if one_constr then nlWildPat else c_Pat], 
-                               gunfold_rhs)]
-
-    gunfold_rhs 
-       | one_constr = mk_unfold_rhs (head data_cons)   -- No need for case
-       | otherwise  = nlHsCase (nlHsVar conIndex_RDR `nlHsApp` c_Expr) 
-                               (map gunfold_alt data_cons)
-
-    gunfold_alt dc = mkSimpleHsAlt (mk_unfold_pat dc) (mk_unfold_rhs dc)
-    mk_unfold_rhs dc = foldr nlHsApp
-                           (nlHsVar z_RDR `nlHsApp` nlHsVar (getRdrName dc))
-                           (replicate (dataConSourceArity dc) (nlHsVar k_RDR))
-
-    mk_unfold_pat dc   -- Last one is a wild-pat, to avoid 
-                       -- redundant test, and annoying warning
-      | tag-fIRST_TAG == n_cons-1 = nlWildPat  -- Last constructor
-      | otherwise = nlConPat intDataCon_RDR [nlLitPat (HsIntPrim (toInteger tag))]
-      where 
-       tag = dataConTag dc
-                         
-       ------------ toConstr
-    toCon_bind = mk_FunBind tycon_loc toConstr_RDR (map to_con_eqn data_cons)
-    to_con_eqn dc = ([nlWildConPat dc], nlHsVar (mk_constr_name dc))
-    
-       ------------ dataTypeOf
-    dataTypeOf_bind = mk_easy_FunBind
-                        tycon_loc
-                        dataTypeOf_RDR
-                       [nlWildPat]
-                        (nlHsVar data_type_name)
-
-       ------------  $dT
-
-    data_type_name = mkDerivedRdrName tycon_name mkDataTOcc
-    datatype_bind  = mkVarBind
-                       tycon_loc
-                       data_type_name
-                      (           nlHsVar mkDataType_RDR 
-                         `nlHsApp` nlHsLit (mkHsString (showSDoc (ppr tycon)))
-                         `nlHsApp` nlList constrs
-                       )
-    constrs = [nlHsVar (mk_constr_name con) | con <- data_cons]
-
-
-       ------------  $cT1 etc
-    mk_constr_name con = mkDerivedRdrName (dataConName con) mkDataCOcc
-    mk_con_bind dc = mkVarBind
-                       tycon_loc
-                       (mk_constr_name dc) 
-                      (nlHsApps mkConstr_RDR (constr_args dc))
-    constr_args dc =
-        [ -- nlHsIntLit (toInteger (dataConTag dc)),           -- Tag
-          nlHsVar data_type_name,                              -- DataType
-          nlHsLit (mkHsString (occNameString dc_occ)), -- String name
-           nlList  labels,                                     -- Field labels
-          nlHsVar fixity]                                      -- Fixity
-       where
-          labels   = map (nlHsLit . mkHsString . getOccString)
-                         (dataConFieldLabels dc)
-         dc_occ   = getOccName dc
-         is_infix = isDataSymOcc dc_occ
-         fixity | is_infix  = infix_RDR
-                | otherwise = prefix_RDR
-
-gfoldl_RDR     = varQual_RDR gENERICS FSLIT("gfoldl")
-gunfold_RDR    = varQual_RDR gENERICS FSLIT("gunfold")
-toConstr_RDR   = varQual_RDR gENERICS FSLIT("toConstr")
-dataTypeOf_RDR = varQual_RDR gENERICS FSLIT("dataTypeOf")
-mkConstr_RDR   = varQual_RDR gENERICS FSLIT("mkConstr")
-mkDataType_RDR = varQual_RDR gENERICS FSLIT("mkDataType")
-conIndex_RDR   = varQual_RDR gENERICS FSLIT("constrIndex")
-prefix_RDR     = dataQual_RDR gENERICS FSLIT("Prefix")
-infix_RDR      = dataQual_RDR gENERICS FSLIT("Infix")
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsection{Generating extra binds (@con2tag@ and @tag2con@)}
-%*                                                                     *
-%************************************************************************
-
-\begin{verbatim}
-data Foo ... = ...
-
-con2tag_Foo :: Foo ... -> Int#
-tag2con_Foo :: Int -> Foo ...  -- easier if Int, not Int#
-maxtag_Foo  :: Int             -- ditto (NB: not unlifted)
-\end{verbatim}
-
-The `tags' here start at zero, hence the @fIRST_TAG@ (currently one)
-fiddling around.
-
-\begin{code}
-data TagThingWanted
-  = GenCon2Tag | GenTag2Con | GenMaxTag
-
-gen_tag_n_con_monobind
-    :: ( RdrName,          -- (proto)Name for the thing in question
-       TyCon,              -- tycon in question
-       TagThingWanted)
-    -> LHsBind RdrName
-
-gen_tag_n_con_monobind (rdr_name, tycon, GenCon2Tag)
-  | lots_of_constructors
-  = mk_FunBind tycon_loc rdr_name [([], get_tag_rhs)]
-
-  | otherwise
-  = mk_FunBind tycon_loc rdr_name (map mk_stuff (tyConDataCons tycon))
-
-  where
-    tycon_loc = getSrcSpan tycon
-
-    tvs = map (mkRdrUnqual . getOccName) (tyConTyVars tycon)
-       -- We can't use gerRdrName because that makes an Exact  RdrName
-       -- and we can't put them in the LocalRdrEnv
-
-       -- Give a signature to the bound variable, so 
-       -- that the case expression generated by getTag is
-       -- monomorphic.  In the push-enter model we get better code.
-    get_tag_rhs = noLoc $ ExprWithTySig 
-                       (nlHsLam (mkSimpleHsAlt (nlVarPat a_RDR) 
-                                             (nlHsApp (nlHsVar getTag_RDR) a_Expr)))
-                       (noLoc (mkExplicitHsForAllTy (map (noLoc.UserTyVar) tvs) (noLoc []) con2tag_ty))
-
-    con2tag_ty = foldl nlHsAppTy (nlHsTyVar (getRdrName tycon)) 
-                      (map nlHsTyVar tvs)
-               `nlHsFunTy` 
-               nlHsTyVar (getRdrName intPrimTyCon)
-
-    lots_of_constructors = tyConFamilySize tycon > mAX_FAMILY_SIZE_FOR_VEC_RETURNS
-
-    mk_stuff :: DataCon -> ([LPat RdrName], LHsExpr RdrName)
-    mk_stuff con = ([nlWildConPat con], 
-                   nlHsLit (HsIntPrim (toInteger ((dataConTag con) - fIRST_TAG))))
-
-gen_tag_n_con_monobind (rdr_name, tycon, GenTag2Con)
-  = mk_FunBind (getSrcSpan tycon) rdr_name 
-       [([nlConVarPat intDataCon_RDR [a_RDR]], 
-          noLoc (ExprWithTySig (nlHsApp (nlHsVar tagToEnum_RDR) a_Expr) 
-                        (nlHsTyVar (getRdrName tycon))))]
-
-gen_tag_n_con_monobind (rdr_name, tycon, GenMaxTag)
-  = mkVarBind (getSrcSpan tycon) rdr_name 
-                 (nlHsApp (nlHsVar intDataCon_RDR) (nlHsLit (HsIntPrim max_tag)))
-  where
-    max_tag =  case (tyConDataCons tycon) of
-                data_cons -> toInteger ((length data_cons) - fIRST_TAG)
-
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsection{Utility bits for generating bindings}
-%*                                                                     *
-%************************************************************************
-
-
-ToDo: Better SrcLocs.
-
-\begin{code}
-compare_gen_Case ::
-         LHsExpr RdrName       -- What to do for equality
-         -> LHsExpr RdrName -> LHsExpr RdrName
-         -> LHsExpr RdrName
-careful_compare_Case :: -- checks for primitive types...
-         TyCon                 -- The tycon we are deriving for
-         -> Type
-         -> LHsExpr RdrName    -- What to do for equality
-         -> LHsExpr RdrName -> LHsExpr RdrName
-         -> LHsExpr RdrName
-
-cmp_eq_Expr a b = nlHsApp (nlHsApp (nlHsVar cmp_eq_RDR) a) b
-       -- Was: compare_gen_Case cmp_eq_RDR
-
-compare_gen_Case (L _ (HsVar eq_tag)) a b | eq_tag == eqTag_RDR
-  = nlHsApp (nlHsApp (nlHsVar compare_RDR) a) b        -- Simple case 
-compare_gen_Case eq a b                                -- General case
-  = nlHsCase (nlHsPar (nlHsApp (nlHsApp (nlHsVar compare_RDR) a) b)) {-of-}
-      [mkSimpleHsAlt (nlNullaryConPat ltTag_RDR) ltTag_Expr,
-       mkSimpleHsAlt (nlNullaryConPat eqTag_RDR) eq,
-       mkSimpleHsAlt (nlNullaryConPat gtTag_RDR) gtTag_Expr]
-
-careful_compare_Case tycon ty eq a b
-  | not (isUnLiftedType ty)
-  = compare_gen_Case eq a b
-  | otherwise      -- We have to do something special for primitive things...
-  = nlHsIf (genOpApp a relevant_eq_op b)
-        eq
-        (nlHsIf (genOpApp a relevant_lt_op b) ltTag_Expr gtTag_Expr)
-  where
-    relevant_eq_op = primOpRdrName (assoc_ty_id "Ord" tycon eq_op_tbl ty)
-    relevant_lt_op = primOpRdrName (assoc_ty_id "Ord" tycon lt_op_tbl ty)
-
-
-box_if_necy :: String          -- The class involved
-           -> TyCon            -- The tycon involved
-           -> LHsExpr RdrName  -- The argument
-           -> Type             -- The argument type
-           -> LHsExpr RdrName  -- Boxed version of the arg
-box_if_necy cls_str tycon arg arg_ty
-  | isUnLiftedType arg_ty = nlHsApp (nlHsVar box_con) arg
-  | otherwise            = arg
-  where
-    box_con = assoc_ty_id cls_str tycon box_con_tbl arg_ty
-
-assoc_ty_id :: String          -- The class involved
-           -> TyCon            -- The tycon involved
-           -> [(Type,a)]       -- The table
-           -> Type             -- The type
-           -> a                -- The result of the lookup
-assoc_ty_id cls_str tycon tbl ty 
-  | null res = pprPanic "Error in deriving:" (text "Can't derive" <+> text cls_str <+> 
-                                             text "for primitive type" <+> ppr ty)
-  | otherwise = head res
-  where
-    res = [id | (ty',id) <- tbl, ty `tcEqType` ty']
-
-eq_op_tbl :: [(Type, PrimOp)]
-eq_op_tbl =
-    [(charPrimTy,      CharEqOp)
-    ,(intPrimTy,       IntEqOp)
-    ,(wordPrimTy,      WordEqOp)
-    ,(addrPrimTy,      AddrEqOp)
-    ,(floatPrimTy,     FloatEqOp)
-    ,(doublePrimTy,    DoubleEqOp)
-    ]
-
-lt_op_tbl :: [(Type, PrimOp)]
-lt_op_tbl =
-    [(charPrimTy,      CharLtOp)
-    ,(intPrimTy,       IntLtOp)
-    ,(wordPrimTy,      WordLtOp)
-    ,(addrPrimTy,      AddrLtOp)
-    ,(floatPrimTy,     FloatLtOp)
-    ,(doublePrimTy,    DoubleLtOp)
-    ]
-
-box_con_tbl =
-    [(charPrimTy,      getRdrName charDataCon)
-    ,(intPrimTy,       getRdrName intDataCon)
-    ,(wordPrimTy,      wordDataCon_RDR)
-    ,(addrPrimTy,      addrDataCon_RDR)
-    ,(floatPrimTy,     getRdrName floatDataCon)
-    ,(doublePrimTy,    getRdrName doubleDataCon)
-    ]
-
------------------------------------------------------------------------
-
-and_Expr :: LHsExpr RdrName -> LHsExpr RdrName -> LHsExpr RdrName
-and_Expr a b = genOpApp a and_RDR    b
-
------------------------------------------------------------------------
-
-eq_Expr :: TyCon -> Type -> LHsExpr RdrName -> LHsExpr RdrName -> LHsExpr RdrName
-eq_Expr tycon ty a b = genOpApp a eq_op b
- where
-   eq_op
-    | not (isUnLiftedType ty) = eq_RDR
-    | otherwise               = primOpRdrName (assoc_ty_id "Eq" tycon eq_op_tbl ty)
-         -- we have to do something special for primitive things...
-\end{code}
-
-\begin{code}
-untag_Expr :: TyCon -> [( RdrName,  RdrName)] -> LHsExpr RdrName -> LHsExpr RdrName
-untag_Expr tycon [] expr = expr
-untag_Expr tycon ((untag_this, put_tag_here) : more) expr
-  = nlHsCase (nlHsPar (nlHsVarApps (con2tag_RDR tycon) [untag_this])) {-of-}
-      [mkSimpleHsAlt (nlVarPat put_tag_here) (untag_Expr tycon more expr)]
-
-cmp_tags_Expr ::  RdrName              -- Comparison op
-            ->  RdrName ->  RdrName    -- Things to compare
-            -> LHsExpr RdrName                 -- What to return if true
-            -> LHsExpr RdrName         -- What to return if false
-            -> LHsExpr RdrName
-
-cmp_tags_Expr op a b true_case false_case
-  = nlHsIf (genOpApp (nlHsVar a) op (nlHsVar b)) true_case false_case
-
-enum_from_to_Expr
-       :: LHsExpr RdrName -> LHsExpr RdrName
-       -> LHsExpr RdrName
-enum_from_then_to_Expr
-       :: LHsExpr RdrName -> LHsExpr RdrName -> LHsExpr RdrName
-       -> LHsExpr RdrName
-
-enum_from_to_Expr      f   t2 = nlHsApp (nlHsApp (nlHsVar enumFromTo_RDR) f) t2
-enum_from_then_to_Expr f t t2 = nlHsApp (nlHsApp (nlHsApp (nlHsVar enumFromThenTo_RDR) f) t) t2
-
-showParen_Expr
-       :: LHsExpr RdrName -> LHsExpr RdrName
-       -> LHsExpr RdrName
-
-showParen_Expr e1 e2 = nlHsApp (nlHsApp (nlHsVar showParen_RDR) e1) e2
-
-nested_compose_Expr :: [LHsExpr RdrName] -> LHsExpr RdrName
-
-nested_compose_Expr [e] = parenify e
-nested_compose_Expr (e:es)
-  = nlHsApp (nlHsApp (nlHsVar compose_RDR) (parenify e)) (nested_compose_Expr es)
-
--- impossible_Expr is used in case RHSs that should never happen.
--- We generate these to keep the desugarer from complaining that they *might* happen!
-impossible_Expr = nlHsApp (nlHsVar error_RDR) (nlHsLit (mkHsString "Urk! in TcGenDeriv"))
-
--- illegal_Expr is used when signalling error conditions in the RHS of a derived
--- method. It is currently only used by Enum.{succ,pred}
-illegal_Expr meth tp msg = 
-   nlHsApp (nlHsVar error_RDR) (nlHsLit (mkHsString (meth ++ '{':tp ++ "}: " ++ msg)))
-
--- illegal_toEnum_tag is an extended version of illegal_Expr, which also allows you
--- to include the value of a_RDR in the error string.
-illegal_toEnum_tag tp maxtag =
-   nlHsApp (nlHsVar error_RDR) 
-           (nlHsApp (nlHsApp (nlHsVar append_RDR)
-                      (nlHsLit (mkHsString ("toEnum{" ++ tp ++ "}: tag ("))))
-                   (nlHsApp (nlHsApp (nlHsApp 
-                          (nlHsVar showsPrec_RDR)
-                          (nlHsIntLit 0))
-                          (nlHsVar a_RDR))
-                          (nlHsApp (nlHsApp 
-                              (nlHsVar append_RDR)
-                              (nlHsLit (mkHsString ") is outside of enumeration's range (0,")))
-                              (nlHsApp (nlHsApp (nlHsApp 
-                                       (nlHsVar showsPrec_RDR)
-                                       (nlHsIntLit 0))
-                                       (nlHsVar maxtag))
-                                       (nlHsLit (mkHsString ")"))))))
-
-parenify e@(L _ (HsVar _)) = e
-parenify e                = mkHsPar e
-
--- genOpApp wraps brackets round the operator application, so that the
--- renamer won't subsequently try to re-associate it. 
-genOpApp e1 op e2 = nlHsPar (nlHsOpApp e1 op e2)
-\end{code}
-
-\begin{code}
-getSrcSpan = srcLocSpan . getSrcLoc
-\end{code}
-
-\begin{code}
-a_RDR          = mkVarUnqual FSLIT("a")
-b_RDR          = mkVarUnqual FSLIT("b")
-c_RDR          = mkVarUnqual FSLIT("c")
-d_RDR          = mkVarUnqual FSLIT("d")
-k_RDR          = mkVarUnqual FSLIT("k")
-z_RDR          = mkVarUnqual FSLIT("z")
-ah_RDR         = mkVarUnqual FSLIT("a#")
-bh_RDR         = mkVarUnqual FSLIT("b#")
-ch_RDR         = mkVarUnqual FSLIT("c#")
-dh_RDR         = mkVarUnqual FSLIT("d#")
-cmp_eq_RDR     = mkVarUnqual FSLIT("cmp_eq")
-
-as_RDRs                = [ mkVarUnqual (mkFastString ("a"++show i)) | i <- [(1::Int) .. ] ]
-bs_RDRs                = [ mkVarUnqual (mkFastString ("b"++show i)) | i <- [(1::Int) .. ] ]
-cs_RDRs                = [ mkVarUnqual (mkFastString ("c"++show i)) | i <- [(1::Int) .. ] ]
-
-a_Expr         = nlHsVar a_RDR
-b_Expr         = nlHsVar b_RDR
-c_Expr         = nlHsVar c_RDR
-ltTag_Expr     = nlHsVar ltTag_RDR
-eqTag_Expr     = nlHsVar eqTag_RDR
-gtTag_Expr     = nlHsVar gtTag_RDR
-false_Expr     = nlHsVar false_RDR
-true_Expr      = nlHsVar true_RDR
-
-a_Pat          = nlVarPat a_RDR
-b_Pat          = nlVarPat b_RDR
-c_Pat          = nlVarPat c_RDR
-d_Pat          = nlVarPat d_RDR
-k_Pat          = nlVarPat k_RDR
-z_Pat          = nlVarPat z_RDR
-
-con2tag_RDR, tag2con_RDR, maxtag_RDR :: TyCon ->  RdrName
--- Generates Orig s RdrName, for the binding positions
-con2tag_RDR tycon = mk_tc_deriv_name tycon "con2tag_"
-tag2con_RDR tycon = mk_tc_deriv_name tycon "tag2con_"
-maxtag_RDR  tycon = mk_tc_deriv_name tycon "maxtag_"
-
-mk_tc_deriv_name tycon str 
-  = mkDerivedRdrName tc_name mk_occ
-  where
-    tc_name = tyConName tycon
-    mk_occ tc_occ = mkVarOccFS (mkFastString new_str)
-                 where
-                   new_str = str ++ occNameString tc_occ ++ "#"
-\end{code}
-
-s RdrName for PrimOps.  Can't be done in PrelNames, because PrimOp imports
-PrelNames, so PrelNames can't import PrimOp.
-
-\begin{code}
-primOpRdrName op = getRdrName (primOpId op)
-
-minusInt_RDR  = primOpRdrName IntSubOp
-eqInt_RDR     = primOpRdrName IntEqOp
-ltInt_RDR     = primOpRdrName IntLtOp
-geInt_RDR     = primOpRdrName IntGeOp
-leInt_RDR     = primOpRdrName IntLeOp
-tagToEnum_RDR = primOpRdrName TagToEnumOp
-
-error_RDR = getRdrName eRROR_ID
-\end{code}