[project @ 2004-11-26 16:19:45 by simonmar]
[ghc-hetmet.git] / ghc / compiler / typecheck / TcGenDeriv.lhs
index cab4e7c..8f8168b 100644 (file)
@@ -17,6 +17,8 @@ module TcGenDeriv (
        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,
@@ -26,38 +28,39 @@ module TcGenDeriv (
 
 #include "HsVersions.h"
 
-import HsSyn           ( InPat(..), HsExpr(..), MonoBinds(..),
-                         Match(..), GRHSs(..), Stmt(..), HsLit(..),
-                         HsBinds(..), StmtCtxt(..),
-                         unguardedRHS, mkSimpleMatch
-                       )
-import RdrHsSyn                ( RdrName(..), varUnqual, mkOpApp,
-                         RdrNameMonoBinds, RdrNameHsExpr, RdrNamePat
-                       )
-import BasicTypes      ( IfaceFlavour(..), RecFlag(..) )
-import FieldLabel       ( fieldLabelName )
-import DataCon         ( isNullaryDataCon, dataConTag,
-                         dataConRawArgTys, fIRST_TAG,
-                         DataCon, ConTag,
+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, getOccName, getSrcLoc, occNameString, 
-                         modAndOcc, OccName, Name )
+import Name            ( getOccString, getSrcLoc, Name, NamedThing(..) )
 
+import HscTypes                ( FixityEnv, lookupFixity )
+import PrelInfo
+import PrelNames
+import MkId            ( eRROR_ID )
 import PrimOp          ( PrimOp(..) )
-import PrelInfo                -- Lots of RdrNames
-import SrcLoc          ( mkGeneratedSrcLoc, SrcLoc )
-import TyCon           ( TyCon, isNewTyCon, tyConDataCons, isEnumerationTyCon,
-                         maybeTyConSingleCon
+import SrcLoc          ( Located(..), noLoc, srcLocSpan )
+import TyCon           ( TyCon, isNewTyCon, tyConDataCons, isEnumerationTyCon, tyConArity,
+                         maybeTyConSingleCon, tyConFamilySize, tyConTyVars, tyConName
                        )
-import Type            ( isUnLiftedType, isUnboxedType, Type )
-import TysPrim         ( charPrimTy, intPrimTy, wordPrimTy, addrPrimTy,
-                         floatPrimTy, doublePrimTy
-                       )
-import Util            ( mapAccumL, zipEqual, zipWithEqual,
-                         zipWith3Equal, nOfThem )
-import Panic           ( panic, assertPanic )
-import Maybes          ( maybeToBool )
+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 Char            ( isAlpha )
+import Constants
 import List            ( partition, intersperse )
+import Outputable
+import FastString
+import OccName
+import Bag
 \end{code}
 
 %************************************************************************
@@ -93,7 +96,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
@@ -140,59 +143,45 @@ instance ... Eq (Foo ...) where
 \end{itemize}
 
 
-deriveEq :: RdrName                            -- Class
-        -> RdrName                             -- Type constructor
-        -> [ (RdrName, [RdrType]) ]    -- Constructors
-        -> (RdrContext,                -- Context for the inst decl
-            [RdrBind],                 -- Binds in the inst decl
-            [RdrBind])                 -- Extra value bindings outside
-
-deriveEq clas tycon constrs 
-  = (context, [eq_bind, ne_bind], [])
-  where
-    context = [(clas, [ty]) | (_, tys) <- constrs, ty <- tys]
-
-    ne_bind = mkBind 
-    (nullary_cons, non_nullary_cons) = partition is_nullary constrs
-    is_nullary (_, args) = null args
-
 \begin{code}
-gen_Eq_binds :: TyCon -> RdrNameMonoBinds
+gen_Eq_binds :: TyCon -> LHsBinds RdrName
 
 gen_Eq_binds tycon
   = let
-       tycon_loc = getSrcLoc tycon
+       tycon_loc = getSrcSpan tycon
+
         (nullary_cons, nonnullary_cons)
            | isNewTyCon tycon = ([], tyConDataCons tycon)
-           | otherwise       = partition isNullaryDataCon (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_RDR,ah_RDR), (b_RDR,bh_RDR)]
-                     (cmp_tags_Expr eqH_Int_RDR ah_RDR bh_RDR true_Expr false_Expr))]
+                              (genOpApp (nlHsVar ah_RDR) eqInt_RDR (nlHsVar bh_RDR)))]
     in
-    mk_FunMonoBind tycon_loc eq_RDR ((map pats_etc nonnullary_cons) ++ rest)
-           `AndMonoBinds`
-    mk_easy_FunMonoBind tycon_loc ne_RDR [a_Pat, b_Pat] [] (
-       HsApp (HsVar not_RDR) (HsPar (mk_easy_App eq_RDR [a_RDR, b_RDR])))
+    listToBag [
+      mk_FunBind tycon_loc eq_RDR ((map pats_etc nonnullary_cons) ++ rest),
+      mk_easy_FunBind tycon_loc ne_RDR [a_Pat, b_Pat] emptyLHsBinds (
+       nlHsApp (nlHsVar not_RDR) (nlHsPar (nlHsVarApps eq_RDR [a_RDR, b_RDR])))
+    ]
   where
     ------------------------------------------------------------------
     pats_etc data_con
       = let
-           con1_pat = ConPatIn data_con_RDR (map VarPatIn as_needed)
-           con2_pat = ConPatIn data_con_RDR (map VarPatIn bs_needed)
+           con1_pat = nlConVarPat data_con_RDR as_needed
+           con2_pat = nlConVarPat data_con_RDR bs_needed
 
-           data_con_RDR = qual_orig_name data_con
+           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  = dataConRawArgTys data_con
+           tys_needed  = dataConOrigArgTys data_con
        in
        ([con1_pat, con2_pat], nested_eq_expr tys_needed as_needed bs_needed)
       where
@@ -200,7 +189,7 @@ gen_Eq_binds tycon
        nested_eq_expr 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))
+           nested_eq ty a b = nlHsPar (eq_Expr tycon ty (nlHsVar a) (nlHsVar b))
 \end{code}
 
 %************************************************************************
@@ -278,7 +267,7 @@ 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:
 
@@ -300,105 +289,74 @@ If there is only one constructor in the Data Type we don't need the WildCard Pat
 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 = getSrcLoc tycon
+    tycon_loc = getSrcSpan tycon
     --------------------------------------------------------------------
-    compare = mk_easy_FunMonoBind tycon_loc compare_RDR
-               [a_Pat, b_Pat]
-               [cmp_eq]
-           (if maybeToBool (maybeTyConSingleCon tycon) then
-
---             cmp_eq_Expr ltTag_Expr eqTag_Expr gtTag_Expr a_Expr b_Expr
--- Wierd.  Was: case (cmp a b) of { LT -> LT; EQ -> EQ; GT -> GT }
-
-               cmp_eq_Expr a_Expr b_Expr
-            else
-               untag_Expr tycon [(a_RDR, ah_RDR), (b_RDR, bh_RDR)]
-                 (cmp_tags_Expr eqH_Int_RDR ah_RDR bh_RDR
-                       -- 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
--- Ditto
-                       cmp_eq_Expr a_Expr b_Expr
-                   )
+
+    compare = mk_easy_FunBind tycon_loc compare_RDR
+                                 [a_Pat, b_Pat] (unitBag cmp_eq) compare_rhs
+    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_RDR ah_RDR bh_RDR 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)
        | isNewTyCon tycon = ([], tyConDataCons tycon)
-       | otherwise       = partition isNullaryDataCon tycon_data_cons
-
-    cmp_eq =
-       mk_FunMonoBind tycon_loc 
-                      cmp_eq_RDR 
-                      (if null nonnullary_cons && (length nullary_cons == 1) then
-                          -- catch this specially to avoid warnings
-                          -- about overlapping patterns from the desugarer.
-                         let 
-                          data_con     = head nullary_cons
-                          data_con_RDR = qual_orig_name data_con
-                           pat          = ConPatIn data_con_RDR []
-                          in
-                         [([pat,pat], eqTag_Expr)]
-                      else
-                         map pats_etc nonnullary_cons ++
-                         -- leave out wildcards to silence desugarer.
-                         (if length tycon_data_cons == 1 then
-                             []
-                          else
-                              [([WildPatIn, WildPatIn], default_rhs)]))
+       | 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 = ConPatIn data_con_RDR (map VarPatIn as_needed)
-           con2_pat = ConPatIn data_con_RDR (map VarPatIn bs_needed)
+           con1_pat = nlConVarPat data_con_RDR as_needed
+           con2_pat = nlConVarPat data_con_RDR bs_needed
 
-           data_con_RDR = qual_orig_name data_con
+           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  = dataConRawArgTys data_con
+           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)
+               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
-    --------------------------------------------------------------------
-
-defaulted = foldr1 AndMonoBinds [lt, le, ge, gt, max_, min_]
-
-lt = mk_easy_FunMonoBind mkGeneratedSrcLoc lt_RDR [a_Pat, b_Pat] [] (
-           compare_Case true_Expr  false_Expr false_Expr a_Expr b_Expr)
-le = mk_easy_FunMonoBind mkGeneratedSrcLoc le_RDR [a_Pat, b_Pat] [] (
-           compare_Case true_Expr  true_Expr  false_Expr a_Expr b_Expr)
-ge = mk_easy_FunMonoBind mkGeneratedSrcLoc ge_RDR [a_Pat, b_Pat] [] (
-           compare_Case false_Expr true_Expr  true_Expr  a_Expr b_Expr)
-gt = mk_easy_FunMonoBind mkGeneratedSrcLoc gt_RDR [a_Pat, b_Pat] [] (
-           compare_Case false_Expr false_Expr true_Expr  a_Expr b_Expr)
-
-max_ = mk_easy_FunMonoBind mkGeneratedSrcLoc max_RDR [a_Pat, b_Pat] [] (
-           compare_Case b_Expr a_Expr a_Expr a_Expr b_Expr)
-min_ = mk_easy_FunMonoBind mkGeneratedSrcLoc min_RDR [a_Pat, b_Pat] [] (
-           compare_Case a_Expr b_Expr b_Expr a_Expr b_Expr)
 \end{code}
 
 %************************************************************************
@@ -443,79 +401,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
-  = succ_enum          `AndMonoBinds`
-    pred_enum          `AndMonoBinds`
-    to_enum             `AndMonoBinds`
-    enum_from          `AndMonoBinds`
-    enum_from_then     `AndMonoBinds`
-    from_enum
+  = listToBag [
+       succ_enum,
+       pred_enum,
+       to_enum,
+       enum_from,
+       enum_from_then,
+       from_enum
+    ]
   where
-    tycon_loc = getSrcLoc tycon
+    tycon_loc = getSrcSpan tycon
     occ_nm    = getOccString tycon
 
     succ_enum
-      = mk_easy_FunMonoBind tycon_loc succ_RDR [a_Pat] [] $
+      = mk_easy_FunBind tycon_loc succ_RDR [a_Pat] emptyLHsBinds $
        untag_Expr tycon [(a_RDR, ah_RDR)] $
-       HsIf (HsApp (HsApp (HsVar eq_RDR) 
-                          (HsVar (maxtag_RDR tycon)))
-                          (mk_easy_App mkInt_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")
-            (HsApp (HsVar (tag2con_RDR tycon))
-                   (HsApp (HsApp (HsVar plus_RDR)
-                                 (mk_easy_App mkInt_RDR [ah_RDR]))
-                          (HsLit (HsInt 1))))
-            tycon_loc
+            (nlHsApp (nlHsVar (tag2con_RDR tycon))
+                   (nlHsApps plus_RDR [nlHsVarApps intDataCon_RDR [ah_RDR],
+                                       nlHsIntLit 1]))
                    
     pred_enum
-      = mk_easy_FunMonoBind tycon_loc pred_RDR [a_Pat] [] $
+      = mk_easy_FunBind tycon_loc pred_RDR [a_Pat] emptyLHsBinds $
        untag_Expr tycon [(a_RDR, ah_RDR)] $
-       HsIf (HsApp (HsApp (HsVar eq_RDR) (HsLit (HsInt 0)))
-                   (mk_easy_App mkInt_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")
-            (HsApp (HsVar (tag2con_RDR tycon))
-                          (HsApp (HsApp (HsVar plus_RDR)
-                                        (mk_easy_App mkInt_RDR [ah_RDR]))
-                                 (HsLit (HsInt (-1)))))
-            tycon_loc
+            (nlHsApp (nlHsVar (tag2con_RDR tycon))
+                          (nlHsApps plus_RDR [nlHsVarApps intDataCon_RDR [ah_RDR],
+                                              nlHsLit (HsInt (-1))]))
 
     to_enum
-      = mk_easy_FunMonoBind tycon_loc toEnum_RDR [a_Pat] [] $
-       HsIf (HsApp (HsApp (HsVar gt_RDR) 
-                          (HsVar a_RDR))
-                          (HsVar (maxtag_RDR tycon)))
+      = mk_easy_FunBind tycon_loc toEnum_RDR [a_Pat] emptyLHsBinds $
+       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))
-             (mk_easy_App (tag2con_RDR tycon) [a_RDR])
-            tycon_loc
 
     enum_from
-      = mk_easy_FunMonoBind tycon_loc enumFrom_RDR [a_Pat] [] $
+      = mk_easy_FunBind tycon_loc enumFrom_RDR [a_Pat] emptyLHsBinds $
          untag_Expr tycon [(a_RDR, ah_RDR)] $
-         HsApp (mk_easy_App map_RDR [tag2con_RDR tycon]) $
-           HsPar (enum_from_to_Expr
-                   (mk_easy_App mkInt_RDR [ah_RDR])
-                   (HsVar (maxtag_RDR tycon)))
+         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 tycon_loc enumFromThen_RDR [a_Pat, b_Pat] [] $
+      = mk_easy_FunBind tycon_loc enumFromThen_RDR [a_Pat, b_Pat] emptyLHsBinds $
          untag_Expr tycon [(a_RDR, ah_RDR), (b_RDR, bh_RDR)] $
-         HsApp (mk_easy_App map_RDR [tag2con_RDR tycon]) $
-           HsPar (enum_from_then_to_Expr
-                   (mk_easy_App mkInt_RDR [ah_RDR])
-                   (mk_easy_App mkInt_RDR [bh_RDR])
-                   (HsIf  (HsApp (HsApp (HsVar gt_RDR)
-                                        (HsVar a_RDR))
-                                        (HsVar b_RDR))
-                          (HsLit (HsInt 0))
-                          (HsVar (maxtag_RDR tycon))
-                          tycon_loc))
+         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_FunMonoBind tycon_loc fromEnum_RDR [a_Pat] [] $
+      = mk_easy_FunBind tycon_loc fromEnum_RDR [a_Pat] emptyLHsBinds $
          untag_Expr tycon [(a_RDR, ah_RDR)] $
-         (mk_easy_App mkInt_RDR [ah_RDR])
+         (nlHsVarApps intDataCon_RDR [ah_RDR])
 \end{code}
 
 %************************************************************************
@@ -527,30 +481,30 @@ gen_Enum_binds tycon
 \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
-    tycon_loc = getSrcLoc tycon
+    tycon_loc = getSrcSpan tycon
 
     ----- enum-flavored: ---------------------------
-    min_bound_enum = mk_easy_FunMonoBind tycon_loc minBound_RDR [] [] (HsVar data_con_1_RDR)
-    max_bound_enum = mk_easy_FunMonoBind tycon_loc maxBound_RDR [] [] (HsVar data_con_N_RDR)
+    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 = qual_orig_name data_con_1
-    data_con_N_RDR = 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         = argFieldCount data_con_1
+    arity         = dataConSourceArity data_con_1
 
-    min_bound_1con = mk_easy_FunMonoBind tycon_loc minBound_RDR [] [] $
-                    mk_easy_App data_con_1_RDR (nOfThem arity minBound_RDR)
-    max_bound_1con = mk_easy_FunMonoBind tycon_loc maxBound_RDR [] [] $
-                    mk_easy_App data_con_1_RDR (nOfThem arity maxBound_RDR)
+    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}
 
 %************************************************************************
@@ -602,7 +556,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}
@@ -612,7 +566,7 @@ 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
@@ -620,130 +574,123 @@ gen_Ix_binds tycon
     else single_con_ixes
   where
     tycon_str = getOccString tycon
-    tycon_loc = getSrcLoc 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 tycon_loc range_RDR 
-               [TuplePatIn [a_Pat, b_Pat] True{-boxed-}] [] $
+      = mk_easy_FunBind tycon_loc range_RDR 
+               [nlTuplePat [a_Pat, b_Pat] Boxed] emptyLHsBinds $
          untag_Expr tycon [(a_RDR, ah_RDR)] $
          untag_Expr tycon [(b_RDR, bh_RDR)] $
-         HsApp (mk_easy_App map_RDR [tag2con_RDR tycon]) $
-             HsPar (enum_from_to_Expr
-                       (mk_easy_App mkInt_RDR [ah_RDR])
-                       (mk_easy_App mkInt_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 tycon_loc index_RDR 
-               [AsPatIn c_RDR (TuplePatIn [a_Pat, b_Pat] True{-boxed-}), 
-                               d_Pat] [] (
-       HsIf (HsPar (mk_easy_App inRange_RDR [c_RDR, d_RDR])) (
+      = mk_easy_FunBind tycon_loc index_RDR 
+               [noLoc (AsPat (noLoc c_RDR) 
+                          (nlTuplePat [a_Pat, nlWildPat] Boxed)), 
+                               d_Pat] emptyLHsBinds (
+       nlHsIf (nlHsPar (nlHsVarApps inRange_RDR [c_RDR, d_RDR])) (
           untag_Expr tycon [(a_RDR, ah_RDR)] (
           untag_Expr tycon [(d_RDR, dh_RDR)] (
           let
-               rhs = mk_easy_App mkInt_RDR [c_RDR]
+               rhs = nlHsVarApps intDataCon_RDR [c_RDR]
           in
-          HsCase
-            (genOpApp (HsVar dh_RDR) minusH_RDR (HsVar ah_RDR))
-            [mkSimpleMatch [VarPatIn c_RDR] rhs Nothing tycon_loc]
-            tycon_loc
+          nlHsCase
+            (genOpApp (nlHsVar dh_RDR) minusInt_RDR (nlHsVar ah_RDR))
+            [mkSimpleHsAlt (nlVarPat c_RDR) rhs]
           ))
        ) {-else-} (
-          HsApp (HsVar error_RDR) (HsLit (HsString (_PK_ ("Ix."++tycon_str++".index: out of range\n"))))
-       )
-       tycon_loc)
+          nlHsApp (nlHsVar error_RDR) (nlHsLit (HsString (mkFastString ("Ix."++tycon_str++".index: out of range\n"))))
+       ))
 
     enum_inRange
-      = mk_easy_FunMonoBind tycon_loc inRange_RDR 
-         [TuplePatIn [a_Pat, b_Pat] True{-boxed-}, c_Pat] [] (
+      = mk_easy_FunBind tycon_loc inRange_RDR 
+         [nlTuplePat [a_Pat, b_Pat] Boxed, c_Pat] emptyLHsBinds (
          untag_Expr tycon [(a_RDR, ah_RDR)] (
          untag_Expr tycon [(b_RDR, bh_RDR)] (
          untag_Expr tycon [(c_RDR, ch_RDR)] (
-         HsIf (genOpApp (HsVar ch_RDR) geH_RDR (HsVar ah_RDR)) (
-            (genOpApp (HsVar ch_RDR) leH_RDR (HsVar bh_RDR))
+         nlHsIf (genOpApp (nlHsVar ch_RDR) geInt_RDR (nlHsVar ah_RDR)) (
+            (genOpApp (nlHsVar ch_RDR) leInt_RDR (nlHsVar bh_RDR))
          ) {-else-} (
             false_Expr
-         ) tycon_loc))))
+         )))))
 
     --------------------------------------------------------------
     single_con_ixes 
-      = single_con_range `AndMonoBinds`
-       single_con_index `AndMonoBinds`
-       single_con_inRange
+      = 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 isUnLiftedType (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    = argFieldCount data_con
-    data_con_RDR = qual_orig_name data_con
+    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  = ConPatIn data_con_RDR (map VarPatIn xs)
-    con_expr     = mk_easy_App data_con_RDR cs_needed
+    con_pat  xs  = nlConVarPat data_con_RDR xs
+    con_expr     = nlHsVarApps data_con_RDR cs_needed
 
     --------------------------------------------------------------
     single_con_range
-      = mk_easy_FunMonoBind tycon_loc range_RDR 
-         [TuplePatIn [con_pat as_needed, con_pat bs_needed] True{-boxed-}] [] $
-       HsDo ListComp stmts tycon_loc
+      = mk_easy_FunBind tycon_loc range_RDR 
+         [nlTuplePat [con_pat as_needed, con_pat bs_needed] Boxed] emptyLHsBinds $
+       nlHsDo ListComp stmts
       where
        stmts = zipWith3Equal "single_con_range" mk_qual as_needed bs_needed cs_needed
                ++
-               [ReturnStmt con_expr]
+               [nlResultStmt con_expr]
 
-       mk_qual a b c = BindStmt (VarPatIn c)
-                                (HsApp (HsVar range_RDR) 
-                                       (ExplicitTuple [HsVar a, HsVar b] True))
-                                tycon_loc
+       mk_qual a b c = nlBindStmt (nlVarPat c)
+                                (nlHsApp (nlHsVar range_RDR) 
+                                       (nlTuple [nlHsVar a, nlHsVar b] Boxed))
 
     ----------------
     single_con_index
-      = mk_easy_FunMonoBind tycon_loc index_RDR 
-               [TuplePatIn [con_pat as_needed, con_pat bs_needed] True, 
-                con_pat cs_needed] [range_size] (
-       foldl mk_index (HsLit (HsInt 0)) (zip3 as_needed bs_needed cs_needed))
+      = mk_easy_FunBind tycon_loc index_RDR 
+               [nlTuplePat [con_pat as_needed, con_pat bs_needed] Boxed, 
+                con_pat cs_needed] (unitBag range_size) (
+       foldl mk_index (nlHsIntLit 0) (zip3 as_needed bs_needed cs_needed))
       where
        mk_index multiply_by (l, u, i)
          = genOpApp (
-              (HsApp (HsApp (HsVar index_RDR) 
-                     (ExplicitTuple [HsVar l, HsVar u] True)) (HsVar i))
+              (nlHsApps index_RDR [nlTuple [nlHsVar l, nlHsVar u] Boxed,  
+                                   nlHsVar i])
           ) plus_RDR (
                genOpApp (
-                   (HsApp (HsVar rangeSize_RDR) 
-                          (ExplicitTuple [HsVar l, HsVar u] True))
+                   (nlHsApp (nlHsVar rangeSize_RDR) 
+                          (nlTuple [nlHsVar l, nlHsVar u] Boxed))
                ) times_RDR multiply_by
           )
 
        range_size
-         = mk_easy_FunMonoBind tycon_loc rangeSize_RDR 
-                       [TuplePatIn [a_Pat, b_Pat] True] [] (
+         = mk_easy_FunBind tycon_loc rangeSize_RDR 
+                       [nlTuplePat [a_Pat, b_Pat] Boxed] emptyLHsBinds (
                genOpApp (
-                   (HsApp (HsApp (HsVar index_RDR) 
-                          (ExplicitTuple [a_Expr, b_Expr] True)) b_Expr)
-               ) plus_RDR (HsLit (HsInt 1)))
+                   (nlHsApps index_RDR [nlTuple [a_Expr, b_Expr] Boxed,
+                                        b_Expr])
+               ) plus_RDR (nlHsIntLit 1))
 
     ------------------
     single_con_inRange
-      = mk_easy_FunMonoBind tycon_loc inRange_RDR 
-               [TuplePatIn [con_pat as_needed, con_pat bs_needed] True, 
+      = mk_easy_FunBind tycon_loc inRange_RDR 
+               [nlTuplePat [con_pat as_needed, con_pat bs_needed] Boxed, 
                 con_pat cs_needed]
-                          [] (
+                          emptyLHsBinds (
          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_RDR) 
-                                     (ExplicitTuple [HsVar a, HsVar b] True)) 
-                              (HsVar c)
+       in_range a b c = nlHsApps inRange_RDR [nlTuple [nlHsVar a, nlHsVar b] Boxed,
+                                              nlHsVar c]
 \end{code}
 
 %************************************************************************
@@ -752,200 +699,463 @@ 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 :: TyCon -> RdrNameMonoBinds
+gen_Read_binds :: FixityEnv -> TyCon -> LHsBinds RdrName
 
-gen_Read_binds tycon
-  = reads_prec `AndMonoBinds` read_list
+gen_Read_binds get_fixity tycon
+  = listToBag [read_prec, default_readlist, default_readlistprec]
   where
-    tycon_loc = getSrcLoc tycon
     -----------------------------------------------------------------------
-    read_list = mk_easy_FunMonoBind tycon_loc readList_RDR [] []
-                 (HsApp (HsVar readList___RDR) (HsPar (HsApp (HsVar readsPrec_RDR) (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 tycon_loc readsPrec_RDR [a_Pat, b_Pat] [] (
-             foldr1 append_Expr read_con_comprehensions
-       )
-      where
-       read_con data_con   -- note: "b" is the string being "read"
-         = let
-               data_con_RDR = qual_orig_name data_con
-               data_con_str= occNameString (getOccName data_con)
-               con_arity   = argFieldCount data_con
-               con_expr    = mk_easy_App data_con_RDR as_needed
-               nullary_con = con_arity == 0
-               labels      = dataConFieldLabels data_con
-               lab_fields  = length labels
-
-               as_needed   = take con_arity as_RDRs
-               bs_needed   
-                | lab_fields == 0 = take con_arity bs_RDRs
-                | otherwise       = take (4*lab_fields + 1) bs_RDRs
-                                      -- (label, '=' and field)*n, (n-1)*',' + '{' + '}'
-               con_qual
-                  = BindStmt
-                         (TuplePatIn [LitPatIn (mkHsString data_con_str), 
-                                      d_Pat] True)
-                         (HsApp (HsVar lex_RDR) c_Expr)
-                         tycon_loc
-
-               str_qual str res draw_from
-                  = BindStmt
-                      (TuplePatIn [LitPatIn (mkHsString str), VarPatIn res] True)
-                      (HsApp (HsVar lex_RDR) draw_from)
-                      tycon_loc
-  
-               read_label f
-                 = let nm = occNameString (getOccName (fieldLabelName f))
-                   in 
-                       [str_qual nm, str_qual "="] 
-                           -- There might be spaces between the label and '='
-
-               field_quals
-                 | lab_fields == 0 =
-                    snd (mapAccumL mk_qual 
-                                   d_Expr 
-                                   (zipWithEqual "as_needed" 
-                                                 (\ con_field draw_from -> (mk_read_qual con_field,
-                                                                            draw_from))
-                                                 as_needed bs_needed))
-                  | otherwise =
-                    snd $
-                    mapAccumL mk_qual d_Expr
-                       (zipEqual "bs_needed"        
-                          ((str_qual "{":
-                            concat (
-                            intersperse [str_qual ","] $
-                            zipWithEqual 
-                               "field_quals"
-                               (\ as b -> as ++ [b])
-                                   -- The labels
-                               (map read_label labels)
-                                   -- The fields
-                               (map mk_read_qual as_needed))) ++ [str_qual "}"])
-                           bs_needed)
-
-               mk_qual draw_from (f, str_left)
-                 = (HsVar str_left,    -- what to draw from down the line...
-                    f str_left draw_from)
-
-               mk_read_qual con_field res draw_from =
-                 BindStmt
-                  (TuplePatIn [VarPatIn con_field, VarPatIn res] True)
-                  (HsApp (HsApp (HsVar readsPrec_RDR) (HsLit (HsInt 10))) draw_from)
-                  tycon_loc
-
-               result_expr = ExplicitTuple [con_expr, if null bs_needed 
-                                                      then d_Expr 
-                                                      else HsVar (last bs_needed)] True
-
-               stmts = con_qual:field_quals ++ [ReturnStmt result_expr]
-               
-               read_paren_arg
-                 = if nullary_con then -- must be False (parens are surely optional)
-                      false_Expr
-                   else -- parens depend on precedence...
-                      HsPar (genOpApp a_Expr gt_RDR (HsLit (HsInt 9)))
-           in
-           HsApp (
-             readParen_Expr read_paren_arg $ HsPar $
-                HsLam (mk_easy_Match tycon_loc [c_Pat] [] $
-                       HsDo ListComp stmts tycon_loc)
-             ) (HsVar b_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_stmt con []]]
+            _     -> [nlHsApp (nlHsVar choose_RDR) 
+                           (nlList (map mk_pair nullary_cons))]
+    
+    mk_pair con = nlTuple [nlHsLit (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]
+      where
+               stmts | is_infix          = infix_stmts
+             | length labels > 0 = lbl_stmts
+             | otherwise         = prefix_stmts
+     
+               prefix_stmts            -- T a b c
+                 = [bindLex (ident_pat (data_con_str_w_parens data_con))]
+                   ++ read_args
+                   ++ [result_stmt data_con as_needed]
+        
+               infix_stmts             -- a %% b
+                 = [read_a1, 
+            bindLex (symbol_pat (data_con_str data_con)),
+            read_a2,
+            result_stmt data_con [a1,a2]]
+     
+               lbl_stmts               -- T { f1 = a, f2 = b }
+                 = [bindLex (ident_pat (data_con_str_w_parens data_con)),
+                    read_punc "{"]
+                   ++ concat (intersperse [read_punc ","] field_stmts)
+                   ++ [read_punc "}", result_stmt data_con as_needed]
+     
+               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
+       (a1:a2:_)           = as_needed
+               prec         = getPrec is_infix get_fixity dc_nm
+
+    ------------------------------------------------------------------------
+    --         Helpers
+    ------------------------------------------------------------------------
+    mk_alt e1 e2     = genOpApp e1 alt_RDR e2
+    bindLex pat             = nlBindStmt pat (nlHsVar lexP_RDR)
+    result_stmt c as = nlResultStmt (nlHsApp (nlHsVar returnM_RDR) (con_app c as))
+    con_app c as     = nlHsVarApps (getRdrName c) as
+    
+    punc_pat s   = nlConPat punc_RDR  [nlLitPat (mkHsString s)]          -- Punc 'c'
+    ident_pat s  = nlConPat ident_RDR [nlLitPat s]               -- Ident "foo"
+    symbol_pat s = nlConPat symbol_RDR [nlLitPat s]              -- Symbol ">>"
+    
+    data_con_str          con = mkHsString (occNameUserString (getOccName con))
+    data_con_str_w_parens con = mkHsString (occNameUserString_with_parens (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 = nlBindStmt (nlVarPat a) (nlHsVarApps step_RDR [readPrec_RDR])
+    
+    read_field lbl a = read_lbl lbl ++
+                      [read_punc "=",
+                       nlBindStmt (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 | is_id_start (head lbl_str) 
+                = [bindLex (ident_pat lbl_lit)]
+                | otherwise
+                = [read_punc "(", 
+                   bindLex (symbol_pat lbl_lit),
+                   read_punc ")"]
+                where  
+                  lbl_str = occNameUserString (getOccName lbl) 
+                  lbl_lit = mkHsString lbl_str
+                  is_id_start c = isAlpha c || c == '_'
 \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 :: TyCon -> RdrNameMonoBinds
+gen_Show_binds :: FixityEnv -> TyCon -> LHsBinds RdrName
 
-gen_Show_binds tycon
-  = shows_prec `AndMonoBinds` show_list
+gen_Show_binds get_fixity tycon
+  = listToBag [shows_prec, show_list]
   where
-    tycon_loc = getSrcLoc tycon
+    tycon_loc = getSrcSpan tycon
     -----------------------------------------------------------------------
-    show_list = mk_easy_FunMonoBind tycon_loc showList_RDR [] []
-                 (HsApp (HsVar showList___RDR) (HsPar (HsApp (HsVar showsPrec_RDR) (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 tycon_loc showsPrec_RDR (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_RDR = qual_orig_name data_con
-               con_arity    = argFieldCount data_con
-               bs_needed    = take con_arity bs_RDRs
-               con_pat      = ConPatIn data_con_RDR (map VarPatIn bs_needed)
-               nullary_con  = con_arity == 0
-                labels       = dataConFieldLabels data_con
-               lab_fields   = length labels
-
-               show_con
-                 = let nm = occNameString (getOccName data_con)
-                       space_ocurly_maybe
-                          | nullary_con     = ""
-                         | lab_fields == 0 = " "
-                         | otherwise       = "{"
-
-                   in
-                       mk_showString_app (nm ++ space_ocurly_maybe)
-
-               show_all con fs
-                 = let
-                        ccurly_maybe 
-                          | lab_fields > 0  = [mk_showString_app "}"]
-                          | otherwise       = []
-                   in
-                       con:fs ++ ccurly_maybe
-
-               show_thingies = show_all show_con real_show_thingies_with_labs
+         | 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        = occNameUserString dc_occ_nm
+            op_con_str     = occNameUserString_with_parens dc_occ_nm
+
+            show_thingies 
+               | is_infix      = [show_arg1, mk_showString_app (" " ++ con_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 
-                 = let nm = occNameString (getOccName (fieldLabelName l)) 
-                   in
-                   mk_showString_app (nm ++ "=")
-
-                mk_showString_app str = HsApp (HsVar showString_RDR)
-                                             (HsLit (mkHsString str))
-
-               real_show_thingies =
-                    [ HsApp (HsApp (HsVar showsPrec_RDR) (HsLit (HsInt 10))) (HsVar b)
-                    | b <- bs_needed ]
-
-                real_show_thingies_with_labs
-                | lab_fields == 0 = intersperse (HsVar showSpace_RDR) real_show_thingies
-                | otherwise       = --Assumption: no of fields == no of labelled fields 
-                                    --            (and in same order)
-                   concat $
-                   intersperse ([mk_showString_app ","]) $ -- Using SLIT()s containing ,s spells trouble.
-                   zipWithEqual "gen_Show_binds"
-                                (\ a b -> [a,b])
-                                (map show_label labels) 
-                                real_show_thingies
+            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       = occNameUserString_with_parens 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
+
+occNameUserString_with_parens :: OccName -> String
+occNameUserString_with_parens occ
+  | isSymOcc occ = '(':nm ++ ")"
+  | otherwise    = nm
+  where
+   nm = occNameUserString occ
+
+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] emptyLHsBinds
+               (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
 
-           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 (genOpApp a_Expr ge_RDR (HsLit (HsInt 10))))
-                                  (HsPar (nested_compose_Expr show_thingies)))
+  $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]
+                        emptyLHsBinds
+                        (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 (occNameUserString 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}
 
 %************************************************************************
@@ -959,7 +1169,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)
@@ -970,35 +1180,53 @@ 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 (rdr_name, tycon, GenCon2Tag)
-  = mk_FunMonoBind (getSrcLoc tycon) rdr_name (map mk_stuff (tyConDataCons tycon))
+  | 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
-    mk_stuff :: DataCon -> ([RdrNamePat], RdrNameHsExpr)
+    tycon_loc = getSrcSpan tycon
 
-    mk_stuff var
-      = ([pat], HsLit (HsIntPrim (toInteger ((dataConTag var) - fIRST_TAG))))
-      where
-       pat    = ConPatIn var_RDR (nOfThem (argFieldCount var) WildPatIn)
-       var_RDR = qual_orig_name var
+    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_FunMonoBind (getSrcLoc tycon) rdr_name (map mk_stuff (tyConDataCons tycon) ++ 
-                                                            [([WildPatIn], impossible_Expr)])
-  where
-    mk_stuff :: DataCon -> ([RdrNamePat], RdrNameHsExpr)
-    mk_stuff var = ([lit_pat], HsVar var_RDR)
-      where
-       lit_pat = ConPatIn mkInt_RDR [LitPatIn (HsIntPrim (toInteger ((dataConTag var) - fIRST_TAG)))]
-       var_RDR  = qual_orig_name var
+  = 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)
-  = mk_easy_FunMonoBind (getSrcLoc tycon) 
-               rdr_name [] [] (HsApp (HsVar mkInt_RDR) (HsLit (HsIntPrim max_tag)))
+  = 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)
@@ -1011,268 +1239,251 @@ gen_tag_n_con_monobind (rdr_name, 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}
-
-\begin{code}
-mk_easy_FunMonoBind :: SrcLoc -> RdrName -> [RdrNamePat]
-                   -> [RdrNameMonoBinds] -> RdrNameHsExpr
-                   -> RdrNameMonoBinds
-
-mk_easy_FunMonoBind loc fun pats binds expr
-  = FunMonoBind fun False{-not infix-} [mk_easy_Match loc pats binds expr] loc
-
-mk_easy_Match loc pats binds expr
-  = mk_match loc pats expr (mkbind binds)
-  where
-    mkbind [] = EmptyBinds
-    mkbind bs = MonoBind (foldr1 AndMonoBinds bs) [] Recursive
-       -- 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 :: SrcLoc -> RdrName
-               -> [([RdrNamePat], RdrNameHsExpr)]
-               -> RdrNameMonoBinds
-
-mk_FunMonoBind loc fun [] = panic "TcGenDeriv:mk_FunMonoBind"
-mk_FunMonoBind loc fun pats_and_exprs
-  = FunMonoBind fun False{-not infix-}
-               [ mk_match loc p e EmptyBinds | (p,e) <-pats_and_exprs ]
-               loc
-
-mk_match loc pats expr binds
-  = Match [] (map paren pats) Nothing 
-         (GRHSs (unguardedRHS expr loc) binds Nothing)
-  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}
 
 ToDo: Better SrcLocs.
 
 \begin{code}
-compare_Case ::
-         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
+         TyCon                 -- The tycon we are deriving for
+         -> Type
+         -> LHsExpr RdrName    -- What to do for equality
+         -> LHsExpr RdrName -> LHsExpr RdrName
+         -> LHsExpr RdrName
 
-compare_Case = compare_gen_Case compare_RDR
-cmp_eq_Expr a b = HsApp (HsApp (HsVar cmp_eq_RDR) a) b
+cmp_eq_Expr a b = nlHsApp (nlHsApp (nlHsVar cmp_eq_RDR) a) b
        -- Was: compare_gen_Case cmp_eq_RDR
 
-compare_gen_Case fun lt eq gt a b
-  = HsCase (HsPar (HsApp (HsApp (HsVar fun) a) b)) {-of-}
-      [mkSimpleMatch [ConPatIn ltTag_RDR []] lt Nothing mkGeneratedSrcLoc,
-       mkSimpleMatch [ConPatIn eqTag_RDR []] eq Nothing mkGeneratedSrcLoc,
-       mkSimpleMatch [ConPatIn gtTag_RDR []] gt Nothing mkGeneratedSrcLoc]
-      mkGeneratedSrcLoc
-
-careful_compare_Case ty lt eq gt a b
-  = if not (isUnboxedType ty) then
-       compare_gen_Case compare_RDR lt eq gt a b
-
-    else -- we have to do something special for primitive things...
-       HsIf (genOpApp a relevant_eq_op b)
-           eq
-           (HsIf (genOpApp a relevant_lt_op b) lt gt mkGeneratedSrcLoc)
-           mkGeneratedSrcLoc
+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, ty == ty']
+    res = [id | (ty',id) <- tbl, ty `tcEqType` ty']
 
+eq_op_tbl :: [(Type, PrimOp)]
 eq_op_tbl =
-    [(charPrimTy,      eqH_Char_RDR)
-    ,(intPrimTy,       eqH_Int_RDR)
-    ,(wordPrimTy,      eqH_Word_RDR)
-    ,(addrPrimTy,      eqH_Addr_RDR)
-    ,(floatPrimTy,     eqH_Float_RDR)
-    ,(doublePrimTy,    eqH_Double_RDR)
+    [(charPrimTy,      CharEqOp)
+    ,(intPrimTy,       IntEqOp)
+    ,(wordPrimTy,      WordEqOp)
+    ,(addrPrimTy,      AddrEqOp)
+    ,(floatPrimTy,     FloatEqOp)
+    ,(doublePrimTy,    DoubleEqOp)
     ]
 
+lt_op_tbl :: [(Type, PrimOp)]
 lt_op_tbl =
-    [(charPrimTy,      ltH_Char_RDR)
-    ,(intPrimTy,       ltH_Int_RDR)
-    ,(wordPrimTy,      ltH_Word_RDR)
-    ,(addrPrimTy,      ltH_Addr_RDR)
-    ,(floatPrimTy,     ltH_Float_RDR)
-    ,(doublePrimTy,    ltH_Double_RDR)
+    [(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 = genOpApp a and_RDR    b
-append_Expr a b = genOpApp a append_RDR 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 (isUnboxedType ty) then
-       genOpApp a eq_RDR  b
-    else -- we have to do something special for primitive things...
-       genOpApp a relevant_eq_op b
-  where
-    relevant_eq_op = assoc_ty_id eq_op_tbl ty
-\end{code}
-
-\begin{code}
-argFieldCount :: DataCon -> Int        -- Works on data and newtype constructors
-argFieldCount con = length (dataConRawArgTys con)
+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-}
-      [mkSimpleMatch [VarPatIn put_tag_here] (untag_Expr tycon more expr) Nothing mkGeneratedSrcLoc]
-      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 (genOpApp (HsVar a) 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_RDR) f) t2
-enum_from_then_to_Expr f t t2 = HsApp (HsApp (HsApp (HsVar enumFromThenTo_RDR) 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_RDR) e1) e2
-readParen_Expr e1 e2 = HsApp (HsApp (HsVar readParen_RDR) 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_RDR) (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 = HsApp (HsVar error_RDR) (HsLit (HsString (_PK_ "Urk! in TcGenDeriv")))
+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 = 
-   HsApp (HsVar error_RDR) (HsLit (HsString (_PK_ (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 =
-   HsApp (HsVar error_RDR) 
-         (HsApp (HsApp (HsVar append_RDR)
-                      (HsLit (HsString (_PK_ ("toEnum{" ++ tp ++ "}: tag (")))))
-                      (HsApp (HsApp (HsApp 
-                          (HsVar showsPrec_RDR)
-                          (HsLit (HsInt 0)))
-                          (HsVar a_RDR))
-                          (HsApp (HsApp 
-                              (HsVar append_RDR)
-                              (HsLit (HsString (_PK_ ") is outside of enumeration's range (0,"))))
-                              (HsApp (HsApp (HsApp 
-                                       (HsVar showsPrec_RDR)
-                                       (HsLit (HsInt 0)))
-                                       (HsVar maxtag))
-                                       (HsLit (HsString (_PK_ ")")))))))
-
-parenify e@(HsVar _) = e
-parenify e          = HsPar e
+   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. 
--- For some reason the renamer doesn't reassociate it right, and I can't
--- be bothered to find out why just now.
+genOpApp e1 op e2 = nlHsPar (nlHsOpApp e1 op e2)
+\end{code}
 
-genOpApp e1 op e2 = mkOpApp e1 op e2
+\begin{code}
+getSrcSpan = srcLocSpan . getSrcLoc
 \end{code}
 
 \begin{code}
-qual_orig_name n = case modAndOcc n of { (m,n) -> Qual m n HiFile }
-
-a_RDR          = varUnqual SLIT("a")
-b_RDR          = varUnqual SLIT("b")
-c_RDR          = varUnqual SLIT("c")
-d_RDR          = varUnqual SLIT("d")
-ah_RDR         = varUnqual SLIT("a#")
-bh_RDR         = varUnqual SLIT("b#")
-ch_RDR         = varUnqual SLIT("c#")
-dh_RDR         = varUnqual SLIT("d#")
-cmp_eq_RDR     = varUnqual SLIT("cmp_eq")
-rangeSize_RDR  = varUnqual SLIT("rangeSize")
-
-as_RDRs                = [ varUnqual (_PK_ ("a"++show i)) | i <- [(1::Int) .. ] ]
-bs_RDRs                = [ varUnqual (_PK_ ("b"++show i)) | i <- [(1::Int) .. ] ]
-cs_RDRs                = [ varUnqual (_PK_ ("c"++show i)) | i <- [(1::Int) .. ] ]
-
-mkHsString s = HsString (_PK_ s)
-
-a_Expr         = HsVar a_RDR
-b_Expr         = HsVar b_RDR
-c_Expr         = HsVar c_RDR
-d_Expr         = HsVar d_RDR
-ltTag_Expr     = HsVar ltTag_RDR
-eqTag_Expr     = HsVar eqTag_RDR
-gtTag_Expr     = HsVar gtTag_RDR
-false_Expr     = HsVar false_RDR
-true_Expr      = HsVar true_RDR
-
-con2tag_Expr tycon = HsVar (con2tag_RDR tycon)
-
-a_Pat          = VarPatIn a_RDR
-b_Pat          = VarPatIn b_RDR
-c_Pat          = VarPatIn c_RDR
-d_Pat          = VarPatIn d_RDR
-
-con2tag_RDR, tag2con_RDR, maxtag_RDR :: TyCon -> RdrName
-
-con2tag_RDR tycon = varUnqual (_PK_ ("con2tag_" ++ occNameString (getOccName tycon) ++ "#"))
-tag2con_RDR tycon = varUnqual (_PK_ ("tag2con_" ++ occNameString (getOccName tycon) ++ "#"))
-maxtag_RDR tycon  = varUnqual (_PK_ ("maxtag_"  ++ occNameString (getOccName tycon) ++ "#"))
+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")
+rangeSize_RDR  = mkVarUnqual FSLIT("rangeSize")
+
+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 = mkOccFS varName (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}