[project @ 2003-07-24 14:41:48 by simonpj]
[ghc-hetmet.git] / ghc / compiler / typecheck / TcGenDeriv.lhs
index ac6abdf..f0269f1 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,
@@ -31,7 +33,7 @@ import HsSyn          ( Pat(..), HsConDetails(..), HsExpr(..), MonoBinds(..),
                          HsBinds(..), HsType(..), HsStmtContext(..),
                          unguardedRHS, mkSimpleMatch, mkMonoBind, andMonoBindList, placeHolderType
                        )
-import RdrName         ( RdrName, mkUnqual, nameRdrName, getRdrName )
+import RdrName         ( RdrName, mkUnqual, mkRdrUnqual, nameRdrName, getRdrName )
 import RdrHsSyn                ( mkHsOpApp, RdrNameMonoBinds, RdrNameHsExpr, RdrNamePat, mkHsDo )
 import BasicTypes      ( RecFlag(..), Fixity(..), FixityDirection(..)
                        , maxPrecedence
@@ -56,15 +58,15 @@ import TyCon                ( TyCon, isNewTyCon, tyConDataCons, isEnumerationTyCon,
                          maybeTyConSingleCon, tyConFamilySize, tyConTyVars
                        )
 import TcType          ( isUnLiftedType, tcEqType, Type )
-import TysPrim         ( charPrimTy, intPrimTy, wordPrimTy, addrPrimTy,
-                         floatPrimTy, doublePrimTy
-                       )
+import TysPrim         ( charPrimTy, intPrimTy, wordPrimTy, addrPrimTy, floatPrimTy, doublePrimTy )
+import TysWiredIn      ( charDataCon, intDataCon, floatDataCon, doubleDataCon, wordDataCon )
 import Util            ( zipWithEqual, isSingleton,
                          zipWith3Equal, nOfThem, zipEqual )
 import Panic           ( panic, assertPanic )
 import Char            ( ord, isAlpha )
 import Constants
 import List            ( partition, intersperse )
+import Outputable
 import FastString
 import OccName
 \end{code}
@@ -149,22 +151,6 @@ 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
 
@@ -209,7 +195,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 = HsPar (eq_Expr tycon ty (HsVar a) (HsVar b))
 \end{code}
 
 %************************************************************************
@@ -366,11 +352,11 @@ gen_Ord_binds tycon
            tys_needed  = dataConOrigArgTys data_con
 
            nested_compare_expr [ty] [a] [b]
-             = careful_compare_Case ty eqTag_Expr (HsVar a) (HsVar b)
+             = careful_compare_Case tycon ty eqTag_Expr (HsVar a) (HsVar b)
 
            nested_compare_expr (ty:tys) (a:as) (b:bs)
              = let eq_expr = nested_compare_expr tys as bs
-               in  careful_compare_Case ty eq_expr (HsVar a) (HsVar b)
+               in  careful_compare_Case tycon ty eq_expr (HsVar a) (HsVar b)
 
        default_rhs | null nullary_cons = impossible_Expr       -- Keep desugarer from complaining about
                                                                -- inexhaustive patterns
@@ -510,8 +496,8 @@ gen_Bounded_binds tycon
     tycon_loc = getSrcLoc 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 = mkVarMonoBind tycon_loc minBound_RDR (HsVar data_con_1_RDR)
+    max_bound_enum = mkVarMonoBind tycon_loc maxBound_RDR (HsVar data_con_N_RDR)
 
     data_con_1   = head data_cons
     data_con_N   = last data_cons
@@ -521,9 +507,9 @@ gen_Bounded_binds tycon
     ----- single-constructor-flavored: -------------
     arity         = dataConSourceArity data_con_1
 
-    min_bound_1con = mk_easy_FunMonoBind tycon_loc minBound_RDR [] [] $
+    min_bound_1con = mkVarMonoBind tycon_loc minBound_RDR $
                     mkHsVarApps data_con_1_RDR (nOfThem arity minBound_RDR)
-    max_bound_1con = mk_easy_FunMonoBind tycon_loc maxBound_RDR [] [] $
+    max_bound_1con = mkVarMonoBind tycon_loc maxBound_RDR $
                     mkHsVarApps data_con_1_RDR (nOfThem arity maxBound_RDR)
 \end{code}
 
@@ -622,7 +608,7 @@ gen_Ix_binds tycon
           in
           HsCase
             (genOpApp (HsVar dh_RDR) minusInt_RDR (HsVar ah_RDR))
-            [mkSimpleMatch [VarPat c_RDR] rhs placeHolderType tycon_loc]
+            [mk_triv_Match (VarPat c_RDR) rhs]
             tycon_loc
           ))
        ) {-else-} (
@@ -651,10 +637,9 @@ gen_Ix_binds tycon
     data_con
       =        case maybeTyConSingleCon tycon of -- just checking...
          Nothing -> panic "get_Ix_binds"
-         Just dc -> if (any isUnLiftedType (dataConOrigArgTys 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    = dataConSourceArity data_con
     data_con_RDR = getRdrName data_con
@@ -769,17 +754,17 @@ gen_Read_binds get_fixity tycon
   where
     -----------------------------------------------------------------------
     default_binds 
-       = mk_easy_FunMonoBind loc readList_RDR     [] [] (HsVar readListDefault_RDR)
+       = mkVarMonoBind loc readList_RDR     (HsVar readListDefault_RDR)
                `AndMonoBinds`
-         mk_easy_FunMonoBind loc readListPrec_RDR [] [] (HsVar readListPrecDefault_RDR)
+         mkVarMonoBind loc readListPrec_RDR (HsVar readListPrecDefault_RDR)
     -----------------------------------------------------------------------
 
     loc       = getSrcLoc tycon
     data_cons = tyConDataCons tycon
     (nullary_cons, non_nullary_cons) = partition isNullaryDataCon data_cons
     
-    read_prec = mk_easy_FunMonoBind loc readPrec_RDR [] [] 
-                                   (HsApp (HsVar parens_RDR) read_cons)
+    read_prec = mkVarMonoBind loc readPrec_RDR
+                             (HsApp (HsVar 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
@@ -805,13 +790,13 @@ gen_Read_binds get_fixity tycon
      
                prefix_stmts            -- T a b c
                  = [bindLex (ident_pat (data_con_str data_con))]
-                   ++ map read_arg as_needed
+                   ++ read_args
                    ++ [result_stmt data_con as_needed]
         
                infix_stmts             -- a %% b
-                 = [read_arg a1, 
+                 = [read_a1, 
             bindLex (symbol_pat (data_con_str data_con)),
-            read_arg a2,
+            read_a2,
             result_stmt data_con [a1,a2]]
      
                lbl_stmts               -- T { f1 = a, f2 = b }
@@ -829,7 +814,9 @@ gen_Read_binds get_fixity tycon
                dc_nm        = getName data_con
                is_infix     = isDataSymOcc (getOccName dc_nm)
                as_needed    = take con_arity as_RDRs
-               (a1:a2:_)    = as_needed
+       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
 
     ------------------------------------------------------------------------
@@ -847,17 +834,20 @@ gen_Read_binds get_fixity tycon
     data_con_str con = mkHsString (occNameUserString (getOccName con))
     
     read_punc c = bindLex (punc_pat c)
-    read_arg a  = BindStmt (VarPat a) (mkHsVarApps step_RDR [readPrec_RDR]) loc
+    read_arg a ty 
+       | isUnLiftedType ty = pprPanic "Error in deriving:" (text "Can't read unlifted types yet:" <+> ppr ty)
+       | otherwise = BindStmt (VarPat a) (mkHsVarApps step_RDR [readPrec_RDR]) loc
     
     read_field lbl a = read_lbl lbl ++
                       [read_punc "=",
                        BindStmt (VarPat a) (mkHsVarApps reset_RDR [readPrec_RDR]) loc]
 
        -- When reading field labels we might encounter
-       --      a = 3
+       --      a  = 3
+       --      _a = 3
        -- or   (#) = 4
        -- Note the parens!
-    read_lbl lbl | isAlpha (head lbl_str) 
+    read_lbl lbl | is_id_start (head lbl_str) 
                 = [bindLex (ident_pat lbl_lit)]
                 | otherwise
                 = [read_punc "(", 
@@ -866,6 +856,7 @@ gen_Read_binds get_fixity tycon
                 where  
                   lbl_str = occNameUserString (getOccName (fieldLabelName lbl)) 
                   lbl_lit = mkHsString lbl_str
+                  is_id_start c = isAlpha c || c == '_'
 \end{code}
 
 
@@ -906,7 +897,7 @@ gen_Show_binds get_fixity tycon
   where
     tycon_loc = getSrcLoc tycon
     -----------------------------------------------------------------------
-    show_list = mk_easy_FunMonoBind tycon_loc showList_RDR [] []
+    show_list = mkVarMonoBind tycon_loc showList_RDR
                  (HsApp (HsVar showList___RDR) (HsPar (HsApp (HsVar showsPrec_RDR) (mkHsIntLit 0))))
     -----------------------------------------------------------------------
     shows_prec = mk_FunMonoBind tycon_loc showsPrec_RDR (map pats_etc (tyConDataCons tycon))
@@ -923,6 +914,7 @@ gen_Show_binds get_fixity tycon
             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       = mkConPat data_con_RDR bs_needed
             nullary_con   = con_arity == 0
              labels        = dataConFieldLabels data_con
@@ -947,16 +939,13 @@ gen_Show_binds get_fixity tycon
                 where
                   occ_nm   = getOccName (fieldLabelName l)
                   nm       = occNameUserString occ_nm
-
                   is_op    = isSymOcc occ_nm       -- Legal, but rare.
-                  the_name 
-                    | is_op     = '(':nm ++ ")"
-                    | otherwise = nm
+                  the_name | is_op     = '(':nm ++ ")"
+                           | otherwise = nm
 
-             show_args = [ mkHsApps showsPrec_RDR [HsLit (HsInt arg_prec), HsVar b]
-                        | b <- bs_needed ]
+             show_args                      = zipWith show_arg bs_needed arg_tys
             (show_arg1:show_arg2:_) = show_args
-            show_prefix_args = intersperse (HsVar showSpace_RDR) show_args
+            show_prefix_args        = intersperse (HsVar showSpace_RDR) show_args
 
                --  Assumption for record syntax: no of fields == no of labelled fields 
                --            (and in same order)
@@ -966,6 +955,12 @@ gen_Show_binds get_fixity tycon
                                | (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 = mkHsApps showsPrec_RDR [HsLit (HsInt arg_prec), 
+                                                        box_if_necy "Show" tycon (HsVar b) arg_ty]
+
                -- Fixity stuff
             is_infix = isDataSymOcc dc_occ_nm
              con_prec_plus_one = 1 + getPrec is_infix get_fixity dc_nm
@@ -1002,6 +997,151 @@ isLRAssoc get_fixity nm =
 
 %************************************************************************
 %*                                                                     *
+\subsection{Typeable}
+%*                                                                     *
+%************************************************************************
+
+From the data type
+
+       data T a b = ....
+
+we generate
+
+       instance (Typeable a, Typeable b) => Typeable (T a b) where
+               typeOf _ = mkTypeRep (mkTyConRep "T")
+                                    [typeOf (undefined::a),
+                                     typeOf (undefined::b)]
+
+Notice the use of lexically scoped type variables.
+
+\begin{code}
+gen_Typeable_binds :: TyCon -> RdrNameMonoBinds
+gen_Typeable_binds tycon
+  = mk_easy_FunMonoBind tycon_loc typeOf_RDR [wildPat] []
+       (mkHsApps mkTypeRep_RDR [tycon_rep, arg_reps])
+  where
+    tycon_loc = getSrcLoc tycon
+    tyvars    = tyConTyVars tycon
+    tycon_rep = HsVar mkTyConRep_RDR `HsApp` HsLit (mkHsString (showSDoc (ppr tycon)))
+    arg_reps  = ExplicitList placeHolderType (map mk tyvars)
+    mk tyvar  = HsApp (HsVar typeOf_RDR) 
+                     (ExprWithTySig (HsVar undefined_RDR)
+                                    (HsTyVar (getRdrName tyvar)))
+\end{code}
+
+
+
+%************************************************************************
+%*                                                                     *
+\subsection{Data}
+%*                                                                     *
+%************************************************************************
+
+From the data type
+
+  data T a b = T1 a b | T2
+
+we generate
+
+  $cT1 = mkConstr 1 "T1" Prefix
+  $cT2 = mkConstr 2 "T2" Prefix
+  $dT  = mkDataType [$con_T1, $con_T2]
+
+  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
+    
+    fromConstr c = case conIndex c of
+               1 -> T1 undefined undefined
+               2 -> T2
+    
+    toConstr (T1 _ _) = $cT1
+    toConstr T2              = $cT2
+    
+    dataTypeOf _ = $dT
+
+\begin{code}
+gen_Data_binds :: FixityEnv
+              -> TyCon 
+              -> (RdrNameMonoBinds,    -- The method bindings
+                  RdrNameMonoBinds)    -- Auxiliary bindings
+gen_Data_binds fix_env tycon
+  = (andMonoBindList [gfoldl_bind, fromCon_bind, toCon_bind, dataTypeOf_bind],
+               -- Auxiliary definitions: the data type and constructors
+     datatype_bind `AndMonoBinds` andMonoBindList (map mk_con_bind data_cons))
+  where
+    tycon_loc = getSrcLoc tycon
+    data_cons = tyConDataCons tycon
+
+       ------------ gfoldl
+    gfoldl_bind = mk_FunMonoBind tycon_loc gfoldl_RDR (map gfoldl_eqn data_cons)
+    gfoldl_eqn con = ([VarPat k_RDR, VarPat z_RDR, mkConPat con_name as_needed], 
+                      foldl mk_k_app (HsVar z_RDR `HsApp` HsVar con_name) as_needed)
+                  where
+                    con_name :: RdrName
+                    con_name = getRdrName con
+                    as_needed = take (dataConSourceArity con) as_RDRs
+                    mk_k_app e v = HsPar (mkHsOpApp e k_RDR (HsVar v))
+
+       ------------ fromConstr
+    fromCon_bind = mk_FunMonoBind tycon_loc fromConstr_RDR [([c_Pat], from_con_rhs)]
+    from_con_rhs = HsCase (HsVar conIndex_RDR `HsApp` c_Expr) 
+                         (map from_con_alt data_cons) tycon_loc
+    from_con_alt dc = mk_triv_Match (LitPat (HsInt (toInteger (dataConTag dc))))
+                                   (mkHsVarApps (getRdrName dc)
+                                                (replicate (dataConSourceArity dc) undefined_RDR))
+                         
+       ------------ toConstr
+    toCon_bind = mk_FunMonoBind tycon_loc toConstr_RDR (map to_con_eqn data_cons)
+    to_con_eqn dc = ([mkWildConPat dc], HsVar (mkConstrName dc))
+    
+       ------------ dataTypeOf
+    dataTypeOf_bind = mk_easy_FunMonoBind tycon_loc dataTypeOf_RDR [wildPat] 
+                                         [] (HsVar data_type_name)
+
+       ------------ $dT
+    data_type_name = mkDataTypeName tycon
+    datatype_bind  = mkVarMonoBind tycon_loc data_type_name
+                                            (ExplicitList placeHolderType constrs)
+    constrs = [HsVar (mkConstrName con) | con <- data_cons]
+
+       ------------ $cT1 etc
+    mk_con_bind dc = mkVarMonoBind tycon_loc (mkConstrName dc) 
+                                            (mkHsApps mkConstr_RDR (constr_args dc))
+    constr_args dc = [mkHsIntLit (toInteger (dataConTag dc)),          -- Tag
+                     HsLit (mkHsString (occNameUserString dc_occ)),    -- String name
+                     HsVar fixity]                                     -- Fixity
+       where
+         dc_occ   = getOccName dc
+         is_infix = isDataSymOcc dc_occ
+         fixity | is_infix  = infix_RDR
+                | otherwise = prefix_RDR
+
+gfoldl_RDR     = varQual_RDR gENERICS_Name FSLIT("gfoldl")
+fromConstr_RDR = varQual_RDR gENERICS_Name FSLIT("fromConstr")
+toConstr_RDR   = varQual_RDR gENERICS_Name FSLIT("toConstr")
+dataTypeOf_RDR = varQual_RDR gENERICS_Name FSLIT("dataTypeOf")
+mkConstr_RDR   = varQual_RDR gENERICS_Name FSLIT("mkConstr")
+mkDataType_RDR = varQual_RDR gENERICS_Name FSLIT("mkDataType")
+conIndex_RDR   = varQual_RDR gENERICS_Name FSLIT("conIndex")
+prefix_RDR     = dataQual_RDR gENERICS_Name FSLIT("Prefix")
+infix_RDR      = dataQual_RDR gENERICS_Name FSLIT("Infix")
+
+mkDataTypeName :: TyCon -> RdrName     -- $tT
+mkDataTypeName tc = mkRdrUnqual (mkDataTOcc (getOccName tc))
+
+mkConstrName :: DataCon -> RdrName     -- $cT1
+mkConstrName con = mkRdrUnqual (mkDataCOcc (getOccName con))
+
+
+apN :: Int -> (a -> a) -> a -> a
+apN 0 k z = z
+apN n k z = apN (n-1) k (k z)
+\end{code}
+
+%************************************************************************
+%*                                                                     *
 \subsection{Generating extra binds (@con2tag@ and @tag2con@)}
 %*                                                                     *
 %************************************************************************
@@ -1055,11 +1195,8 @@ gen_tag_n_con_monobind (rdr_name, tycon, GenCon2Tag)
     lots_of_constructors = tyConFamilySize tycon > mAX_FAMILY_SIZE_FOR_VEC_RETURNS
 
     mk_stuff :: DataCon -> ([RdrNamePat], RdrNameHsExpr)
-    mk_stuff var
-      = ([pat], HsLit (HsIntPrim (toInteger ((dataConTag var) - fIRST_TAG))))
-      where
-       pat    = ConPatIn var_RDR (PrefixCon (nOfThem (dataConSourceArity var) wildPat))
-       var_RDR = getRdrName var
+    mk_stuff con = ([mkWildConPat con], 
+                   HsLit (HsIntPrim (toInteger ((dataConTag con) - fIRST_TAG))))
 
 gen_tag_n_con_monobind (rdr_name, tycon, GenTag2Con)
   = mk_FunMonoBind (getSrcLoc tycon) rdr_name 
@@ -1068,8 +1205,8 @@ gen_tag_n_con_monobind (rdr_name, tycon, GenTag2Con)
                         (HsTyVar (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)))
+  = mkVarMonoBind (getSrcLoc tycon) rdr_name 
+                 (HsApp (HsVar mkInt_RDR) (HsLit (HsIntPrim max_tag)))
   where
     max_tag =  case (tyConDataCons tycon) of
                 data_cons -> toInteger ((length data_cons) - fIRST_TAG)
@@ -1097,6 +1234,9 @@ multi-clause definitions; it generates:
 \end{verbatim}
 
 \begin{code}
+mkVarMonoBind :: SrcLoc -> RdrName -> RdrNameHsExpr -> RdrNameMonoBinds
+mkVarMonoBind loc var rhs = mk_easy_FunMonoBind loc var [] [] rhs
+
 mk_easy_FunMonoBind :: SrcLoc -> RdrName -> [RdrNamePat]
                    -> [RdrNameMonoBinds] -> RdrNameHsExpr
                    -> RdrNameMonoBinds
@@ -1110,6 +1250,8 @@ mk_easy_Match loc pats binds expr
        -- "recursive" MonoBinds, and it is its job to sort things out
        -- from there.
 
+mk_triv_Match pat expr = mkSimpleMatch [pat] expr placeHolderType generatedSrcLoc
+
 mk_FunMonoBind :: SrcLoc -> RdrName
                -> [([RdrNamePat], RdrNameHsExpr)]
                -> RdrNameMonoBinds
@@ -1138,6 +1280,7 @@ mkHsChar c   = HsChar   (ord c)
 
 mkConPat con vars   = ConPatIn con (PrefixCon (map VarPat vars))
 mkNullaryConPat con = ConPatIn con (PrefixCon [])
+mkWildConPat con    = ConPatIn (getRdrName con) (PrefixCon (nOfThem (dataConSourceArity con) wildPat))
 \end{code}
 
 ToDo: Better SrcLocs.
@@ -1148,7 +1291,8 @@ compare_gen_Case ::
          -> RdrNameHsExpr -> RdrNameHsExpr
          -> RdrNameHsExpr
 careful_compare_Case :: -- checks for primitive types...
-         Type
+         TyCon                 -- The tycon we are deriving for
+         -> Type
          -> RdrNameHsExpr      -- What to do for equality
          -> RdrNameHsExpr -> RdrNameHsExpr
          -> RdrNameHsExpr
@@ -1160,29 +1304,46 @@ compare_gen_Case (HsVar eq_tag) a b | eq_tag == eqTag_RDR
   = HsApp (HsApp (HsVar compare_RDR) a) b      -- Simple case 
 compare_gen_Case eq a b                                -- General case
   = HsCase (HsPar (HsApp (HsApp (HsVar compare_RDR) a) b)) {-of-}
-      [mkSimpleMatch [mkNullaryConPat ltTag_RDR] ltTag_Expr placeHolderType generatedSrcLoc,
-       mkSimpleMatch [mkNullaryConPat eqTag_RDR] eq placeHolderType generatedSrcLoc,
-       mkSimpleMatch [mkNullaryConPat gtTag_RDR] gtTag_Expr placeHolderType generatedSrcLoc]
+      [mk_triv_Match (mkNullaryConPat ltTag_RDR) ltTag_Expr,
+       mk_triv_Match (mkNullaryConPat eqTag_RDR) eq,
+       mk_triv_Match (mkNullaryConPat gtTag_RDR) gtTag_Expr]
       generatedSrcLoc
 
-careful_compare_Case ty eq a b
-  | not (isUnLiftedType ty) =
-       compare_gen_Case eq a b
-  | otherwise               =
-         -- we have to do something special for primitive things...
-       HsIf (genOpApp a relevant_eq_op b)
-           eq
-           (HsIf (genOpApp a relevant_lt_op b) ltTag_Expr gtTag_Expr generatedSrcLoc)
-           generatedSrcLoc
+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...
+  = HsIf (genOpApp a relevant_eq_op b)
+        eq
+        (HsIf (genOpApp a relevant_lt_op b) ltTag_Expr gtTag_Expr generatedSrcLoc)
+        generatedSrcLoc
   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 = assoc_ty_id "Ord" tycon eq_op_tbl ty
+    relevant_lt_op = assoc_ty_id "Ord" tycon lt_op_tbl ty
+
+
+box_if_necy :: String          -- The class involved
+           -> TyCon            -- The tycon involved
+           -> RdrNameHsExpr    -- The argument
+           -> Type             -- The argument type
+           -> RdrNameHsExpr    -- Boxed version of the arg
+box_if_necy cls_str tycon arg arg_ty
+  | isUnLiftedType arg_ty = HsApp (HsVar box_con) arg
+  | otherwise            = arg
   where
-    res = [id | (ty',id) <- tyids, ty `tcEqType` ty']
+    box_con = assoc_ty_id cls_str tycon box_con_tbl arg_ty
+
+assoc_ty_id :: String          -- The class involved
+           -> TyCon            -- The tycon involved
+           -> [(Type,a)]       -- The table
+           -> Type             -- The type
+           -> a                -- The result of the lookup
+assoc_ty_id cls_str tycon tbl ty 
+  | null res = pprPanic "Error in deriving:" (text "Can't derive" <+> text cls_str <+> 
+                                             text "for primitive type" <+> ppr ty)
+  | otherwise = head res
+  where
+    res = [id | (ty',id) <- tbl, ty `tcEqType` ty']
 
 eq_op_tbl =
     [(charPrimTy,      eqChar_RDR)
@@ -1202,6 +1363,15 @@ lt_op_tbl =
     ,(doublePrimTy,    ltDouble_RDR)
     ]
 
+box_con_tbl =
+    [(charPrimTy,      getRdrName charDataCon)
+    ,(intPrimTy,       getRdrName intDataCon)
+    ,(wordPrimTy,      getRdrName wordDataCon)
+    ,(addrPrimTy,      addrDataCon_RDR)
+    ,(floatPrimTy,     getRdrName floatDataCon)
+    ,(doublePrimTy,    getRdrName doubleDataCon)
+    ]
+
 -----------------------------------------------------------------------
 
 and_Expr, append_Expr :: RdrNameHsExpr -> RdrNameHsExpr -> RdrNameHsExpr
@@ -1211,14 +1381,14 @@ append_Expr a b = genOpApp a append_RDR b
 
 -----------------------------------------------------------------------
 
-eq_Expr :: Type -> RdrNameHsExpr -> RdrNameHsExpr -> RdrNameHsExpr
-eq_Expr ty a b = genOpApp a eq_op b
+eq_Expr :: TyCon -> Type -> RdrNameHsExpr -> RdrNameHsExpr -> RdrNameHsExpr
+eq_Expr tycon ty a b = genOpApp a eq_op b
  where
    eq_op
     | not (isUnLiftedType ty) = eq_RDR
     | otherwise               =
          -- we have to do something special for primitive things...
-       assoc_ty_id eq_op_tbl ty
+       assoc_ty_id "Eq" tycon eq_op_tbl ty
 
 \end{code}
 
@@ -1227,7 +1397,7 @@ untag_Expr :: TyCon -> [(RdrName, RdrName)] -> RdrNameHsExpr -> RdrNameHsExpr
 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 [VarPat put_tag_here] (untag_Expr tycon more expr) placeHolderType generatedSrcLoc]
+      [mk_triv_Match (VarPat put_tag_here) (untag_Expr tycon more expr)]
       generatedSrcLoc
 
 cmp_tags_Expr :: RdrName               -- Comparison op
@@ -1308,6 +1478,9 @@ a_RDR             = varUnqual FSLIT("a")
 b_RDR          = varUnqual FSLIT("b")
 c_RDR          = varUnqual FSLIT("c")
 d_RDR          = varUnqual FSLIT("d")
+e_RDR          = varUnqual FSLIT("e")
+k_RDR          = varUnqual FSLIT("k")
+z_RDR          = varUnqual FSLIT("z") :: RdrName
 ah_RDR         = varUnqual FSLIT("a#")
 bh_RDR         = varUnqual FSLIT("b#")
 ch_RDR         = varUnqual FSLIT("c#")
@@ -1324,6 +1497,7 @@ a_Expr            = HsVar a_RDR
 b_Expr         = HsVar b_RDR
 c_Expr         = HsVar c_RDR
 d_Expr         = HsVar d_RDR
+z_Expr         = HsVar z_RDR
 ltTag_Expr     = HsVar ltTag_RDR
 eqTag_Expr     = HsVar eqTag_RDR
 gtTag_Expr     = HsVar gtTag_RDR