[project @ 2006-01-06 16:30:17 by simonmar]
[ghc-hetmet.git] / ghc / compiler / typecheck / TcGenDeriv.lhs
index f449cca..94bb152 100644 (file)
@@ -1,5 +1,5 @@
 %
-% (c) The GRASP/AQUA Project, Glasgow University, 1992-1996
+% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
 %
 \section[TcGenDeriv]{Generating derived instance declarations}
 
@@ -9,88 +9,57 @@ This module is nominally ``subordinate'' to @TcDeriv@, which is the
 This is where we do all the grimy bindings' generation.
 
 \begin{code}
-#include "HsVersions.h"
-
 module TcGenDeriv (
-       a_Expr,
-       a_PN,
-       a_Pat,
-       ah_PN,
-       b_Expr,
-       b_PN,
-       b_Pat,
-       bh_PN,
-       c_Expr,
-       c_PN,
-       c_Pat,
-       ch_PN,
-       cmp_eq_PN,
-       d_Expr,
-       d_PN,
-       d_Pat,
-       dh_PN,
-       eqH_Int_PN,
-       eqTag_Expr,
-       eq_PN,
-       error_PN,
-       false_Expr,
-       false_PN,
-       geH_PN,
        gen_Bounded_binds,
        gen_Enum_binds,
-       gen_Eval_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,
-       gtTag_Expr,
-       gt_PN,
-       leH_PN,
-       ltH_Int_PN,
-       ltTag_Expr,
-       lt_PN,
-       minusH_PN,
-       mkInt_PN,
-       rangeSize_PN,
-       true_Expr,
-       true_PN,
-
-       con2tag_PN, tag2con_PN, maxtag_PN,
+
+       con2tag_RDR, tag2con_RDR, maxtag_RDR,
 
        TagThingWanted(..)
     ) where
 
-IMP_Ubiq()
-IMPORT_1_3(List(partition))
-
-import HsSyn           ( HsBinds(..), Bind(..), MonoBinds(..), Match(..), GRHSsAndBinds(..),
-                         GRHS(..), HsExpr(..), HsLit(..), InPat(..), Qualifier(..), Stmt,
-                         ArithSeqInfo, Sig, PolyType, FixityDecl, Fake )
-import RdrHsSyn                ( SYN_IE(RdrNameMonoBinds), SYN_IE(RdrNameHsExpr), SYN_IE(RdrNamePat) )
-import RnHsSyn         ( RenamedFixityDecl(..) )
---import RnUtils
-
-import Id              ( GenId, dataConNumFields, isNullaryDataCon, dataConTag,
-                         dataConRawArgTys, fIRST_TAG,
-                         isDataCon, SYN_IE(DataCon), SYN_IE(ConTag) )
-import IdUtils         ( primOpId )
-import Maybes          ( maybeToBool )
-import Name            ( origName, preludeQual, nameOf, RdrName(..), OrigName(..) )
-import PrelMods                ( pRELUDE, gHC__, iX )
-import PrelVals                ( eRROR_ID )
+#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          ( mkGeneratedSrcLoc )
-import TyCon           ( TyCon, tyConDataCons, isEnumerationTyCon, maybeTyConSingleCon )
-import Type            ( eqTy, isPrimType )
-import TysPrim         ( charPrimTy, intPrimTy, wordPrimTy, addrPrimTy,
-                         floatPrimTy, doublePrimTy
+import SrcLoc          ( Located(..), noLoc, srcLocSpan )
+import TyCon           ( TyCon, isNewTyCon, tyConDataCons, isEnumerationTyCon, tyConArity,
+                         maybeTyConSingleCon, tyConFamilySize, tyConTyVars, tyConName
                        )
-import TysWiredIn      ( falseDataCon, trueDataCon, intDataCon )
---import Unique
-import Util            ( mapAccumL, zipEqual, zipWith3Equal, nOfThem, panic, assertPanic )
+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}
 
 %************************************************************************
@@ -126,7 +95,7 @@ data Foo ... = N1 | N2 ... | Nn | O1 a b | O2 Int | O3 Double b b | ...
 (==) (O3 a1 b1 c1) (O3 a2 b2 c2) = a1 == a2 && b1 == b2 && c1 == c2
 \end{verbatim}
 
-  Note: if we're comparing unboxed things, e.g., if \tr{a1} and
+  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
@@ -172,51 +141,54 @@ instance ... Eq (Foo ...) where
   produced don't get through the typechecker.
 \end{itemize}
 
+
 \begin{code}
-gen_Eq_binds :: TyCon -> RdrNameMonoBinds
+gen_Eq_binds :: TyCon -> LHsBinds RdrName
 
 gen_Eq_binds tycon
   = let
-       (nullary_cons, nonnullary_cons)
-         = partition isNullaryDataCon (tyConDataCons tycon)
+       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
-                    [([a_Pat, b_Pat], false_Expr)]
+                    [([nlWildPat, nlWildPat], false_Expr)]
            else -- calc. and compare the tags
                 [([a_Pat, b_Pat],
-                   untag_Expr tycon [(a_PN,ah_PN), (b_PN,bh_PN)]
-                     (cmp_tags_Expr eqH_Int_PN ah_PN bh_PN true_Expr false_Expr))]
+                   untag_Expr tycon [(a_RDR,ah_RDR), (b_RDR,bh_RDR)]
+                              (genOpApp (nlHsVar ah_RDR) eqInt_RDR (nlHsVar bh_RDR)))]
     in
-    mk_FunMonoBind eq_PN ((map pats_etc nonnullary_cons) ++ rest)
-    `AndMonoBinds` boring_ne_method
+    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 = ConPatIn data_con_PN (map VarPatIn as_needed)
-           con2_pat = ConPatIn data_con_PN (map VarPatIn bs_needed)
+           con1_pat = nlConVarPat data_con_RDR as_needed
+           con2_pat = nlConVarPat data_con_RDR bs_needed
 
-           data_con_PN = qual_orig_name data_con
+           data_con_RDR = getRdrName data_con
            con_arity   = length tys_needed
-           as_needed   = take con_arity as_PNs
-           bs_needed   = take con_arity bs_PNs
-           tys_needed  = dataConRawArgTys data_con
+           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
-         = foldr1 and_Expr (zipWith3Equal "nested_eq" nested_eq tys as bs)
+         = foldl1 and_Expr (zipWith3Equal "nested_eq" nested_eq tys as bs)
          where
-           nested_eq ty a b = HsPar (eq_Expr ty (HsVar a) (HsVar b))
-
-boring_ne_method
-  = mk_easy_FunMonoBind ne_PN [a_Pat, b_Pat] [] $
-       HsApp (HsVar not_PN) (HsPar (mk_easy_App eq_PN [a_PN, b_PN]))
+           nested_eq ty a b = nlHsPar (eq_Expr tycon ty (nlHsVar a) (nlHsVar b))
 \end{code}
 
 %************************************************************************
@@ -294,9 +266,10 @@ cmp_eq (O3 a1 b1 c1) (O3 a2 b2 c2)
     }
 \end{verbatim}
 
-  Again, we must be careful about unboxed comparisons.  For example,
+  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
@@ -311,80 +284,80 @@ 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 -> RdrNameMonoBinds
+gen_Ord_binds :: TyCon -> LHsBinds RdrName
 
 gen_Ord_binds tycon
-  = defaulted `AndMonoBinds` compare
+  = unitBag compare    -- `AndMonoBinds` compare       
+               -- The default declaration in PrelBase handles this
   where
+    tycon_loc = getSrcSpan tycon
     --------------------------------------------------------------------
-    compare = mk_easy_FunMonoBind compare_PN
-               [a_Pat, b_Pat]
-               [cmp_eq]
-           (if maybeToBool (maybeTyConSingleCon tycon) then
-               cmp_eq_Expr ltTag_Expr eqTag_Expr gtTag_Expr a_Expr b_Expr
-            else
-               untag_Expr tycon [(a_PN, ah_PN), (b_PN, bh_PN)]
-                 (cmp_tags_Expr eqH_Int_PN ah_PN bh_PN
-                       -- True case; they are equal
-                       -- If an enumeration type we are done; else
-                       -- recursively compare their components
-                   (if isEnumerationTyCon tycon then
-                       eqTag_Expr
-                    else
-                       cmp_eq_Expr ltTag_Expr eqTag_Expr gtTag_Expr a_Expr b_Expr
-                   )
+
+    compare = L tycon_loc (FunBind (L tycon_loc compare_RDR) False compare_matches placeHolderNames)
+    compare_matches = mkMatchGroup [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 ltH_Int_PN ah_PN bh_PN ltTag_Expr gtTag_Expr)))
+                       (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)
-      = partition isNullaryDataCon (tyConDataCons tycon)
+       | 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)])
 
-    cmp_eq
-      = mk_FunMonoBind cmp_eq_PN (map pats_etc nonnullary_cons ++ deflt_pats_etc)
       where
        pats_etc data_con
          = ([con1_pat, con2_pat],
             nested_compare_expr tys_needed as_needed bs_needed)
          where
-           con1_pat = ConPatIn data_con_PN (map VarPatIn as_needed)
-           con2_pat = ConPatIn data_con_PN (map VarPatIn bs_needed)
+           con1_pat = nlConVarPat data_con_RDR as_needed
+           con2_pat = nlConVarPat data_con_RDR bs_needed
 
-           data_con_PN = qual_orig_name data_con
+           data_con_RDR = getRdrName data_con
            con_arity   = length tys_needed
-           as_needed   = take con_arity as_PNs
-           bs_needed   = take con_arity bs_PNs
-           tys_needed  = dataConRawArgTys data_con
+           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 ty ltTag_Expr eqTag_Expr gtTag_Expr (HsVar a) (HsVar 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 ty ltTag_Expr eq_expr gtTag_Expr (HsVar a) (HsVar b)
-
-       deflt_pats_etc
-         = if null nullary_cons
-           then []
-           else [([a_Pat, b_Pat], eqTag_Expr)]
-    --------------------------------------------------------------------
+               in  careful_compare_Case tycon ty eq_expr (nlHsVar a) (nlHsVar b)
 
-defaulted = foldr1 AndMonoBinds [lt, le, ge, gt, max_, min_]
-
-lt = mk_easy_FunMonoBind lt_PN [a_Pat, b_Pat] [] (
-           compare_Case true_Expr  false_Expr false_Expr a_Expr b_Expr)
-le = mk_easy_FunMonoBind le_PN [a_Pat, b_Pat] [] (
-           compare_Case true_Expr  true_Expr  false_Expr a_Expr b_Expr)
-ge = mk_easy_FunMonoBind ge_PN [a_Pat, b_Pat] [] (
-           compare_Case false_Expr true_Expr  true_Expr  a_Expr b_Expr)
-gt = mk_easy_FunMonoBind gt_PN [a_Pat, b_Pat] [] (
-           compare_Case false_Expr false_Expr true_Expr  a_Expr b_Expr)
-
-max_ = mk_easy_FunMonoBind max_PN [a_Pat, b_Pat] [] (
-           compare_Case b_Expr a_Expr a_Expr a_Expr b_Expr)
-min_ = mk_easy_FunMonoBind min_PN [a_Pat, b_Pat] [] (
-           compare_Case a_Expr b_Expr b_Expr a_Expr b_Expr)
+       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}
 
 %************************************************************************
@@ -403,6 +376,11 @@ we use both @con2tag_Foo@ and @tag2con_Foo@ functions, as well as a
 
 \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...
@@ -424,37 +402,75 @@ instance ... Enum (Foo ...) where
 For @enumFromTo@ and @enumFromThenTo@, we use the default methods.
 
 \begin{code}
-gen_Enum_binds :: TyCon -> RdrNameMonoBinds
+gen_Enum_binds :: TyCon -> LHsBinds RdrName
 
 gen_Enum_binds tycon
-  = enum_from `AndMonoBinds` enum_from_then
+  = 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_FunMonoBind enumFrom_PN [a_Pat] [] $
-         untag_Expr tycon [(a_PN, ah_PN)] $
-         HsApp (mk_easy_App map_PN [tag2con_PN tycon]) $
-           HsPar (enum_from_to_Expr
-                   (mk_easy_App mkInt_PN [ah_PN])
-                   (HsVar (maxtag_PN tycon)))
+      = 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_FunMonoBind enumFromThen_PN [a_Pat, b_Pat] [] $
-         untag_Expr tycon [(a_PN, ah_PN), (b_PN, bh_PN)] $
-         HsApp (mk_easy_App map_PN [tag2con_PN tycon]) $
-           HsPar (enum_from_then_to_Expr
-                   (mk_easy_App mkInt_PN [ah_PN])
-                   (mk_easy_App mkInt_PN [bh_PN])
-                   (HsVar (maxtag_PN tycon)))
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsubsection{Generating @Eval@ instance declarations}
-%*                                                                     *
-%************************************************************************
-
-\begin{code}
-gen_Eval_binds tycon = EmptyMonoBinds
+      = 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}
 
 %************************************************************************
@@ -466,29 +482,30 @@ gen_Eval_binds tycon = EmptyMonoBinds
 \begin{code}
 gen_Bounded_binds tycon
   = if isEnumerationTyCon tycon then
-       min_bound_enum `AndMonoBinds` max_bound_enum
+       listToBag [ min_bound_enum, max_bound_enum ]
     else
-       ASSERT(length data_cons == 1)
-       min_bound_1con `AndMonoBinds` max_bound_1con
+       ASSERT(isSingleton data_cons)
+       listToBag [ min_bound_1con, max_bound_1con ]
   where
-    data_cons     = tyConDataCons tycon
+    data_cons = tyConDataCons tycon
+    tycon_loc = getSrcSpan tycon
 
     ----- enum-flavored: ---------------------------
-    min_bound_enum = mk_easy_FunMonoBind minBound_PN [] [] (HsVar data_con_1_PN)
-    max_bound_enum = mk_easy_FunMonoBind maxBound_PN [] [] (HsVar data_con_N_PN)
+    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_PN = qual_orig_name data_con_1
-    data_con_N_PN = qual_orig_name data_con_N
+    data_con_1_RDR = getRdrName data_con_1
+    data_con_N_RDR = getRdrName data_con_N
 
     ----- single-constructor-flavored: -------------
-    arity         = dataConNumFields data_con_1
+    arity         = dataConSourceArity data_con_1
 
-    min_bound_1con = mk_easy_FunMonoBind minBound_PN [] [] $
-                    mk_easy_App data_con_1_PN (nOfThem arity minBound_PN)
-    max_bound_1con = mk_easy_FunMonoBind maxBound_PN [] [] $
-                    mk_easy_App data_con_1_PN (nOfThem arity maxBound_PN)
+    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}
 
 %************************************************************************
@@ -517,11 +534,11 @@ instance ... Ix (Foo ...) where
        map tag2con_Foo (enumFromTo (I# a#) (I# b#))
        }}
 
-    index c@(a, b) d
-      = if inRange c d
-       then case (con2tag_Foo d -# con2tag_Foo a) of
+    -- 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#
-       else error "Ix.Foo.index: out of range"
 
     inRange (a, b) c
       = let
@@ -540,7 +557,7 @@ instance ... Ix (Foo ...) where
          False
        }}}
 \end{verbatim}
-(modulo suitable case-ification to handle the unboxed tags)
+(modulo suitable case-ification to handle the unlifted tags)
 
 For a single-constructor type (NB: this includes all tuples), e.g.,
 \begin{verbatim}
@@ -550,114 +567,118 @@ we follow the scheme given in Figure~19 of the Haskell~1.2 report
 (p.~147).
 
 \begin{code}
-gen_Ix_binds :: TyCon -> RdrNameMonoBinds
+gen_Ix_binds :: TyCon -> LHsBinds RdrName
 
 gen_Ix_binds tycon
   = if isEnumerationTyCon tycon
     then enum_ixes
     else single_con_ixes
   where
-    tycon_str = _UNPK_ (nameOf (origName "gen_Ix_binds" tycon))
+    tycon_loc = getSrcSpan tycon
 
     --------------------------------------------------------------
-    enum_ixes = enum_range `AndMonoBinds`
-               enum_index `AndMonoBinds` enum_inRange
+    enum_ixes = listToBag [ enum_range, enum_index, enum_inRange ]
 
     enum_range
-      = mk_easy_FunMonoBind range_PN [TuplePatIn [a_Pat, b_Pat]] [] $
-         untag_Expr tycon [(a_PN, ah_PN)] $
-         untag_Expr tycon [(b_PN, bh_PN)] $
-         HsApp (mk_easy_App map_PN [tag2con_PN tycon]) $
-             HsPar (enum_from_to_Expr
-                       (mk_easy_App mkInt_PN [ah_PN])
-                       (mk_easy_App mkInt_PN [bh_PN]))
+      = 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_FunMonoBind index_PN [AsPatIn c_PN (TuplePatIn [a_Pat, b_Pat]), d_Pat] [] (
-       HsIf (HsPar (mk_easy_App inRange_PN [c_PN, d_PN])) (
-          untag_Expr tycon [(a_PN, ah_PN)] (
-          untag_Expr tycon [(d_PN, dh_PN)] (
+      = 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
-               grhs = [OtherwiseGRHS (mk_easy_App mkInt_PN [c_PN]) mkGeneratedSrcLoc]
+               rhs = nlHsVarApps intDataCon_RDR [c_RDR]
           in
-          HsCase
-            (HsPar (OpApp (HsVar dh_PN) (HsVar minusH_PN) (HsVar ah_PN)))
-            [PatMatch (VarPatIn c_PN)
-                               (GRHSMatch (GRHSsAndBindsIn grhs EmptyBinds))]
-            mkGeneratedSrcLoc
+          nlHsCase
+            (genOpApp (nlHsVar dh_RDR) minusInt_RDR (nlHsVar ah_RDR))
+            [mkSimpleHsAlt (nlVarPat c_RDR) rhs]
           ))
-       ) {-else-} (
-          HsApp (HsVar error_PN) (HsLit (HsString (_PK_ ("Ix."++tycon_str++".index: out of range\n"))))
        )
-       mkGeneratedSrcLoc)
 
     enum_inRange
-      = mk_easy_FunMonoBind inRange_PN [TuplePatIn [a_Pat, b_Pat], c_Pat] [] (
-         untag_Expr tycon [(a_PN, ah_PN)] (
-         untag_Expr tycon [(b_PN, bh_PN)] (
-         untag_Expr tycon [(c_PN, ch_PN)] (
-         HsIf (HsPar (OpApp (HsVar ch_PN) (HsVar geH_PN) (HsVar ah_PN))) (
-            (OpApp (HsVar ch_PN) (HsVar leH_PN) (HsVar bh_PN))
+      = 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
-         ) mkGeneratedSrcLoc))))
+         ))))
 
     --------------------------------------------------------------
-    single_con_ixes = single_con_range `AndMonoBinds`
-               single_con_index `AndMonoBinds` single_con_inRange
+    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 -> if (any isPrimType (dataConRawArgTys dc)) then
-                        error ("ERROR: Can't derive Ix for a single-constructor type with primitive argument types: "++tycon_str)
-                    else
-                        dc
+         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   = dataConNumFields data_con
-    data_con_PN = qual_orig_name data_con
-    con_pat  xs = ConPatIn data_con_PN (map VarPatIn xs)
-    con_expr xs = mk_easy_App data_con_PN xs
+    con_arity    = dataConSourceArity data_con
+    data_con_RDR = getRdrName data_con
 
-    as_needed = take con_arity as_PNs
-    bs_needed = take con_arity bs_PNs
-    cs_needed = take con_arity cs_PNs
+    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_FunMonoBind range_PN [TuplePatIn [con_pat as_needed, con_pat bs_needed]] [] (
-         ListComp (con_expr cs_needed) (zipWith3Equal "single_con_range" mk_qual as_needed bs_needed cs_needed)
-       )
+      = mk_easy_FunBind tycon_loc range_RDR 
+         [nlTuplePat [con_pat as_needed, con_pat bs_needed] Boxed] $
+       nlHsDo ListComp stmts con_expr
       where
-       mk_qual a b c = GeneratorQual (VarPatIn c)
-                           (HsApp (HsVar range_PN) (ExplicitTuple [HsVar a, HsVar b]))
+       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_FunMonoBind index_PN [TuplePatIn [con_pat as_needed, con_pat bs_needed], con_pat cs_needed] [range_size] (
-       foldl mk_index (HsLit (HsInt 0)) (zip3 as_needed bs_needed cs_needed))
+      = 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
-       mk_index multiply_by (l, u, i)
-         =OpApp (
-               (HsApp (HsApp (HsVar index_PN) (ExplicitTuple [HsVar l, HsVar u])) (HsVar i))
-          ) (HsVar plus_PN) (
-               OpApp (
-                   (HsApp (HsVar rangeSize_PN) (ExplicitTuple [HsVar l, HsVar u]))
-               ) (HsVar times_PN) multiply_by
+       -- 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)
           )
-
-       range_size
-         = mk_easy_FunMonoBind rangeSize_PN [TuplePatIn [a_Pat, b_Pat]] [] (
-               OpApp (
-                   (HsApp (HsApp (HsVar index_PN) (ExplicitTuple [a_Expr, b_Expr])) b_Expr)
-               ) (HsVar plus_PN) (HsLit (HsInt 1)))
+       mk_one l u i
+         = nlHsApps unsafeIndex_RDR [nlTuple [nlHsVar l, nlHsVar u] Boxed, nlHsVar i]
 
     ------------------
     single_con_inRange
-      = mk_easy_FunMonoBind inRange_PN [TuplePatIn [con_pat as_needed, con_pat bs_needed], con_pat cs_needed] [] (
-         foldl1 and_Expr (zipWith3Equal "single_con_inRange" in_range as_needed bs_needed cs_needed))
+      = 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 = HsApp (HsApp (HsVar inRange_PN) (ExplicitTuple [HsVar a, HsVar b])) (HsVar c)
+       in_range a b c = nlHsApps inRange_RDR [nlTuple [nlHsVar a, nlHsVar b] Boxed,
+                                              nlHsVar c]
 \end{code}
 
 %************************************************************************
@@ -666,117 +687,467 @@ gen_Ix_binds tycon
 %*                                                                     *
 %************************************************************************
 
-Ignoring all the infix-ery mumbo jumbo (ToDo)
+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 :: [RenamedFixityDecl] -> TyCon -> RdrNameMonoBinds
+gen_Read_binds :: FixityEnv -> TyCon -> LHsBinds RdrName
 
-gen_Read_binds fixities tycon
-  = reads_prec `AndMonoBinds` read_list
+gen_Read_binds get_fixity tycon
+  = listToBag [read_prec, default_readlist, default_readlistprec]
   where
     -----------------------------------------------------------------------
-    read_list = mk_easy_FunMonoBind readList_PN [] []
-                 (HsApp (HsVar readList___PN) (HsPar (HsApp (HsVar readsPrec_PN) (HsLit (HsInt 0)))))
+    default_readlist 
+       = mkVarBind loc readList_RDR     (nlHsVar readListDefault_RDR)
+
+    default_readlistprec
+       = mkVarBind loc readListPrec_RDR (nlHsVar readListPrecDefault_RDR)
     -----------------------------------------------------------------------
-    reads_prec
-      = let
-           read_con_comprehensions
-             = map read_con (tyConDataCons tycon)
-       in
-       mk_easy_FunMonoBind readsPrec_PN [a_Pat, b_Pat] [] (
-             foldl1 append_Expr read_con_comprehensions
-       )
+
+    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
-       read_con data_con   -- note: "b" is the string being "read"
-         = let
-               data_con_PN = qual_orig_name data_con
-               data_con_str= nameOf (origName "gen_Read_binds" data_con)
-               con_arity   = dataConNumFields data_con
-               as_needed   = take con_arity as_PNs
-               bs_needed   = take con_arity bs_PNs
-               con_expr    = mk_easy_App data_con_PN as_needed
-               nullary_con = isNullaryDataCon data_con
-
-               con_qual
-                 = GeneratorQual
-                     (TuplePatIn [LitPatIn (HsString data_con_str), d_Pat])
-                     (HsApp (HsVar lex_PN) c_Expr)
-
-               field_quals = snd (mapAccumL mk_qual d_Expr (zipEqual "as_needed" as_needed bs_needed))
-
-               read_paren_arg
-                 = if nullary_con then -- must be False (parens are surely optional)
-                      false_Expr
-                   else -- parens depend on precedence...
-                      HsPar (OpApp a_Expr (HsVar gt_PN) (HsLit (HsInt 9)))
-           in
-           HsApp (
-             readParen_Expr read_paren_arg $ HsPar $
-                HsLam (mk_easy_Match [c_Pat] []  (
-                  ListComp (ExplicitTuple [con_expr,
-                           if null bs_needed then d_Expr else HsVar (last bs_needed)])
-                   (con_qual : field_quals)))
-             ) (HsVar b_PN)
-         where
-           mk_qual draw_from (con_field, str_left)
-             = (HsVar str_left,        -- what to draw from down the line...
-                GeneratorQual
-                 (TuplePatIn [VarPatIn con_field, VarPatIn str_left])
-                 (HsApp (HsApp (HsVar readsPrec_PN) (HsLit (HsInt 10))) draw_from))
+               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}
 %*                                                                     *
 %************************************************************************
 
-Ignoring all the infix-ery mumbo jumbo (ToDo)
+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 :: [RenamedFixityDecl] -> TyCon -> RdrNameMonoBinds
+gen_Show_binds :: FixityEnv -> TyCon -> LHsBinds RdrName
 
-gen_Show_binds fixities tycon
-  = shows_prec `AndMonoBinds` show_list
+gen_Show_binds get_fixity tycon
+  = listToBag [shows_prec, show_list]
   where
+    tycon_loc = getSrcSpan tycon
     -----------------------------------------------------------------------
-    show_list = mk_easy_FunMonoBind showList_PN [] []
-                 (HsApp (HsVar showList___PN) (HsPar (HsApp (HsVar showsPrec_PN) (HsLit (HsInt 0)))))
+    show_list = mkVarBind tycon_loc showList_RDR
+                 (nlHsApp (nlHsVar showList___RDR) (nlHsPar (nlHsApp (nlHsVar showsPrec_RDR) (nlHsIntLit 0))))
     -----------------------------------------------------------------------
-    shows_prec
-      = mk_FunMonoBind showsPrec_PN (map pats_etc (tyConDataCons tycon))
+    shows_prec = mk_FunBind tycon_loc showsPrec_RDR (map pats_etc (tyConDataCons tycon))
       where
        pats_etc data_con
-         = let
-               data_con_PN = qual_orig_name data_con
-               con_arity   = dataConNumFields data_con
-               bs_needed   = take con_arity bs_PNs
-               con_pat     = ConPatIn data_con_PN (map VarPatIn bs_needed)
-               nullary_con = isNullaryDataCon data_con
-
-               show_con
-                 = let (OrigName mod nm) = origName "gen_Show_binds" data_con
-                       space_maybe = if nullary_con then _NIL_ else SLIT(" ")
-                   in
-                       HsApp (HsVar showString_PN) (HsLit (HsString (nm _APPEND_ space_maybe)))
-
-               show_thingies = show_con : (spacified real_show_thingies)
-
-               real_show_thingies
-                 = [ HsApp (HsApp (HsVar showsPrec_PN) (HsLit (HsInt 10))) (HsVar b)
-                 | b <- bs_needed ]
-           in
-           if nullary_con then  -- skip the showParen junk...
-               ASSERT(null bs_needed)
-               ([a_Pat, con_pat], show_con)
-           else
-               ([a_Pat, con_pat],
-                   showParen_Expr (HsPar (OpApp a_Expr (HsVar ge_PN) (HsLit (HsInt 10))))
-                                  (HsPar (nested_compose_Expr show_thingies)))
-         where
-           spacified []     = []
-           spacified [x]    = [x]
-           spacified (x:xs) = (x : (HsVar showSpace_PN) : spacified xs)
+         | 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}
 
 %************************************************************************
@@ -790,7 +1161,7 @@ data Foo ... = ...
 
 con2tag_Foo :: Foo ... -> Int#
 tag2con_Foo :: Int -> Foo ...  -- easier if Int, not Int#
-maxtag_Foo  :: Int             -- ditto (NB: not unboxed)
+maxtag_Foo  :: Int             -- ditto (NB: not unlifted)
 \end{verbatim}
 
 The `tags' here start at zero, hence the @fIRST_TAG@ (currently one)
@@ -801,40 +1172,57 @@ data TagThingWanted
   = GenCon2Tag | GenTag2Con | GenMaxTag
 
 gen_tag_n_con_monobind
-    :: (RdrName,           -- (proto)Name for the thing in question
+    :: ( RdrName,          -- (proto)Name for the thing in question
        TyCon,              -- tycon in question
        TagThingWanted)
-    -> RdrNameMonoBinds
+    -> LHsBind RdrName
 
-gen_tag_n_con_monobind (pn, tycon, GenCon2Tag)
-  = mk_FunMonoBind pn (map mk_stuff (tyConDataCons tycon))
-  where
-    mk_stuff :: DataCon -> ([RdrNamePat], RdrNameHsExpr)
+gen_tag_n_con_monobind (rdr_name, tycon, GenCon2Tag)
+  | lots_of_constructors
+  = mk_FunBind tycon_loc rdr_name [([], get_tag_rhs)]
 
-    mk_stuff var
-      = ASSERT(isDataCon var)
-       ([pat], HsLit (HsIntPrim (toInteger ((dataConTag var) - fIRST_TAG))))
-      where
-       pat    = ConPatIn var_PN (nOfThem (dataConNumFields var) WildPatIn)
-       var_PN = qual_orig_name var
+  | otherwise
+  = mk_FunBind tycon_loc rdr_name (map mk_stuff (tyConDataCons tycon))
 
-gen_tag_n_con_monobind (pn, tycon, GenTag2Con)
-  = mk_FunMonoBind pn (map mk_stuff (tyConDataCons tycon))
   where
-    mk_stuff :: DataCon -> ([RdrNamePat], RdrNameHsExpr)
-
-    mk_stuff var
-      = ASSERT(isDataCon var)
-       ([lit_pat], HsVar var_PN)
-      where
-       lit_pat = ConPatIn mkInt_PN [LitPatIn (HsIntPrim (toInteger ((dataConTag var) - fIRST_TAG)))]
-       var_PN  = qual_orig_name var
-
-gen_tag_n_con_monobind (pn, tycon, GenMaxTag)
-  = mk_easy_FunMonoBind pn [] [] (HsApp (HsVar mkInt_PN) (HsLit (HsIntPrim max_tag)))
+    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}
 
 %************************************************************************
@@ -843,309 +1231,250 @@ gen_tag_n_con_monobind (pn, tycon, GenMaxTag)
 %*                                                                     *
 %************************************************************************
 
-@mk_easy_FunMonoBind fun pats binds expr@ generates:
-\begin{verbatim}
-    fun pat1 pat2 ... patN = expr where binds
-\end{verbatim}
 
-@mk_FunMonoBind fun [([p1a, p1b, ...], e1), ...]@ is for
-multi-clause definitions; it generates:
-\begin{verbatim}
-    fun p1a p1b ... p1N = e1
-    fun p2a p2b ... p2N = e2
-    ...
-    fun pMa pMb ... pMN = eM
-\end{verbatim}
+ToDo: Better SrcLocs.
 
 \begin{code}
-mk_easy_FunMonoBind :: RdrName -> [RdrNamePat]
-                   -> [RdrNameMonoBinds] -> RdrNameHsExpr
-                   -> RdrNameMonoBinds
-
-mk_easy_FunMonoBind fun pats binds expr
-  = FunMonoBind fun False{-not infix-} [mk_easy_Match pats binds expr] mkGeneratedSrcLoc
-
-mk_easy_Match pats binds expr
-  = mk_match pats expr (mkbind binds)
-  where
-    mkbind [] = EmptyBinds
-    mkbind bs = SingleBind (RecBind (foldr1 AndMonoBinds bs))
-       -- The renamer expects everything in its input to be a
-       -- "recursive" MonoBinds, and it is its job to sort things out
-       -- from there.
-
-mk_FunMonoBind :: RdrName
-               -> [([RdrNamePat], RdrNameHsExpr)]
-               -> RdrNameMonoBinds
-
-mk_FunMonoBind fun [] = panic "TcGenDeriv:mk_FunMonoBind"
-mk_FunMonoBind fun pats_and_exprs
-  = FunMonoBind fun False{-not infix-}
-               [ mk_match p e EmptyBinds | (p,e) <-pats_and_exprs ]
-               mkGeneratedSrcLoc
-
-mk_match pats expr binds
-  = foldr PatMatch
-         (GRHSMatch (GRHSsAndBindsIn [OtherwiseGRHS expr mkGeneratedSrcLoc] binds))
-         (map paren pats)
-  where
-    paren p@(VarPatIn _) = p
-    paren other_p       = ParPatIn other_p
-\end{code}
-
-\begin{code}
-mk_easy_App f xs = foldl HsApp (HsVar f) (map HsVar xs)
-\end{code}
-
-\begin{code}
-compare_Case, cmp_eq_Expr ::
-         RdrNameHsExpr -> RdrNameHsExpr -> RdrNameHsExpr
-         -> RdrNameHsExpr -> RdrNameHsExpr
-         -> RdrNameHsExpr
 compare_gen_Case ::
-         RdrName
-         -> RdrNameHsExpr -> RdrNameHsExpr -> RdrNameHsExpr
-         -> RdrNameHsExpr -> RdrNameHsExpr
-         -> RdrNameHsExpr
+         LHsExpr RdrName       -- What to do for equality
+         -> LHsExpr RdrName -> LHsExpr RdrName
+         -> LHsExpr RdrName
 careful_compare_Case :: -- checks for primitive types...
-         Type
-         -> RdrNameHsExpr -> RdrNameHsExpr -> RdrNameHsExpr
-         -> RdrNameHsExpr -> RdrNameHsExpr
-         -> RdrNameHsExpr
-
-compare_Case = compare_gen_Case compare_PN
-cmp_eq_Expr = compare_gen_Case cmp_eq_PN
-
-compare_gen_Case fun lt eq gt a b
-  = HsCase (HsPar (HsApp (HsApp (HsVar fun) a) b)) {-of-}
-      [PatMatch (ConPatIn ltTag_PN [])
-         (GRHSMatch (GRHSsAndBindsIn [OtherwiseGRHS lt mkGeneratedSrcLoc] EmptyBinds)),
-
-       PatMatch (ConPatIn eqTag_PN [])
-         (GRHSMatch (GRHSsAndBindsIn [OtherwiseGRHS eq mkGeneratedSrcLoc] EmptyBinds)),
-
-       PatMatch (ConPatIn gtTag_PN [])
-         (GRHSMatch (GRHSsAndBindsIn [OtherwiseGRHS gt mkGeneratedSrcLoc] EmptyBinds))]
-       mkGeneratedSrcLoc
-
-careful_compare_Case ty lt eq gt a b
-  = if not (isPrimType ty) then
-       compare_gen_Case compare_PN lt eq gt a b
-
-    else -- we have to do something special for primitive things...
-       HsIf (HsPar (OpApp a (HsVar relevant_eq_op) b))
-           eq
-           (HsIf (HsPar (OpApp a (HsVar relevant_lt_op) b)) lt gt mkGeneratedSrcLoc)
-           mkGeneratedSrcLoc
+         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 = assoc_ty_id eq_op_tbl ty
-    relevant_lt_op = assoc_ty_id lt_op_tbl ty
-
-assoc_ty_id tyids ty 
-  = if null res then panic "assoc_ty"
-    else head res
+    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) <- tyids, eqTy ty ty']
+    res = [id | (ty',id) <- tbl, ty `tcEqType` ty']
 
+eq_op_tbl :: [(Type, PrimOp)]
 eq_op_tbl =
-    [(charPrimTy,      eqH_Char_PN)
-    ,(intPrimTy,       eqH_Int_PN)
-    ,(wordPrimTy,      eqH_Word_PN)
-    ,(addrPrimTy,      eqH_Addr_PN)
-    ,(floatPrimTy,     eqH_Float_PN)
-    ,(doublePrimTy,    eqH_Double_PN)
+    [(charPrimTy,      CharEqOp)
+    ,(intPrimTy,       IntEqOp)
+    ,(wordPrimTy,      WordEqOp)
+    ,(addrPrimTy,      AddrEqOp)
+    ,(floatPrimTy,     FloatEqOp)
+    ,(doublePrimTy,    DoubleEqOp)
     ]
 
+lt_op_tbl :: [(Type, PrimOp)]
 lt_op_tbl =
-    [(charPrimTy,      ltH_Char_PN)
-    ,(intPrimTy,       ltH_Int_PN)
-    ,(wordPrimTy,      ltH_Word_PN)
-    ,(addrPrimTy,      ltH_Addr_PN)
-    ,(floatPrimTy,     ltH_Float_PN)
-    ,(doublePrimTy,    ltH_Double_PN)
+    [(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, append_Expr :: RdrNameHsExpr -> RdrNameHsExpr -> RdrNameHsExpr
+-----------------------------------------------------------------------
 
-and_Expr    a b = OpApp a (HsVar and_PN)    b
-append_Expr a b = OpApp a (HsVar append_PN) b
+and_Expr :: LHsExpr RdrName -> LHsExpr RdrName -> LHsExpr RdrName
+and_Expr a b = genOpApp a and_RDR    b
 
 -----------------------------------------------------------------------
 
-eq_Expr :: Type -> RdrNameHsExpr -> RdrNameHsExpr -> RdrNameHsExpr
-eq_Expr ty a b
-  = if not (isPrimType ty) then
-       OpApp a (HsVar eq_PN)  b
-    else -- we have to do something special for primitive things...
-       OpApp a (HsVar relevant_eq_op) b
-  where
-    relevant_eq_op = assoc_ty_id eq_op_tbl ty
+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)] -> RdrNameHsExpr -> RdrNameHsExpr
+untag_Expr :: TyCon -> [( RdrName,  RdrName)] -> LHsExpr RdrName -> LHsExpr RdrName
 untag_Expr tycon [] expr = expr
 untag_Expr tycon ((untag_this, put_tag_here) : more) expr
-  = HsCase (HsPar (HsApp (con2tag_Expr tycon) (HsVar untag_this))) {-of-}
-      [PatMatch (VarPatIn put_tag_here)
-                       (GRHSMatch (GRHSsAndBindsIn grhs EmptyBinds))]
-      mkGeneratedSrcLoc
-  where
-    grhs = [OtherwiseGRHS (untag_Expr tycon more expr) mkGeneratedSrcLoc]
+  = 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
-            -> RdrNameHsExpr           -- What to return if true
-            -> RdrNameHsExpr           -- What to return if false
-            -> RdrNameHsExpr
+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
-  = HsIf (HsPar (OpApp (HsVar a) (HsVar op) (HsVar b))) true_case false_case mkGeneratedSrcLoc
+  = nlHsIf (genOpApp (nlHsVar a) op (nlHsVar b)) true_case false_case
 
 enum_from_to_Expr
-       :: RdrNameHsExpr -> RdrNameHsExpr
-       -> RdrNameHsExpr
+       :: LHsExpr RdrName -> LHsExpr RdrName
+       -> LHsExpr RdrName
 enum_from_then_to_Expr
-       :: RdrNameHsExpr -> RdrNameHsExpr -> RdrNameHsExpr
-       -> RdrNameHsExpr
+       :: LHsExpr RdrName -> LHsExpr RdrName -> LHsExpr RdrName
+       -> LHsExpr RdrName
 
-enum_from_to_Expr      f   t2 = HsApp (HsApp (HsVar enumFromTo_PN) f) t2
-enum_from_then_to_Expr f t t2 = HsApp (HsApp (HsApp (HsVar enumFromThenTo_PN) f) t) t2
+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, readParen_Expr
-       :: RdrNameHsExpr -> RdrNameHsExpr
-       -> RdrNameHsExpr
+showParen_Expr
+       :: LHsExpr RdrName -> LHsExpr RdrName
+       -> LHsExpr RdrName
 
-showParen_Expr e1 e2 = HsApp (HsApp (HsVar showParen_PN) e1) e2
-readParen_Expr e1 e2 = HsApp (HsApp (HsVar readParen_PN) e1) e2
+showParen_Expr e1 e2 = nlHsApp (nlHsApp (nlHsVar showParen_RDR) e1) e2
 
-nested_compose_Expr :: [RdrNameHsExpr] -> RdrNameHsExpr
+nested_compose_Expr :: [LHsExpr RdrName] -> LHsExpr RdrName
 
 nested_compose_Expr [e] = parenify e
 nested_compose_Expr (e:es)
-  = HsApp (HsApp (HsVar compose_PN) (parenify e)) (nested_compose_Expr 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}
 
-parenify e@(HsVar _) = e
-parenify e          = HsPar e
+\begin{code}
+getSrcSpan = srcLocSpan . getSrcLoc
 \end{code}
 
 \begin{code}
-qual_orig_name n = case (origName "qual_orig_name" n) of { OrigName m n -> Qual m n }
-
-a_PN           = Unqual SLIT("a")
-b_PN           = Unqual SLIT("b")
-c_PN           = Unqual SLIT("c")
-d_PN           = Unqual SLIT("d")
-ah_PN          = Unqual SLIT("a#")
-bh_PN          = Unqual SLIT("b#")
-ch_PN          = Unqual SLIT("c#")
-dh_PN          = Unqual SLIT("d#")
-cmp_eq_PN      = Unqual SLIT("cmp_eq")
-rangeSize_PN   = Qual iX SLIT("rangeSize")
-
-as_PNs         = [ Unqual (_PK_ ("a"++show i)) | i <- [(1::Int) .. ] ]
-bs_PNs         = [ Unqual (_PK_ ("b"++show i)) | i <- [(1::Int) .. ] ]
-cs_PNs         = [ Unqual (_PK_ ("c"++show i)) | i <- [(1::Int) .. ] ]
-
-eq_PN           = preludeQual {-SLIT("Eq")-}  SLIT("==")
-ne_PN           = preludeQual {-SLIT("Eq")-}  SLIT("/=")
-le_PN           = preludeQual {-SLIT("Ord")-} SLIT("<=")
-lt_PN           = preludeQual {-SLIT("Ord")-} SLIT("<")
-ge_PN           = preludeQual {-SLIT("Ord")-} SLIT(">=")
-gt_PN           = preludeQual {-SLIT("Ord")-} SLIT(">")
-max_PN          = preludeQual {-SLIT("Ord")-} SLIT("max")
-min_PN          = preludeQual {-SLIT("Ord")-} SLIT("min")
-compare_PN      = preludeQual {-SLIT("Ord")-} SLIT("compare")
-minBound_PN     = preludeQual {-SLIT("Bounded")-} SLIT("minBound")
-maxBound_PN     = preludeQual {-SLIT("Bounded")-} SLIT("maxBound")
-enumFrom_PN     = preludeQual {-SLIT("Enum")-} SLIT("enumFrom")
-enumFromTo_PN   = preludeQual {-SLIT("Enum")-} SLIT("enumFromTo")
-enumFromThen_PN         = preludeQual {-SLIT("Enum")-} SLIT("enumFromThen")
-enumFromThenTo_PN= preludeQual {-SLIT("Enum")-} SLIT("enumFromThenTo")
-range_PN        = Qual iX   SLIT("range")
-index_PN        = Qual iX   SLIT("index")
-inRange_PN      = Qual iX   SLIT("inRange")
-readsPrec_PN    = preludeQual {-SLIT("Read")-} SLIT("readsPrec")
-readList_PN     = preludeQual {-SLIT("Read")-} SLIT("readList")
-showsPrec_PN    = preludeQual {-SLIT("Show")-} SLIT("showsPrec")
-showList_PN     = preludeQual {-SLIT("Show")-} SLIT("showList")
-plus_PN                 = preludeQual {-SLIT("Num")-}  SLIT("+")
-times_PN        = preludeQual {-SLIT("Num")-}  SLIT("*")
-ltTag_PN        = preludeQual SLIT("LT")
-eqTag_PN        = preludeQual SLIT("EQ")
-gtTag_PN        = preludeQual SLIT("GT")
-
-eqH_Char_PN    = prelude_primop CharEqOp
-ltH_Char_PN    = prelude_primop CharLtOp
-eqH_Word_PN    = prelude_primop WordEqOp
-ltH_Word_PN    = prelude_primop WordLtOp
-eqH_Addr_PN    = prelude_primop AddrEqOp
-ltH_Addr_PN    = prelude_primop AddrLtOp
-eqH_Float_PN   = prelude_primop FloatEqOp
-ltH_Float_PN   = prelude_primop FloatLtOp
-eqH_Double_PN  = prelude_primop DoubleEqOp
-ltH_Double_PN  = prelude_primop DoubleLtOp
-eqH_Int_PN     = prelude_primop IntEqOp
-ltH_Int_PN     = prelude_primop IntLtOp
-geH_PN         = prelude_primop IntGeOp
-leH_PN         = prelude_primop IntLeOp
-minusH_PN      = prelude_primop IntSubOp
-
-prelude_primop   o = case (origName "prelude_primop" (primOpId o)) of { OrigName m n -> Qual m n }
-
-false_PN       = preludeQual SLIT("False")
-true_PN                = preludeQual SLIT("True")
-and_PN         = preludeQual SLIT("&&")
-not_PN         = preludeQual SLIT("not")
-append_PN      = preludeQual SLIT("++")
-map_PN         = preludeQual SLIT("map")
-compose_PN     = preludeQual SLIT(".")
-mkInt_PN       = preludeQual SLIT("I#")
-error_PN       = preludeQual SLIT("error")
-showString_PN  = preludeQual SLIT("showString")
-showParen_PN   = preludeQual SLIT("showParen")
-readParen_PN   = preludeQual SLIT("readParen")
-lex_PN         = Qual gHC__  SLIT("lex")
-showSpace_PN   = Qual gHC__  SLIT("showSpace")
-showList___PN   = Qual gHC__  SLIT("showList__")
-readList___PN   = Qual gHC__  SLIT("readList__")
-
-a_Expr         = HsVar a_PN
-b_Expr         = HsVar b_PN
-c_Expr         = HsVar c_PN
-d_Expr         = HsVar d_PN
-ltTag_Expr     = HsVar ltTag_PN
-eqTag_Expr     = HsVar eqTag_PN
-gtTag_Expr     = HsVar gtTag_PN
-false_Expr     = HsVar false_PN
-true_Expr      = HsVar true_PN
-
-con2tag_Expr tycon = HsVar (con2tag_PN tycon)
-
-a_Pat          = VarPatIn a_PN
-b_Pat          = VarPatIn b_PN
-c_Pat          = VarPatIn c_PN
-d_Pat          = VarPatIn d_PN
-
-con2tag_PN, tag2con_PN, maxtag_PN :: TyCon -> RdrName
-
-con2tag_PN tycon
-  = let        (OrigName mod nm) = origName "con2tag_PN" tycon
-       con2tag   = SLIT("con2tag_") _APPEND_ nm _APPEND_ SLIT("#")
-    in
-    Qual mod con2tag
+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}
 
-tag2con_PN tycon
-  = let        (OrigName mod nm) = origName "tag2con_PN" tycon
-       tag2con   = SLIT("tag2con_") _APPEND_ nm _APPEND_ SLIT("#")
-    in
-    Qual mod tag2con
+s RdrName for PrimOps.  Can't be done in PrelNames, because PrimOp imports
+PrelNames, so PrelNames can't import PrimOp.
 
-maxtag_PN tycon
-  = let        (OrigName mod nm) = origName "maxtag_PN" tycon
-       maxtag    = SLIT("maxtag_") _APPEND_ nm _APPEND_ SLIT("#")
-    in
-    Qual mod maxtag
+\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}